diff --git a/packages/carbon-web-components/.storybook/main.ts b/packages/carbon-web-components/.storybook/main.ts index 7c002530418..bc8fae8c5ab 100644 --- a/packages/carbon-web-components/.storybook/main.ts +++ b/packages/carbon-web-components/.storybook/main.ts @@ -45,6 +45,8 @@ const stories = glob.sync( '../src/**/modal.stories.ts', '../src/**/modal.mdx', '../src/**/file-uploader.stories.ts', + '../src/**/multi-select.mdx', + '../src/**/multi-select.stories.ts', '../src/**/notification.mdx', '../src/**/actionable-notification.stories.ts', '../src/**/inline-notification.stories.ts', diff --git a/packages/carbon-web-components/src/components/multi-select/multi-select-story.ts b/packages/carbon-web-components/src/components/multi-select/multi-select-story.ts deleted file mode 100644 index aee2bf265bf..00000000000 --- a/packages/carbon-web-components/src/components/multi-select/multi-select-story.ts +++ /dev/null @@ -1,292 +0,0 @@ -/** - * @license - * - * Copyright IBM Corp. 2019, 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 { html } from 'lit'; -import { boolean, select } from '@storybook/addon-knobs'; -import { ifDefined } from 'lit/directives/if-defined.js'; -import textNullable from '../../../.storybook/knob-text-nullable'; -import { prefix } from '../../globals/settings'; -import { - DROPDOWN_SIZE, - DROPDOWN_TYPE, - DROPDOWN_DIRECTION, - SELECTION_FEEDBACK_OPTION, -} from './multi-select'; -import './multi-select-item'; -import '../../../.storybook/templates/with-layer'; -import storyDocs from './multi-select-story.mdx'; - -const sizes = { - [`Small size (${DROPDOWN_SIZE.SMALL})`]: DROPDOWN_SIZE.SMALL, - [`Medium size (${DROPDOWN_SIZE.MEDIUM})`]: DROPDOWN_SIZE.MEDIUM, - [`Large size (${DROPDOWN_SIZE.LARGE})`]: DROPDOWN_SIZE.LARGE, -}; - -const directionOptions = { - [`Top`]: DROPDOWN_DIRECTION.TOP, - [`Bottom`]: DROPDOWN_DIRECTION.BOTTOM, -}; - -const types = { - Default: null, - [`Inline (${DROPDOWN_TYPE.INLINE})`]: DROPDOWN_TYPE.INLINE, -}; - -const selectionFeedbackOptions = { - [`Top (${SELECTION_FEEDBACK_OPTION.TOP})`]: SELECTION_FEEDBACK_OPTION.TOP, - [`Fixed (${SELECTION_FEEDBACK_OPTION.FIXED})`]: - SELECTION_FEEDBACK_OPTION.FIXED, - [`Top-after-reopen (${SELECTION_FEEDBACK_OPTION.TOP_AFTER_REOPEN})`]: - SELECTION_FEEDBACK_OPTION.TOP_AFTER_REOPEN, -}; - -export const Default = () => { - return html` - - An example option that is really long to show what should be done to - handle long text - Option 1 - Option 2 - Option 3 - a disabled item - Option 4 - Option 5 - - `; -}; - -Default.decorators = [ - (story) => html`
${story()}
`, -]; - -export const Filterable = () => { - return html` - - An example option that is really long to show what should be done to - handle long text - Option 1 - Option 2 - Option 3 - a disabled item - Option 4 - Option 5 - - `; -}; - -Filterable.decorators = [ - (story) => html`
${story()}
`, -]; - -export const FilterableWithLayer = () => { - return html` - -
- - An example option that is really long to show what should be done - to handle long text - Option 1 - Option 2 - Option 3 - a disabled item - Option 4 - Option 5 - -
-
- `; -}; - -export const WithInitialSelectedItems = () => { - return html` - - An example option that is really long to show what should be done to - handle long text - Option 1 - Option 2 - Option 3 - a disabled item - Option 4 - Option 5 - - `; -}; - -WithInitialSelectedItems.decorators = [ - (story) => html`
${story()}
`, -]; - -export const WithLayer = () => { - return html` - -
- - An example option that is really long to show what should be done - to handle long text - Option 1 - Option 2 - Option 3 - a disabled item - Option 4 - Option 5 - -
-
- `; -}; - -export const Playground = (args) => { - const { - clearSelectionLabel, - direction, - disabled, - helperText, - hideLabel, - locale, - invalid, - invalidText, - readOnly, - titleText, - selectionFeedback, - size, - label, - type, - value, - warn, - warnText, - } = args?.[`${prefix}-multi-select`] ?? {}; - return html` - - An example option that is really long to show what should be done to - handle long text - Option 1 - Option 2 - Option 3 - a disabled item - Option 4 - Option 5 - - `; -}; - -Playground.decorators = [ - (story) => html`
${story()}
`, -]; - -export default { - title: 'Components/Multi select', - parameters: { - ...storyDocs.parameters, - knobs: { - [`${prefix}-multi-select`]: () => ({ - clearSelectionDescription: textNullable( - 'Clear selection description for a11y (clear-selection-description)', - 'Total items selected: ' - ), - clearSelectionText: textNullable( - 'Clear selection text for a11y (clear-selection-text)', - 'To clear selection, press Delete or Backspace.' - ), - disabled: boolean('Disabled (disabled)', false), - direction: select( - 'Direction', - directionOptions, - DROPDOWN_DIRECTION.BOTTOM - ), - helperText: textNullable( - 'Helper text (helper-text)', - 'Optional helper text' - ), - hideLabel: boolean('Hide label (hide-label)', false), - locale: textNullable('Locale (locale)', 'en'), - invalid: boolean('Show invalid state (invalid)', false), - invalidText: textNullable('Invalid text (invalid-text)', 'whoopsie!'), - titleText: textNullable( - 'Title text (title-text)', - 'This is a MultiSelect Title' - ), - label: textNullable('Label of field (label)', 'This is a label'), - size: select('Size (size)', sizes, DROPDOWN_SIZE.MEDIUM), - selectionFeedback: select( - 'Selection feedback (selection-feedback)', - selectionFeedbackOptions, - SELECTION_FEEDBACK_OPTION.TOP_AFTER_REOPEN - ), - readOnly: boolean('Read only (read-only)', false), - type: select('Type (type)', types, null), - warn: boolean('Warn (warn)', false), - warnText: textNullable('Warn text (warn-text)', 'whoopsie!'), - }), - }, - }, -}; diff --git a/packages/carbon-web-components/src/components/multi-select/multi-select-story.mdx b/packages/carbon-web-components/src/components/multi-select/multi-select.mdx similarity index 94% rename from packages/carbon-web-components/src/components/multi-select/multi-select-story.mdx rename to packages/carbon-web-components/src/components/multi-select/multi-select.mdx index 610080c30ae..37702b3e828 100644 --- a/packages/carbon-web-components/src/components/multi-select/multi-select-story.mdx +++ b/packages/carbon-web-components/src/components/multi-select/multi-select.mdx @@ -1,5 +1,8 @@ -import { Props, Description } from '@storybook/addon-docs/blocks'; +import { ArgsTable, Meta, Description } from '@storybook/addon-docs/blocks'; import { cdnJs, cdnCss } from '../../globals/internal/storybook-cdn'; +import * as MultiSelectStories from './multi-select.stories'; + + # Multi select @@ -103,7 +106,7 @@ Note: For `boolean` attributes, `true` means simply setting the attribute (e.g. ``) and `false` means not setting the attribute (e.g. `` without `open` attribute). - + ## `` attributes and properties @@ -111,4 +114,4 @@ Note: For `boolean` attributes, `true` means simply setting the attribute (e.g. ``) and `false` means not setting the attribute (e.g. `` without `disabled` attribute). - + diff --git a/packages/carbon-web-components/src/components/multi-select/multi-select.stories.ts b/packages/carbon-web-components/src/components/multi-select/multi-select.stories.ts new file mode 100644 index 00000000000..0b627d4c1ca --- /dev/null +++ b/packages/carbon-web-components/src/components/multi-select/multi-select.stories.ts @@ -0,0 +1,364 @@ +/** + * @license + * + * Copyright IBM Corp. 2019, 2024 + * + * 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 { html } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { + DROPDOWN_SIZE, + DROPDOWN_TYPE, + DROPDOWN_DIRECTION, + SELECTION_FEEDBACK_OPTION, +} from './multi-select'; +import './multi-select-item'; +import '../layer/index'; +import '../../../.storybook/templates/with-layer'; +import storyDocs from './multi-select.mdx'; + +const sizes = { + [`Small size (${DROPDOWN_SIZE.SMALL})`]: DROPDOWN_SIZE.SMALL, + [`Medium size (${DROPDOWN_SIZE.MEDIUM})`]: DROPDOWN_SIZE.MEDIUM, + [`Large size (${DROPDOWN_SIZE.LARGE})`]: DROPDOWN_SIZE.LARGE, +}; + +const directionOptions = { + [`Top`]: DROPDOWN_DIRECTION.TOP, + [`Bottom`]: DROPDOWN_DIRECTION.BOTTOM, +}; + +const types = { + Default: null, + [`Inline (${DROPDOWN_TYPE.INLINE})`]: DROPDOWN_TYPE.INLINE, +}; + +const selectionFeedbackOptions = { + [`Top (${SELECTION_FEEDBACK_OPTION.TOP})`]: SELECTION_FEEDBACK_OPTION.TOP, + [`Fixed (${SELECTION_FEEDBACK_OPTION.FIXED})`]: + SELECTION_FEEDBACK_OPTION.FIXED, + [`Top-after-reopen (${SELECTION_FEEDBACK_OPTION.TOP_AFTER_REOPEN})`]: + SELECTION_FEEDBACK_OPTION.TOP_AFTER_REOPEN, +}; + +const args = { + clearSelectionDescription: 'Total items selected: ', + clearSelectionText: 'To clear selection, press Delete or Backspace.', + disabled: false, + direction: DROPDOWN_DIRECTION.BOTTOM, + helperText: 'Optional helper text', + hideLabel: false, + locale: 'en', + invalid: false, + invalidText: 'whoopsie!', + titleText: 'This is a MultiSelect Title', + label: 'This is a label', + size: DROPDOWN_SIZE.MEDIUM, + selectionFeedback: SELECTION_FEEDBACK_OPTION.TOP_AFTER_REOPEN, + readOnly: false, + type: null, + warn: false, + warnText: 'whoopsie!', +}; + +const argTypes = { + clearSelectionDescription: { + control: 'text', + description: + 'Specify the text that should be read for screen readers that describes total items selected.', + }, + clearSelectionText: { + control: 'text', + description: + 'Specify the text that should be read for screen readers to clear selection.', + }, + disabled: { + control: 'boolean', + description: 'Disable the control.', + }, + direction: { + control: 'select', + description: + 'Specify the direction of the multiselect dropdown. Can be either top or bottom.', + options: directionOptions, + }, + helperText: { + control: 'text', + description: + 'Provide helper text that is used alongside the control label for additional help.', + }, + hideLabel: { + control: 'boolean', + description: 'Specify whether the title text should be hidden or not.', + }, + locale: { + control: 'text', + description: + 'Specify the locale of the control. Used for the default compareItems used for sorting the list of items in the control.', + }, + invalid: { + control: 'boolean', + description: 'Is the current selection invalid?', + }, + invalidText: { + control: 'text', + description: 'If invalid, what is the error?', + }, + titleText: { + control: 'text', + description: + 'Provide text to be used in a <label> element that is tied to the multiselect via ARIA attributes.', + }, + label: { + control: 'text', + description: + 'Generic label that will be used as the textual representation of what this field is for.', + }, + size: { + control: 'select', + description: + 'Specify the size of the ListBox. Currently supports either sm, md or lg as an option.', + options: sizes, + }, + selectionFeedback: { + control: 'select', + description: + "Specify feedback (mode) of the selection. top: selected item jumps to top fixed: selected item stays at it's position top-after-reopen: selected item jump to top after reopen dropdown.", + options: selectionFeedbackOptions, + }, + readOnly: { + control: 'boolean', + description: 'Whether or not the Dropdown is readonly.', + }, + type: { + control: 'select', + description: "Specify 'inline' to create an inline multi-select.", + options: types, + }, + warn: { + control: 'boolean', + description: 'Specify whether the control is currently in warning state.', + }, + warnText: { + control: 'text', + description: + 'Provide the text that is displayed when the control is in warning state.', + }, +}; + +export const Default = { + decorators: [(story) => html`
${story()}
`], + render: () => { + return html` + + An example option that is really long to show what should be done to + handle long text + Option 1 + Option 2 + Option 3 - a disabled item + Option 4 + Option 5 + + `; + }, +}; + +export const Filterable = { + decorators: [(story) => html`
${story()}
`], + render: () => { + return html` + + An example option that is really long to show what should be done to + handle long text + Option 1 + Option 2 + Option 3 - a disabled item + Option 4 + Option 5 + + `; + }, +}; + +export const FilterableWithLayer = { + render: () => { + return html` + +
+ + An example option that is really long to show what should be done + to handle long text + Option 1 + Option 2 + Option 3 - a disabled item + Option 4 + Option 5 + +
+
+ `; + }, +}; + +export const WithInitialSelectedItems = { + decorators: [(story) => html`
${story()}
`], + render: () => { + return html` + + An example option that is really long to show what should be done to + handle long text + Option 1 + Option 2 + Option 3 - a disabled item + Option 4 + Option 5 + + `; + }, +}; + +export const WithLayer = { + render: () => { + return html` + +
+ + An example option that is really long to show what should be done + to handle long text + Option 1 + Option 2 + Option 3 - a disabled item + Option 4 + Option 5 + +
+
+ `; + }, +}; + +export const Playground = { + args, + argTypes, + decorators: [(story) => html`
${story()}
`], + render: (args) => { + const { + clearSelectionLabel, + direction, + disabled, + helperText, + hideLabel, + locale, + invalid, + invalidText, + readOnly, + titleText, + selectionFeedback, + size, + label, + type, + value, + warn, + warnText, + } = args ?? {}; + return html` + + An example option that is really long to show what should be done to + handle long text + Option 1 + Option 2 + Option 3 - a disabled item + Option 4 + Option 5 + + `; + }, +}; + +const meta = { + title: 'Components/Multi Select', + parameters: { + docs: { + page: storyDocs, + }, + }, +}; + +export default meta;