From bdc5573383595344ccb3b63a70232dbb15d34b8e Mon Sep 17 00:00:00 2001 From: Guilherme Datilio Ribeiro Date: Wed, 23 Oct 2024 11:21:39 -0300 Subject: [PATCH] Move Feature Flag out of Experimental (#17806) * feat: adding feature flag item to stable * feat: added combobox floating styles * fix: imported all dynamic floating styles to stable * feat: added remaning feature flags * fix: fixed a tile and overflow paths in avt tests * test: fixed tests * fix: removed parameter from main.js * fix: fixed naming * fix: moved flag details to the top level --- .../OverflowMenu/OverflowMenu-test.e2e.js | 16 - e2e/components/Tile/Tile-test.e2e.js | 18 +- packages/react/.storybook/preview.js | 21 +- .../ComboBox/ComboBox.featureflag.stories.js | 79 +++ .../Combobox.DynamicStyles.featureflag.mdx | 39 ++ .../ComboButton.DynamicStyles.featureflag.mdx | 35 ++ .../ComboButton.featureflag.stories.js | 48 ++ .../ComposedModal.featureflag.mdx | 2 +- .../ComposedModal.featureflag.stories.js | 321 +---------- .../Dropdown.DynamicStyles.featureflag.mdx | 40 ++ .../Dropdown/Dropdown.featureflag.stories.js | 82 +++ .../MenuButton.DynamicStyles.featureflag.mdx | 35 ++ .../MenuButton.featureflag.stories.js | 46 ++ .../components/Modal/Modal.featureflag.mdx | 2 +- .../Modal/Modal.featureflag.stories.js | 508 +----------------- .../MultiSelect.DynamicStyles.featureflag.mdx | 40 ++ .../MultiSelect.featureflag.stories.js | 78 +++ .../Notification/Notification.featureflag.mdx | 6 +- ...ionableNotification.featureflag.stories.js | 33 +- ...verflowMenu.DynamicStyles.featureflag.mdx} | 55 +- .../OverflowMenu.featureflag.stories.js | 63 +-- .../DynamicStyles.featureflag.stories.js | 409 -------------- ... => Popover.DynamicStyles.featureflag.mdx} | 2 +- .../Popover/Popover.featureflag.stories.js | 90 ++++ .../StructuredList.featureflag.mdx | 16 + .../StructuredList.featureflag.stories.js | 121 +---- .../src/components/Tile/Tile.featureflag.mdx | 20 + .../Tile/Tile.featureflag.stories.js | 3 +- .../Toggletip.DynamicStyles.featureflag.mdx | 48 ++ .../Toggletip.featureflag.stories.js | 89 +++ .../Tooltip.DynamicStyles.featureflag.mdx | 42 ++ .../Tooltip/Tooltip.featureflag.stories.js | 75 +++ .../TreeView/TreeView.featureflag.mdx | 6 +- .../TreeView/TreeView.featureflag.stories.js | 10 +- 34 files changed, 1021 insertions(+), 1477 deletions(-) create mode 100644 packages/react/src/components/ComboBox/ComboBox.featureflag.stories.js create mode 100644 packages/react/src/components/ComboBox/Combobox.DynamicStyles.featureflag.mdx create mode 100644 packages/react/src/components/ComboButton/ComboButton.DynamicStyles.featureflag.mdx create mode 100644 packages/react/src/components/ComboButton/ComboButton.featureflag.stories.js create mode 100644 packages/react/src/components/Dropdown/Dropdown.DynamicStyles.featureflag.mdx create mode 100644 packages/react/src/components/Dropdown/Dropdown.featureflag.stories.js create mode 100644 packages/react/src/components/MenuButton/MenuButton.DynamicStyles.featureflag.mdx create mode 100644 packages/react/src/components/MenuButton/MenuButton.featureflag.stories.js create mode 100644 packages/react/src/components/MultiSelect/MultiSelect.DynamicStyles.featureflag.mdx create mode 100644 packages/react/src/components/MultiSelect/MultiSelect.featureflag.stories.js rename packages/react/src/components/OverflowMenu/{next/OverflowMenu.mdx => OverflowMenu.DynamicStyles.featureflag.mdx} (54%) delete mode 100644 packages/react/src/components/Popover/DynamicStyles.featureflag.stories.js rename packages/react/src/components/Popover/{DynamicStyles.featureflag.mdx => Popover.DynamicStyles.featureflag.mdx} (94%) create mode 100644 packages/react/src/components/Popover/Popover.featureflag.stories.js create mode 100644 packages/react/src/components/StructuredList/StructuredList.featureflag.mdx create mode 100644 packages/react/src/components/Tile/Tile.featureflag.mdx create mode 100644 packages/react/src/components/Toggletip/Toggletip.DynamicStyles.featureflag.mdx create mode 100644 packages/react/src/components/Toggletip/Toggletip.featureflag.stories.js create mode 100644 packages/react/src/components/Tooltip/Tooltip.DynamicStyles.featureflag.mdx create mode 100644 packages/react/src/components/Tooltip/Tooltip.featureflag.stories.js diff --git a/e2e/components/OverflowMenu/OverflowMenu-test.e2e.js b/e2e/components/OverflowMenu/OverflowMenu-test.e2e.js index 0fcd3b09a926..24ecf578cbe5 100644 --- a/e2e/components/OverflowMenu/OverflowMenu-test.e2e.js +++ b/e2e/components/OverflowMenu/OverflowMenu-test.e2e.js @@ -29,22 +29,6 @@ test.describe('OverflowMenu', () => { theme, }); }); - - test('feature flags default @vrt', async ({ page }) => { - await snapshotStory(page, { - component: 'OverflowMenu', - id: 'experimental-feature-flags-overflowmenu--overflow-menu', - theme, - }); - }); - - test('feature flags render custom icon @vrt', async ({ page }) => { - await snapshotStory(page, { - component: 'OverflowMenu', - id: 'experimental-feature-flags-overflowmenu--custom-icon', - theme, - }); - }); }); }); }); diff --git a/e2e/components/Tile/Tile-test.e2e.js b/e2e/components/Tile/Tile-test.e2e.js index e2c2044f25f2..ca1f8e6e1306 100644 --- a/e2e/components/Tile/Tile-test.e2e.js +++ b/e2e/components/Tile/Tile-test.e2e.js @@ -105,7 +105,7 @@ test.describe('Tile', () => { test('feature flags clickable @vrt', async ({ page }) => { await snapshotStory(page, { component: 'Tile', - id: 'experimental-feature-flags-tile--clickable', + id: 'components-tile-feature-flag--clickable', theme, }); }); @@ -113,7 +113,7 @@ test.describe('Tile', () => { test('feature flags clickable with layer @vrt', async ({ page }) => { await snapshotStory(page, { component: 'Tile', - id: 'experimental-feature-flags-tile--clickable-with-layer', + id: 'components-tile-feature-flag--clickable-with-layer', theme, }); }); @@ -121,7 +121,7 @@ test.describe('Tile', () => { test('feature flags selectable @vrt', async ({ page }) => { await snapshotStory(page, { component: 'Tile', - id: 'experimental-feature-flags-tile--selectable', + id: 'components-tile-feature-flag--selectable', theme, }); }); @@ -129,7 +129,7 @@ test.describe('Tile', () => { test('feature flags multi select @vrt', async ({ page }) => { await snapshotStory(page, { component: 'Tile', - id: 'experimental-feature-flags-tile--multi-select', + id: 'components-tile-feature-flag--multi-select', theme, }); }); @@ -137,7 +137,7 @@ test.describe('Tile', () => { test('feature flags radio @vrt', async ({ page }) => { await snapshotStory(page, { component: 'Tile', - id: 'experimental-feature-flags-tile--radio', + id: 'components-tile-feature-flag--radio', theme, }); }); @@ -145,7 +145,7 @@ test.describe('Tile', () => { test('feature flags radio with layer @vrt', async ({ page }) => { await snapshotStory(page, { component: 'Tile', - id: 'experimental-feature-flags-tile--radio-with-layer', + id: 'components-tile-feature-flag--radio-with-layer', theme, }); }); @@ -153,7 +153,7 @@ test.describe('Tile', () => { test('feature flags expandable @vrt', async ({ page }) => { await snapshotStory(page, { component: 'Tile', - id: 'experimental-feature-flags-tile--expandable', + id: 'components-tile-feature-flag--expandable', theme, }); }); @@ -163,7 +163,7 @@ test.describe('Tile', () => { }) => { await snapshotStory(page, { component: 'Tile', - id: 'experimental-feature-flags-tile--expandable-with-interactive', + id: 'components-tile-feature-flag--expandable-with-interactive', theme, }); }); @@ -171,7 +171,7 @@ test.describe('Tile', () => { test('feature flags expandable with layer @vrt', async ({ page }) => { await snapshotStory(page, { component: 'Tile', - id: 'experimental-feature-flags-tile--expandable-with-layer', + id: 'components-tile-feature-flag--expandable-with-layer', theme, }); }); diff --git a/packages/react/.storybook/preview.js b/packages/react/.storybook/preview.js index b6a875703359..2503fc5b9c2f 100644 --- a/packages/react/.storybook/preview.js +++ b/packages/react/.storybook/preview.js @@ -265,19 +265,30 @@ const parameters = { return titleA.localeCompare(titleB); } + if (titleA !== titleB) { + if (idA.includes('flag-details') && !idB.includes('flag-details')) { + return -1; + } + if (idB.includes('flag-details') && !idA.includes('flag-details')) { + return 1; + } + return titleA.localeCompare(titleB); + } + // To sort the stories, we first build up a list of matches based on // keywords. Each keyword has a specific weight that will be used to // determine order later on. - const UNKNOWN_KEYWORD = 4; + const UNKNOWN_KEYWORD = 5; const keywords = new Map([ ['welcome', 0], ['overview', 1], ['default', 2], ['usage', 3], - ['playground', 5], - ['development', 6], - ['deprecated', 7], - ['unstable', 8], + ['flag-details', 4], + ['playground', 6], + ['development', 7], + ['deprecated', 8], + ['unstable', 9], ]); const matches = new Map(); diff --git a/packages/react/src/components/ComboBox/ComboBox.featureflag.stories.js b/packages/react/src/components/ComboBox/ComboBox.featureflag.stories.js new file mode 100644 index 000000000000..bd29262b88d5 --- /dev/null +++ b/packages/react/src/components/ComboBox/ComboBox.featureflag.stories.js @@ -0,0 +1,79 @@ +/** + * Copyright IBM Corp. 2016, 2023 + * + * 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 { ComboBox } from '../ComboBox'; +import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; + +export default { + title: 'Components/ComboBox/Feature Flag', + component: ComboBox, + tags: ['!autodocs'], + decorators: [ + (Story) => ( + + + + ), + ], +}; + +const comboBoxItems = [ + { + id: 'option-0', + text: 'An example option that is really long to show what should be done to handle long text', + }, + { + id: 'option-1', + text: 'Option 1', + }, + { + id: 'option-2', + text: 'Option 2', + }, + { + id: 'option-3', + text: 'Option 3 - a disabled item', + disabled: true, + }, + { + id: 'option-4', + text: 'Option 4', + }, + { + id: 'option-5', + text: 'Option 5', + }, +]; + +export const FloatingStyles = (args) => ( + {}} + id="carbon-combobox" + items={comboBoxItems} + itemToString={(item) => (item ? item.text : '')} + titleText="ComboBox title" + helperText="Combobox helper text" + {...args} + /> +); + +FloatingStyles.args = { + direction: 'bottom', +}; + +FloatingStyles.argTypes = { + direction: { + options: ['top', 'bottom'], + control: { + type: 'radio', + }, + }, +}; diff --git a/packages/react/src/components/ComboBox/Combobox.DynamicStyles.featureflag.mdx b/packages/react/src/components/ComboBox/Combobox.DynamicStyles.featureflag.mdx new file mode 100644 index 000000000000..863a95f6dcaf --- /dev/null +++ b/packages/react/src/components/ComboBox/Combobox.DynamicStyles.featureflag.mdx @@ -0,0 +1,39 @@ +import { Meta } from '@storybook/blocks'; + + + +# Dynamically set floating styles + +Components with `autoAlign` use the +[`floating-ui`](https://github.com/floating-ui/floating-ui) library to handle +the dynamic positioning of floating elements relative to their trigger / anchor +element. This also includes collision detection that repositions the floating +element as necessary to keep it visible within the viewport. In the majority of +cases, the styling from the `floating-ui` 'fixed' positioning strategy prevents +the floating element from being +[clipped](https://floating-ui.com/docs/misc#clipping) by an ancestor element. + +The `enable-v12-dynamic-floating-styles` flag enables this dynamic styling +without the collision detection. + +**Note**: The flag has no effect when used with `autoAlign` because `autoAlign` +includes both the dynamic positioning styles and collision detection. + +## Enable dynamic setting of floating styles + +```js + + {}} + id="carbon-combobox" + items={comboBoxItems} + itemToString={(item) => (item ? item.text : '')} + titleText="ComboBox title" + helperText="Combobox helper text" + {...args} + /> + +``` diff --git a/packages/react/src/components/ComboButton/ComboButton.DynamicStyles.featureflag.mdx b/packages/react/src/components/ComboButton/ComboButton.DynamicStyles.featureflag.mdx new file mode 100644 index 000000000000..0ad98da86e7f --- /dev/null +++ b/packages/react/src/components/ComboButton/ComboButton.DynamicStyles.featureflag.mdx @@ -0,0 +1,35 @@ +import { Meta } from '@storybook/blocks'; + + + +# Dynamically set floating styles + +Components with `autoAlign` use the +[`floating-ui`](https://github.com/floating-ui/floating-ui) library to handle +the dynamic positioning of floating elements relative to their trigger / anchor +element. This also includes collision detection that repositions the floating +element as necessary to keep it visible within the viewport. In the majority of +cases, the styling from the `floating-ui` 'fixed' positioning strategy prevents +the floating element from being +[clipped](https://floating-ui.com/docs/misc#clipping) by an ancestor element. + +The `enable-v12-dynamic-floating-styles` flag enables this dynamic styling +without the collision detection. + +**Note**: The flag has no effect when used with `autoAlign` because `autoAlign` +includes both the dynamic positioning styles and collision detection. + +## Enable dynamic setting of floating styles + +```js + + + + + + + +``` diff --git a/packages/react/src/components/ComboButton/ComboButton.featureflag.stories.js b/packages/react/src/components/ComboButton/ComboButton.featureflag.stories.js new file mode 100644 index 000000000000..1beffb298483 --- /dev/null +++ b/packages/react/src/components/ComboButton/ComboButton.featureflag.stories.js @@ -0,0 +1,48 @@ +/** + * Copyright IBM Corp. 2016, 2023 + * + * 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 { ComboButton } from '../ComboButton'; +import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; +import { MenuItem } from '../Menu'; + +export default { + title: 'Components/ComboButton/Feature Flag', + component: ComboButton, + tags: ['!autodocs'], + decorators: [ + (Story) => ( + + + + ), + ], +}; + +export const FloatingStyles = (args) => ( + + + + + +); + +FloatingStyles.args = { + menuAlignment: 'bottom', +}; + +FloatingStyles.argTypes = { + menuAlignment: { + options: ['top', 'bottom'], + control: { + type: 'radio', + }, + }, +}; diff --git a/packages/react/src/components/ComposedModal/ComposedModal.featureflag.mdx b/packages/react/src/components/ComposedModal/ComposedModal.featureflag.mdx index 089d688b9848..42358509d7aa 100644 --- a/packages/react/src/components/ComposedModal/ComposedModal.featureflag.mdx +++ b/packages/react/src/components/ComposedModal/ComposedModal.featureflag.mdx @@ -1,6 +1,6 @@ import { Meta } from '@storybook/blocks'; - + # ComposedModal diff --git a/packages/react/src/components/ComposedModal/ComposedModal.featureflag.stories.js b/packages/react/src/components/ComposedModal/ComposedModal.featureflag.stories.js index 3d004a4131f8..660963ca7790 100644 --- a/packages/react/src/components/ComposedModal/ComposedModal.featureflag.stories.js +++ b/packages/react/src/components/ComposedModal/ComposedModal.featureflag.stories.js @@ -25,20 +25,17 @@ import { } from '../StructuredList'; import mdx from './ComposedModal.featureflag.mdx'; import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; +import { title } from 'process'; export default { - title: 'Experimental/Feature Flags/ComposedModal', + title: 'Components/ComposedModal/Feature Flag', component: ComposedModal, subcomponents: { ModalHeader, ModalBody, ModalFooter, }, - parameters: { - docs: { - page: mdx, - }, - }, + tags: ['!autodocs'], decorators: [ (Story) => ( @@ -48,315 +45,7 @@ export default { ], }; -export const Default = () => { - const [open, setOpen] = useState(true); - return ( - <> - - setOpen(false)}> - - -

- Custom domains direct requests for your apps in this Cloud Foundry - organization to a URL that you own. A custom domain can be a shared - domain, a shared subdomain, or a shared domain and host. -

- - -
- -
- - ); -}; - -export const FullWidth = () => { - const [open, setOpen] = useState(true); - return ( - <> - - setOpen(false)} isFullWidth> - - - - - - - Column A - - - Column B - - - Column C - - - - - - Row 1 - Row 1 - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc - dui magna, finibus id tortor sed, aliquet bibendum augue. - Aenean posuere sem vel euismod dignissim. Nulla ut cursus - dolor. Pellentesque vulputate nisl a porttitor interdum. - - - - Row 2 - Row 2 - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc - dui magna, finibus id tortor sed, aliquet bibendum augue. - Aenean posuere sem vel euismod dignissim. Nulla ut cursus - dolor. Pellentesque vulputate nisl a porttitor interdum. - - - - Row 3 - Row 3 - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc - dui magna, finibus id tortor sed, aliquet bibendum augue. - Aenean posuere sem vel euismod dignissim. Nulla ut cursus - dolor. Pellentesque vulputate nisl a porttitor interdum. - - - - - - - - - ); -}; - -export const PassiveModal = () => { - const [open, setOpen] = useState(true); - return ( - <> - - setOpen(false)}> - - - - - ); -}; - -export const WithStateManager = () => { - const button = useRef(); - - /** - * Simple state manager for modals. - */ - const ModalStateManager = ({ - renderLauncher: LauncherContent, - children: ModalContent, - }) => { - const [open, setOpen] = useState(false); - return ( - <> - {!ModalContent || typeof document === 'undefined' - ? null - : ReactDOM.createPortal( - , - document.body - )} - {LauncherContent && } - - ); - }; - return ( - ( - - )}> - {({ open, setOpen }) => ( - { - setOpen(false); - }} - launcherButtonRef={button}> - - -

- Custom domains direct requests for your apps in this Cloud Foundry - organization to a URL that you own. A custom domain can be a - shared domain, a shared subdomain, or a shared domain and host. -

- - -
- -
- )} -
- ); -}; - -export const WithScrollingContent = () => { - const [open, setOpen] = useState(true); - return ( - <> - - setOpen(false)}> - - -

- Custom domains direct requests for your apps in this Cloud Foundry - organization to a URL that you own. A custom domain can be a shared - domain, a shared subdomain, or a shared domain and host. -

-

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus - eu nibh odio. Nunc a consequat est, id porttitor sapien. Proin vitae - leo vitae orci tincidunt auctor eget eget libero. Ut tincidunt - ultricies fringilla. Aliquam erat volutpat. Aenean arcu odio, - elementum vel vehicula vitae, porttitor ac lorem. Sed viverra elit - ac risus tincidunt fermentum. Ut sollicitudin nibh id risus ornare - ornare. Etiam gravida orci ut lectus dictum, quis ultricies felis - mollis. Mauris nec commodo est, nec faucibus nibh. Nunc commodo ante - quis pretium consectetur. Ut ac nisl vitae mi mattis vulputate a at - elit. Nullam porttitor ex eget mi feugiat mattis. Nunc non sodales - magna. Proin ornare tellus quis hendrerit egestas. Donec pharetra - leo nec molestie sollicitudin.{' '} -

- -
- -
- - (item ? item.text : '')} - /> -
- -
- - ); -}; - -export const WithInlineLoading = () => { - const [open, setOpen] = useState(true); - const [status, setStatus] = useState('inactive'); - const [description, setDescription] = useState('Submitting...'); - - const fakePromise = () => { - return new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, 2000); - }); - }; - - const submit = async () => { - setStatus('active'); - - await fakePromise(); - - setDescription('Submited!'); - setStatus('finished'); - }; - - const resetStatus = () => { - setStatus('inactive'); - setDescription('Submitting...'); - }; - - return ( - <> - - setOpen(false)}> - - -

- Custom domains direct requests for your apps in this Cloud Foundry - organization to a URL that you own. A custom domain can be a shared - domain, a shared subdomain, or a shared domain and host. -

- - -
- -
- - ); -}; - -export const Playground = (args) => { +export const FocusWrapWithoutSentinels = (args) => { const [open, setOpen] = useState(true); return ( <> @@ -395,7 +84,7 @@ export const Playground = (args) => { ); }; -Playground.argTypes = { +FocusWrapWithoutSentinels.argTypes = { children: { table: { disable: true, diff --git a/packages/react/src/components/Dropdown/Dropdown.DynamicStyles.featureflag.mdx b/packages/react/src/components/Dropdown/Dropdown.DynamicStyles.featureflag.mdx new file mode 100644 index 000000000000..fa05b32fc4cb --- /dev/null +++ b/packages/react/src/components/Dropdown/Dropdown.DynamicStyles.featureflag.mdx @@ -0,0 +1,40 @@ +import { Meta } from '@storybook/blocks'; + + + +# Dynamically set floating styles + +Components with `autoAlign` use the +[`floating-ui`](https://github.com/floating-ui/floating-ui) library to handle +the dynamic positioning of floating elements relative to their trigger / anchor +element. This also includes collision detection that repositions the floating +element as necessary to keep it visible within the viewport. In the majority of +cases, the styling from the `floating-ui` 'fixed' positioning strategy prevents +the floating element from being +[clipped](https://floating-ui.com/docs/misc#clipping) by an ancestor element. + +The `enable-v12-dynamic-floating-styles` flag enables this dynamic styling +without the collision detection. + +**Note**: The flag has no effect when used with `autoAlign` because `autoAlign` +includes both the dynamic positioning styles and collision detection. + +## Enable dynamic setting of floating styles + +```js + + (item ? item.text : '')} + {...args} + /> + +``` diff --git a/packages/react/src/components/Dropdown/Dropdown.featureflag.stories.js b/packages/react/src/components/Dropdown/Dropdown.featureflag.stories.js new file mode 100644 index 000000000000..9b4d226e7710 --- /dev/null +++ b/packages/react/src/components/Dropdown/Dropdown.featureflag.stories.js @@ -0,0 +1,82 @@ +/** + * Copyright IBM Corp. 2016, 2023 + * + * 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 { Dropdown } from '../Dropdown'; +import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; + +// eslint-disable-next-line storybook/csf-component +export default { + title: 'Components/Dropdown/Feature Flag', + component: Dropdown, + tags: ['!autodocs'], + decorators: [ + (Story) => ( + + + + ), + ], +}; + +const items = [ + { + text: 'Lorem, ipsum dolor sit amet consectetur adipisicing elit.', + }, + { + text: 'Option 1', + }, + { + text: 'Option 2', + }, + { + text: 'Option 3 - a disabled item', + disabled: true, + }, + { + text: 'Option 4', + }, + { + text: 'Option 5', + }, + { + text: 'Option 6', + }, + { + text: 'Option 7', + }, + { + text: 'Option 8', + }, +]; + +export const FloatingStyles = (args) => ( + (item ? item.text : '')} + {...args} + /> +); + +FloatingStyles.args = { + direction: 'bottom', +}; + +FloatingStyles.argTypes = { + direction: { + options: ['top', 'bottom'], + control: { + type: 'radio', + }, + }, +}; diff --git a/packages/react/src/components/MenuButton/MenuButton.DynamicStyles.featureflag.mdx b/packages/react/src/components/MenuButton/MenuButton.DynamicStyles.featureflag.mdx new file mode 100644 index 000000000000..0d076fccc96a --- /dev/null +++ b/packages/react/src/components/MenuButton/MenuButton.DynamicStyles.featureflag.mdx @@ -0,0 +1,35 @@ +import { Meta } from '@storybook/blocks'; + + + +# Dynamically set floating styles + +Components with `autoAlign` use the +[`floating-ui`](https://github.com/floating-ui/floating-ui) library to handle +the dynamic positioning of floating elements relative to their trigger / anchor +element. This also includes collision detection that repositions the floating +element as necessary to keep it visible within the viewport. In the majority of +cases, the styling from the `floating-ui` 'fixed' positioning strategy prevents +the floating element from being +[clipped](https://floating-ui.com/docs/misc#clipping) by an ancestor element. + +The `enable-v12-dynamic-floating-styles` flag enables this dynamic styling +without the collision detection. + +**Note**: The flag has no effect when used with `autoAlign` because `autoAlign` +includes both the dynamic positioning styles and collision detection. + +## Enable dynamic setting of floating styles + +```js + + + + + + + +``` diff --git a/packages/react/src/components/MenuButton/MenuButton.featureflag.stories.js b/packages/react/src/components/MenuButton/MenuButton.featureflag.stories.js new file mode 100644 index 000000000000..eccee719efe3 --- /dev/null +++ b/packages/react/src/components/MenuButton/MenuButton.featureflag.stories.js @@ -0,0 +1,46 @@ +/** + * Copyright IBM Corp. 2016, 2023 + * + * 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 { MenuItem } from '../Menu'; +import { MenuButton } from '../MenuButton'; +import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; + +// eslint-disable-next-line storybook/csf-component +export default { + title: 'Components/MenuButton/Feature Flag', + component: MenuButton, + tags: ['!autodocs'], + decorators: [ + (Story) => ( + + + + ), + ], +}; + +export const FloatingStyles = (args) => ( + + + + + +); + +FloatingStyles.args = { + menuAlignment: 'bottom', +}; + +FloatingStyles.argTypes = { + menuAlignment: { + options: ['top', 'bottom'], + control: { + type: 'radio', + }, + }, +}; diff --git a/packages/react/src/components/Modal/Modal.featureflag.mdx b/packages/react/src/components/Modal/Modal.featureflag.mdx index 1b67dd19bbaa..c7e5be3c5577 100644 --- a/packages/react/src/components/Modal/Modal.featureflag.mdx +++ b/packages/react/src/components/Modal/Modal.featureflag.mdx @@ -1,6 +1,6 @@ import { Meta } from '@storybook/blocks'; - + # Modal diff --git a/packages/react/src/components/Modal/Modal.featureflag.stories.js b/packages/react/src/components/Modal/Modal.featureflag.stories.js index d4bfcc2ad1f1..32043d7eb068 100644 --- a/packages/react/src/components/Modal/Modal.featureflag.stories.js +++ b/packages/react/src/components/Modal/Modal.featureflag.stories.js @@ -5,9 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import React, { useState, useRef } from 'react'; -import ReactDOM from 'react-dom'; -import { action } from '@storybook/addon-actions'; +import React, { useState } from 'react'; import Modal from './Modal'; import Button from '../Button'; import Select from '../Select'; @@ -15,24 +13,12 @@ import MultiSelect from '../MultiSelect'; import Dropdown from '../Dropdown'; import SelectItem from '../SelectItem'; import TextInput from '../TextInput'; -import mdx from './Modal.featureflag.mdx'; import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; -import { - StructuredListWrapper, - StructuredListHead, - StructuredListBody, - StructuredListRow, - StructuredListCell, -} from '../StructuredList'; export default { - title: 'Experimental/Feature Flags/Modal', + title: 'Components/Modal/Feature Flag', component: Modal, - parameters: { - docs: { - page: mdx, - }, - }, + tags: ['!autodocs'], decorators: [ (Story) => ( @@ -42,7 +28,7 @@ export default { ], }; -export const Default = () => { +export const FocusWrapWithoutSentinel = () => { const [open, setOpen] = useState(true); return ( <> @@ -99,489 +85,3 @@ export const Default = () => { ); }; - -export const FullWidth = () => { - const [open, setOpen] = useState(true); - return ( - <> - - setOpen(false)} - isFullWidth - modalHeading="Full Width Modal" - modalLabel="An example of a modal with no padding" - primaryButtonText="Add" - secondaryButtonText="Cancel"> - - - - - Column A - - - Column B - - - Column C - - - - - - Row 1 - Row 1 - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc - dui magna, finibus id tortor sed, aliquet bibendum augue. Aenean - posuere sem vel euismod dignissim. Nulla ut cursus dolor. - Pellentesque vulputate nisl a porttitor interdum. - - - - Row 2 - Row 2 - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc - dui magna, finibus id tortor sed, aliquet bibendum augue. Aenean - posuere sem vel euismod dignissim. Nulla ut cursus dolor. - Pellentesque vulputate nisl a porttitor interdum. - - - - Row 3 - Row 3 - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc - dui magna, finibus id tortor sed, aliquet bibendum augue. Aenean - posuere sem vel euismod dignissim. Nulla ut cursus dolor. - Pellentesque vulputate nisl a porttitor interdum. - - - - - - - ); -}; - -export const DangerModal = () => { - const [open, setOpen] = useState(true); - return ( - <> - - setOpen(false)} - danger - modalHeading="Are you sure you want to delete this custom domain?" - modalLabel="Account resources" - primaryButtonText="Delete" - secondaryButtonText="Cancel" - /> - - ); -}; - -const buttons = { - 'One (1)': '1', - 'Two (2)': '2', - 'Three (3)': '3', -}; -const modalFooter = (numberOfButtons) => { - const secondaryButtons = () => { - switch (numberOfButtons) { - case '1': - return { - secondaryButtons: [], - }; - case '2': - return { - secondaryButtonText: 'Cancel', - }; - case '3': - return { - secondaryButtons: [ - { - buttonText: 'Keep both', - onClick: action('onClick'), - }, - { - buttonText: 'Rename', - onClick: action('onClick'), - }, - ], - }; - default: - return null; - } - }; - return { - ...secondaryButtons(), - }; -}; - -export const WithScrollingContent = () => { - const [open, setOpen] = useState(true); - return ( - <> - - setOpen(false)} - hasScrollingContent - modalHeading="Add a custom domain" - modalLabel="Account resources" - primaryButtonText="Add" - secondaryButtonText="Cancel"> -

- Custom domains direct requests for your apps in this Cloud Foundry - organization to a URL that you own. A custom domain can be a shared - domain, a shared subdomain, or a shared domain and host. -

-

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eu - nibh odio. Nunc a consequat est, id porttitor sapien. Proin vitae leo - vitae orci tincidunt auctor eget eget libero. Ut tincidunt ultricies - fringilla. Aliquam erat volutpat. Aenean arcu odio, elementum vel - vehicula vitae, porttitor ac lorem. Sed viverra elit ac risus - tincidunt fermentum. Ut sollicitudin nibh id risus ornare ornare. - Etiam gravida orci ut lectus dictum, quis ultricies felis mollis. - Mauris nec commodo est, nec faucibus nibh. Nunc commodo ante quis - pretium consectetur. Ut ac nisl vitae mi mattis vulputate a at elit. - Nullam porttitor ex eget mi feugiat mattis. Nunc non sodales magna. - Proin ornare tellus quis hendrerit egestas. Donec pharetra leo nec - molestie sollicitudin.{' '} -

- -
- -
- - (item ? item.text : '')} - /> -
- - ); -}; - -export const Playground = ({ numberOfButtons, ...args }) => { - const [open, setOpen] = useState(true); - return ( - <> - - { - action(e); - setOpen(false); - }} - modalHeading="Add a custom domain" - primaryButtonText="Add" - secondaryButtonText="Cancel" - aria-label="Modal content" - open={open} - {...args} - {...modalFooter(numberOfButtons)}> -

- Custom domains direct requests for your apps in this Cloud Foundry - organization to a URL that you own. A custom domain can be a shared - domain, a shared subdomain, or a shared domain and host. -

- - - {args.hasScrollingContent && ( - <> -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id - accumsan augue. Phasellus consequat augue vitae tellus tincidunt - posuere. Curabitur justo urna, consectetur vel elit iaculis, - ultrices condimentum risus. Nulla facilisi. Etiam venenatis - molestie tellus. Quisque consectetur non risus eu rutrum.{' '} -

-

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id - accumsan augue. Phasellus consequat augue vitae tellus tincidunt - posuere. Curabitur justo urna, consectetur vel elit iaculis, - ultrices condimentum risus. Nulla facilisi. Etiam venenatis - molestie tellus. Quisque consectetur non risus eu rutrum.{' '} -

-

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id - accumsan augue. Phasellus consequat augue vitae tellus tincidunt - posuere. Curabitur justo urna, consectetur vel elit iaculis, - ultrices condimentum risus. Nulla facilisi. Etiam venenatis - molestie tellus. Quisque consectetur non risus eu rutrum.{' '} -

-

Lorem ipsum

-

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id - accumsan augue. Phasellus consequat augue vitae tellus tincidunt - posuere. Curabitur justo urna, consectetur vel elit iaculis, - ultrices condimentum risus. Nulla facilisi. Etiam venenatis - molestie tellus. Quisque consectetur non risus eu rutrum.{' '} -

-

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id - accumsan augue. Phasellus consequat augue vitae tellus tincidunt - posuere. Curabitur justo urna, consectetur vel elit iaculis, - ultrices condimentum risus. Nulla facilisi. Etiam venenatis - molestie tellus. Quisque consectetur non risus eu rutrum.{' '} -

-

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id - accumsan augue. Phasellus consequat augue vitae tellus tincidunt - posuere. Curabitur justo urna, consectetur vel elit iaculis, - ultrices condimentum risus. Nulla facilisi. Etiam venenatis - molestie tellus. Quisque consectetur non risus eu rutrum.{' '} -

-

- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean id - accumsan augue. Phasellus consequat augue vitae tellus tincidunt - posuere. Curabitur justo urna, consectetur vel elit iaculis, - ultrices condimentum risus. Nulla facilisi. Etiam venenatis - molestie tellus. Quisque consectetur non risus eu rutrum.{' '} -

- - )} -
- - ); -}; - -Playground.args = { - numberOfButtons: 'Two (2)', -}; - -Playground.argTypes = { - children: { - table: { - disable: true, - }, - }, - className: { - table: { - disable: true, - }, - }, - id: { - table: { - disable: true, - }, - }, - modalHeading: { - control: 'text', - }, - modalLabel: { - control: 'text', - }, - numberOfButtons: { - description: 'Count of Footer Buttons', - options: Object.keys(buttons), - mapping: buttons, - control: { - type: 'inline-radio', - labels: Object.keys(buttons), - }, - }, - onKeyDown: { - action: 'onKeyDown', - }, - onRequestSubmit: { - action: 'onRequestSubmit', - }, - onSecondarySubmit: { - action: 'onSecondarySubmit', - table: { - disable: true, - }, - }, - primaryButtonText: { - control: 'text', - }, - secondaryButtons: { - table: { - disable: true, - }, - }, - secondaryButtonText: { - control: 'text', - table: { - disable: true, - }, - }, - selectorPrimaryFocus: { - table: { - disable: true, - }, - }, - selectorsFloatingMenus: { - table: { - disable: true, - }, - }, -}; - -export const WithStateManager = () => { - /** - * Simple state manager for modals. - */ - const ModalStateManager = ({ - renderLauncher: LauncherContent, - children: ModalContent, - }) => { - const [open, setOpen] = useState(false); - return ( - <> - {!ModalContent || typeof document === 'undefined' - ? null - : ReactDOM.createPortal( - , - document.body - )} - {LauncherContent && } - - ); - }; - - const button = useRef(); - - return ( - ( - - )}> - {({ open, setOpen }) => ( - setOpen(false)}> -

- Custom domains direct requests for your apps in this Cloud Foundry - organization to a URL that you own. A custom domain can be a shared - domain, a shared subdomain, or a shared domain and host. -

- - -
- )} -
- ); -}; - -export const PassiveModal = () => { - const [open, setOpen] = useState(true); - return ( - <> - - setOpen(false)} - passiveModal - modalHeading="You have been successfully signed out" - /> - - ); -}; - -export const WithInlineLoading = () => { - const [status, setStatus] = useState('inactive'); - const [description, setDescription] = useState('Deleting...'); - - const fakePromise = () => { - return new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, 2000); - }); - }; - - const submit = async () => { - setStatus('active'); - - await fakePromise(); - - setDescription('Deleted!'); - setStatus('finished'); - }; - - const resetStatus = () => { - setStatus('inactive'); - setDescription('Deleting...'); - }; - - const [open, setOpen] = useState(true); - return ( - <> - - setOpen(false)} - danger - modalHeading="Are you sure you want to delete this custom domain?" - modalLabel="Account resources" - primaryButtonText="Delete" - secondaryButtonText="Cancel" - onRequestSubmit={submit} - loadingStatus={status} - loadingDescription={description} - onLoadingSuccess={resetStatus} - /> - - ); -}; diff --git a/packages/react/src/components/MultiSelect/MultiSelect.DynamicStyles.featureflag.mdx b/packages/react/src/components/MultiSelect/MultiSelect.DynamicStyles.featureflag.mdx new file mode 100644 index 000000000000..679649439397 --- /dev/null +++ b/packages/react/src/components/MultiSelect/MultiSelect.DynamicStyles.featureflag.mdx @@ -0,0 +1,40 @@ +import { Meta } from '@storybook/blocks'; + + + +# Dynamically set floating styles + +Components with `autoAlign` use the +[`floating-ui`](https://github.com/floating-ui/floating-ui) library to handle +the dynamic positioning of floating elements relative to their trigger / anchor +element. This also includes collision detection that repositions the floating +element as necessary to keep it visible within the viewport. In the majority of +cases, the styling from the `floating-ui` 'fixed' positioning strategy prevents +the floating element from being +[clipped](https://floating-ui.com/docs/misc#clipping) by an ancestor element. + +The `enable-v12-dynamic-floating-styles` flag enables this dynamic styling +without the collision detection. + +**Note**: The flag has no effect when used with `autoAlign` because `autoAlign` +includes both the dynamic positioning styles and collision detection. + +## Enable dynamic setting of floating styles + +```js + + (item ? item.text : '')} + selectionFeedback="top-after-reopen" + /> + +``` diff --git a/packages/react/src/components/MultiSelect/MultiSelect.featureflag.stories.js b/packages/react/src/components/MultiSelect/MultiSelect.featureflag.stories.js new file mode 100644 index 000000000000..94a5e298890d --- /dev/null +++ b/packages/react/src/components/MultiSelect/MultiSelect.featureflag.stories.js @@ -0,0 +1,78 @@ +/** + * Copyright IBM Corp. 2016, 2023 + * + * 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 { MultiSelect } from '../MultiSelect'; +import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; + +// eslint-disable-next-line storybook/csf-component +export default { + title: 'Components/MultiSelect/Feature Flag', + component: MultiSelect, + tags: ['!autodocs'], + decorators: [ + (Story) => ( + + + + ), + ], +}; + +const comboBoxItems = [ + { + id: 'option-0', + text: 'An example option that is really long to show what should be done to handle long text', + }, + { + id: 'option-1', + text: 'Option 1', + }, + { + id: 'option-2', + text: 'Option 2', + }, + { + id: 'option-3', + text: 'Option 3 - a disabled item', + disabled: true, + }, + { + id: 'option-4', + text: 'Option 4', + }, + { + id: 'option-5', + text: 'Option 5', + }, +]; + +export const FloatingStyles = (args) => ( + (item ? item.text : '')} + selectionFeedback="top-after-reopen" + /> +); + +FloatingStyles.args = { + direction: 'bottom', +}; + +FloatingStyles.argTypes = { + direction: { + options: ['top', 'bottom'], + control: { + type: 'radio', + }, + }, +}; diff --git a/packages/react/src/components/Notification/Notification.featureflag.mdx b/packages/react/src/components/Notification/Notification.featureflag.mdx index 76402993cc06..05902fdf4758 100644 --- a/packages/react/src/components/Notification/Notification.featureflag.mdx +++ b/packages/react/src/components/Notification/Notification.featureflag.mdx @@ -1,7 +1,9 @@ import { Meta } from '@storybook/blocks'; - - + # ActionableNotification [Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/Notification) diff --git a/packages/react/src/components/Notification/stories/ActionableNotification.featureflag.stories.js b/packages/react/src/components/Notification/stories/ActionableNotification.featureflag.stories.js index 77e64b88d70f..bba8629198a3 100644 --- a/packages/react/src/components/Notification/stories/ActionableNotification.featureflag.stories.js +++ b/packages/react/src/components/Notification/stories/ActionableNotification.featureflag.stories.js @@ -8,18 +8,13 @@ import React from 'react'; import { ActionableNotification } from '../../Notification'; import { action } from '@storybook/addon-actions'; -import mdx from '../Notification.featureflag.mdx'; import { WithFeatureFlags } from '../../../../.storybook/templates/WithFeatureFlags'; // eslint-disable-next-line storybook/csf-component export default { - title: 'Experimental/Feature Flags/Notifications/Actionable', + title: 'Components/Notifications/Actionable/Feature Flag', component: ActionableNotification, - parameters: { - docs: { - page: mdx, - }, - }, + tags: ['!autodocs'], decorators: [ (Story) => ( @@ -38,27 +33,11 @@ export default { }, }; -export const Default = () => ( - +export const FocusWrapWithoutSentinels = (args) => ( + ); -Default.argTypes = { - hasFocus: { - table: { - disable: true, - }, - }, -}; - -export const Playground = (args) => ; - -Playground.argTypes = { +FocusWrapWithoutSentinels.argTypes = { ['aria-label']: { table: { disable: true, @@ -94,7 +73,7 @@ Playground.argTypes = { }, }, }; -Playground.args = { +FocusWrapWithoutSentinels.args = { actionButtonLabel: 'Action', inline: false, title: 'Notification title', diff --git a/packages/react/src/components/OverflowMenu/next/OverflowMenu.mdx b/packages/react/src/components/OverflowMenu/OverflowMenu.DynamicStyles.featureflag.mdx similarity index 54% rename from packages/react/src/components/OverflowMenu/next/OverflowMenu.mdx rename to packages/react/src/components/OverflowMenu/OverflowMenu.DynamicStyles.featureflag.mdx index 771acef5cbdd..b0ced447d795 100644 --- a/packages/react/src/components/OverflowMenu/next/OverflowMenu.mdx +++ b/packages/react/src/components/OverflowMenu/OverflowMenu.DynamicStyles.featureflag.mdx @@ -1,6 +1,6 @@ -import { ArgTypes, Canvas, Story, Meta } from '@storybook/addon-docs'; +import { Meta } from '@storybook/blocks'; - + # OverflowMenu @@ -47,15 +47,48 @@ the `menuAlignment` prop. ## menuTarget Prop -The `menuTarget` prop specifies where the `OverflowMenu` should render, which is particularly useful when using `OverflowMenu` inside a modal. By default, the menu renders in `document.body`, but this can disrupt focus order in modals or other components with focus management. - -Pass the `menuTarget` prop to render the `OverflowMenu` inside the modal or any specific element where you want it to render: - - - -## Component API - - +The `menuTarget` prop specifies where the `OverflowMenu` should render, which is +particularly useful when using `OverflowMenu` inside a modal. By default, the +menu renders in `document.body`, but this can disrupt focus order in modals or +other components with focus management. + +Pass the `menuTarget` prop to render the `OverflowMenu` inside the modal or any +specific element where you want it to render: + +## Dynamically set floating styles + +Components with `autoAlign` use the +[`floating-ui`](https://github.com/floating-ui/floating-ui) library to handle +the dynamic positioning of floating elements relative to their trigger / anchor +element. This also includes collision detection that repositions the floating +element as necessary to keep it visible within the viewport. In the majority of +cases, the styling from the `floating-ui` 'fixed' positioning strategy prevents +the floating element from being +[clipped](https://floating-ui.com/docs/misc#clipping) by an ancestor element. + +The `enable-v12-dynamic-floating-styles` flag enables this dynamic styling +without the collision detection. + +**Note**: The flag has no effect when used with `autoAlign` because `autoAlign` +includes both the dynamic positioning styles and collision detection. + +## Enable dynamic setting of floating styles + +```js + + + + + + + + + + +``` ## Feedback diff --git a/packages/react/src/components/OverflowMenu/OverflowMenu.featureflag.stories.js b/packages/react/src/components/OverflowMenu/OverflowMenu.featureflag.stories.js index eedcf977575b..e82bc4ef903a 100644 --- a/packages/react/src/components/OverflowMenu/OverflowMenu.featureflag.stories.js +++ b/packages/react/src/components/OverflowMenu/OverflowMenu.featureflag.stories.js @@ -6,10 +6,6 @@ */ import React, { useRef, useEffect } from 'react'; -import { action } from '@storybook/addon-actions'; - -import { ArrowsVertical } from '@carbon/icons-react'; - import { MenuItem, MenuItemDivider, @@ -17,14 +13,11 @@ import { MenuItemRadioGroup, MenuItemSelectable, } from '../Menu'; - import { OverflowMenu } from './'; -import mdx from './next/OverflowMenu.mdx'; - import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; export default { - title: 'Experimental/Feature Flags/OverflowMenu', + title: 'Components/OverflowMenu/Feature Flag', component: OverflowMenu, subcomponents: { MenuItem, @@ -33,11 +26,7 @@ export default { MenuItemRadioGroup, MenuItemDivider, }, - parameters: { - docs: { - page: mdx, - }, - }, + tags: ['!autodocs'], decorators: [ (Story) => ( @@ -47,21 +36,6 @@ export default { ], }; -export const _OverflowMenu = () => { - const onClick = action('onClick (MenuItem)'); - - return ( - - - - - - - - - ); -}; - export const AutoAlign = () => { const ref = useRef(); @@ -107,24 +81,6 @@ export const Nested = () => { ); }; -export const CustomIcon = () => { - return ( - - - - - - ); -}; - export const WithMenuAlignment = (args) => { return ( <> @@ -182,6 +138,21 @@ export const WithMenuAlignment = (args) => { ); }; +export const FloatingStyles = () => { + return ( +
+ + + + + + + + +
+ ); +}; + export const Playground = (args) => { return ( diff --git a/packages/react/src/components/Popover/DynamicStyles.featureflag.stories.js b/packages/react/src/components/Popover/DynamicStyles.featureflag.stories.js deleted file mode 100644 index 29f5de862e7d..000000000000 --- a/packages/react/src/components/Popover/DynamicStyles.featureflag.stories.js +++ /dev/null @@ -1,409 +0,0 @@ -/** - * Copyright IBM Corp. 2016, 2023 - * - * 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, { useState } from 'react'; -import { Information, Checkbox as CheckboxIcon } from '@carbon/icons-react'; -import { ComboBox } from '../ComboBox'; -import { ComboButton } from '../ComboButton'; -import { Dropdown } from '../Dropdown'; -import { Link } from '../Link'; -import { Button } from '../Button'; -import { - ToggletipLabel, - Toggletip, - ToggletipButton, - ToggletipContent, - ToggletipActions, -} from '../Toggletip'; -import { Tooltip } from '../Tooltip'; -import { MenuItem, MenuItemDivider } from '../Menu'; -import { MenuButton } from '../MenuButton'; -import { MultiSelect } from '../MultiSelect'; -import { Popover, PopoverContent } from '../Popover'; -import { OverflowMenu } from '../OverflowMenu'; -import { action } from '@storybook/addon-actions'; -import mdx from './DynamicStyles.featureflag.mdx'; -import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; - -import './story.scss'; -import '../Tooltip/story.scss'; - -// eslint-disable-next-line storybook/csf-component -export default { - title: 'Experimental/Feature Flags/Dynamic floating styles', - component: Dropdown, - parameters: { - docs: { - page: mdx, - }, - }, - decorators: [ - (Story) => ( - - - - ), - ], -}; - -const comboBoxItems = [ - { - id: 'option-0', - text: 'An example option that is really long to show what should be done to handle long text', - }, - { - id: 'option-1', - text: 'Option 1', - }, - { - id: 'option-2', - text: 'Option 2', - }, - { - id: 'option-3', - text: 'Option 3 - a disabled item', - disabled: true, - }, - { - id: 'option-4', - text: 'Option 4', - }, - { - id: 'option-5', - text: 'Option 5', - }, -]; - -export const _ComboBox = (args) => ( - {}} - id="carbon-combobox" - items={comboBoxItems} - itemToString={(item) => (item ? item.text : '')} - titleText="ComboBox title" - helperText="Combobox helper text" - {...args} - /> -); - -_ComboBox.args = { - direction: 'bottom', -}; - -_ComboBox.argTypes = { - direction: { - options: ['top', 'bottom'], - control: { - type: 'radio', - }, - }, -}; - -export const _ComboButton = (args) => ( - - - - - -); - -_ComboButton.args = { - menuAlignment: 'bottom', -}; - -_ComboButton.argTypes = { - menuAlignment: { - options: ['top', 'bottom'], - control: { - type: 'radio', - }, - }, -}; - -const items = [ - { - text: 'Lorem, ipsum dolor sit amet consectetur adipisicing elit.', - }, - { - text: 'Option 1', - }, - { - text: 'Option 2', - }, - { - text: 'Option 3 - a disabled item', - disabled: true, - }, - { - text: 'Option 4', - }, - { - text: 'Option 5', - }, - { - text: 'Option 6', - }, - { - text: 'Option 7', - }, - { - text: 'Option 8', - }, -]; - -export const _Dropdown = (args) => ( - (item ? item.text : '')} - {...args} - /> -); - -_Dropdown.args = { - direction: 'bottom', -}; - -_Dropdown.argTypes = { - direction: { - options: ['top', 'bottom'], - control: { - type: 'radio', - }, - }, -}; - -export const _Popover = (args) => { - const [open, setOpen] = useState(true); - - return ( -
- -
- { - setOpen(!open); - }} - /> -
- -
-

This popover uses autoAlign

-

- Scroll the container up, down, left or right to observe how the - popover will automatically change its position in attempt to stay - within the viewport. This works on initial render in addition to - on scroll. -

-
-
-
-
- ); -}; - -_Popover.args = { - align: 'bottom', -}; - -_Popover.argTypes = { - align: { - options: [ - 'top', - 'top-start', - 'top-end', - - 'bottom', - 'bottom-start', - 'bottom-end', - - 'left', - 'left-end', - 'left-start', - - 'right', - 'right-end', - 'right-start', - ], - control: { - type: 'select', - }, - }, -}; - -export const _MenuButton = (args) => ( - - - - - -); - -_MenuButton.args = { - menuAlignment: 'bottom', -}; - -_MenuButton.argTypes = { - menuAlignment: { - options: ['top', 'bottom'], - control: { - type: 'radio', - }, - }, -}; - -export const _MultiSelect = (args) => ( - (item ? item.text : '')} - selectionFeedback="top-after-reopen" - /> -); - -_MultiSelect.args = { - direction: 'bottom', -}; - -_MultiSelect.argTypes = { - direction: { - options: ['top', 'bottom'], - control: { - type: 'radio', - }, - }, -}; - -export const _Toggletip = (args) => { - return ( -
- Toggletip label - - - - - -

- Scroll the container up, down, left or right to observe how the - Toggletip will automatically change its position in attempt to stay - within the viewport. This works on initial render in addition to on - scroll. -

- - Link action - - -
-
-
- ); -}; - -_Toggletip.args = { - align: 'bottom', -}; - -_Toggletip.argTypes = { - align: { - options: [ - 'top', - 'top-start', - 'top-end', - - 'bottom', - 'bottom-start', - 'bottom-end', - - 'left', - 'left-end', - 'left-start', - - 'right', - 'right-end', - 'right-start', - ], - control: { - type: 'select', - }, - }, -}; - -export const _Tooltip = (args) => { - const tooltipLabel = - 'Scroll the container up, down, left or right to observe how the tooltip will automatically change its position in attempt to stay within the viewport. This works on initial render in addition to on scroll.'; - return ( -
- - - -
- ); -}; - -_Tooltip.args = { - align: 'bottom', -}; - -_Tooltip.argTypes = { - align: { - options: [ - 'top', - 'top-start', - 'top-end', - - 'bottom', - 'bottom-start', - 'bottom-end', - - 'left', - 'left-end', - 'left-start', - - 'right', - 'right-end', - 'right-start', - ], - control: { - type: 'select', - }, - }, -}; - -export const _OverflowMenu = () => { - return ( -
- - - - - - - - -
- ); -}; diff --git a/packages/react/src/components/Popover/DynamicStyles.featureflag.mdx b/packages/react/src/components/Popover/Popover.DynamicStyles.featureflag.mdx similarity index 94% rename from packages/react/src/components/Popover/DynamicStyles.featureflag.mdx rename to packages/react/src/components/Popover/Popover.DynamicStyles.featureflag.mdx index 2e7ebd8f7704..967326e51c66 100644 --- a/packages/react/src/components/Popover/DynamicStyles.featureflag.mdx +++ b/packages/react/src/components/Popover/Popover.DynamicStyles.featureflag.mdx @@ -1,6 +1,6 @@ import { Meta } from '@storybook/blocks'; - + # Dynamically set floating styles diff --git a/packages/react/src/components/Popover/Popover.featureflag.stories.js b/packages/react/src/components/Popover/Popover.featureflag.stories.js new file mode 100644 index 000000000000..bace7c794d74 --- /dev/null +++ b/packages/react/src/components/Popover/Popover.featureflag.stories.js @@ -0,0 +1,90 @@ +/** + * Copyright IBM Corp. 2016, 2023 + * + * 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, { useState } from 'react'; +import { Popover, PopoverContent } from '../Popover'; +import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; +import { Checkbox as CheckboxIcon } from '@carbon/icons-react'; + +import './story.scss'; + +// eslint-disable-next-line storybook/csf-component +export default { + title: 'Components/Popover/Feature Flag', + component: Popover, + tags: ['!autodocs'], + decorators: [ + (Story) => ( + + + + ), + ], +}; + +export const FloatingStyles = (args) => { + const [open, setOpen] = useState(true); + + return ( +
+ +
+ { + setOpen(!open); + }} + /> +
+ +
+

This popover uses autoAlign

+

+ Scroll the container up, down, left or right to observe how the + popover will automatically change its position in attempt to stay + within the viewport. This works on initial render in addition to + on scroll. +

+
+
+
+
+ ); +}; + +FloatingStyles.args = { + align: 'bottom', +}; + +FloatingStyles.argTypes = { + align: { + options: [ + 'top', + 'top-start', + 'top-end', + + 'bottom', + 'bottom-start', + 'bottom-end', + + 'left', + 'left-end', + 'left-start', + + 'right', + 'right-end', + 'right-start', + ], + control: { + type: 'select', + }, + }, +}; diff --git a/packages/react/src/components/StructuredList/StructuredList.featureflag.mdx b/packages/react/src/components/StructuredList/StructuredList.featureflag.mdx new file mode 100644 index 000000000000..ffc6182b91ac --- /dev/null +++ b/packages/react/src/components/StructuredList/StructuredList.featureflag.mdx @@ -0,0 +1,16 @@ +import { Meta } from '@storybook/blocks'; + + + +# Structured List + +## Enable structured list visible icons + +```js + + + +``` diff --git a/packages/react/src/components/StructuredList/StructuredList.featureflag.stories.js b/packages/react/src/components/StructuredList/StructuredList.featureflag.stories.js index 5ffccb1d6256..ce6db2ecd284 100644 --- a/packages/react/src/components/StructuredList/StructuredList.featureflag.stories.js +++ b/packages/react/src/components/StructuredList/StructuredList.featureflag.stories.js @@ -6,7 +6,6 @@ */ import React from 'react'; -import mdx from './StructuredList.mdx'; import { WithLayer } from '../../../.storybook/templates/WithLayer'; import { useFeatureFlag } from '../FeatureFlags'; @@ -18,11 +17,10 @@ import { StructuredListInput, StructuredListCell, } from './'; -import StructuredListSkeleton from './StructuredList.Skeleton'; import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; -const experimentalClassname = 'experimental-tile'; + export default { - title: 'Experimental/Feature Flags/StructuredList', + title: 'Components/StructuredList/Feature Flag', component: StructuredListWrapper, subcomponents: { StructuredListHead, @@ -31,11 +29,7 @@ export default { StructuredListInput, StructuredListCell, }, - parameters: { - docs: { - page: mdx, - }, - }, + tags: ['!autodocs'], argTypes: { children: { table: { @@ -52,67 +46,6 @@ export default { ], }; -export const Default = (args) => { - return ( -
- - - - ColumnA - ColumnB - ColumnC - - - - - Row 1 - Row 1 - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc dui - magna, finibus id tortor sed, aliquet bibendum augue. Aenean - posuere sem vel euismod dignissim. Nulla ut cursus dolor. - Pellentesque vulputate nisl a porttitor interdum. - - - - Row 2 - Row 2 - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc dui - magna, finibus id tortor sed, aliquet bibendum augue. Aenean - posuere sem vel euismod dignissim. Nulla ut cursus dolor. - Pellentesque vulputate nisl a porttitor interdum. - - - - -
- ); -}; - -Default.args = { - isCondensed: false, - isFlush: false, -}; - -Default.argTypes = { - selection: { - control: { - disable: true, - }, - }, - isCondensed: { - control: { - type: 'boolean', - }, - }, - isFlush: { - control: { - type: 'boolean', - }, - }, -}; - const structuredListBodyRowGenerator = (numRows) => { return Array.apply(null, Array(numRows)).map((n, i) => ( @@ -189,51 +122,3 @@ export const WithBackgroundLayer = () => { ); }; - -export const Skeleton = (args) => ( -
- -
-); - -Skeleton.args = { - rowCount: 5, -}; - -Skeleton.argTypes = { - isFlush: { - table: { - disable: true, - }, - }, - isCondensed: { - table: { - disable: true, - }, - }, - ariaLabel: { - table: { - disable: true, - }, - }, - ['aria-label']: { - table: { - disable: true, - }, - }, - className: { - table: { - disable: true, - }, - }, - selection: { - table: { - disable: true, - }, - }, - rowCount: { - control: { - type: 'number', - }, - }, -}; diff --git a/packages/react/src/components/Tile/Tile.featureflag.mdx b/packages/react/src/components/Tile/Tile.featureflag.mdx new file mode 100644 index 000000000000..7cd18c0c94d5 --- /dev/null +++ b/packages/react/src/components/Tile/Tile.featureflag.mdx @@ -0,0 +1,20 @@ +import { Meta } from '@storybook/blocks'; + + + +# Experimental Tile Contrast + +Designed to meet accessibility standards, particularly regarding contrast +minimums. The new variant ensures that tiles are more accessible to users with +visual impairments. + +## Enable experimental tile contrast + +```js + + ... + +``` diff --git a/packages/react/src/components/Tile/Tile.featureflag.stories.js b/packages/react/src/components/Tile/Tile.featureflag.stories.js index 4e850c40f0b9..16af744b56b0 100644 --- a/packages/react/src/components/Tile/Tile.featureflag.stories.js +++ b/packages/react/src/components/Tile/Tile.featureflag.stories.js @@ -35,7 +35,7 @@ import { WithLayer } from '../../../.storybook/templates/WithLayer'; import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; export default { - title: 'Experimental/Feature Flags/Tile', + title: 'Components/Tile/Feature Flag', component: Tile, subcomponents: { ClickableTile, @@ -60,6 +60,7 @@ export default {
), ], + tags: ['!autodocs'], }; const experimentalClassname = 'experimental-tile'; diff --git a/packages/react/src/components/Toggletip/Toggletip.DynamicStyles.featureflag.mdx b/packages/react/src/components/Toggletip/Toggletip.DynamicStyles.featureflag.mdx new file mode 100644 index 000000000000..557612ee9f0e --- /dev/null +++ b/packages/react/src/components/Toggletip/Toggletip.DynamicStyles.featureflag.mdx @@ -0,0 +1,48 @@ +import { Meta } from '@storybook/blocks'; + + + +# Dynamically set floating styles + +Components with `autoAlign` use the +[`floating-ui`](https://github.com/floating-ui/floating-ui) library to handle +the dynamic positioning of floating elements relative to their trigger / anchor +element. This also includes collision detection that repositions the floating +element as necessary to keep it visible within the viewport. In the majority of +cases, the styling from the `floating-ui` 'fixed' positioning strategy prevents +the floating element from being +[clipped](https://floating-ui.com/docs/misc#clipping) by an ancestor element. + +The `enable-v12-dynamic-floating-styles` flag enables this dynamic styling +without the collision detection. + +**Note**: The flag has no effect when used with `autoAlign` because `autoAlign` +includes both the dynamic positioning styles and collision detection. + +## Enable dynamic setting of floating styles + +```js + + Toggletip label + + + + + +

+ Scroll the container up, down, left or right to observe how the + Toggletip will automatically change its position in attempt to stay + within the viewport. This works on initial render in addition to on + scroll. +

+ + Link action + + +
+
+
+``` diff --git a/packages/react/src/components/Toggletip/Toggletip.featureflag.stories.js b/packages/react/src/components/Toggletip/Toggletip.featureflag.stories.js new file mode 100644 index 000000000000..8df267a679da --- /dev/null +++ b/packages/react/src/components/Toggletip/Toggletip.featureflag.stories.js @@ -0,0 +1,89 @@ +/** + * Copyright IBM Corp. 2016, 2023 + * + * 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 { Information } from '@carbon/icons-react'; + +import { Link } from '../Link'; +import { Button } from '../Button'; +import { + ToggletipLabel, + Toggletip, + ToggletipButton, + ToggletipContent, + ToggletipActions, +} from '../Toggletip'; +import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; + +// eslint-disable-next-line storybook/csf-component +export default { + title: 'Components/Toggletip/Feature Flag', + component: Toggletip, + tags: ['!autodocs'], + + decorators: [ + (Story) => ( + + + + ), + ], +}; + +export const FloatingStyles = (args) => { + return ( +
+ Toggletip label + + + + + +

+ Scroll the container up, down, left or right to observe how the + Toggletip will automatically change its position in attempt to stay + within the viewport. This works on initial render in addition to on + scroll. +

+ + Link action + + +
+
+
+ ); +}; + +FloatingStyles.args = { + align: 'bottom', +}; + +FloatingStyles.argTypes = { + align: { + options: [ + 'top', + 'top-start', + 'top-end', + + 'bottom', + 'bottom-start', + 'bottom-end', + + 'left', + 'left-end', + 'left-start', + + 'right', + 'right-end', + 'right-start', + ], + control: { + type: 'select', + }, + }, +}; diff --git a/packages/react/src/components/Tooltip/Tooltip.DynamicStyles.featureflag.mdx b/packages/react/src/components/Tooltip/Tooltip.DynamicStyles.featureflag.mdx new file mode 100644 index 000000000000..7f3dc5f16434 --- /dev/null +++ b/packages/react/src/components/Tooltip/Tooltip.DynamicStyles.featureflag.mdx @@ -0,0 +1,42 @@ +import { Meta } from '@storybook/blocks'; + + + +# Dynamically set floating styles + +Components with `autoAlign` use the +[`floating-ui`](https://github.com/floating-ui/floating-ui) library to handle +the dynamic positioning of floating elements relative to their trigger / anchor +element. This also includes collision detection that repositions the floating +element as necessary to keep it visible within the viewport. In the majority of +cases, the styling from the `floating-ui` 'fixed' positioning strategy prevents +the floating element from being +[clipped](https://floating-ui.com/docs/misc#clipping) by an ancestor element. + +The `enable-v12-dynamic-floating-styles` flag enables this dynamic styling +without the collision detection. + +**Note**: The flag has no effect when used with `autoAlign` because `autoAlign` +includes both the dynamic positioning styles and collision detection. + +## Enable dynamic setting of floating styles + +```js + +
+ + + +
+
+``` diff --git a/packages/react/src/components/Tooltip/Tooltip.featureflag.stories.js b/packages/react/src/components/Tooltip/Tooltip.featureflag.stories.js new file mode 100644 index 000000000000..6a46044a48fb --- /dev/null +++ b/packages/react/src/components/Tooltip/Tooltip.featureflag.stories.js @@ -0,0 +1,75 @@ +/** + * Copyright IBM Corp. 2016, 2023 + * + * 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 { Information } from '@carbon/icons-react'; +import { Tooltip } from '../Tooltip'; +import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; + +import './story.scss'; + +// eslint-disable-next-line storybook/csf-component +export default { + title: 'Components/Tooltip/Feature Flag', + component: Tooltip, + tags: ['!autodocs'], + decorators: [ + (Story) => ( + + + + ), + ], +}; + +export const FloatingStyles = (args) => { + const tooltipLabel = + 'Scroll the container up, down, left or right to observe how the tooltip will automatically change its position in attempt to stay within the viewport. This works on initial render in addition to on scroll.'; + return ( +
+ + + +
+ ); +}; + +FloatingStyles.args = { + align: 'bottom', +}; + +FloatingStyles.argTypes = { + align: { + options: [ + 'top', + 'top-start', + 'top-end', + + 'bottom', + 'bottom-start', + 'bottom-end', + + 'left', + 'left-end', + 'left-start', + + 'right', + 'right-end', + 'right-start', + ], + control: { + type: 'select', + }, + }, +}; diff --git a/packages/react/src/components/TreeView/TreeView.featureflag.mdx b/packages/react/src/components/TreeView/TreeView.featureflag.mdx index 4ea18ac7a634..b78502969762 100644 --- a/packages/react/src/components/TreeView/TreeView.featureflag.mdx +++ b/packages/react/src/components/TreeView/TreeView.featureflag.mdx @@ -1,8 +1,10 @@ import { Meta } from '@storybook/blocks'; - + -# TreeView controllable API +# TreeView controllable + +API The new controllable API of TreeView allows you to synchronize the state of `selected` and `active` with your application. diff --git a/packages/react/src/components/TreeView/TreeView.featureflag.stories.js b/packages/react/src/components/TreeView/TreeView.featureflag.stories.js index 62db42ffbf63..964246b33436 100644 --- a/packages/react/src/components/TreeView/TreeView.featureflag.stories.js +++ b/packages/react/src/components/TreeView/TreeView.featureflag.stories.js @@ -10,8 +10,6 @@ import { action } from '@storybook/addon-actions'; import { Document, Folder } from '@carbon/icons-react'; import { Button, VStack } from '../../'; -import mdx from './TreeView.featureflag.mdx'; - import { TreeView, TreeNode } from './'; import { WithFeatureFlags } from '../../../.storybook/templates/WithFeatureFlags'; @@ -184,16 +182,12 @@ function renderTree(nodes) { } export default { - title: 'Experimental/Feature Flags/TreeView', + title: 'components/TreeView/Feature Flag', component: TreeView, subcomponents: { TreeNode, }, - parameters: { - docs: { - page: mdx, - }, - }, + tags: ['!autodocs'], args: { onSelect: action('onSelect'), },