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;