Skip to content

Commit

Permalink
Improve API docs for anchor and tab components (#2126)
Browse files Browse the repository at this point in the history
# Pull Request

## 🤨 Rationale

As part of #824 we want to improve the accuracy and comprehensiveness of
our storybook API documentation. This PR covers:
- anchor
- anchor button
- anchor tab and related components
- tab and related components

## 👩‍💻 Implementation

1. Followed same patterns as previous PRs to restructure MDX files and
to add API categories to story files
2. Refactored anchor tab and tab to include separate stories for their
child components, similar to what I did for menu

## 🧪 Testing

Storybook exploration

## ✅ Checklist

<!--- Review the list and put an x in the boxes that apply or ~~strike
through~~ around items that don't (along with an explanation). -->

- [x] I have updated the project documentation to reflect my changes or
determined no changes are needed.
  • Loading branch information
jattasNI authored May 21, 2024
1 parent b46ed40 commit 63403fc
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 64 deletions.
9 changes: 9 additions & 0 deletions packages/storybook/src/nimble/anchor-button/anchor-button.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,26 @@ 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';

<Meta of={anchorButtonStories} />
<Title of={anchorButtonStories} />

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 <Tag name={buttonTag}/> instead.

<Canvas of={anchorButtonStories.outlineAnchorButton} />

## API

<Controls of={anchorButtonStories.outlineAnchorButton} />

<ComponentApisLink />

## Styling

<StylingDocs components={{ Button: anchorButtonTag }} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -53,29 +53,46 @@ const metadata: Meta<AnchorButtonArgs> = {
`),
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',
Expand Down
28 changes: 26 additions & 2 deletions packages/storybook/src/nimble/anchor-tabs/anchor-tabs.mdx
Original file line number Diff line number Diff line change
@@ -1,19 +1,43 @@
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';

<Meta of={anchorTabsStories} />
<Title of={anchorTabsStories} />

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 <Tag name={tabsTag}/> instead.

<Canvas of={anchorTabsStories.anchorTabs} />

## API

<Controls of={anchorTabsStories.anchorTabs} />

<ComponentApisLink />

### Anchor Tab

Use the <Tag name={anchorTabTag} /> child element to add new tabs to the <Tag name={anchorTabsTag} />.

<Canvas of={anchorTabsStories.anchorTab} />
<Controls of={anchorTabsStories.anchorTab} />

### Tabs Toolbar

Use the <Tag name={tabsToolbarTag} /> child element to add a toolbar next to the tabs.

<Canvas of={anchorTabsStories.tabsToolbar} />
<Controls of={anchorTabsStories.tabsToolbar} />

{/* ## Styling */}

{/* ## Usage */}
Expand Down
116 changes: 89 additions & 27 deletions packages/storybook/src/nimble/anchor-tabs/anchor-tabs.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<TabsArgs> = {
const metadata: Meta<AnchorTabsArgs> = {
title: 'Components/Anchor Tabs',
parameters: {},
// prettier-ignore
};

export default metadata;

export const anchorTabs: StoryObj<AnchorTabsArgs> = {
render: createUserSelectedThemeStory(html`
<${anchorTabsTag} activeid="${x => x.activeId}">
${when(x => x.toolbar, html<TabsArgs>`<${tabsToolbarTag}><${buttonTag} appearance="ghost">Toolbar Button</${buttonTag}></${tabsToolbarTag}>`)}
<${anchorTabTag} id="1" ?disabled="${x => x.tabDisabled}" href="${x => x.tabHref}">Google</${anchorTabTag}>
<${anchorTabTag} id="2" href="https://www.ni.com">NI</${anchorTabTag}>
<${anchorTabTag} id="3" href="https://nimble.ni.dev">Nimble</${anchorTabTag}>
</${anchorTabsTag}>
<${anchorTabsTag} activeid="${x => x.activeid}">
<${anchorTabTag} id="1" disabled href="https://www.google.com">Google</${anchorTabTag}>
<${anchorTabTag} id="2" href="https://www.ni.com">NI</${anchorTabTag}>
<${anchorTabTag} id="3" href="https://nimble.ni.dev">Nimble</${anchorTabTag}>
</${anchorTabsTag}>
`),
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<AnchorTabArgs> = {
render: createUserSelectedThemeStory(html`
<${anchorTabsTag} activeid="1">
<${anchorTabTag} id="1" ?disabled="${x => x.disabled}" href="${x => x.href}">${x => x.title}</${anchorTabTag}>
<${anchorTabTag} id="2" href="https://www.ni.com">NI</${anchorTabTag}>
<${anchorTabTag} id="3" href="https://nimble.ni.dev">Nimble</${anchorTabTag}>
</${anchorTabsTag}>
`),
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<TabsArgs> = {};
export const tabsToolbar: StoryObj<ToolbarArgs> = {
render: createUserSelectedThemeStory(html`
<${anchorTabsTag} activeid="1">
${when(x => x.toolbar, html<ToolbarArgs>`<${tabsToolbarTag}><${buttonTag} appearance="ghost">Toolbar Button</${buttonTag}></${tabsToolbarTag}>`)}
<${anchorTabTag} id="1" disabled href="https://www.google.com">Google</${anchorTabTag}>
<${anchorTabTag} id="2" href="https://www.ni.com">NI</${anchorTabTag}>
<${anchorTabTag} id="3" href="https://nimble.ni.dev">Nimble</${anchorTabTag}>
</${anchorTabsTag}>
`),
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,
}
};
6 changes: 6 additions & 0 deletions packages/storybook/src/nimble/anchor/anchor.mdx
Original file line number Diff line number Diff line change
@@ -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';

<Meta of={anchorStories} />
Expand All @@ -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.

<Canvas of={anchorStories.anchor} />

## API

<Controls of={anchorStories.anchor} />

<ComponentApisLink />

{/* ## Styling */}

{/* ## Usage */}
Expand Down
19 changes: 14 additions & 5 deletions packages/storybook/src/nimble/anchor/anchor.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -35,23 +35,32 @@ const metadata: Meta<AnchorArgs> = {
>${x => x.label}</${anchorTag}> to navigate.</span>
`),
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: {
Expand Down
Loading

0 comments on commit 63403fc

Please sign in to comment.