diff --git a/e2e/components/FluidNumberInput/FluidNumberInput-test.e2e.js b/e2e/components/FluidNumberInput/FluidNumberInput-test.e2e.js new file mode 100644 index 000000000000..7a5791f73b31 --- /dev/null +++ b/e2e/components/FluidNumberInput/FluidNumberInput-test.e2e.js @@ -0,0 +1,37 @@ +/** + * Copyright IBM Corp. 2016, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +const { expect, test } = require('@playwright/test'); +const { themes } = require('../../test-utils/env'); +const { snapshotStory, visitStory } = require('../../test-utils/storybook'); + +test.describe('FluidNumberInput', () => { + themes.forEach((theme) => { + test.describe(theme, () => { + test('fluid text input @vrt', async ({ page }) => { + await snapshotStory(page, { + component: 'FluidNumberInput', + id: 'experimental-unstable-fluidnumberinput--default', + theme, + }); + }); + }); + }); + + test('accessibility-checker @avt', async ({ page }) => { + await visitStory(page, { + component: 'FluidNumberInput', + id: 'experimental-unstable-fluidnumberinput--default', + globals: { + theme: 'white', + }, + }); + await expect(page).toHaveNoACViolations('FluidNumberInput'); + }); +}); diff --git a/packages/carbon-components-react/scss/components/fluid-combo-box/_fluid-combo-box.scss b/packages/carbon-components-react/scss/components/fluid-combo-box/_fluid-combo-box.scss new file mode 100644 index 000000000000..64a4f14b230e --- /dev/null +++ b/packages/carbon-components-react/scss/components/fluid-combo-box/_fluid-combo-box.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components-react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-combo-box/fluid-combo-box'; diff --git a/packages/carbon-components-react/scss/components/fluid-combo-box/_index.scss b/packages/carbon-components-react/scss/components/fluid-combo-box/_index.scss new file mode 100644 index 000000000000..a64f42c9dd51 --- /dev/null +++ b/packages/carbon-components-react/scss/components/fluid-combo-box/_index.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components-react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-combo-box'; diff --git a/packages/carbon-components-react/scss/components/fluid-multiselect/_fluid-multiselect.scss b/packages/carbon-components-react/scss/components/fluid-multiselect/_fluid-multiselect.scss new file mode 100644 index 000000000000..9dee4ac39a3c --- /dev/null +++ b/packages/carbon-components-react/scss/components/fluid-multiselect/_fluid-multiselect.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components-react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-multiselect/fluid-multiselect'; diff --git a/packages/carbon-components-react/scss/components/fluid-multiselect/_index.scss b/packages/carbon-components-react/scss/components/fluid-multiselect/_index.scss new file mode 100644 index 000000000000..19e1d9b4ee48 --- /dev/null +++ b/packages/carbon-components-react/scss/components/fluid-multiselect/_index.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components-react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-multiselect'; diff --git a/packages/carbon-components-react/scss/components/fluid-number-input/_fluid-number-input.scss b/packages/carbon-components-react/scss/components/fluid-number-input/_fluid-number-input.scss new file mode 100644 index 000000000000..59d1d7a6f5b3 --- /dev/null +++ b/packages/carbon-components-react/scss/components/fluid-number-input/_fluid-number-input.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components-react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-number-input/fluid-number-input'; diff --git a/packages/carbon-components-react/scss/components/fluid-number-input/_index.scss b/packages/carbon-components-react/scss/components/fluid-number-input/_index.scss new file mode 100644 index 000000000000..c0cb30559629 --- /dev/null +++ b/packages/carbon-components-react/scss/components/fluid-number-input/_index.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components-react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-number-input'; diff --git a/packages/carbon-components/scss/components/fluid-combo-box/_fluid-combo-box.scss b/packages/carbon-components/scss/components/fluid-combo-box/_fluid-combo-box.scss new file mode 100644 index 000000000000..1e76f17a7e78 --- /dev/null +++ b/packages/carbon-components/scss/components/fluid-combo-box/_fluid-combo-box.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-combo-box/fluid-combo-box'; diff --git a/packages/carbon-components/scss/components/fluid-combo-box/_index.scss b/packages/carbon-components/scss/components/fluid-combo-box/_index.scss new file mode 100644 index 000000000000..a91f4f0b496b --- /dev/null +++ b/packages/carbon-components/scss/components/fluid-combo-box/_index.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-combo-box'; diff --git a/packages/carbon-components/scss/components/fluid-multiselect/_fluid-multiselect.scss b/packages/carbon-components/scss/components/fluid-multiselect/_fluid-multiselect.scss new file mode 100644 index 000000000000..924ab38ff959 --- /dev/null +++ b/packages/carbon-components/scss/components/fluid-multiselect/_fluid-multiselect.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-multiselect/fluid-multiselect'; diff --git a/packages/carbon-components/scss/components/fluid-multiselect/_index.scss b/packages/carbon-components/scss/components/fluid-multiselect/_index.scss new file mode 100644 index 000000000000..46c1623dfe37 --- /dev/null +++ b/packages/carbon-components/scss/components/fluid-multiselect/_index.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-multiselect'; diff --git a/packages/carbon-components/scss/components/fluid-number-input/_fluid-number-input.scss b/packages/carbon-components/scss/components/fluid-number-input/_fluid-number-input.scss new file mode 100644 index 000000000000..024e025923f2 --- /dev/null +++ b/packages/carbon-components/scss/components/fluid-number-input/_fluid-number-input.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-number-input/fluid-number-input'; diff --git a/packages/carbon-components/scss/components/fluid-number-input/_index.scss b/packages/carbon-components/scss/components/fluid-number-input/_index.scss new file mode 100644 index 000000000000..0cb04ae4fba6 --- /dev/null +++ b/packages/carbon-components/scss/components/fluid-number-input/_index.scss @@ -0,0 +1,9 @@ +// Code generated by carbon-components. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-number-input'; diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index 7322a1dccb03..448be7c2adcb 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -9826,6 +9826,100 @@ Map { }, }, }, + "unstable__FluidNumberInput" => Object { + "$$typeof": Symbol(react.forward_ref), + "propTypes": Object { + "allowEmpty": Object { + "type": "bool", + }, + "className": Object { + "type": "string", + }, + "defaultValue": Object { + "args": Array [ + Array [ + Object { + "type": "number", + }, + Object { + "type": "string", + }, + ], + ], + "type": "oneOfType", + }, + "disableWheel": Object { + "type": "bool", + }, + "disabled": Object { + "type": "bool", + }, + "iconDescription": Object { + "type": "string", + }, + "id": Object { + "isRequired": true, + "type": "string", + }, + "invalid": Object { + "type": "bool", + }, + "invalidText": Object { + "type": "node", + }, + "label": Object { + "type": "node", + }, + "max": Object { + "type": "number", + }, + "min": Object { + "type": "number", + }, + "onChange": Object { + "type": "func", + }, + "onClick": Object { + "type": "func", + }, + "onKeyUp": Object { + "type": "func", + }, + "step": Object { + "type": "number", + }, + "translateWithId": Object { + "type": "func", + }, + "value": Object { + "args": Array [ + Array [ + Object { + "type": "number", + }, + Object { + "type": "string", + }, + ], + ], + "type": "oneOfType", + }, + "warn": Object { + "type": "bool", + }, + "warnText": Object { + "type": "node", + }, + }, + "render": [Function], + }, + "unstable__FluidNumberInputSkeleton" => Object { + "propTypes": Object { + "className": Object { + "type": "string", + }, + }, + }, "unstable__FluidSelect" => Object { "$$typeof": Symbol(react.forward_ref), "propTypes": Object { diff --git a/packages/react/scss/components/fluid-combo-box/_fluid-combo-box.scss b/packages/react/scss/components/fluid-combo-box/_fluid-combo-box.scss new file mode 100644 index 000000000000..9d064aaccedf --- /dev/null +++ b/packages/react/scss/components/fluid-combo-box/_fluid-combo-box.scss @@ -0,0 +1,9 @@ +// Code generated by @carbon/react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-combo-box/fluid-combo-box'; diff --git a/packages/react/scss/components/fluid-combo-box/_index.scss b/packages/react/scss/components/fluid-combo-box/_index.scss new file mode 100644 index 000000000000..b8c4dc60abba --- /dev/null +++ b/packages/react/scss/components/fluid-combo-box/_index.scss @@ -0,0 +1,9 @@ +// Code generated by @carbon/react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-combo-box'; diff --git a/packages/react/scss/components/fluid-multiselect/_fluid-multiselect.scss b/packages/react/scss/components/fluid-multiselect/_fluid-multiselect.scss new file mode 100644 index 000000000000..85dc568d85ec --- /dev/null +++ b/packages/react/scss/components/fluid-multiselect/_fluid-multiselect.scss @@ -0,0 +1,9 @@ +// Code generated by @carbon/react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-multiselect/fluid-multiselect'; diff --git a/packages/react/scss/components/fluid-multiselect/_index.scss b/packages/react/scss/components/fluid-multiselect/_index.scss new file mode 100644 index 000000000000..58c807b8c7b2 --- /dev/null +++ b/packages/react/scss/components/fluid-multiselect/_index.scss @@ -0,0 +1,9 @@ +// Code generated by @carbon/react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-multiselect'; diff --git a/packages/react/scss/components/fluid-number-input/_fluid-number-input.scss b/packages/react/scss/components/fluid-number-input/_fluid-number-input.scss new file mode 100644 index 000000000000..6bb1dc097f31 --- /dev/null +++ b/packages/react/scss/components/fluid-number-input/_fluid-number-input.scss @@ -0,0 +1,9 @@ +// Code generated by @carbon/react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-number-input/fluid-number-input'; diff --git a/packages/react/scss/components/fluid-number-input/_index.scss b/packages/react/scss/components/fluid-number-input/_index.scss new file mode 100644 index 000000000000..83fc59567a63 --- /dev/null +++ b/packages/react/scss/components/fluid-number-input/_index.scss @@ -0,0 +1,9 @@ +// Code generated by @carbon/react. DO NOT EDIT. +// +// Copyright IBM Corp. 2018, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward '@carbon/styles/scss/components/fluid-number-input'; diff --git a/packages/react/src/__tests__/index-test.js b/packages/react/src/__tests__/index-test.js index a34dd9bf8859..42e45baf6741 100644 --- a/packages/react/src/__tests__/index-test.js +++ b/packages/react/src/__tests__/index-test.js @@ -239,6 +239,8 @@ describe('Carbon Components React', () => { "unstable__FluidDropdownSkeleton", "unstable__FluidMultiSelect", "unstable__FluidMultiSelectSkeleton", + "unstable__FluidNumberInput", + "unstable__FluidNumberInputSkeleton", "unstable__FluidSelect", "unstable__FluidSelectSkeleton", "unstable__FluidTextArea", diff --git a/packages/react/src/components/FluidComboBox/FluidComboBox.stories.js b/packages/react/src/components/FluidComboBox/FluidComboBox.stories.js index c49c27a9c330..5d2c387fff2d 100644 --- a/packages/react/src/components/FluidComboBox/FluidComboBox.stories.js +++ b/packages/react/src/components/FluidComboBox/FluidComboBox.stories.js @@ -18,6 +18,9 @@ import { Information } from '@carbon/icons-react'; export default { title: 'Experimental/unstable__FluidComboBox', component: FluidComboBox, + subcomponents: { + FluidComboBoxSkeleton, + }, }; const items = [ diff --git a/packages/react/src/components/FluidDatePicker/FluidDatePicker.stories.js b/packages/react/src/components/FluidDatePicker/FluidDatePicker.stories.js index 0022126ab5d0..60ab5ecfde15 100644 --- a/packages/react/src/components/FluidDatePicker/FluidDatePicker.stories.js +++ b/packages/react/src/components/FluidDatePicker/FluidDatePicker.stories.js @@ -20,6 +20,9 @@ import { Information } from '@carbon/icons-react'; export default { title: 'Experimental/unstable__FluidDatePicker', component: FluidDatePicker, + subcomponents: { + FluidDatePickerSkeleton, + }, }; const ToggleTip = ( diff --git a/packages/react/src/components/FluidDropdown/FluidDropdown.stories.js b/packages/react/src/components/FluidDropdown/FluidDropdown.stories.js index f747737cf06f..0f6797afe3e3 100644 --- a/packages/react/src/components/FluidDropdown/FluidDropdown.stories.js +++ b/packages/react/src/components/FluidDropdown/FluidDropdown.stories.js @@ -18,6 +18,9 @@ import { Information } from '@carbon/icons-react'; export default { title: 'Experimental/unstable__FluidDropdown', component: FluidDropdown, + subcomponents: { + FluidDropdownSkeleton, + }, }; const items = [ diff --git a/packages/react/src/components/FluidForm/FluidForm.stories.js b/packages/react/src/components/FluidForm/FluidForm.stories.js index 6b8a4eeff38c..710655f509f7 100644 --- a/packages/react/src/components/FluidForm/FluidForm.stories.js +++ b/packages/react/src/components/FluidForm/FluidForm.stories.js @@ -17,6 +17,7 @@ import FluidTextInput from '../FluidTextInput'; import FluidTextArea from '../FluidTextArea'; import FluidTimePicker from '../FluidTimePicker'; import FluidTimePickerSelect from '../FluidTimePickerSelect'; +import FluidNumberInput from '../FluidNumberInput'; import ModalWrapper from '../ModalWrapper'; const additionalProps = { @@ -100,7 +101,19 @@ export const Default = () => ( - +
+ + +
+ +
+ +
+
+ + ); +} + +FluidNumberInputSkeleton.propTypes = { + /** + * Specify an optional className to be applied to the outer FluidForm wrapper + */ + className: PropTypes.string, +}; + +export default FluidNumberInputSkeleton; diff --git a/packages/react/src/components/FluidNumberInput/FluidNumberInput.js b/packages/react/src/components/FluidNumberInput/FluidNumberInput.js new file mode 100644 index 000000000000..ed45d60fadb9 --- /dev/null +++ b/packages/react/src/components/FluidNumberInput/FluidNumberInput.js @@ -0,0 +1,134 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import PropTypes from 'prop-types'; +import React from 'react'; +import classnames from 'classnames'; +import { NumberInput } from '../NumberInput'; +import { usePrefix } from '../../internal/usePrefix'; +import { FormContext } from '../FluidForm/FormContext'; + +const FluidNumberInput = React.forwardRef(function FluidNumberInput( + { className, ...other }, + ref +) { + const prefix = usePrefix(); + const classNames = classnames(`${prefix}--number-input--fluid`, className); + + return ( + + + + ); +}); + +FluidNumberInput.propTypes = { + /** + * `true` to allow empty string. + */ + allowEmpty: PropTypes.bool, + + /** + * Specify an optional className to be applied to the wrapper node + */ + className: PropTypes.string, + + /** + * Optional starting value for uncontrolled state + */ + defaultValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + + /** + * Specify if the wheel functionality for the input should be disabled, or not + */ + disableWheel: PropTypes.bool, + + /** + * Specify if the control should be disabled, or not + */ + disabled: PropTypes.bool, + + /** + * Provide a description for up/down icons that can be read by screen readers + */ + iconDescription: PropTypes.string, + + /** + * Specify a custom `id` for the input + */ + id: PropTypes.string.isRequired, + + /** + * Specify if the currently value is invalid. + */ + invalid: PropTypes.bool, + + /** + * Message which is displayed if the value is invalid. + */ + invalidText: PropTypes.node, + + /** + * Generic `label` that will be used as the textual representation of what + * this field is for + */ + label: PropTypes.node, + + /** + * The maximum value. + */ + max: PropTypes.number, + + /** + * The minimum value. + */ + min: PropTypes.number, + + /** + * Provide an optional handler that is called when the internal state of + * NumberInput changes. This handler is called with event and state info. + * `(event, { value, direction }) => void` + */ + onChange: PropTypes.func, + + /** + * Provide an optional function to be called when the up/down button is clicked + */ + onClick: PropTypes.func, + + /** + * Provide an optional function to be called when a key is pressed in the number input + */ + onKeyUp: PropTypes.func, + + /** + * Specify how much the values should increase/decrease upon clicking on up/down button + */ + step: PropTypes.number, + + /** + * Provide custom text for the component for each translation id + */ + translateWithId: PropTypes.func, + + /** + * Specify the value of the input + */ + value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + + /** + * Specify whether the control is currently in warning state + */ + warn: PropTypes.bool, + + /** + * Provide the text that is displayed when the control is in warning state + */ + warnText: PropTypes.node, +}; + +export default FluidNumberInput; diff --git a/packages/react/src/components/FluidNumberInput/FluidNumberInput.stories.js b/packages/react/src/components/FluidNumberInput/FluidNumberInput.stories.js new file mode 100644 index 000000000000..102398b6e2f1 --- /dev/null +++ b/packages/react/src/components/FluidNumberInput/FluidNumberInput.stories.js @@ -0,0 +1,145 @@ +/** + * Copyright IBM Corp. 2016, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import { FluidNumberInput, FluidNumberInputSkeleton } from '.'; +import { + ToggletipLabel, + Toggletip, + ToggletipButton, + ToggletipContent, +} from '../Toggletip'; +import { Information } from '@carbon/icons-react'; + +export default { + title: 'Experimental/unstable__FluidNumberInput', + component: FluidNumberInput, + subcomponents: { + FluidNumberInputSkeleton, + }, +}; + +const ToggleTip = ( + <> + Label + + + + + +

Additional field information here.

+
+
+ +); + +export const Default = () => ( +
+ +
+
+ +
+
+ +
+); + +export const Skeleton = () => ( +
+ +
+); + +export const Playground = (args) => ( +
+ +
+); + +Playground.argTypes = { + playgroundWidth: { + control: { type: 'range', min: 300, max: 800, step: 50 }, + defaultValue: 400, + }, + defaultValue: { + control: { + type: 'number', + }, + defaultValue: 50, + }, + invalid: { + control: { + type: 'boolean', + }, + defaultValue: false, + }, + invalidText: { + control: { + type: 'text', + }, + defaultValue: + 'Error message that is really long can wrap to more lines but should not be excessively long.', + }, + disabled: { + control: { + type: 'boolean', + }, + defaultValue: false, + }, + label: { + control: { + type: 'text', + }, + defaultValue: 'Label', + }, + warn: { + control: { + type: 'boolean', + }, + defaultValue: false, + }, + warnText: { + control: { + type: 'text', + }, + defaultValue: + 'Warning message that is really long can wrap to more lines but should not be excessively long.', + }, +}; diff --git a/packages/react/src/components/FluidNumberInput/__tests__/FluidNumberInput-test.js b/packages/react/src/components/FluidNumberInput/__tests__/FluidNumberInput-test.js new file mode 100644 index 000000000000..e4d1609003e2 --- /dev/null +++ b/packages/react/src/components/FluidNumberInput/__tests__/FluidNumberInput-test.js @@ -0,0 +1,29 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import FluidNumberInput from '../FluidNumberInput'; +import { render } from '@testing-library/react'; +import { FeatureFlags } from '../../FeatureFlags'; + +const prefix = 'cds'; + +describe('FluidNumberInput', () => { + describe('renders as expected - Component API', () => { + it('should render as expected', () => { + const { container } = render( + + + + ); + + expect(container.firstChild).toHaveClass( + `${prefix}--number-input--fluid` + ); + }); + }); +}); diff --git a/packages/react/src/components/FluidNumberInput/index.js b/packages/react/src/components/FluidNumberInput/index.js new file mode 100644 index 000000000000..eb52477dc3a8 --- /dev/null +++ b/packages/react/src/components/FluidNumberInput/index.js @@ -0,0 +1,11 @@ +/** + * Copyright IBM Corp. 2016, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +export default from './FluidNumberInput'; +export FluidNumberInput from './FluidNumberInput'; + +export { default as FluidNumberInputSkeleton } from './FluidNumberInput.Skeleton'; diff --git a/packages/react/src/components/FluidSelect/FluidSelect.stories.js b/packages/react/src/components/FluidSelect/FluidSelect.stories.js index a265f9907612..2ff712acab41 100644 --- a/packages/react/src/components/FluidSelect/FluidSelect.stories.js +++ b/packages/react/src/components/FluidSelect/FluidSelect.stories.js @@ -20,6 +20,9 @@ import { Information } from '@carbon/icons-react'; export default { title: 'Experimental/unstable__FluidSelect', component: FluidSelect, + subcomponents: { + FluidSelectSkeleton, + }, argTypes: { onChange: { action: 'onChange', diff --git a/packages/react/src/components/FluidTextArea/FluidTextArea.stories.js b/packages/react/src/components/FluidTextArea/FluidTextArea.stories.js index 89da14d91fbd..2e80e02442cf 100644 --- a/packages/react/src/components/FluidTextArea/FluidTextArea.stories.js +++ b/packages/react/src/components/FluidTextArea/FluidTextArea.stories.js @@ -20,6 +20,9 @@ import { Information } from '@carbon/icons-react'; export default { title: 'Experimental/unstable__FluidTextArea', component: FluidTextArea, + subcomponents: { + FluidTextAreaSkeleton, + }, argTypes: { hideLabel: { table: { diff --git a/packages/react/src/components/FluidTextInput/FluidTextInput.stories.js b/packages/react/src/components/FluidTextInput/FluidTextInput.stories.js index 33c7a3477eb9..3ef559d89dda 100644 --- a/packages/react/src/components/FluidTextInput/FluidTextInput.stories.js +++ b/packages/react/src/components/FluidTextInput/FluidTextInput.stories.js @@ -20,6 +20,9 @@ import './test.scss'; export default { title: 'Experimental/unstable__FluidTextInput', component: FluidTextInput, + subcomponents: { + FluidTextInputSkeleton, + }, }; export const Default = () => ( diff --git a/packages/react/src/components/FluidTimePicker/FluidTimePicker.stories.js b/packages/react/src/components/FluidTimePicker/FluidTimePicker.stories.js index cd7d9acbb24d..ea0e71a93f99 100644 --- a/packages/react/src/components/FluidTimePicker/FluidTimePicker.stories.js +++ b/packages/react/src/components/FluidTimePicker/FluidTimePicker.stories.js @@ -21,6 +21,10 @@ import { Information } from '@carbon/icons-react'; export default { title: 'Experimental/unstable__FluidTimePicker', component: FluidTimePicker, + subcomponents: { + FluidTimePickerSelect, + FluidTimePickerSkeleton, + }, }; const ToggleTip = ( diff --git a/packages/react/src/components/NumberInput/NumberInput.js b/packages/react/src/components/NumberInput/NumberInput.js index cb8445630fa2..a258bd29cf74 100644 --- a/packages/react/src/components/NumberInput/NumberInput.js +++ b/packages/react/src/components/NumberInput/NumberInput.js @@ -8,12 +8,13 @@ import { Add, Subtract } from '@carbon/icons-react'; import cx from 'classnames'; import PropTypes from 'prop-types'; -import React, { useRef, useState } from 'react'; +import React, { useRef, useState, useContext } from 'react'; import { useFeatureFlag } from '../FeatureFlags'; import { useMergedRefs } from '../../internal/useMergedRefs'; import { useNormalizedInputProps as normalize } from '../../internal/useNormalizedInputProps'; import { usePrefix } from '../../internal/usePrefix'; import deprecate from '../../prop-types/deprecate'; +import { FormContext } from '../FluidForm'; export const translationIds = { 'increment.number': 'increment.number', @@ -57,6 +58,8 @@ const NumberInput = React.forwardRef(function NumberInput(props, forwardRef) { ...rest } = props; const prefix = usePrefix(); + const { isFluid } = useContext(FormContext); + const [isFocused, setIsFocused] = useState(false); const [value, setValue] = useState(() => { if (controlledValue !== undefined) { return controlledValue; @@ -138,8 +141,27 @@ const NumberInput = React.forwardRef(function NumberInput(props, forwardRef) { } } + const handleFocus = (evt) => { + if (evt.target.type === 'button') { + setIsFocused(false); + } else { + setIsFocused(evt.type === 'focus' ? true : false); + } + }; + + const outerElementClasses = cx(`${prefix}--form-item`, { + [customClassName]: enabled, + [`${prefix}--number-input--fluid--invalid`]: + isFluid && normalizedProps.invalid, + [`${prefix}--number-input--fluid--focus`]: isFluid && isFocused, + [`${prefix}--number-input--fluid--disabled`]: isFluid && disabled, + }); + return ( -
+
@@ -245,6 +267,7 @@ const NumberInput = React.forwardRef(function NumberInput(props, forwardRef) {
)}
+ {isFluid &&
} {normalizedProps.validation ? ( normalizedProps.validation ) : ( diff --git a/packages/react/src/index.js b/packages/react/src/index.js index 3c57f051ba91..bb2cdee38f4c 100644 --- a/packages/react/src/index.js +++ b/packages/react/src/index.js @@ -230,6 +230,10 @@ export { FluidMultiSelect as unstable__FluidMultiSelect, FluidMultiSelectSkeleton as unstable__FluidMultiSelectSkeleton, } from './components/FluidMultiSelect'; +export { + FluidNumberInput as unstable__FluidNumberInput, + FluidNumberInputSkeleton as unstable__FluidNumberInputSkeleton, +} from './components/FluidNumberInput'; export { FluidSelect as unstable__FluidSelect, FluidSelectSkeleton as unstable__FluidSelectSkeleton, diff --git a/packages/styles/__tests__/__snapshots__/styles-test.js.snap b/packages/styles/__tests__/__snapshots__/styles-test.js.snap index 1a350efc4ceb..672628eb91b6 100644 --- a/packages/styles/__tests__/__snapshots__/styles-test.js.snap +++ b/packages/styles/__tests__/__snapshots__/styles-test.js.snap @@ -262,6 +262,16 @@ Array [ "importPath": "@carbon/styles/scss/components/form", "relativePath": "scss/components/form", }, + Object { + "filepath": "scss/components/fluid-combo-box/_fluid-combo-box.scss", + "importPath": "@carbon/styles/scss/components/fluid-combo-box/fluid-combo-box", + "relativePath": "scss/components/fluid-combo-box/fluid-combo-box", + }, + Object { + "filepath": "scss/components/fluid-combo-box/_index.scss", + "importPath": "@carbon/styles/scss/components/fluid-combo-box", + "relativePath": "scss/components/fluid-combo-box", + }, Object { "filepath": "scss/components/fluid-date-picker/_fluid-date-picker.scss", "importPath": "@carbon/styles/scss/components/fluid-date-picker/fluid-date-picker", @@ -292,6 +302,26 @@ Array [ "importPath": "@carbon/styles/scss/components/fluid-list-box", "relativePath": "scss/components/fluid-list-box", }, + Object { + "filepath": "scss/components/fluid-multiselect/_fluid-multiselect.scss", + "importPath": "@carbon/styles/scss/components/fluid-multiselect/fluid-multiselect", + "relativePath": "scss/components/fluid-multiselect/fluid-multiselect", + }, + Object { + "filepath": "scss/components/fluid-multiselect/_index.scss", + "importPath": "@carbon/styles/scss/components/fluid-multiselect", + "relativePath": "scss/components/fluid-multiselect", + }, + Object { + "filepath": "scss/components/fluid-number-input/_fluid-number-input.scss", + "importPath": "@carbon/styles/scss/components/fluid-number-input/fluid-number-input", + "relativePath": "scss/components/fluid-number-input/fluid-number-input", + }, + Object { + "filepath": "scss/components/fluid-number-input/_index.scss", + "importPath": "@carbon/styles/scss/components/fluid-number-input", + "relativePath": "scss/components/fluid-number-input", + }, Object { "filepath": "scss/components/fluid-select/_fluid-select.scss", "importPath": "@carbon/styles/scss/components/fluid-select/fluid-select", diff --git a/packages/styles/files.js b/packages/styles/files.js index 621fd5c62685..1e91b581c514 100644 --- a/packages/styles/files.js +++ b/packages/styles/files.js @@ -71,12 +71,18 @@ const files = [ 'scss/components/file-uploader/_index.scss', 'scss/components/form/_form.scss', 'scss/components/form/_index.scss', + 'scss/components/fluid-combo-box/_fluid-combo-box.scss', + 'scss/components/fluid-combo-box/_index.scss', 'scss/components/fluid-date-picker/_fluid-date-picker.scss', 'scss/components/fluid-date-picker/_index.scss', 'scss/components/fluid-dropdown/_fluid-dropdown.scss', 'scss/components/fluid-dropdown/_index.scss', 'scss/components/fluid-list-box/_fluid-list-box.scss', 'scss/components/fluid-list-box/_index.scss', + 'scss/components/fluid-multiselect/_fluid-multiselect.scss', + 'scss/components/fluid-multiselect/_index.scss', + 'scss/components/fluid-number-input/_fluid-number-input.scss', + 'scss/components/fluid-number-input/_index.scss', 'scss/components/fluid-select/_fluid-select.scss', 'scss/components/fluid-select/_index.scss', 'scss/components/fluid-text-area/_fluid-text-area.scss', diff --git a/packages/styles/scss/components/_index.scss b/packages/styles/scss/components/_index.scss index 7890dc352fab..20d2b7883985 100644 --- a/packages/styles/scss/components/_index.scss +++ b/packages/styles/scss/components/_index.scss @@ -28,6 +28,7 @@ @use 'fluid-dropdown'; @use 'fluid-list-box'; @use 'fluid-multiselect'; +@use 'fluid-number-input'; @use 'fluid-select'; @use 'fluid-text-area'; @use 'fluid-text-input'; diff --git a/packages/styles/scss/components/fluid-multiselect/_fluid-multiselect.scss b/packages/styles/scss/components/fluid-multiselect/_fluid-multiselect.scss index 55cc0ebacc12..d14cbe279d4d 100644 --- a/packages/styles/scss/components/fluid-multiselect/_fluid-multiselect.scss +++ b/packages/styles/scss/components/fluid-multiselect/_fluid-multiselect.scss @@ -6,7 +6,7 @@ // //----------------------------- -// Fluid ComboBox +// Fluid Multiselect //----------------------------- @use '../../config' as *; @use '../../motion' as *; diff --git a/packages/styles/scss/components/fluid-number-input/_fluid-number-input.scss b/packages/styles/scss/components/fluid-number-input/_fluid-number-input.scss new file mode 100644 index 000000000000..26475ed6ec18 --- /dev/null +++ b/packages/styles/scss/components/fluid-number-input/_fluid-number-input.scss @@ -0,0 +1,263 @@ +// +// Copyright IBM Corp. 2022 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +//----------------------------- +// Fluid Number Input +//----------------------------- +@use '../../config' as *; +@use '../../motion' as *; +@use '../../spacing' as *; +@use '../../theme' as *; +@use '../../utilities/convert' as *; +@use '../../utilities/focus-outline' as *; +@use '../number-input'; + +@mixin fluid-number-input { + .#{$prefix}--number-input--fluid { + position: relative; + height: 100%; + background: $field; + } + + .#{$prefix}--number-input--fluid .#{$prefix}--label { + position: absolute; + z-index: 1; + top: rem(13px); + left: $spacing-05; + display: flex; + width: calc(100% - 2rem); + height: rem(16px); + align-items: center; + margin: 0; + -ms-overflow-style: none; + overflow-x: scroll; + scrollbar-width: none; + white-space: nowrap; + } + + .#{$prefix}--number-input--fluid .#{$prefix}--label::-webkit-scrollbar { + display: none; + } + + .#{$prefix}--number-input--fluid input[type='number'] { + min-height: rem(64px); + padding: rem(32px) rem(80px) rem(13px) $spacing-05; + background: transparent; + outline: none; + } + + .#{$prefix}--number-input--fluid .#{$prefix}--number__controls { + top: rem(23px); + height: rem(40px); + transform: translate(0); + } + + .#{$prefix}--number-input--fluid .#{$prefix}--number__control-btn, + .#{$prefix}--number-input--fluid + input[type='number']:focus + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn { + border-bottom: 1px solid transparent; + } + + // Focus Overrides + .#{$prefix}--number-input--fluid.#{$prefix}--number-input--fluid--focus + .#{$prefix}--number { + @include focus-outline('outline'); + } + + // Weird overrides (needed to override focus borders on stepper buttons when hovered while input has focus) + .#{$prefix}--number-input--fluid:not(.#{$prefix}--number-input--fluid--invalid) + .#{$prefix}--number + .#{$prefix}--number__input-wrapper:not(.#{$prefix}--number__input-wrapper--warning) + input[type='number']:focus + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn:hover { + outline: 2px solid transparent; + } + + .#{$prefix}--number-input--fluid:not(.#{$prefix}--number-input--fluid--invalid) + .#{$prefix}--number + .#{$prefix}--number__input-wrapper:not(.#{$prefix}--number__input-wrapper--warning) + input[type='number']:focus + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn:hover::before { + top: auto; + bottom: 0; + left: 0; + width: 100%; + height: 1px; + background: $focus; + } + // End weirdness + + .#{$prefix}--number-input--fluid:not(.#{$prefix}--number-input--fluid--invalid) + .#{$prefix}--number-input-wrapper:not(.#{$prefix}--number-input-wrapper__warning) + input[type='number']:focus + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn:hover { + border-bottom: 1px solid $focus; + outline: none; + } + + .#{$prefix}--number-input--fluid + input[type='number'] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn::after { + top: 0; + height: calc(100% - rem(1px)); + } + + .#{$prefix}--number-input--fluid.#{$prefix}--number-input--fluid--focus + input[type='number'] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn.up-icon::after { + background: $focus; + } + + .#{$prefix}--number-input--fluid + input[type='number'] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn.up-icon::after { + height: calc(100%); + } + + .#{$prefix}--number-input--fluid.#{$prefix}--number-input--fluid--focus + input[type='number'] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn.up-icon:hover::after { + height: calc(100%); + background-color: $focus; + } + + .#{$prefix}--number-input--fluid--invalid + input[type='number'][data-invalid] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn:focus, + .#{$prefix}--number-input--fluid--invalid + .#{$prefix}--number + input[type='number'][data-invalid] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn:focus:hover { + @include focus-outline('outline'); + } + + // Invalid styles + .#{$prefix}--number-input--fluid .#{$prefix}--number-input__divider { + display: none; + } + + .#{$prefix}--number-input--fluid .#{$prefix}--number__invalid { + top: rem(73px); + right: $spacing-05; + pointer-events: none; + } + + .#{$prefix}--number-input--fluid + .#{$prefix}--number__controls + .#{$prefix}--number__rule-divider:first-of-type { + display: none; + } + + .#{$prefix}--number-input--fluid + .#{$prefix}--number__input-wrapper--warning + input[type='number'] { + border-bottom: 1px solid transparent; + } + + .#{$prefix}--number-input--fluid + .#{$prefix}--number__input-wrapper--warning + input[type='number']:focus { + outline: none; + } + + .#{$prefix}--number-input--fluid.#{$prefix}--number-input--fluid--invalid + .#{$prefix}--number-input__divider, + .#{$prefix}--number-input--fluid + .#{$prefix}--number__input-wrapper--warning + + .#{$prefix}--number-input__divider { + position: absolute; + top: rem(63px); + display: block; + width: calc(100% - 2rem); + height: rem(1px); + border: none; + border-bottom: 1px solid $border-subtle; + margin: 0 1rem; + } + + .#{$prefix}--number-input--fluid .#{$prefix}--form-requirement { + padding: $spacing-03 rem(40px) $spacing-03 $spacing-05; + margin: 0; + } + + .#{$prefix}--number-input--fluid.#{$prefix}--number-input--fluid--invalid:not(.#{$prefix}--number-input--fluid--focus) + .#{$prefix}--number { + @include focus-outline('invalid'); + } + + .#{$prefix}--number-input--fluid--invalid + .#{$prefix}--number[data-invalid] + input[type='number'] { + border-bottom: 1px solid transparent; + } + + .#{$prefix}--number-input--fluid--invalid + .#{$prefix}--number[data-invalid] + input[type='number'], + .#{$prefix}--number-input--fluid--invalid + .#{$prefix}--number + input[type='number'][data-invalid] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn:hover, + .#{$prefix}--number-input--fluid + .#{$prefix}--number__input-wrapper--warning + input[type='number'] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn:hover:not(:focus) { + outline: none; + } + + .#{$prefix}--number-input--fluid.#{$prefix}--number-input--invalid + .#{$prefix}--number__input-wrapper + input[type='number'] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn, + .#{$prefix}--number-input--fluid + .#{$prefix}--number__input-wrapper--warning + input[type='number'] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn { + border-bottom: none; + } + + .#{$prefix}--number-input--fluid--invalid + .#{$prefix}--number + input[type='number'][data-invalid] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn, + .#{$prefix}--number-input--fluid + .#{$prefix}--number + input[type='number'] + ~ .#{$prefix}--number__controls + .#{$prefix}--number__control-btn { + border: initial; + border-bottom-width: rem(1px); + } + + // Disabled states + .#{$prefix}--number-input--fluid--disabled:not(.#{$prefix}--number-input--fluid--invalid) + .#{$prefix}--number { + border-bottom: 1px solid $border-subtle; + } + + .#{$prefix}--number-input--fluid--disabled.#{$prefix}--number-input--fluid--invalid + .#{$prefix}--number + input[type='number']:disabled { + background-color: transparent; + } +} diff --git a/packages/styles/scss/components/fluid-number-input/_index.scss b/packages/styles/scss/components/fluid-number-input/_index.scss new file mode 100644 index 000000000000..87a2e12907be --- /dev/null +++ b/packages/styles/scss/components/fluid-number-input/_index.scss @@ -0,0 +1,11 @@ +// +// Copyright IBM Corp. 2022 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@forward 'fluid-number-input'; +@use 'fluid-number-input'; + +@include fluid-number-input.fluid-number-input; diff --git a/packages/styles/scss/components/form/_form.scss b/packages/styles/scss/components/form/_form.scss index b1725bfc391d..468f51611383 100644 --- a/packages/styles/scss/components/form/_form.scss +++ b/packages/styles/scss/components/form/_form.scss @@ -110,7 +110,7 @@ $input-label-weight: 400 !default; } input[type='number'] { - font-family: carbon--font-family('mono'); + font-family: font-family('sans'); } input[data-invalid]:not(:focus), diff --git a/packages/styles/scss/components/number-input/_number-input.scss b/packages/styles/scss/components/number-input/_number-input.scss index 2406eb410198..fcff70a33e49 100644 --- a/packages/styles/scss/components/number-input/_number-input.scss +++ b/packages/styles/scss/components/number-input/_number-input.scss @@ -32,7 +32,7 @@ } .#{$prefix}--number input[type='number'] { - @include type-style('code-01'); + @include type-style('body-compact-01'); @include focus-outline('reset'); display: inline-flex; @@ -50,7 +50,7 @@ background-color: $field; border-radius: 0; color: $text-primary; - font-family: font-family('mono'); + font-family: font-family('sans'); font-weight: 400; transition: background-color $duration-fast-01 motion(standard, productive), outline $duration-fast-01 motion(standard, productive);