diff --git a/packages/storybook/src/nimble/anchor-button/anchor-button.mdx b/packages/storybook/src/nimble/anchor-button/anchor-button.mdx index 0658b77bea..e4b1fcbe1b 100644 --- a/packages/storybook/src/nimble/anchor-button/anchor-button.mdx +++ b/packages/storybook/src/nimble/anchor-button/anchor-button.mdx @@ -9,7 +9,9 @@ import { import TargetDocs from '../patterns/anchor/target-docs.mdx'; import ContentHiddenDocs from '../patterns/button/content-hidden-docs.mdx'; import StylingDocs from '../patterns/button/styling-docs.mdx'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; import { anchorButtonTag } from '@ni/nimble-components/dist/esm/anchor-button'; +import { buttonTag } from '@ni/nimble-components/dist/esm/button'; import * as anchorButtonStories from './anchor-button.stories'; @@ -17,9 +19,16 @@ import * as anchorButtonStories from './anchor-button.stories'; An anchor button is a component with the visual appearance of a button, but it navigates like an anchor/link when pressed. +If you want a button that triggers an action or event, use the instead. + + +## API + + + ## Styling diff --git a/packages/storybook/src/nimble/anchor-button/anchor-button.stories.ts b/packages/storybook/src/nimble/anchor-button/anchor-button.stories.ts index 66d8266908..ff8315443d 100644 --- a/packages/storybook/src/nimble/anchor-button/anchor-button.stories.ts +++ b/packages/storybook/src/nimble/anchor-button/anchor-button.stories.ts @@ -14,7 +14,7 @@ import { endIconDescription, iconDescription } from '../patterns/button/doc-strings'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory, disabledDescription, textContentDescription } from '../../utilities/storybook'; import { hrefDescription } from '../patterns/anchor/anchor-docs'; interface AnchorButtonArgs { @@ -53,29 +53,46 @@ const metadata: Meta = { `), argTypes: { href: { - description: hrefDescription({ componentName: 'anchor button', includeDisable: false }) + description: hrefDescription({ componentName: 'anchor button', includeDisable: false }), + table: { category: apiCategory.attributes } }, appearance: { options: Object.keys(ButtonAppearance), control: { type: 'radio' }, - description: appearanceDescription + description: appearanceDescription, + table: { category: apiCategory.attributes } }, appearanceVariant: { name: 'appearance-variant', options: Object.keys(ButtonAppearanceVariant), control: { type: 'radio' }, - description: appearanceVariantDescription + description: appearanceVariantDescription, + table: { category: apiCategory.attributes } + }, + contentHidden: { + name: 'content-hidden', + description: contentHiddenDescription, + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'anchor button' }), + table: { category: apiCategory.attributes } + }, + label: { + name: 'default', + description: textContentDescription({ componentName: 'anchor button' }), + table: { category: apiCategory.slots } }, icon: { - description: iconDescription + name: 'start', + description: iconDescription, + table: { category: apiCategory.slots } }, endIcon: { - description: endIconDescription + name: 'end', + description: endIconDescription, + table: { category: apiCategory.slots } }, - contentHidden: { - name: 'content-hidden', - description: contentHiddenDescription - } }, args: { label: 'Anchor Button', diff --git a/packages/storybook/src/nimble/anchor-tabs/anchor-tabs.mdx b/packages/storybook/src/nimble/anchor-tabs/anchor-tabs.mdx index 50bfd9f5ae..d52d8a329e 100644 --- a/packages/storybook/src/nimble/anchor-tabs/anchor-tabs.mdx +++ b/packages/storybook/src/nimble/anchor-tabs/anchor-tabs.mdx @@ -1,6 +1,10 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import TargetDocs from '../patterns/anchor/target-docs.mdx'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; import { anchorTabTag } from '@ni/nimble-components/dist/esm/anchor-tab'; +import { anchorTabsTag } from '@ni/nimble-components/dist/esm/anchor-tabs'; +import { tabsToolbarTag } from '@ni/nimble-components/dist/esm/tabs-toolbar'; +import { tabsTag } from '@ni/nimble-components/dist/esm/tabs'; import * as anchorTabsStories from './anchor-tabs.stories'; @@ -8,12 +12,32 @@ import * as anchorTabsStories from './anchor-tabs.stories'; Anchor tabs are a sequence of links that are styled to look like tab elements, where one link can be distinguished as the currently active item. Use this component instead of the standard tabs component when each tab -represents a different URL to navigate to. Use the standard tabs component when the tabs should switch between different -tab panels hosted on the same page. +represents a different URL to navigate to. + +If you want the tabs to switch between different tab panels hosted on the same page, use the instead. + +## API + + + +### Anchor Tab + +Use the child element to add new tabs to the . + + + + +### Tabs Toolbar + +Use the child element to add a toolbar next to the tabs. + + + + {/* ## Styling */} {/* ## Usage */} diff --git a/packages/storybook/src/nimble/anchor-tabs/anchor-tabs.stories.ts b/packages/storybook/src/nimble/anchor-tabs/anchor-tabs.stories.ts index d8f9abce46..4a7d272aa4 100644 --- a/packages/storybook/src/nimble/anchor-tabs/anchor-tabs.stories.ts +++ b/packages/storybook/src/nimble/anchor-tabs/anchor-tabs.stories.ts @@ -4,49 +4,111 @@ import { anchorTabTag } from '@ni/nimble-components/dist/esm/anchor-tab'; import { tabsToolbarTag } from '@ni/nimble-components/dist/esm/tabs-toolbar'; import { buttonTag } from '@ni/nimble-components/dist/esm/button'; import { anchorTabsTag } from '@ni/nimble-components/dist/esm/anchor-tabs'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory, disabledDescription } from '../../utilities/storybook'; +import { hrefDescription } from '../patterns/anchor/anchor-docs'; -interface TabsArgs { - activeId: string; +interface AnchorTabsArgs { + activeid: string; + content: undefined; +} + +interface AnchorTabArgs { + href: string; + disabled: boolean; + id: string; + title: string; +} + +interface ToolbarArgs { toolbar: boolean; - tabHref: string; - tabDisabled: boolean; } -const metadata: Meta = { +const metadata: Meta = { title: 'Components/Anchor Tabs', - parameters: {}, - // prettier-ignore +}; + +export default metadata; + +export const anchorTabs: StoryObj = { render: createUserSelectedThemeStory(html` - <${anchorTabsTag} activeid="${x => x.activeId}"> - ${when(x => x.toolbar, html`<${tabsToolbarTag}><${buttonTag} appearance="ghost">Toolbar Button`)} - <${anchorTabTag} id="1" ?disabled="${x => x.tabDisabled}" href="${x => x.tabHref}">Google - <${anchorTabTag} id="2" href="https://www.ni.com">NI - <${anchorTabTag} id="3" href="https://nimble.ni.dev">Nimble - + <${anchorTabsTag} activeid="${x => x.activeid}"> + <${anchorTabTag} id="1" disabled href="https://www.google.com">Google + <${anchorTabTag} id="2" href="https://www.ni.com">NI + <${anchorTabTag} id="3" href="https://nimble.ni.dev">Nimble + `), argTypes: { - activeId: { + activeid: { options: ['None', '1', '2', '3'], control: { type: 'radio' }, description: - "The `id` of the `nimble-anchor-tab` that should be indicated as currently active/selected. It is the application's responsibility to set `activeId` to the tab matching the currently loaded URL." - }, - tabHref: { - name: 'tab 1 href' + `The \`id\` of the \`${anchorTabTag}\` that should be indicated as currently active/selected. It is the application's responsibility to set \`activeid\` to the tab matching the currently loaded URL.`, + table: { category: apiCategory.attributes } }, - tabDisabled: { - name: 'tab 1 disabled' + content: { + name: 'default', + description: 'Add tabs or a toolbar by slotting them as child content in the default slot.', + control: false, + table: { category: apiCategory.slots } } }, args: { - activeId: 'None', - toolbar: false, - tabHref: 'https://www.google.com', - tabDisabled: false + activeid: 'None', } }; -export default metadata; +export const anchorTab: StoryObj = { + render: createUserSelectedThemeStory(html` + <${anchorTabsTag} activeid="1"> + <${anchorTabTag} id="1" ?disabled="${x => x.disabled}" href="${x => x.href}">${x => x.title} + <${anchorTabTag} id="2" href="https://www.ni.com">NI + <${anchorTabTag} id="3" href="https://nimble.ni.dev">Nimble + + `), + argTypes: { + href: { + description: hrefDescription({ componentName: 'anchor tab', includeDisable: false }), + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'anchor tab' }), + table: { category: apiCategory.attributes } + }, + id: { + description: `Set the \`id\` attribute on each tab and use the value to set the \`activeid\` attribute on the \`${anchorTabsTag}\` element to indicate the currently selected tab.`, + control: false, + table: { category: apiCategory.attributes } + }, + title: { + name: 'default', + description: 'Set the name of each tab by providing text content in its default slot.', + table: { category: apiCategory.slots } + } + }, + args: { + href: 'https://www.google.com', + disabled: false, + title: 'Google' + } +}; -export const anchorTabs: StoryObj = {}; +export const tabsToolbar: StoryObj = { + render: createUserSelectedThemeStory(html` + <${anchorTabsTag} activeid="1"> + ${when(x => x.toolbar, html`<${tabsToolbarTag}><${buttonTag} appearance="ghost">Toolbar Button`)} + <${anchorTabTag} id="1" disabled href="https://www.google.com">Google + <${anchorTabTag} id="2" href="https://www.ni.com">NI + <${anchorTabTag} id="3" href="https://nimble.ni.dev">Nimble + + `), + argTypes: { + toolbar: { + name: 'default', + description: `Add a tabs toolbar as a child of the tabs and populate its content with \`${buttonTag}\` elements.`, + table: { category: apiCategory.slots } + } + }, + args: { + toolbar: true, + } +}; diff --git a/packages/storybook/src/nimble/anchor/anchor.mdx b/packages/storybook/src/nimble/anchor/anchor.mdx index 2deb5598d5..401187de3d 100644 --- a/packages/storybook/src/nimble/anchor/anchor.mdx +++ b/packages/storybook/src/nimble/anchor/anchor.mdx @@ -1,5 +1,6 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import TargetDocs from '../patterns/anchor/target-docs.mdx'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; import * as anchorStories from './anchor.stories'; @@ -8,8 +9,13 @@ import * as anchorStories from './anchor.stories'; Per [W3C](https://www.w3.org/WAI/ARIA/apg/patterns/link/), an anchor/link widget provides an interactive reference to a resource. The target resource can be either external or local, i.e., either outside or within the current page or application. + +## API + + + {/* ## Styling */} {/* ## Usage */} diff --git a/packages/storybook/src/nimble/anchor/anchor.stories.ts b/packages/storybook/src/nimble/anchor/anchor.stories.ts index beb99d05b4..4feea6190c 100644 --- a/packages/storybook/src/nimble/anchor/anchor.stories.ts +++ b/packages/storybook/src/nimble/anchor/anchor.stories.ts @@ -3,7 +3,7 @@ import { html } from '@microsoft/fast-element'; import { bodyFont } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens'; import { anchorTag } from '@ni/nimble-components/dist/esm/anchor'; import { AnchorAppearance } from '@ni/nimble-components/dist/esm/anchor/types'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../utilities/storybook'; import { hrefDescription } from '../patterns/anchor/anchor-docs'; interface AnchorArgs { @@ -35,23 +35,32 @@ const metadata: Meta = { >${x => x.label} to navigate. `), argTypes: { + label: { + name: 'default', + description: 'The text to display in the anchor.', + table: { category: apiCategory.slots } + }, href: { - description: hrefDescription({ componentName: 'anchor', includeDisable: true }) + description: hrefDescription({ componentName: 'anchor', includeDisable: true }), + table: { category: apiCategory.attributes } }, underlineHidden: { name: 'underline-hidden', description: - 'Causes the underline to be hidden except on hover. Set this for anchors that are not part of blocks of text.' + 'Causes the underline to be hidden except on hover. Set this for anchors that are not part of blocks of text.', + table: { category: apiCategory.attributes } }, appearance: { options: Object.keys(AnchorAppearance), control: { type: 'radio' }, description: - 'Set to `prominent` to make the anchor appear in a different color than normal text.' + 'Set to `prominent` to make the anchor appear in a different color than normal text.', + table: { category: apiCategory.attributes } }, contenteditable: { description: - 'Set this to the string "true" (or an empty string) when the anchor is within an editable region (i.e. element/hierarchy with [contenteditable](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable)). Whereas native elements inherit their `contenteditable` value by default, the `nimble-anchor` requires this attribute be explicitly set.' + 'Set this to the string "true" (or an empty string) when the anchor is within an editable region (i.e. element/hierarchy with [contenteditable](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable)). Whereas native elements inherit their `contenteditable` value by default, the `nimble-anchor` requires this attribute be explicitly set.', + table: { category: apiCategory.attributes } } }, args: { diff --git a/packages/storybook/src/nimble/tabs/tabs.mdx b/packages/storybook/src/nimble/tabs/tabs.mdx index 7d56916cbd..1782cd2943 100644 --- a/packages/storybook/src/nimble/tabs/tabs.mdx +++ b/packages/storybook/src/nimble/tabs/tabs.mdx @@ -1,6 +1,12 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import { NimbleTabs } from './tabs.react'; import * as tabsStories from './tabs.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; +import { anchorTabsTag } from '@ni/nimble-components/dist/esm/anchor-tabs'; +import { tabTag } from '@ni/nimble-components/dist/esm/tab'; +import { tabsTag } from '@ni/nimble-components/dist/esm/tabs'; +import { tabPanelTag } from '@ni/nimble-components/dist/esm/tab-panel'; +import { tabsToolbarTag } from '@ni/nimble-components/dist/esm/tabs-toolbar'; @@ -10,15 +16,43 @@ sections of content, known as tab panels, that display one panel of content at a associated tab element, that when activated, displays the panel. The list of tab elements is arranged along one edge of the currently displayed panel, most commonly the top edge. -Content in tab panels should be sized and arranged such that it fits horizontally within the panel to avoid -horizontal scrolling. Content may be any height; the tab panel will display a vertical scrollbar if necessary. - -If you want a sequence of tabs that navigate to different URLs, use the Anchor Tabs component instead. +If you want a sequence of tabs that navigate to different URLs, use the <Tag name={anchorTabsTag}/> instead. <Canvas of={tabsStories.tabs} /> + +## API + <Controls of={tabsStories.tabs} /> -{/* ## Styling */} +<ComponentApisLink /> + +### Tab + +Use the <Tag name={tabTag} /> child element to add new tabs to the <Tag name={tabsTag} />. + +<Canvas of={tabsStories.tab} /> +<Controls of={tabsStories.tab} /> + +### Tab Panel + +Use the <Tag name={tabPanelTag} /> child element to add a panel of content for each <Tag name={tabTag} />. + +<Canvas of={tabsStories.tabPanel} /> +<Controls of={tabsStories.tabPanel} /> + +### Tab Toolbar + +Use the <Tag name={tabsToolbarTag} /> child element to add a toolbar next to the tabs. + +<Canvas of={tabsStories.tabToolbar} /> +<Controls of={tabsStories.tabToolbar} /> + +## Styling + +### Sizing + +Content in tab panels should be sized and arranged such that it fits horizontally within the panel to avoid +horizontal scrolling. Content may be any height; the tab panel will display a vertical scrollbar if necessary. {/* ## Usage */} diff --git a/packages/storybook/src/nimble/tabs/tabs.stories.ts b/packages/storybook/src/nimble/tabs/tabs.stories.ts index 88067b48fa..de69429b61 100644 --- a/packages/storybook/src/nimble/tabs/tabs.stories.ts +++ b/packages/storybook/src/nimble/tabs/tabs.stories.ts @@ -6,12 +6,26 @@ import { tabTag } from '@ni/nimble-components/dist/esm/tab'; import { tabPanelTag } from '@ni/nimble-components/dist/esm/tab-panel'; import { tabsToolbarTag } from '@ni/nimble-components/dist/esm/tabs-toolbar'; import { tabsTag } from '@ni/nimble-components/dist/esm/tabs'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory, disabledDescription } from '../../utilities/storybook'; interface TabsArgs { - activeId: string; + activeid: string; + content: undefined; + change: undefined; +} + +interface TabArgs { + disabled: boolean; + id: string; + title: string; +} + +interface TabPanelArgs { + content: string; +} + +interface ToolbarArgs { toolbar: boolean; - tabDisabled: boolean; } const metadata: Meta<TabsArgs> = { @@ -22,11 +36,15 @@ const metadata: Meta<TabsArgs> = { handles: ['change'] } }, +}; + +export default metadata; + +export const tabs: StoryObj<TabsArgs> = { // prettier-ignore render: createUserSelectedThemeStory(html` - <${tabsTag} activeid="${x => x.activeId}"> - ${when(x => x.toolbar, html<TabsArgs>`<${tabsToolbarTag}><${buttonTag} appearance="ghost">Toolbar Button</${buttonTag}></${tabsToolbarTag}>`)} - <${tabTag} id="1" ?disabled="${x => x.tabDisabled}">Tab One</${tabTag}> + <${tabsTag} activeid="${x => x.activeid}"> + <${tabTag} id="1" disabled">Tab One</${tabTag}> <${tabTag} id="2">Tab Two</${tabTag}> <${tabTag} id="3">Tab Three</${tabTag}> <${tabPanelTag}>Content of the first tab</${tabPanelTag}> @@ -35,21 +53,101 @@ const metadata: Meta<TabsArgs> = { </${tabsTag}> `), argTypes: { - activeId: { + activeid: { options: ['1', '2', '3'], - control: { type: 'radio' } + control: { type: 'radio' }, + description: `The \`id\` of the \`${tabTag}\` that should be indicated as currently active/selected.`, + table: { category: apiCategory.attributes } + }, + content: { + name: 'default', + description: 'Add tabs, tab panels, or a toolbar by slotting them as child content in the default slot.', + control: false, + table: { category: apiCategory.slots } }, - tabDisabled: { - name: 'tab 1 disabled' + change: { + description: 'Fires when the active tab is changed', + control: false, + table: { category: apiCategory.events } } }, args: { - activeId: '1', - toolbar: false, - tabDisabled: false + activeid: '1', } }; -export default metadata; +export const tab: StoryObj<TabArgs> = { + // prettier-ignore + render: createUserSelectedThemeStory(html` + <${tabsTag}> + <${tabTag} id="1" ?disabled="${x => x.disabled}">Tab One</${tabTag}> + <${tabTag} id="2">${x => x.title}</${tabTag}> + <${tabPanelTag}>Content of the first tab</${tabPanelTag}> + <${tabPanelTag}>Content of the second tab</${tabPanelTag}> + </${tabsTag}> + `), + argTypes: { + disabled: { + description: disabledDescription({ componentName: 'tab' }), + table: { category: apiCategory.attributes } + }, + id: { + description: `Optionally set the \`id\` attribute on each tab and use the value to set the \`activeid\` attribute on the \`${tabsTag}\` element to indicate the currently selected tab. Nimble will automatically generate sequential ids if not provided.`, + control: false, + table: { category: apiCategory.attributes } + }, + title: { + name: 'default', + description: 'Set the name of each tab by providing text content in its default slot.', + table: { category: apiCategory.slots } + } + }, + args: { + disabled: true, + title: 'Tab Two' + } +}; + +export const tabPanel: StoryObj<TabPanelArgs> = { + // prettier-ignore + render: createUserSelectedThemeStory(html` + <${tabsTag}> + <${tabTag}>Tab One</${tabTag}> + <${tabTag}>Tab Two</${tabTag}> + <${tabPanelTag}>${x => x.content}</${tabPanelTag}> + <${tabPanelTag}>Content of the second tab</${tabPanelTag}> + </${tabsTag}> + `), + argTypes: { + content: { + description: 'Populate the content of each tab panel by slotting arbitrary HTML into its default slot.', + table: { category: apiCategory.slots } + } + }, + args: { + content: 'Content of the first tab' + } +}; -export const tabs: StoryObj<TabsArgs> = {}; +export const tabToolbar: StoryObj<ToolbarArgs> = { + // prettier-ignore + render: createUserSelectedThemeStory(html` + <${tabsTag}> + ${when(x => x.toolbar, html<TabsArgs>`<${tabsToolbarTag}><${buttonTag} appearance="ghost">Toolbar Button</${buttonTag}></${tabsToolbarTag}>`)} + <${tabTag}>Tab One</${tabTag}> + <${tabTag}>Tab Two</${tabTag}> + <${tabPanelTag}>Content of the first tab</${tabPanelTag}> + <${tabPanelTag}>Content of the second tab</${tabPanelTag}> + </${tabsTag}> + `), + argTypes: { + toolbar: { + name: 'default', + description: `Add a tabs toolbar as a child of the tabs and populate its content with \`${buttonTag}\` elements.`, + table: { category: apiCategory.slots } + } + }, + args: { + toolbar: true, + } +}; \ No newline at end of file