From 427e3caacfa1112880fe9204d9fc2402901536ff Mon Sep 17 00:00:00 2001 From: rajsite Date: Wed, 22 May 2024 12:46:26 -0500 Subject: [PATCH 1/8] applying package updates [skip ci] --- ...ents-c95624bc-cd16-460d-87c2-3cc41a85be50.json | 7 ------- packages/nimble-components/CHANGELOG.json | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 7 deletions(-) delete mode 100644 change/@ni-nimble-components-c95624bc-cd16-460d-87c2-3cc41a85be50.json diff --git a/change/@ni-nimble-components-c95624bc-cd16-460d-87c2-3cc41a85be50.json b/change/@ni-nimble-components-c95624bc-cd16-460d-87c2-3cc41a85be50.json deleted file mode 100644 index 71d242f88e..0000000000 --- a/change/@ni-nimble-components-c95624bc-cd16-460d-87c2-3cc41a85be50.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "none", - "comment": "Update build time global type extensions", - "packageName": "@ni/nimble-components", - "email": "rajsite@users.noreply.github.com", - "dependentChangeType": "none" -} diff --git a/packages/nimble-components/CHANGELOG.json b/packages/nimble-components/CHANGELOG.json index baa8f266a3..a04cbfb799 100644 --- a/packages/nimble-components/CHANGELOG.json +++ b/packages/nimble-components/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/nimble-components", "entries": [ + { + "date": "Wed, 22 May 2024 17:46:25 GMT", + "version": "29.1.4", + "tag": "@ni/nimble-components_v29.1.4", + "comments": { + "none": [ + { + "author": "rajsite@users.noreply.github.com", + "package": "@ni/nimble-components", + "commit": "699ce37952cf27977915aeb8f9b9341ce701002e", + "comment": "Update build time global type extensions" + } + ] + } + }, { "date": "Tue, 21 May 2024 22:53:18 GMT", "version": "29.1.4", From 5e4882a41568361919fc96a91243fc37cd831208 Mon Sep 17 00:00:00 2001 From: m-akinc <7282195+m-akinc@users.noreply.github.com> Date: Wed, 22 May 2024 13:16:27 -0500 Subject: [PATCH 2/8] Update anchor focus styling (#2113) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Pull Request ## ๐Ÿคจ Rationale Part of #2011 ## ๐Ÿ‘ฉโ€๐Ÿ’ป Implementation Squared the styling of the anchor with the [design in Figma](https://www.figma.com/design/PO9mFOu5BCl8aJvFchEeuN/Nimble_Components?node-id=8729-84171&t=ZWhzibWRmDT2XoD7-0): - Keyboard focus: we have decided to keep the double underline, but change the color of the link so it is more noticeable. - `appearance="prominent"` no longer does anything under the Color theme (updated Storybook docs) - Fixed transparency (0.6 -> 0.75) for active link color under the Color theme ## ๐Ÿงช Testing Manually tested in Storybook. We have existing visual tests for this. ## โœ… Checklist - [x] I have updated the project documentation to reflect my changes or determined no changes are needed. --------- Co-authored-by: mollykreis <20542556+mollykreis@users.noreply.github.com> Co-authored-by: Milan Raj --- ...le-components-e3d5df53-15c3-4fe1-8552-ad4db8dbddbd.json | 7 +++++++ packages/nimble-components/src/anchor/styles.ts | 2 ++ .../nimble-components/src/theme-provider/design-tokens.ts | 6 +++--- packages/storybook/.storybook/preview.js | 2 +- packages/storybook/src/nimble/anchor/anchor.stories.ts | 5 +++-- .../table-column/anchor/table-column-anchor.stories.ts | 2 +- 6 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 change/@ni-nimble-components-e3d5df53-15c3-4fe1-8552-ad4db8dbddbd.json diff --git a/change/@ni-nimble-components-e3d5df53-15c3-4fe1-8552-ad4db8dbddbd.json b/change/@ni-nimble-components-e3d5df53-15c3-4fe1-8552-ad4db8dbddbd.json new file mode 100644 index 0000000000..fd91f8681f --- /dev/null +++ b/change/@ni-nimble-components-e3d5df53-15c3-4fe1-8552-ad4db8dbddbd.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fix anchor focus styling", + "packageName": "@ni/nimble-components", + "email": "7282195+m-akinc@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/nimble-components/src/anchor/styles.ts b/packages/nimble-components/src/anchor/styles.ts index bf85674dda..34988347fc 100644 --- a/packages/nimble-components/src/anchor/styles.ts +++ b/packages/nimble-components/src/anchor/styles.ts @@ -2,6 +2,7 @@ import { css } from '@microsoft/fast-element'; import { display } from '../utilities/style/display'; import { focusVisible } from '../utilities/style/focus'; import { + borderHoverColor, linkActiveFontColor, linkActiveProminentFontColor, linkDisabledFontColor, @@ -62,6 +63,7 @@ export const styles = css` outline: none; box-shadow: inset 0px -1px; text-decoration: underline; + color: ${borderHoverColor}; } } diff --git a/packages/nimble-components/src/theme-provider/design-tokens.ts b/packages/nimble-components/src/theme-provider/design-tokens.ts index da7017182f..78d1dd3de6 100644 --- a/packages/nimble-components/src/theme-provider/design-tokens.ts +++ b/packages/nimble-components/src/theme-provider/design-tokens.ts @@ -508,7 +508,7 @@ export const [ element, DigitalGreenLight, DigitalGreenLight, - hexToRgbaCssColor(White, 0.6) + hexToRgbaCssColor(White, 0.75) ), (element: HTMLElement) => hexToRgbaCssColor(getDefaultFontColorForTheme(element), 0.3), LinkLightUiFamily, @@ -527,7 +527,7 @@ export const [ linkProminentFontLineHeight ] = createFontTokens( tokenNames.linkProminentFont, - (element: HTMLElement) => getColorForTheme(element, DigitalGreenDark105, PowerGreen, PowerGreen), + (element: HTMLElement) => getColorForTheme(element, DigitalGreenDark105, PowerGreen, White), (element: HTMLElement) => hexToRgbaCssColor(getDefaultFontColorForTheme(element), 0.3), LinkLightUiFamily, LinkLightUiWeight, @@ -549,7 +549,7 @@ export const [ element, DigitalGreenLight, DigitalGreenLight, - hexToRgbaCssColor(White, 0.6) + hexToRgbaCssColor(White, 0.75) ), (element: HTMLElement) => hexToRgbaCssColor(getDefaultFontColorForTheme(element), 0.3), LinkLightUiFamily, diff --git a/packages/storybook/.storybook/preview.js b/packages/storybook/.storybook/preview.js index 2c1fc41d47..99b228ab50 100644 --- a/packages/storybook/.storybook/preview.js +++ b/packages/storybook/.storybook/preview.js @@ -105,5 +105,5 @@ configureActions({ depth: 1 }); -// Update the GUID on this line to trigger a turbosnap full rebuild: 3e3470f8-2a6c-4474-b409-409c1dfbecea +// Update the GUID on this line to trigger a turbosnap full rebuild: 354fdf0e-bdb4-4dd9-a6e4-21bf71c6efe6 // See https://www.chromatic.com/docs/turbosnap/#full-rebuilds diff --git a/packages/storybook/src/nimble/anchor/anchor.stories.ts b/packages/storybook/src/nimble/anchor/anchor.stories.ts index eeba4f6ba2..8adbdce556 100644 --- a/packages/storybook/src/nimble/anchor/anchor.stories.ts +++ b/packages/storybook/src/nimble/anchor/anchor.stories.ts @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html } from '@microsoft/fast-element'; -import { bodyFont } from '../../../../nimble-components/src/theme-provider/design-tokens'; +import { bodyFont, bodyFontColor } from '../../../../nimble-components/src/theme-provider/design-tokens'; import { anchorTag } from '../../../../nimble-components/src/anchor'; import { AnchorAppearance } from '../../../../nimble-components/src/anchor/types'; import { apiCategory, createUserSelectedThemeStory } from '../../utilities/storybook'; @@ -24,6 +24,7 @@ const metadata: Meta = { @@ -54,7 +55,7 @@ const metadata: Meta = { 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. This has no effect under the Color theme.', table: { category: apiCategory.attributes } }, contenteditable: { diff --git a/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.stories.ts b/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.stories.ts index 4dd5494b8f..f9362f28a3 100644 --- a/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.stories.ts +++ b/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.stories.ts @@ -114,7 +114,7 @@ export const anchorColumn: StoryObj = { 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. This has no effect under the Color theme.' }, underlineHidden: { name: 'underline-hidden', From 1cbdc2c597da51509f9ee3785ed291461f9dcf2d Mon Sep 17 00:00:00 2001 From: rajsite Date: Wed, 22 May 2024 13:32:15 -0500 Subject: [PATCH 3/8] applying package updates [skip ci] --- ...ents-e3d5df53-15c3-4fe1-8552-ad4db8dbddbd.json | 7 ------- package-lock.json | 14 +++++++------- .../nimble-angular/CHANGELOG.json | 15 +++++++++++++++ .../angular-workspace/nimble-angular/CHANGELOG.md | 10 +++++++++- .../angular-workspace/nimble-angular/package.json | 4 ++-- .../spright-angular/CHANGELOG.json | 15 +++++++++++++++ .../spright-angular/CHANGELOG.md | 10 +++++++++- .../spright-angular/package.json | 4 ++-- packages/nimble-components/CHANGELOG.json | 15 +++++++++++++++ packages/nimble-components/CHANGELOG.md | 10 +++++++++- packages/nimble-components/package.json | 2 +- packages/spright-components/CHANGELOG.json | 15 +++++++++++++++ packages/spright-components/CHANGELOG.md | 10 +++++++++- packages/spright-components/package.json | 4 ++-- 14 files changed, 110 insertions(+), 25 deletions(-) delete mode 100644 change/@ni-nimble-components-e3d5df53-15c3-4fe1-8552-ad4db8dbddbd.json diff --git a/change/@ni-nimble-components-e3d5df53-15c3-4fe1-8552-ad4db8dbddbd.json b/change/@ni-nimble-components-e3d5df53-15c3-4fe1-8552-ad4db8dbddbd.json deleted file mode 100644 index fd91f8681f..0000000000 --- a/change/@ni-nimble-components-e3d5df53-15c3-4fe1-8552-ad4db8dbddbd.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "patch", - "comment": "Fix anchor focus styling", - "packageName": "@ni/nimble-components", - "email": "7282195+m-akinc@users.noreply.github.com", - "dependentChangeType": "patch" -} diff --git a/package-lock.json b/package-lock.json index e529ef3846..8b0aa2aae5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33291,7 +33291,7 @@ }, "packages/angular-workspace/nimble-angular": { "name": "@ni/nimble-angular", - "version": "24.3.1", + "version": "24.3.2", "license": "MIT", "dependencies": { "tslib": "^2.2.0" @@ -33302,12 +33302,12 @@ "@angular/forms": "^16.2.12", "@angular/localize": "^16.2.12", "@angular/router": "^16.2.12", - "@ni/nimble-components": "^29.1.4" + "@ni/nimble-components": "^29.1.5" } }, "packages/angular-workspace/spright-angular": { "name": "@ni/spright-angular", - "version": "1.0.5", + "version": "1.0.6", "license": "MIT", "dependencies": { "tslib": "^2.2.0" @@ -33315,7 +33315,7 @@ "peerDependencies": { "@angular/common": "^16.2.12", "@angular/core": "^16.2.12", - "@ni/spright-components": "^1.0.5" + "@ni/spright-components": "^1.0.6" } }, "packages/blazor-workspace": { @@ -33400,7 +33400,7 @@ }, "packages/nimble-components": { "name": "@ni/nimble-components", - "version": "29.1.4", + "version": "29.1.5", "license": "MIT", "dependencies": { "@microsoft/fast-colors": "^5.3.1", @@ -33548,14 +33548,14 @@ }, "packages/spright-components": { "name": "@ni/spright-components", - "version": "1.0.5", + "version": "1.0.6", "license": "MIT", "dependencies": { "@microsoft/fast-colors": "^5.3.1", "@microsoft/fast-element": "^1.12.0", "@microsoft/fast-foundation": "^2.49.6", "@microsoft/fast-web-utilities": "^6.0.0", - "@ni/nimble-components": "29.1.4", + "@ni/nimble-components": "29.1.5", "@ni/nimble-tokens": "^6.13.6", "tslib": "^2.2.0" }, diff --git a/packages/angular-workspace/nimble-angular/CHANGELOG.json b/packages/angular-workspace/nimble-angular/CHANGELOG.json index 5738e20c1f..469e32e281 100644 --- a/packages/angular-workspace/nimble-angular/CHANGELOG.json +++ b/packages/angular-workspace/nimble-angular/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/nimble-angular", "entries": [ + { + "date": "Wed, 22 May 2024 18:32:15 GMT", + "version": "24.3.2", + "tag": "@ni/nimble-angular_v24.3.2", + "comments": { + "patch": [ + { + "author": "beachball", + "package": "@ni/nimble-angular", + "comment": "Bump @ni/nimble-components to v29.1.5", + "commit": "not available" + } + ] + } + }, { "date": "Tue, 21 May 2024 22:53:18 GMT", "version": "24.3.1", diff --git a/packages/angular-workspace/nimble-angular/CHANGELOG.md b/packages/angular-workspace/nimble-angular/CHANGELOG.md index c2c6ddb47f..55a9510483 100644 --- a/packages/angular-workspace/nimble-angular/CHANGELOG.md +++ b/packages/angular-workspace/nimble-angular/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/nimble-angular -This log was last generated on Tue, 21 May 2024 22:53:18 GMT and should not be manually modified. +This log was last generated on Wed, 22 May 2024 18:32:15 GMT and should not be manually modified. +## 24.3.2 + +Wed, 22 May 2024 18:32:15 GMT + +### Patches + +- Bump @ni/nimble-components to v29.1.5 + ## 24.3.1 Tue, 21 May 2024 22:53:18 GMT diff --git a/packages/angular-workspace/nimble-angular/package.json b/packages/angular-workspace/nimble-angular/package.json index fd4a05b073..3a30e24141 100644 --- a/packages/angular-workspace/nimble-angular/package.json +++ b/packages/angular-workspace/nimble-angular/package.json @@ -1,6 +1,6 @@ { "name": "@ni/nimble-angular", - "version": "24.3.1", + "version": "24.3.2", "description": "Angular components for the NI Nimble Design System", "scripts": { "invoke-publish": "npm run invoke-publish:setup && cd ../dist/nimble-angular && npm publish", @@ -32,7 +32,7 @@ "@angular/forms": "^16.2.12", "@angular/localize": "^16.2.12", "@angular/router": "^16.2.12", - "@ni/nimble-components": "^29.1.4" + "@ni/nimble-components": "^29.1.5" }, "dependencies": { "tslib": "^2.2.0" diff --git a/packages/angular-workspace/spright-angular/CHANGELOG.json b/packages/angular-workspace/spright-angular/CHANGELOG.json index 94107a9f79..777ef8a43d 100644 --- a/packages/angular-workspace/spright-angular/CHANGELOG.json +++ b/packages/angular-workspace/spright-angular/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/spright-angular", "entries": [ + { + "date": "Wed, 22 May 2024 18:32:15 GMT", + "version": "1.0.6", + "tag": "@ni/spright-angular_v1.0.6", + "comments": { + "patch": [ + { + "author": "beachball", + "package": "@ni/spright-angular", + "comment": "Bump @ni/spright-components to v1.0.6", + "commit": "not available" + } + ] + } + }, { "date": "Tue, 21 May 2024 22:53:18 GMT", "version": "1.0.5", diff --git a/packages/angular-workspace/spright-angular/CHANGELOG.md b/packages/angular-workspace/spright-angular/CHANGELOG.md index 214a429ba6..48ad0e9884 100644 --- a/packages/angular-workspace/spright-angular/CHANGELOG.md +++ b/packages/angular-workspace/spright-angular/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/spright-angular -This log was last generated on Tue, 21 May 2024 22:53:18 GMT and should not be manually modified. +This log was last generated on Wed, 22 May 2024 18:32:15 GMT and should not be manually modified. +## 1.0.6 + +Wed, 22 May 2024 18:32:15 GMT + +### Patches + +- Bump @ni/spright-components to v1.0.6 + ## 1.0.5 Tue, 21 May 2024 22:53:18 GMT diff --git a/packages/angular-workspace/spright-angular/package.json b/packages/angular-workspace/spright-angular/package.json index 4bdbb9fbc6..470abf6567 100644 --- a/packages/angular-workspace/spright-angular/package.json +++ b/packages/angular-workspace/spright-angular/package.json @@ -1,6 +1,6 @@ { "name": "@ni/spright-angular", - "version": "1.0.5", + "version": "1.0.6", "description": "Angular components for NI Spright", "scripts": { "invoke-publish": "npm run invoke-publish:setup && cd ../dist/spright-angular && npm publish", @@ -24,7 +24,7 @@ "peerDependencies": { "@angular/common": "^16.2.12", "@angular/core": "^16.2.12", - "@ni/spright-components": "^1.0.5" + "@ni/spright-components": "^1.0.6" }, "dependencies": { "tslib": "^2.2.0" diff --git a/packages/nimble-components/CHANGELOG.json b/packages/nimble-components/CHANGELOG.json index a04cbfb799..05c40131ae 100644 --- a/packages/nimble-components/CHANGELOG.json +++ b/packages/nimble-components/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/nimble-components", "entries": [ + { + "date": "Wed, 22 May 2024 18:32:15 GMT", + "version": "29.1.5", + "tag": "@ni/nimble-components_v29.1.5", + "comments": { + "patch": [ + { + "author": "7282195+m-akinc@users.noreply.github.com", + "package": "@ni/nimble-components", + "commit": "5e4882a41568361919fc96a91243fc37cd831208", + "comment": "Fix anchor focus styling" + } + ] + } + }, { "date": "Wed, 22 May 2024 17:46:25 GMT", "version": "29.1.4", diff --git a/packages/nimble-components/CHANGELOG.md b/packages/nimble-components/CHANGELOG.md index 9000fb6457..68a3a438d4 100644 --- a/packages/nimble-components/CHANGELOG.md +++ b/packages/nimble-components/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/nimble-components -This log was last generated on Tue, 21 May 2024 22:53:18 GMT and should not be manually modified. +This log was last generated on Wed, 22 May 2024 18:32:15 GMT and should not be manually modified. +## 29.1.5 + +Wed, 22 May 2024 18:32:15 GMT + +### Patches + +- Fix anchor focus styling ([ni/nimble@5e4882a](https://github.com/ni/nimble/commit/5e4882a41568361919fc96a91243fc37cd831208)) + ## 29.1.4 Tue, 21 May 2024 22:53:18 GMT diff --git a/packages/nimble-components/package.json b/packages/nimble-components/package.json index ccdeb40ca9..16694478c4 100644 --- a/packages/nimble-components/package.json +++ b/packages/nimble-components/package.json @@ -1,6 +1,6 @@ { "name": "@ni/nimble-components", - "version": "29.1.4", + "version": "29.1.5", "description": "Styled web components for the NI Nimble Design System", "scripts": { "build": "npm run generate-icons && npm run generate-workers && npm run build-components && npm run bundle-components && npm run generate-scss", diff --git a/packages/spright-components/CHANGELOG.json b/packages/spright-components/CHANGELOG.json index cec3ee95c7..43524f3379 100644 --- a/packages/spright-components/CHANGELOG.json +++ b/packages/spright-components/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/spright-components", "entries": [ + { + "date": "Wed, 22 May 2024 18:32:15 GMT", + "version": "1.0.6", + "tag": "@ni/spright-components_v1.0.6", + "comments": { + "patch": [ + { + "author": "beachball", + "package": "@ni/spright-components", + "comment": "Bump @ni/nimble-components to v29.1.5", + "commit": "not available" + } + ] + } + }, { "date": "Tue, 21 May 2024 22:53:18 GMT", "version": "1.0.5", diff --git a/packages/spright-components/CHANGELOG.md b/packages/spright-components/CHANGELOG.md index b06e390c65..d009bb41d1 100644 --- a/packages/spright-components/CHANGELOG.md +++ b/packages/spright-components/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/spright-components -This log was last generated on Tue, 21 May 2024 22:53:18 GMT and should not be manually modified. +This log was last generated on Wed, 22 May 2024 18:32:15 GMT and should not be manually modified. +## 1.0.6 + +Wed, 22 May 2024 18:32:15 GMT + +### Patches + +- Bump @ni/nimble-components to v29.1.5 + ## 1.0.5 Tue, 21 May 2024 22:53:18 GMT diff --git a/packages/spright-components/package.json b/packages/spright-components/package.json index 46b5a74e31..a7d3c47187 100644 --- a/packages/spright-components/package.json +++ b/packages/spright-components/package.json @@ -1,6 +1,6 @@ { "name": "@ni/spright-components", - "version": "1.0.5", + "version": "1.0.6", "description": "NI Spright Components", "scripts": { "build": "npm run build-components && npm run bundle-components", @@ -55,7 +55,7 @@ "@microsoft/fast-element": "^1.12.0", "@microsoft/fast-foundation": "^2.49.6", "@microsoft/fast-web-utilities": "^6.0.0", - "@ni/nimble-components": "29.1.4", + "@ni/nimble-components": "29.1.5", "@ni/nimble-tokens": "^6.13.6", "tslib": "^2.2.0" }, From 54232ae573d4aa72ad72ae7d1f8bf535c6ac5afc Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Fri, 24 May 2024 15:48:19 -0500 Subject: [PATCH 4/8] Improve API documentation for input components (#2132) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Pull Request ## ๐Ÿคจ Rationale Ongoing efforts towards #824. This PR covers input components: - select - combobox - radio group - text area - text field - number field - checkbox - switch ## ๐Ÿ‘ฉโ€๐Ÿ’ป Implementation Generally follow patterns from previous PRs like #2126 and #2117. A few interesting notes: 1. components have different behaviors regarding whether they sync their `value` property to an attribute. I documented the behavior I observed by adding a new table category for properties that don't have attributes (also used by checkbox indeterminate property). 2. not yet documenting a recommendation to use form association / CVAs instead of change events and value properties. Until I do so, the `placeholder` docs for select are outside any table category. 3. added another new table category for localizable strings. 4. not yet documenting list option API in the select and combobox stories. We (probably Meyer) are going to tackle this in a follow up after #2111. ## ๐Ÿงช Testing ## โœ… Checklist - [x] I have updated the project documentation to reflect my changes or determined no changes are needed. --------- Co-authored-by: m-akinc <7282195+m-akinc@users.noreply.github.com> --- .../storybook/src/docs/component-apis.mdx | 2 +- .../src/nimble/checkbox/checkbox.mdx | 5 ++ .../src/nimble/checkbox/checkbox.stories.ts | 32 ++++++- .../src/nimble/combobox/combobox.mdx | 5 ++ .../src/nimble/combobox/combobox.stories.ts | 58 ++++++++++-- .../base/label-user-stories-utils.ts | 6 +- .../src/nimble/number-field/number-field.mdx | 5 ++ .../number-field/number-field.stories.ts | 53 +++++++++-- .../src/nimble/radio-group/radio-group.mdx | 14 ++- .../nimble/radio-group/radio-group.stories.ts | 88 +++++++++++++++---- .../storybook/src/nimble/select/select.mdx | 5 ++ .../src/nimble/select/select.stories.ts | 70 +++++++++------ .../storybook/src/nimble/switch/switch.mdx | 5 ++ .../src/nimble/switch/switch.stories.ts | 33 ++++++- .../src/nimble/text-area/text-area.mdx | 5 ++ .../src/nimble/text-area/text-area.stories.ts | 70 +++++++++++---- .../src/nimble/text-field/text-field.mdx | 5 ++ .../nimble/text-field/text-field.stories.ts | 81 ++++++++++++++--- .../toggle-button/toggle-button.stories.ts | 3 +- packages/storybook/src/utilities/storybook.ts | 12 +++ 20 files changed, 457 insertions(+), 100 deletions(-) diff --git a/packages/storybook/src/docs/component-apis.mdx b/packages/storybook/src/docs/component-apis.mdx index ea1a7970e0..23c5727154 100644 --- a/packages/storybook/src/docs/component-apis.mdx +++ b/packages/storybook/src/docs/component-apis.mdx @@ -45,7 +45,7 @@ Or in a named slot: ## Attributes and Properties Configure components from HTML using attributes or from code using properties. Attributes and properties typically -correspond to each other one-to-one; Nimble documentation refers to the attribute name. +correspond to each other one-to-one; Nimble documentation refers to the attribute name unless otherwise specified. ### Attributes diff --git a/packages/storybook/src/nimble/checkbox/checkbox.mdx b/packages/storybook/src/nimble/checkbox/checkbox.mdx index 51ebc12fe1..f74563e147 100644 --- a/packages/storybook/src/nimble/checkbox/checkbox.mdx +++ b/packages/storybook/src/nimble/checkbox/checkbox.mdx @@ -1,6 +1,7 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import { NimbleCheckbox } from './checkbox.react'; import * as checkboxStories from './checkbox.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; @@ -8,7 +9,11 @@ import * as checkboxStories from './checkbox.stories'; Per [W3C](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/) - The dual-state checkbox is the most common type, as it allows the user to toggle between two choices: checked and not checked. <Canvas of={checkboxStories.checkbox} /> + +## API + <Controls of={checkboxStories.checkbox} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/checkbox/checkbox.stories.ts b/packages/storybook/src/nimble/checkbox/checkbox.stories.ts index 77d12fb9b0..9fc08aa0bd 100644 --- a/packages/storybook/src/nimble/checkbox/checkbox.stories.ts +++ b/packages/storybook/src/nimble/checkbox/checkbox.stories.ts @@ -2,13 +2,15 @@ import { html } from '@microsoft/fast-element'; import { withActions } from '@storybook/addon-actions/decorator'; import type { HtmlRenderer, Meta, StoryObj } from '@storybook/html'; import { checkboxTag } from '../../../../nimble-components/src/checkbox'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory, disabledDescription, slottedLabelDescription } from '../../utilities/storybook'; interface CheckboxArgs { label: string; checked: boolean; + checkedProperty: undefined; indeterminate: boolean; disabled: boolean; + change: undefined; } const metadata: Meta<CheckboxArgs> = { @@ -29,13 +31,37 @@ const metadata: Meta<CheckboxArgs> = { </${checkboxTag}> `), argTypes: { + label: { + name: 'default', + description: slottedLabelDescription({ componentName: 'checkbox' }), + table: { category: apiCategory.slots } + }, + checked: { + description: 'Whether the checkbox is initially checked. Setting this attribute after the checkbox initializes will not affect its visual state. Note that the `checked` property behaves differently than the `checked` attribute.', + table: { category: apiCategory.attributes } + }, + checkedProperty: { + name: 'checked', + description: 'Whether the checkbox is checked. Setting this property affects the checkbox visual state and interactively changing the checkbox state affects this property. Note that the `checked` property behaves differently than the `checked` attribute.', + table: { category: apiCategory.nonAttributeProperties } + }, indeterminate: { description: `Whether the checkbox is in the indeterminate (i.e. partially checked) state. Configured programmatically, not by attribute. <details> <summary>Usage details</summary> -The \`indeterminate\` state is not automatically changed when the user changes the \`checked\` state. Client applications that use \`indeterminate\` state are responsible for subscribing to the \`change\` event to respond to this situation. -</details>` +The \`indeterminate\` state is not automatically changed when the user interactively changes the checked state. Client applications that use \`indeterminate\` state are responsible for subscribing to the \`change\` event to respond to this situation. +</details>`, + table: { category: apiCategory.nonAttributeProperties } + }, + disabled: { + description: disabledDescription({ componentName: 'checkbox' }), + table: { category: apiCategory.attributes } + }, + change: { + description: 'Event emitted when the user checks or unchecks the checkbox.', + table: { category: apiCategory.events }, + control: false } }, args: { diff --git a/packages/storybook/src/nimble/combobox/combobox.mdx b/packages/storybook/src/nimble/combobox/combobox.mdx index 905f6f331a..b97c3e7a16 100644 --- a/packages/storybook/src/nimble/combobox/combobox.mdx +++ b/packages/storybook/src/nimble/combobox/combobox.mdx @@ -1,5 +1,6 @@ import { Controls, Canvas, Meta, Title, Description } from '@storybook/blocks'; import * as comboboxStories from './combobox.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; import { listOptionTag } from '../../../../nimble-components/src/list-option/'; <Meta of={comboboxStories} /> @@ -7,7 +8,11 @@ import { listOptionTag } from '../../../../nimble-components/src/list-option/'; <Description of={comboboxStories} /> <Canvas of={comboboxStories.underlineCombobox} /> + +## API + <Controls of={comboboxStories.underlineCombobox} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/combobox/combobox.stories.ts b/packages/storybook/src/nimble/combobox/combobox.stories.ts index 3cb2be4ed1..9842dce5cf 100644 --- a/packages/storybook/src/nimble/combobox/combobox.stories.ts +++ b/packages/storybook/src/nimble/combobox/combobox.stories.ts @@ -10,8 +10,16 @@ import { DropdownPosition } from '../../../../nimble-components/src/patterns/dropdown/types'; import { + apiCategory, + appearanceDescription, createUserSelectedThemeStory, - disableStorybookZoomTransform + disableStorybookZoomTransform, + disabledDescription, + dropdownPositionDescription, + errorTextDescription, + errorVisibleDescription, + optionsDescription, + placeholderDescription } from '../../utilities/storybook'; interface ComboboxArgs { @@ -24,6 +32,8 @@ interface ComboboxArgs { currentValue: string; appearance: string; placeholder: string; + change: undefined; + input: undefined; } interface OptionArgs { @@ -117,22 +127,43 @@ const metadata: Meta<ComboboxArgs> = { description: `- inline: Automatically matches the first option that matches the start of the entered text. - list: Filters the dropdown to options that start with the entered text. - both: Automatically matches and filters list to options that start with the entered text. -- none: No autocomplete (default).` +- none: No autocomplete (default).`, + table: { category: apiCategory.attributes } }, dropDownPosition: { + name: 'position', options: [DropdownPosition.above, DropdownPosition.below], - control: { type: 'select' } + control: { type: 'select' }, + description: dropdownPositionDescription({ componentName: 'combobox' }), + table: { category: apiCategory.attributes } }, appearance: { options: Object.values(DropdownAppearance), - control: { type: 'radio' } + control: { type: 'radio' }, + description: appearanceDescription({ componentName: 'combobox' }), + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'combobox' }), + table: { category: apiCategory.attributes } }, errorText: { - description: - 'A message to be displayed when the text field is in the invalid state explaining why the value is invalid' + name: 'error-text', + description: errorTextDescription, + table: { category: apiCategory.attributes } + }, + errorVisible: { + name: 'error-visible', + description: errorVisibleDescription, + table: { category: apiCategory.attributes } + }, + placeholder: { + description: placeholderDescription({ componentName: 'combobox' }), + table: { category: apiCategory.attributes } }, optionsType: { - name: 'options', + name: 'default', + description: optionsDescription, options: Object.values(ExampleOptionsType), control: { type: 'radio', @@ -141,7 +172,18 @@ const metadata: Meta<ComboboxArgs> = { [ExampleOptionsType.wideOptions]: 'Wide options', [ExampleOptionsType.manyOptions]: 'Many options' } - } + }, + table: { category: apiCategory.slots } + }, + change: { + description: 'Emitted when the user changes the selected option, either by selecting an item from the dropdown or by committing a typed value.', + table: { category: apiCategory.events }, + control: false + }, + input: { + description: 'Emitted when the user types in the combobox. Use this event if you need to update the list of options based on the text input.', + table: { category: apiCategory.events }, + control: false } }, args: { diff --git a/packages/storybook/src/nimble/label-provider/base/label-user-stories-utils.ts b/packages/storybook/src/nimble/label-provider/base/label-user-stories-utils.ts index c8910e30f6..11fe9458e6 100644 --- a/packages/storybook/src/nimble/label-provider/base/label-user-stories-utils.ts +++ b/packages/storybook/src/nimble/label-provider/base/label-user-stories-utils.ts @@ -1,5 +1,6 @@ import type { Meta } from '@storybook/html'; import type { DesignToken } from '@microsoft/fast-foundation'; +import { apiCategory } from '../../../utilities/storybook'; export interface LabelUserArgs { usedLabels: null; @@ -26,8 +27,9 @@ export function addLabelUseMetadata<TArgs extends LabelUserArgs>( description: `Label Provider:\`${labelProviderTag}\` ${tokenContent} -See the "Tokens/Label Providers" docs page for more information. +See the [Tokens/Label Providers docs page](./?path=/docs/tokens-label-providers--docs) for more information. `, - control: false + control: false, + table: { category: apiCategory.localizableLabels } }; } diff --git a/packages/storybook/src/nimble/number-field/number-field.mdx b/packages/storybook/src/nimble/number-field/number-field.mdx index 36afea60a9..9cd985ff36 100644 --- a/packages/storybook/src/nimble/number-field/number-field.mdx +++ b/packages/storybook/src/nimble/number-field/number-field.mdx @@ -1,6 +1,7 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import { NimbleNumberField } from './number-field.react'; import * as numberFieldStories from './number-field.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; <Meta of={numberFieldStories} /> <Title of={numberFieldStories} /> @@ -8,7 +9,11 @@ import * as numberFieldStories from './number-field.stories'; Similar to a single line text box but only used for numeric data. The controls allow the user to increment and decrement the value. <Canvas of={numberFieldStories.underlineNumberField} /> + +## API + <Controls of={numberFieldStories.underlineNumberField} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/number-field/number-field.stories.ts b/packages/storybook/src/nimble/number-field/number-field.stories.ts index 0a7f83867e..c6c9e43444 100644 --- a/packages/storybook/src/nimble/number-field/number-field.stories.ts +++ b/packages/storybook/src/nimble/number-field/number-field.stories.ts @@ -12,7 +12,7 @@ import { addLabelUseMetadata, type LabelUserArgs } from '../label-provider/base/label-user-stories-utils'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, appearanceDescription, createUserSelectedThemeStory, disabledDescription, errorTextDescription, errorVisibleDescription, slottedLabelDescription } from '../../utilities/storybook'; interface NumberFieldArgs extends LabelUserArgs { label: string; @@ -25,6 +25,8 @@ interface NumberFieldArgs extends LabelUserArgs { disabled: boolean; errorVisible: boolean; errorText: string; + change: undefined; + input: undefined; } const metadata: Meta<NumberFieldArgs> = { @@ -52,30 +54,63 @@ const metadata: Meta<NumberFieldArgs> = { </${numberFieldTag}> `), argTypes: { + label: { + name: 'default', + description: `${slottedLabelDescription({ componentName: 'number field' })}`, + table: { category: apiCategory.slots } + }, + value: { + description: 'The number displayed in the number field. Note that the property value is not synced to an attribute.', + table: { category: apiCategory.nonAttributeProperties } + }, appearance: { options: Object.values(NumberFieldAppearance), - control: { type: 'radio' } + control: { type: 'radio' }, + description: appearanceDescription({ componentName: 'number field' }), + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'number field' }), + table: { category: apiCategory.attributes } }, step: { description: - 'The amount to increase or decrease the value when a step button is pressed.' + 'The amount to increase or decrease the value when a step button is pressed.', + table: { category: apiCategory.attributes } }, hideStep: { name: 'hide-step', description: - 'Configures the visibility of the increment and decrement step buttons. Consider hiding the buttons if the input values will commonly have varied levels of precision (for example both integers and decimal numbers).' + 'Configures the visibility of the increment and decrement step buttons. Consider hiding the buttons if the input values will commonly have varied levels of precision (for example both integers and decimal numbers).', + table: { category: apiCategory.attributes } }, min: { - description: 'The minimum value that can be set.' + description: 'The minimum value that can be set.', + table: { category: apiCategory.attributes } }, max: { - description: 'The maximum value that can be set.' + description: 'The maximum value that can be set.', + table: { category: apiCategory.attributes } + }, + errorVisible: { + name: 'error-visible', + description: errorVisibleDescription, + table: { category: apiCategory.attributes } }, errorText: { - name: 'error-text' + name: 'error-text', + description: errorTextDescription, + table: { category: apiCategory.attributes } }, - errorVisible: { - name: 'error-visible' + change: { + description: 'Event emitted when the user commits a new value to the number field.', + table: { category: apiCategory.events }, + control: false + }, + input: { + description: 'Event emitted on each user keystroke within the number field.', + table: { category: apiCategory.events }, + control: false } }, args: { diff --git a/packages/storybook/src/nimble/radio-group/radio-group.mdx b/packages/storybook/src/nimble/radio-group/radio-group.mdx index 544a458456..4757996328 100644 --- a/packages/storybook/src/nimble/radio-group/radio-group.mdx +++ b/packages/storybook/src/nimble/radio-group/radio-group.mdx @@ -1,5 +1,6 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import * as radioGroupStories from './radio-group.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; <Meta of={radioGroupStories} /> <Title of={radioGroupStories} /> @@ -7,7 +8,16 @@ import * as radioGroupStories from './radio-group.stories'; Per [W3C](https://www.w3.org/WAI/ARIA/apg/patterns/radio/) - A radio group is a set of checkable buttons, known as radio buttons, where no more than one of the buttons can be checked at a time. Some implementations may initialize the set with all buttons in the unchecked state in order to force the user to check one of the buttons before moving past a certain point in the workflow. <Canvas of={radioGroupStories.radioGroup} /> + +## API + <Controls of={radioGroupStories.radioGroup} /> +<ComponentApisLink /> + +### Radio + +<Canvas of={radioGroupStories.radio} /> +<Controls of={radioGroupStories.radio} /> {/* ## Styling */} @@ -17,7 +27,9 @@ Per [W3C](https://www.w3.org/WAI/ARIA/apg/patterns/radio/) - A radio group is a ### Angular Usage -The Angular CVA for the radio button group ignores the value of `callSetDisabledState` configured on the form module. +When using radio buttons in an Angular form, you must explicitly set either `name` or `formControlName` on each radio button. In that scenario, setting `name` on the group is ineffective. + +The Angular control value accessor for the radio button group ignores the value of `callSetDisabledState` configured on the form module. Instead, it always uses the default value of `'always'`. {/* ## Accessibility */} diff --git a/packages/storybook/src/nimble/radio-group/radio-group.stories.ts b/packages/storybook/src/nimble/radio-group/radio-group.stories.ts index ee53aefbd3..8fa5a613cf 100644 --- a/packages/storybook/src/nimble/radio-group/radio-group.stories.ts +++ b/packages/storybook/src/nimble/radio-group/radio-group.stories.ts @@ -4,7 +4,7 @@ import { withActions } from '@storybook/addon-actions/decorator'; import type { HtmlRenderer, Meta, StoryObj } from '@storybook/html'; import { radioTag } from '../../../../nimble-components/src/radio'; import { radioGroupTag } from '../../../../nimble-components/src/radio-group'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory, disabledDescription, slottedLabelDescription } from '../../utilities/storybook'; interface RadioGroupArgs { label: string; @@ -12,10 +12,26 @@ interface RadioGroupArgs { disabled: boolean; name: string; value: string; + buttons: undefined; + change: undefined; +} + +interface RadioArgs { + label: string; + value: string; + disabled: boolean; + name: string; } const metadata: Meta<RadioGroupArgs> = { title: 'Components/Radio Group', +}; + +export default metadata; + +const nameDescription = 'Radio buttons whose values are mutually exclusive should set the same `name` attribute. Setting the name on the group sets it on all child radio buttons. When using radio buttons in an Angular form, you must explicitly set either `name` or `formControlName` on each radio button. In that scenario, setting `name` on the group is ineffective.'; + +export const radioGroup: StoryObj<RadioGroupArgs> = { decorators: [withActions<HtmlRenderer>], parameters: { actions: { @@ -47,32 +63,72 @@ const metadata: Meta<RadioGroupArgs> = { options: ['none', 'apple', 'mango', 'orange'], control: { type: 'radio' - } + }, + description: 'The currently selected radio button. Each button should specify its unique value using its `value` attribute.', + table: { category: apiCategory.attributes } }, label: { description: - 'You must provide a `label` element with `slot="label"` as content of the `nimble-radio-group`.' + 'A `label` element containing text that describes the group of options.', + table: { category: apiCategory.slots } }, orientation: { options: Object.values(Orientation), control: { - type: 'radio', - labels: { - [Orientation.horizontal]: 'Horizontal', - [Orientation.vertical]: 'Vertical' - } + type: 'radio' }, - table: { - defaultValue: { summary: 'Horizontal' } - } + description: 'The orientation of the radio buttons.', + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'radio group' }), + table: { category: apiCategory.attributes } }, name: { - description: - 'Radio buttons whose values are mutually exclusive should set the same `name` attribute. Setting the name on the group sets it on all child radio buttons. When using radio buttons in an Angular form, you must explicitly set either `name` or `formControlName` on each radio button. In that scenario, setting `name` on the group is ineffective.' + description: nameDescription, + table: { category: apiCategory.attributes } + }, + buttons: { + name: 'default', + description: `The \`${radioTag}\` elements to display in the group.`, + control: false, + table: { category: apiCategory.slots } + }, + change: { + description: 'Event emitted when the user selects a new value in the radio group.', + table: { category: apiCategory.events }, + control: false } } }; -export default metadata; - -export const radioGroup: StoryObj<RadioGroupArgs> = {}; +export const radio: StoryObj<RadioArgs> = { + render: createUserSelectedThemeStory(html` + <${radioTag} value="${x => x.value}" ?disabled="${x => x.disabled}">${x => x.label}</${radioTag}> + `), + args: { + disabled: false, + name: 'fruit', + label: 'Apple', + value: 'none' + }, + argTypes: { + value: { + control: false, + description: 'The value of the radio button. Used by the radio group `value` attribute to determine the selected radio button.', + table: { category: apiCategory.attributes } + }, + label: { + description: slottedLabelDescription({ componentName: 'radio button' }), + table: { category: apiCategory.slots } + }, + disabled: { + description: disabledDescription({ componentName: 'radio button' }), + table: { category: apiCategory.attributes } + }, + name: { + description: nameDescription, + table: { category: apiCategory.attributes } + }, + } +}; diff --git a/packages/storybook/src/nimble/select/select.mdx b/packages/storybook/src/nimble/select/select.mdx index 7cc9b5e2c2..cbcffab33e 100644 --- a/packages/storybook/src/nimble/select/select.mdx +++ b/packages/storybook/src/nimble/select/select.mdx @@ -1,6 +1,7 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import { NimbleSelect } from './select.react'; import * as selectStories from './select.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; import { listOptionTag } from '../../../../nimble-components/src/list-option'; <Meta of={selectStories} /> @@ -9,7 +10,11 @@ import { listOptionTag } from '../../../../nimble-components/src/list-option'; Select is a control for selecting amongst a set of options. Its value comes from the `value` of the currently selected <Tag name={listOptionTag}/>, or, if no value exists for that option, the option's content. Upon clicking on the element, the other options are visible. <Canvas of={selectStories.underlineSelect} /> + +## API + <Controls of={selectStories.underlineSelect} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/select/select.stories.ts b/packages/storybook/src/nimble/select/select.stories.ts index edaf4264d9..eea0bfb5df 100644 --- a/packages/storybook/src/nimble/select/select.stories.ts +++ b/packages/storybook/src/nimble/select/select.stories.ts @@ -8,8 +8,15 @@ import { ExampleOptionsType } from '../../../../nimble-components/src/select/tes import { DropdownAppearance } from '../../../../nimble-components/src/patterns/dropdown/types'; import { + apiCategory, + appearanceDescription, createUserSelectedThemeStory, - disableStorybookZoomTransform + disableStorybookZoomTransform, + disabledDescription, + dropdownPositionDescription, + errorTextDescription, + errorVisibleDescription, + optionsDescription } from '../../utilities/storybook'; interface SelectArgs { @@ -22,6 +29,7 @@ interface SelectArgs { filterMode: keyof typeof FilterMode; placeholder: boolean; clearable: boolean; + change: undefined; } interface OptionArgs { @@ -67,32 +75,20 @@ const optionSets = { [ExampleOptionsType.manyOptions]: manyOptions } as const; -const dropdownPositionDescription = ` -The \`dropDownPosition\` attribute controls the position of the dropdown relative to the \`Select\`. The default is \`below\`, which will display the dropdown below the \`Select\`. The \`above\` setting will display the dropdown above the \`Select\`. -`; - -const appearanceDescription = ` -This attribute affects the appearance of the \`Select\`. The default appearance is \`underline\`, which displays a line beneath the selected value. The \`outline\` appearance displays a border around the entire component. The \`block\` appearance applies a background for the entire component. -`; - -const errorTextDescription = ` -A message to be displayed when the text field is in the invalid state explaining why the value is invalid. -`; - const filterModeDescription = ` -This attribute controls the filtering behavior of the \`Select\`. The default of \`none\` results in a dropdown with no input for filtering. A non-'none' setting results in a search input placed at the top or the bottom of the dropdown when opened (depending on where the popup is shown relative to the component). The \`standard\` setting will perform a case-insensitive and diacritic-insensitive filtering of the available options anywhere within the text of each option. +Controls the filtering behavior of the select. The default of \`none\` results in a dropdown with no input for filtering. A non-'none' setting results in a search input placed at the top or the bottom of the dropdown when opened (depending on where the dropdown is shown relative to the component). The \`standard\` setting will perform a case-insensitive and diacritic-insensitive filtering of the available options anywhere within the text of each option. -It is recommended that if the \`Select\` has 15 or fewer options that you use the \`none\` setting for the \`filter-mode\`. +It is recommended that if the select has 15 or fewer options that you use the \`none\` setting for the \`filter-mode\`. `; const placeholderDescription = ` -To display placeholder text within the \`Select\` you must provide an option that has the \`disabled\`, \`selected\` and \`hidden\` attributes set. This option will not be available in the dropdown, and its contents will be used as the placeholder text. Note that giving the placeholder an initial \`selected\` state is only necessary to display the placeholder initially. If another option is selected initially the placeholder will be displayed upon clearing the current value. +To display placeholder text within the select you must provide an option that has the \`disabled\`, \`selected\` and \`hidden\` attributes set. This option will not be available in the dropdown, and its contents will be used as the placeholder text. Note that giving the placeholder an initial \`selected\` state is only necessary to display the placeholder initially. If another option is selected initially the placeholder will be displayed upon clearing the current value. -Any \`Select\` without a default selected option should provide placeholder text. Placeholder text should always follow the pattern "Select [thing(s)]", for example "Select country". Use sentence casing and don't include punctuation at the end of the prompt. +Any select without a default selected option should provide placeholder text. Placeholder text should always follow the pattern "Select [thing(s)]", for example "Select country". Use sentence casing and don't include punctuation at the end of the prompt. `; const clearableDescription = ` -When the \`clearable\` attribute is set, a clear button will be displayed in the \`Select\` when a value is selected. Clicking the clear button will clear the selected value and display the placeholder text, if available, or will result in a blank display. +When the \`clearable\` attribute is set, a clear button will be displayed in the select when a value is selected. Clicking the clear button will clear the selected value and display the placeholder text, if available, or will result in a blank display. `; const metadata: Meta<SelectArgs> = { @@ -139,38 +135,52 @@ const metadata: Meta<SelectArgs> = { `), argTypes: { dropDownPosition: { + name: 'position', options: ['above', 'below'], control: { type: 'select' }, - description: dropdownPositionDescription + description: dropdownPositionDescription({ componentName: 'select' }), + table: { category: apiCategory.attributes } }, appearance: { options: Object.values(DropdownAppearance), control: { type: 'radio' }, - description: appearanceDescription + description: appearanceDescription({ componentName: 'select' }), + table: { category: apiCategory.attributes } }, filterMode: { options: Object.keys(FilterMode), control: { type: 'radio' }, name: 'filter-mode', - description: filterModeDescription + description: filterModeDescription, + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'select' }), + table: { category: apiCategory.attributes } }, errorText: { name: 'error-text', - description: errorTextDescription + description: errorTextDescription, + table: { category: apiCategory.attributes } }, errorVisible: { - name: 'error-visible' + name: 'error-visible', + description: errorVisibleDescription, + table: { category: apiCategory.attributes } }, placeholder: { name: 'placeholder', - description: placeholderDescription + description: placeholderDescription, + // TODO: move this to a list-option story or create a table category to indicate there isn't a single 'placeholder' attribute }, clearable: { name: 'clearable', - description: clearableDescription + description: clearableDescription, + table: { category: apiCategory.attributes } }, optionsType: { - name: 'options', + name: 'default', + description: optionsDescription, options: Object.values(ExampleOptionsType), control: { type: 'radio', @@ -179,7 +189,13 @@ const metadata: Meta<SelectArgs> = { [ExampleOptionsType.manyOptions]: 'Many options', [ExampleOptionsType.wideOptions]: 'Wide options' } - } + }, + table: { category: apiCategory.slots } + }, + change: { + description: 'Emitted when the user changes the selected option.', + table: { category: apiCategory.events }, + control: false } }, args: { diff --git a/packages/storybook/src/nimble/switch/switch.mdx b/packages/storybook/src/nimble/switch/switch.mdx index 4a7c671fe0..1b7cbea2d9 100644 --- a/packages/storybook/src/nimble/switch/switch.mdx +++ b/packages/storybook/src/nimble/switch/switch.mdx @@ -1,6 +1,7 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import { NimbleSwitch } from './switch.react'; import * as switchStories from './switch.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; <Meta of={switchStories} /> <Title of={switchStories} /> @@ -13,7 +14,11 @@ be checked or not checked and can optionally also allow for a partially checked pressed or not pressed and can optionally allow for a partially pressed state. <Canvas of={switchStories.switchStory} /> + +## API + <Controls of={switchStories.switchStory} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/switch/switch.stories.ts b/packages/storybook/src/nimble/switch/switch.stories.ts index 1b183b32da..6c034fbae0 100644 --- a/packages/storybook/src/nimble/switch/switch.stories.ts +++ b/packages/storybook/src/nimble/switch/switch.stories.ts @@ -2,7 +2,7 @@ import { html, when } from '@microsoft/fast-element'; import { withActions } from '@storybook/addon-actions/decorator'; import type { HtmlRenderer, Meta, StoryObj } from '@storybook/html'; import { switchTag } from '../../../../nimble-components/src/switch'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory, disabledDescription, slottedLabelDescription } from '../../utilities/storybook'; interface SwitchArgs { label: string; @@ -10,6 +10,7 @@ interface SwitchArgs { disabled: boolean; checkedMessage: string; uncheckedMessage: string; + change: undefined; } const metadata: Meta<SwitchArgs> = { @@ -31,6 +32,36 @@ const metadata: Meta<SwitchArgs> = { ${when(x => x.uncheckedMessage, html<SwitchArgs>`<span slot="unchecked-message">${x => x.uncheckedMessage}</span>`)} </${switchTag}> `), + argTypes: { + label: { + name: 'default', + description: `${slottedLabelDescription({ componentName: 'switch' })}`, + table: { category: apiCategory.slots } + }, + checked: { + description: 'Whether the switch is toggled on.', + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'switch' }), + table: { category: apiCategory.attributes } + }, + checkedMessage: { + name: 'checked-message', + description: 'A `span` element containing the message to display when the switch is toggled on.', + table: { category: apiCategory.slots } + }, + uncheckedMessage: { + name: 'unchecked-message', + description: 'A `span` element containing the message to display when the switch is toggled off.', + table: { category: apiCategory.slots } + }, + change: { + description: 'Event emitted when the user toggles the switch.', + table: { category: apiCategory.events }, + control: false + } + }, args: { label: 'Switch', checked: true, diff --git a/packages/storybook/src/nimble/text-area/text-area.mdx b/packages/storybook/src/nimble/text-area/text-area.mdx index 5dff1d0092..95f8412d35 100644 --- a/packages/storybook/src/nimble/text-area/text-area.mdx +++ b/packages/storybook/src/nimble/text-area/text-area.mdx @@ -1,6 +1,7 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import { NimbleTextArea } from './text-area.react'; import * as textAreaStories from './text-area.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; <Meta of={textAreaStories} /> <Title of={textAreaStories} /> @@ -10,7 +11,11 @@ A multi-line text input control. The text area is often used in a form to collec If you configure your text area to be resizable (with the `resize` attribute) in a certain dimension, do not set an explicit size for that dimension (via `height` and/or `width` `style` properties), or you may experience unexpected resize behavior. If you want to set the initial size of a resizable text area, use the `rows` and/or `cols` attribute(s). <Canvas of={textAreaStories.outlineTextArea} /> + +## API + <Controls of={textAreaStories.outlineTextArea} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/text-area/text-area.stories.ts b/packages/storybook/src/nimble/text-area/text-area.stories.ts index 1acc8e8625..16736c3873 100644 --- a/packages/storybook/src/nimble/text-area/text-area.stories.ts +++ b/packages/storybook/src/nimble/text-area/text-area.stories.ts @@ -3,7 +3,7 @@ import { withActions } from '@storybook/addon-actions/decorator'; import type { HtmlRenderer, Meta, StoryObj } from '@storybook/html'; import { textAreaTag } from '../../../../nimble-components/src/text-area'; import { TextAreaAppearance, TextAreaResize } from '../../../../nimble-components/src/text-area/types'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, appearanceDescription, createUserSelectedThemeStory, disabledDescription, errorTextDescription, errorVisibleDescription, placeholderDescription, slottedLabelDescription } from '../../utilities/storybook'; import { loremIpsum } from '../../utilities/lorem-ipsum'; interface TextAreaArgs { @@ -20,6 +20,7 @@ interface TextAreaArgs { rows: number; cols: number; maxlength: number; + change: undefined; } const metadata: Meta<TextAreaArgs> = { @@ -52,40 +53,71 @@ const metadata: Meta<TextAreaArgs> = { appearance: { options: Object.values(TextAreaAppearance), control: { type: 'radio' }, - table: { - defaultValue: { summary: 'outline' } - } + description: appearanceDescription({ componentName: 'text area' }), + table: { category: apiCategory.attributes } + }, + label: { + name: 'default', + description: `${slottedLabelDescription({ componentName: 'text area' })}`, + table: { category: apiCategory.slots } + }, + placeholder: { + description: placeholderDescription({ componentName: 'text area' }), + table: { category: apiCategory.attributes } + }, + value: { + description: 'The string displayed in the text area. Note that the property value is not synced to an attribute.', + table: { category: apiCategory.nonAttributeProperties } + }, + readonly: { + description: 'Disallows input on the text area while maintaining enabled appearance.', + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'text area' }), + table: { category: apiCategory.attributes } + }, + errorText: { + name: 'error-text', + description: errorTextDescription, + table: { category: apiCategory.attributes } + }, + errorVisible: { + name: 'error-visible', + description: errorVisibleDescription, + table: { category: apiCategory.attributes } + }, + spellcheck: { + description: 'Specifies whether the text area is subject to spell checking by the underlying browser/OS.', + table: { category: apiCategory.attributes } }, resize: { description: 'Direction(s) the text area is sizeable by the user. Setting a fixed `height` and `width` on the text area is not supported while it is sizeable. You may instead use `rows` and `cols` to set an initial size.', options: Object.values(TextAreaResize), control: { type: 'select' }, - table: { - defaultValue: { summary: 'none' } - } + table: { category: apiCategory.attributes } + }, rows: { - description: 'Number of visible rows of text.' + description: 'Number of visible rows of text.', + table: { category: apiCategory.attributes } }, cols: { description: 'Visible width of the text, in average character widths', - table: { - defaultValue: { summary: '20' } - } + table: { category: apiCategory.attributes } + }, maxlength: { description: - 'Maximum number of characters that may be entered by the user' - }, - errorVisible: { - description: - 'Whether the text area should be styled to indicate that it is in an invalid state' + 'Maximum number of characters that may be entered by the user', + table: { category: apiCategory.attributes } }, - errorText: { - description: - 'A message to be displayed when the text area is in the invalid state explaining why the value is invalid' + change: { + description: 'Event emitted when the user commits a new value to the text area.', + table: { category: apiCategory.events }, + control: false } }, args: { diff --git a/packages/storybook/src/nimble/text-field/text-field.mdx b/packages/storybook/src/nimble/text-field/text-field.mdx index 3a0ca2a25c..658158cafc 100644 --- a/packages/storybook/src/nimble/text-field/text-field.mdx +++ b/packages/storybook/src/nimble/text-field/text-field.mdx @@ -1,6 +1,7 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import { NimbleTextField } from './text-field.react'; import * as textFieldStories from './text-field.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; <Meta of={textFieldStories} /> <Title of={textFieldStories} /> @@ -8,7 +9,11 @@ import * as textFieldStories from './text-field.stories'; A single-line text field. <Canvas of={textFieldStories.underlineTextField} /> + +## API + <Controls of={textFieldStories.underlineTextField} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/text-field/text-field.stories.ts b/packages/storybook/src/nimble/text-field/text-field.stories.ts index b0d2211939..893f2530ff 100644 --- a/packages/storybook/src/nimble/text-field/text-field.stories.ts +++ b/packages/storybook/src/nimble/text-field/text-field.stories.ts @@ -6,25 +6,29 @@ import { iconPencilTag } from '../../../../nimble-components/src/icons/pencil'; import { iconTagTag } from '../../../../nimble-components/src/icons/tag'; import { textFieldTag } from '../../../../nimble-components/src/text-field'; import { TextFieldAppearance, TextFieldType } from '../../../../nimble-components/src/text-field/types'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, appearanceDescription, createUserSelectedThemeStory, disabledDescription, errorTextDescription, errorVisibleDescription, placeholderDescription, slottedLabelDescription } from '../../utilities/storybook'; interface TextFieldArgs { label: string; + placeholder: string; type: TextFieldType; appearance: string; fullBleed: boolean; value: string; + valueAttribute: string; readonly: boolean; disabled: boolean; errorVisible: boolean; errorText: string; actionButton: boolean; leftIcon: boolean; + change: undefined; + input: undefined; } -const leftIconDescription = 'To place an icon at the far-left of the text-field, set `slot="start"` on the icon.'; +const leftIconDescription = 'An icon to display at the start of the text field.'; -const actionButtonDescription = `To place content such as a button at the far-right of the text-field, set \`slot="actions"\` on the content. +const actionButtonDescription = `Content such as a button at the end of the text field. Note: The content in the \`actions\` slot will not adjust based on the state of the text-field (e.g. disabled or readonly). It is the responsibility of the consuming application to make any necessary adjustments. For example, if the buttons should be disabled when the text-field is disabled, the @@ -42,10 +46,10 @@ const metadata: Meta<TextFieldArgs> = { // prettier-ignore render: createUserSelectedThemeStory(html` <${textFieldTag} - placeholder="${x => x.label}" + placeholder="${x => x.placeholder}" + :value="${x => x.value}" type="${x => x.type}" appearance="${x => x.appearance}" - value="${x => x.value}" ?readonly="${x => x.readonly}" ?disabled="${x => x.disabled}" error-text="${x => x.errorText}" @@ -65,31 +69,84 @@ const metadata: Meta<TextFieldArgs> = { </${textFieldTag}> `), argTypes: { + label: { + name: 'default', + description: `${slottedLabelDescription({ componentName: 'text field' })}`, + table: { category: apiCategory.slots } + }, + placeholder: { + description: placeholderDescription({ componentName: 'text field' }), + table: { category: apiCategory.attributes } + }, type: { options: Object.values(TextFieldType), - control: { type: 'select' } + control: { type: 'radio' }, + description: 'They type of input to accept and render in the text field. This corresponds to [the `type` attribute of the native `input` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#type) though only a subset of values are supported.', + table: { category: apiCategory.attributes } }, appearance: { options: Object.values(TextFieldAppearance), - control: { type: 'radio' } + control: { type: 'radio' }, + description: appearanceDescription({ componentName: 'text field' }), + table: { category: apiCategory.attributes } }, fullBleed: { + name: 'full-bleed', description: - 'Remove the start and end margins causing the text to stretch across the full control width. Only applies to the frameless appearance.' + 'Remove the start and end margins causing the text to stretch across the full control width. Only applies to the frameless appearance.', + table: { category: apiCategory.attributes } + }, + value: { + description: 'The string displayed in the text field. Note that the property and attribute behave differently.', + table: { category: apiCategory.nonAttributeProperties } + }, + valueAttribute: { + name: 'value', + description: 'The initial string displayed in the text field. Changing this after the text field initializes has no effect. Note that the property behave differently.', + table: { category: apiCategory.attributes } + }, + readonly: { + description: 'Disallows input on the text field while maintaining enabled appearance.', + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'text field' }), + table: { category: apiCategory.attributes } + }, + errorVisible: { + name: 'error-visible', + description: errorVisibleDescription, + table: { category: apiCategory.attributes } }, errorText: { - description: - 'A message to be displayed when the text field is in the invalid state explaining why the value is invalid' + name: 'error-text', + description: errorTextDescription, + table: { category: apiCategory.attributes } }, actionButton: { - description: actionButtonDescription + name: 'actions', + description: actionButtonDescription, + table: { category: apiCategory.slots } }, leftIcon: { - description: leftIconDescription + name: 'start', + description: leftIconDescription, + table: { category: apiCategory.slots } + }, + change: { + description: 'Event emitted when the user commits a new value to the text field.', + table: { category: apiCategory.events }, + control: false + }, + input: { + description: 'Event emitted on each user keystroke within the text field.', + table: { category: apiCategory.events }, + control: false } }, args: { label: 'default label', + placeholder: 'Enter text...', type: TextFieldType.text, appearance: 'underline', fullBleed: false, diff --git a/packages/storybook/src/nimble/toggle-button/toggle-button.stories.ts b/packages/storybook/src/nimble/toggle-button/toggle-button.stories.ts index e57d15a8e3..64ca61d926 100644 --- a/packages/storybook/src/nimble/toggle-button/toggle-button.stories.ts +++ b/packages/storybook/src/nimble/toggle-button/toggle-button.stories.ts @@ -83,7 +83,8 @@ const metadata: Meta<ToggleButtonArgs> = { }, change: { description: 'Fires when the toggle button is pressed via mouse or keyboard.', - table: { category: apiCategory.events } + table: { category: apiCategory.events }, + control: false } }, // prettier-ignore diff --git a/packages/storybook/src/utilities/storybook.ts b/packages/storybook/src/utilities/storybook.ts index 0bff54dabb..5e94feaff8 100644 --- a/packages/storybook/src/utilities/storybook.ts +++ b/packages/storybook/src/utilities/storybook.ts @@ -2,6 +2,7 @@ import { html, ViewTemplate } from '@microsoft/fast-element'; import { themeProviderTag } from '../../../nimble-components/src/theme-provider'; import { bodyFont } from '../../../nimble-components/src/theme-provider/design-tokens'; import type { Theme } from '../../../nimble-components/src/theme-provider/types'; +import { listOptionTag } from '../../../nimble-components/src/list-option'; import { BackgroundState, backgroundStates, @@ -165,10 +166,21 @@ export const disableStorybookZoomTransform = ` export const apiCategory = { attributes: 'Attributes', events: 'Events', + localizableLabels: 'Localizable Labels', methods: 'Methods', + nonAttributeProperties: 'Properties', slots: 'Slots' } as const; +export const appearanceDescription = (options: { componentName: string }): string => `This attribute affects the appearance of the ${options.componentName}.`; export const iconDescription = 'Set `slot="start"` to include an icon before the text content.'; export const disabledDescription = (options: { componentName: string }): string => `Styles the ${options.componentName} as disabled and prevents focus and user interaction.`; +export const slottedLabelDescription = (options: { componentName: string }): string => `Label text to display adjacent to the ${options.componentName} describing its purpose to the user.`; export const textContentDescription = (options: { componentName: string }): string => `The text content of the ${options.componentName}.`; +export const placeholderDescription = (options: { componentName: string }): string => `Placeholder text to display when no value has been entered in the ${options.componentName}.`; + +export const errorTextDescription = 'A message to be displayed explaining why the value is invalid. Only visible when `error-visible` is set.'; +export const errorVisibleDescription = 'When set to `true`, the `error-text` message will be displayed.'; + +export const dropdownPositionDescription = (options: { componentName: string }): string => `Controls the position of the dropdown relative to the ${options.componentName}.`; +export const optionsDescription = `The \`${listOptionTag}\` items for the user to select from.`; From 2855db4fe58a8d1df112ea656215696d9582f9ea Mon Sep 17 00:00:00 2001 From: mollykreis <20542556+mollykreis@users.noreply.github.com> Date: Tue, 28 May 2024 14:58:07 -0500 Subject: [PATCH 5/8] Update banner button styles (#2130) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Pull Request ## ๐Ÿคจ Rationale The "dismiss" button in the `nimble-banner` had the wrong styling in the following ways: - It was the wrong size. It was 16x16, but it should have been 24x24. - It was using the wrong icon. It was using the `xmark` icon, but it should have been using the `times` icon. - The hover styling was wrong. It had custom styling to make it look like a ghost button with a fill on hover (not like any of our standard `nimble-button` appearance modes). Instead, it should be a standard `content-hidden`, `appearance="ghost"`, `appearance-variant="primary"` button. Note: A number of these differences were because the design spec was updated after the banner was initially implemented. ## ๐Ÿ‘ฉโ€๐Ÿ’ป Implementation 1. Wrapped the contents of the banner's template in a theme provider hard-coded to the `color` theme 2. Updated storybook docs to specify that a slotted `action` button should use the `primary` appearance variant 3. Updated instances of the banner within nimble to set `appearance-variant="primary"` on slotted buttons Those three changes allowed me to remove a lot of custom styling from the banner. ## ๐Ÿงช Testing - Verified that the only chromatic change was due to the "dismiss" button ## โœ… 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). --> - [ ] I have updated the project documentation to reflect my changes or determined no changes are needed. --- ...-db9e952a-a79d-4aa2-a8e9-b3455ee2b620.json | 7 ++ .../nimble-components/src/banner/styles.ts | 56 ++-------- .../nimble-components/src/banner/template.ts | 101 +++++++++--------- .../nimble/banner/banner-matrix.stories.ts | 3 +- .../src/nimble/banner/banner.stories.ts | 12 ++- 5 files changed, 75 insertions(+), 104 deletions(-) create mode 100644 change/@ni-nimble-components-db9e952a-a79d-4aa2-a8e9-b3455ee2b620.json diff --git a/change/@ni-nimble-components-db9e952a-a79d-4aa2-a8e9-b3455ee2b620.json b/change/@ni-nimble-components-db9e952a-a79d-4aa2-a8e9-b3455ee2b620.json new file mode 100644 index 0000000000..8ea8f8a6d8 --- /dev/null +++ b/change/@ni-nimble-components-db9e952a-a79d-4aa2-a8e9-b3455ee2b620.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Update banner styling to align with visual design spec", + "packageName": "@ni/nimble-components", + "email": "20542556+mollykreis@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/nimble-components/src/banner/styles.ts b/packages/nimble-components/src/banner/styles.ts index 8a33c0352f..a9c03a6e4a 100644 --- a/packages/nimble-components/src/banner/styles.ts +++ b/packages/nimble-components/src/banner/styles.ts @@ -12,19 +12,12 @@ import { import { display } from '../utilities/style/display'; import { - actionRgbPartialColor, applicationBackgroundColor, bodyFont, - borderHoverColor, - buttonLabelFontColor, + bodyFontColor, controlHeight, controlSlimHeight, - fillSelectedColor, - iconColor, - iconSize, - linkActiveFontColor, - linkDisabledFontColor, - linkFontColor, + smallPadding, standardPadding } from '../theme-provider/design-tokens'; import { Theme } from '../theme-provider/types'; @@ -40,8 +33,6 @@ export const styles = css` font-size: 12.8px; align-items: top; overflow: hidden; - color: ${White}; - ${iconColor.cssCustomProperty}: ${hexToRgbaCssColor(White, 0.6)}; } :host(:not([open])) { @@ -49,6 +40,7 @@ export const styles = css` } .container { + color: ${bodyFontColor}; display: flex; width: 100%; } @@ -59,6 +51,7 @@ export const styles = css` justify-content: center; margin-top: 8px; flex: 0 0 auto; + opacity: 0.6; } .text { @@ -85,6 +78,8 @@ export const styles = css` align-items: center; justify-content: center; align-self: flex-start; + margin-top: ${smallPadding}; + ${controlHeight.cssCustomProperty}: ${controlSlimHeight}; } slot[name='action'] { @@ -95,53 +90,14 @@ export const styles = css` } slot[name='action']::slotted(nimble-anchor) { - ${linkFontColor.cssCustomProperty}: ${White}; - ${linkDisabledFontColor.cssCustomProperty}: ${White}; - ${linkActiveFontColor.cssCustomProperty}: ${hexToRgbaCssColor( - White, - 0.6 - )}; font-size: 12.8px; } - slot[name='action']::slotted(nimble-button) { - ${controlHeight.cssCustomProperty}: ${controlSlimHeight}; - ${buttonLabelFontColor.cssCustomProperty}: ${White}; - ${fillSelectedColor.cssCustomProperty}: ${hexToRgbaCssColor( - White, - 0.2 - )}; - ${borderHoverColor.cssCustomProperty}: ${White}; - } - - slot[name='action']::slotted(nimble-button[appearance='outline']) { - ${actionRgbPartialColor.cssCustomProperty}: ${White} - } - .dismiss { width: 48px; display: flex; justify-content: center; } - - .dismiss nimble-button { - ${controlHeight.cssCustomProperty}: 16px; - ${iconSize.cssCustomProperty}: 14px; - ${buttonLabelFontColor.cssCustomProperty}: ${White}; - ${borderHoverColor.cssCustomProperty}: transparent; - ${fillSelectedColor.cssCustomProperty}: ${hexToRgbaCssColor( - White, - 0.2 - )}; - } - - .dismiss nimble-button:focus-within { - outline: 2px solid ${White}; - } - - .dismiss nimble-button:hover { - background: ${hexToRgbaCssColor(White, 0.2)}; - } `.withBehaviors( themeBehavior( Theme.light, diff --git a/packages/nimble-components/src/banner/template.ts b/packages/nimble-components/src/banner/template.ts index c2568336d9..2bfbfa39f5 100644 --- a/packages/nimble-components/src/banner/template.ts +++ b/packages/nimble-components/src/banner/template.ts @@ -4,7 +4,7 @@ import { buttonTag } from '../button'; import { iconExclamationMarkTag } from '../icons/exclamation-mark'; import { iconInfoTag } from '../icons/info'; import { iconTriangleFilledTag } from '../icons/triangle-filled'; -import { iconXmarkTag } from '../icons/xmark'; +import { iconTimesTag } from '../icons/times'; import { BannerSeverity } from './types'; import { popupIconErrorLabel, @@ -12,57 +12,62 @@ import { popupDismissLabel, popupIconWarningLabel } from '../label-provider/core/label-tokens'; +import { themeProviderTag } from '../theme-provider'; +import { Theme } from '../theme-provider/types'; +import { ButtonAppearance, ButtonAppearanceVariant } from '../button/types'; // prettier-ignore export const template = html<Banner>` - <div class="container" - role="status" - aria-atomic="${x => x.ariaAtomic}" - aria-busy="${x => x.ariaBusy}" - aria-controls="${x => x.ariaControls}" - aria-current="${x => x.ariaCurrent}" - aria-describedby="${x => x.ariaDescribedby}" - aria-details="${x => x.ariaDetails}" - aria-disabled="${x => x.ariaDisabled}" - aria-errormessage="${x => x.ariaErrormessage}" - aria-expanded="${x => x.ariaExpanded}" - aria-flowto="${x => x.ariaFlowto}" - aria-haspopup="${x => x.ariaHaspopup}" - aria-hidden="${x => x.ariaHidden}" - aria-invalid="${x => x.ariaInvalid}" - aria-keyshortcuts="${x => x.ariaKeyshortcuts}" - aria-label="${x => x.ariaLabel}" - aria-labelledby="titleSlot" - aria-live="${x => x.ariaLive}" - aria-owns="${x => x.ariaOwns}" - aria-relevant="${x => x.ariaRelevant}" - aria-roledescription="${x => x.ariaRoledescription}" - > - <div class="icon"> - ${when(x => x.severity === BannerSeverity.error, html<Banner>` - <${iconExclamationMarkTag} role="img" aria-label="${x => popupIconErrorLabel.getValueFor(x)}"></${iconExclamationMarkTag}> - `)} - ${when(x => x.severity === BannerSeverity.warning, html<Banner>` - <${iconTriangleFilledTag} role="img" aria-label="${x => popupIconWarningLabel.getValueFor(x)}"></${iconTriangleFilledTag}> - `)} - ${when(x => x.severity === BannerSeverity.information, html<Banner>` - <${iconInfoTag} role="img" aria-label="${x => popupIconInformationLabel.getValueFor(x)}"></${iconInfoTag}> - `)} - </div> - <div class="text"> - <slot name="title" id="titleSlot"></slot> - <slot></slot> - </div> - <div class="controls"> - <slot name="action"></slot> - <div class="dismiss"> - ${when(x => !x.preventDismiss, html<Banner>` - <${buttonTag} appearance="ghost" content-hidden @click="${x => x.dismissBanner()}"> - <${iconXmarkTag} slot="start"></${iconXmarkTag}> - ${x => popupDismissLabel.getValueFor(x)} - </${buttonTag}> + <${themeProviderTag} theme="${Theme.color}"> + <div class="container" + role="status" + aria-atomic="${x => x.ariaAtomic}" + aria-busy="${x => x.ariaBusy}" + aria-controls="${x => x.ariaControls}" + aria-current="${x => x.ariaCurrent}" + aria-describedby="${x => x.ariaDescribedby}" + aria-details="${x => x.ariaDetails}" + aria-disabled="${x => x.ariaDisabled}" + aria-errormessage="${x => x.ariaErrormessage}" + aria-expanded="${x => x.ariaExpanded}" + aria-flowto="${x => x.ariaFlowto}" + aria-haspopup="${x => x.ariaHaspopup}" + aria-hidden="${x => x.ariaHidden}" + aria-invalid="${x => x.ariaInvalid}" + aria-keyshortcuts="${x => x.ariaKeyshortcuts}" + aria-label="${x => x.ariaLabel}" + aria-labelledby="titleSlot" + aria-live="${x => x.ariaLive}" + aria-owns="${x => x.ariaOwns}" + aria-relevant="${x => x.ariaRelevant}" + aria-roledescription="${x => x.ariaRoledescription}" + > + <div class="icon"> + ${when(x => x.severity === BannerSeverity.error, html<Banner>` + <${iconExclamationMarkTag} role="img" aria-label="${x => popupIconErrorLabel.getValueFor(x)}"></${iconExclamationMarkTag}> + `)} + ${when(x => x.severity === BannerSeverity.warning, html<Banner>` + <${iconTriangleFilledTag} role="img" aria-label="${x => popupIconWarningLabel.getValueFor(x)}"></${iconTriangleFilledTag}> `)} + ${when(x => x.severity === BannerSeverity.information, html<Banner>` + <${iconInfoTag} role="img" aria-label="${x => popupIconInformationLabel.getValueFor(x)}"></${iconInfoTag}> + `)} + </div> + <div class="text"> + <slot name="title" id="titleSlot"></slot> + <slot></slot> + </div> + <div class="controls"> + <slot name="action"></slot> + <div class="dismiss"> + ${when(x => !x.preventDismiss, html<Banner>` + <${buttonTag} appearance="${ButtonAppearance.ghost}" appearance-variant="${ButtonAppearanceVariant.primary}" content-hidden @click="${x => x.dismissBanner()}"> + <${iconTimesTag} slot="start"></${iconTimesTag}> + ${x => popupDismissLabel.getValueFor(x)} + </${buttonTag}> + `)} + </div> </div> </div> - </div> + </${themeProviderTag}> `; diff --git a/packages/storybook/src/nimble/banner/banner-matrix.stories.ts b/packages/storybook/src/nimble/banner/banner-matrix.stories.ts index 3ff0b4850f..3f927302f2 100644 --- a/packages/storybook/src/nimble/banner/banner-matrix.stories.ts +++ b/packages/storybook/src/nimble/banner/banner-matrix.stories.ts @@ -6,6 +6,7 @@ import { anchorTag } from '../../../../nimble-components/src/anchor'; import { iconKeyTag } from '../../../../nimble-components/src/icons/key'; import { bannerTag } from '../../../../nimble-components/src/banner'; import { BannerSeverity } from '../../../../nimble-components/src/banner/types'; +import { ButtonAppearanceVariant } from '../../../../nimble-components/src/button/types'; import { createStory } from '../../utilities/storybook'; import { createMatrix, @@ -72,7 +73,7 @@ const component = ( <${anchorTag} slot="action" href="#">${longText ? loremIpsum.substring(0, 78) : 'Nimble anchor'}</${anchorTag}> `)} ${when(() => buttonAppearance, html` - <${buttonTag} slot="action" appearance="${buttonAppearance!}" content-hidden=${iconButton}> + <${buttonTag} slot="action" appearance="${buttonAppearance!}" appearance-variant="${ButtonAppearanceVariant.primary}" content-hidden=${iconButton}> ${when(() => iconButton, html` <${iconKeyTag} slot="start"></${iconKeyTag}> `)} diff --git a/packages/storybook/src/nimble/banner/banner.stories.ts b/packages/storybook/src/nimble/banner/banner.stories.ts index a5bb042c64..06e6f9fb59 100644 --- a/packages/storybook/src/nimble/banner/banner.stories.ts +++ b/packages/storybook/src/nimble/banner/banner.stories.ts @@ -1,8 +1,10 @@ import { html, when } from '@microsoft/fast-element'; import { withActions } from '@storybook/addon-actions/decorator'; import type { HtmlRenderer, Meta, StoryObj } from '@storybook/html'; +import { Theme } from '../../../../nimble-components/src/theme-provider/types'; import { iconKeyTag } from '../../../../nimble-components/src/icons/key'; import { buttonTag } from '../../../../nimble-components/src/button'; +import { ButtonAppearance, ButtonAppearanceVariant } from '../../../../nimble-components/src/button/types'; import { anchorTag } from '../../../../nimble-components/src/anchor'; import { labelProviderCoreTag } from '../../../../nimble-components/src/label-provider/core'; import { popupDismissLabel } from '../../../../nimble-components/src/label-provider/core/label-tokens'; @@ -61,11 +63,11 @@ export const _banner: StoryObj<BannerArgs> = { <span slot="title">${x => x.title}</span> ${x => x.text} ${when(x => x.action === 'button (ghost)', html` - <${buttonTag} slot="action" appearance="ghost">Do action</${buttonTag}>`)} + <${buttonTag} slot="action" appearance="${ButtonAppearance.ghost}" appearance-variant="${ButtonAppearanceVariant.primary}">Do action</${buttonTag}>`)} ${when(x => x.action === 'button (outline)', html` - <${buttonTag} slot="action" appearance="outline">Do action</${buttonTag}>`)} + <${buttonTag} slot="action" appearance="${ButtonAppearance.outline}" appearance-variant="${ButtonAppearanceVariant.primary}">Do action</${buttonTag}>`)} ${when(x => x.action === 'icon button (outline)', html` - <${buttonTag} slot="action" appearance="outline" content-hidden> + <${buttonTag} slot="action" appearance="${ButtonAppearance.outline}" appearance-variant="${ButtonAppearanceVariant.primary}" content-hidden> <${iconKeyTag} slot="start"></${iconKeyTag}> Do action </${buttonTag}>`)} @@ -91,13 +93,13 @@ export const _banner: StoryObj<BannerArgs> = { options: Object.keys(BannerSeverity), control: { type: 'radio' }, description: - 'Severity of the message presented by the banner. Controls the displayed color and icon. If not set, the banner has a neutral appearance.' + `Severity of the message presented by the banner. Controls the icon displayed within the banner and, in themes other than \`${Theme.color}\`, controls the background color of the banner. If not set, the banner has a neutral appearance.` }, action: { options: Object.values(ActionType), control: { type: 'radio' }, description: - 'The `action` slot provides a place to display a button or anchor that you provide. If you provide a button, it should have either the `"ghost"` or `"outline"` appearance.' + 'The `action` slot provides a place to display a button or anchor that you provide. If you provide a button, it should have either the `"ghost"` or `"outline"` appearance and have the `"primary"` appearance variant.' }, preventDismiss: { name: 'prevent-dismiss', From 7596926bc32aee79fe58146929db06596648035e Mon Sep 17 00:00:00 2001 From: rajsite <rajsite@users.noreply.github.com> Date: Tue, 28 May 2024 15:13:14 -0500 Subject: [PATCH 6/8] applying package updates [skip ci] --- ...ents-db9e952a-a79d-4aa2-a8e9-b3455ee2b620.json | 7 ------- package-lock.json | 14 +++++++------- .../nimble-angular/CHANGELOG.json | 15 +++++++++++++++ .../angular-workspace/nimble-angular/CHANGELOG.md | 10 +++++++++- .../angular-workspace/nimble-angular/package.json | 4 ++-- .../spright-angular/CHANGELOG.json | 15 +++++++++++++++ .../spright-angular/CHANGELOG.md | 10 +++++++++- .../spright-angular/package.json | 4 ++-- packages/nimble-components/CHANGELOG.json | 15 +++++++++++++++ packages/nimble-components/CHANGELOG.md | 10 +++++++++- packages/nimble-components/package.json | 2 +- packages/spright-components/CHANGELOG.json | 15 +++++++++++++++ packages/spright-components/CHANGELOG.md | 10 +++++++++- packages/spright-components/package.json | 4 ++-- 14 files changed, 110 insertions(+), 25 deletions(-) delete mode 100644 change/@ni-nimble-components-db9e952a-a79d-4aa2-a8e9-b3455ee2b620.json diff --git a/change/@ni-nimble-components-db9e952a-a79d-4aa2-a8e9-b3455ee2b620.json b/change/@ni-nimble-components-db9e952a-a79d-4aa2-a8e9-b3455ee2b620.json deleted file mode 100644 index 8ea8f8a6d8..0000000000 --- a/change/@ni-nimble-components-db9e952a-a79d-4aa2-a8e9-b3455ee2b620.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "patch", - "comment": "Update banner styling to align with visual design spec", - "packageName": "@ni/nimble-components", - "email": "20542556+mollykreis@users.noreply.github.com", - "dependentChangeType": "patch" -} diff --git a/package-lock.json b/package-lock.json index 8b0aa2aae5..e38382310f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33291,7 +33291,7 @@ }, "packages/angular-workspace/nimble-angular": { "name": "@ni/nimble-angular", - "version": "24.3.2", + "version": "24.3.3", "license": "MIT", "dependencies": { "tslib": "^2.2.0" @@ -33302,12 +33302,12 @@ "@angular/forms": "^16.2.12", "@angular/localize": "^16.2.12", "@angular/router": "^16.2.12", - "@ni/nimble-components": "^29.1.5" + "@ni/nimble-components": "^29.1.6" } }, "packages/angular-workspace/spright-angular": { "name": "@ni/spright-angular", - "version": "1.0.6", + "version": "1.0.7", "license": "MIT", "dependencies": { "tslib": "^2.2.0" @@ -33315,7 +33315,7 @@ "peerDependencies": { "@angular/common": "^16.2.12", "@angular/core": "^16.2.12", - "@ni/spright-components": "^1.0.6" + "@ni/spright-components": "^1.0.7" } }, "packages/blazor-workspace": { @@ -33400,7 +33400,7 @@ }, "packages/nimble-components": { "name": "@ni/nimble-components", - "version": "29.1.5", + "version": "29.1.6", "license": "MIT", "dependencies": { "@microsoft/fast-colors": "^5.3.1", @@ -33548,14 +33548,14 @@ }, "packages/spright-components": { "name": "@ni/spright-components", - "version": "1.0.6", + "version": "1.0.7", "license": "MIT", "dependencies": { "@microsoft/fast-colors": "^5.3.1", "@microsoft/fast-element": "^1.12.0", "@microsoft/fast-foundation": "^2.49.6", "@microsoft/fast-web-utilities": "^6.0.0", - "@ni/nimble-components": "29.1.5", + "@ni/nimble-components": "29.1.6", "@ni/nimble-tokens": "^6.13.6", "tslib": "^2.2.0" }, diff --git a/packages/angular-workspace/nimble-angular/CHANGELOG.json b/packages/angular-workspace/nimble-angular/CHANGELOG.json index 469e32e281..21efca717b 100644 --- a/packages/angular-workspace/nimble-angular/CHANGELOG.json +++ b/packages/angular-workspace/nimble-angular/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/nimble-angular", "entries": [ + { + "date": "Tue, 28 May 2024 20:13:14 GMT", + "version": "24.3.3", + "tag": "@ni/nimble-angular_v24.3.3", + "comments": { + "patch": [ + { + "author": "beachball", + "package": "@ni/nimble-angular", + "comment": "Bump @ni/nimble-components to v29.1.6", + "commit": "not available" + } + ] + } + }, { "date": "Wed, 22 May 2024 18:32:15 GMT", "version": "24.3.2", diff --git a/packages/angular-workspace/nimble-angular/CHANGELOG.md b/packages/angular-workspace/nimble-angular/CHANGELOG.md index 55a9510483..69be77df81 100644 --- a/packages/angular-workspace/nimble-angular/CHANGELOG.md +++ b/packages/angular-workspace/nimble-angular/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/nimble-angular -This log was last generated on Wed, 22 May 2024 18:32:15 GMT and should not be manually modified. +This log was last generated on Tue, 28 May 2024 20:13:14 GMT and should not be manually modified. <!-- Start content --> +## 24.3.3 + +Tue, 28 May 2024 20:13:14 GMT + +### Patches + +- Bump @ni/nimble-components to v29.1.6 + ## 24.3.2 Wed, 22 May 2024 18:32:15 GMT diff --git a/packages/angular-workspace/nimble-angular/package.json b/packages/angular-workspace/nimble-angular/package.json index 3a30e24141..934068fc43 100644 --- a/packages/angular-workspace/nimble-angular/package.json +++ b/packages/angular-workspace/nimble-angular/package.json @@ -1,6 +1,6 @@ { "name": "@ni/nimble-angular", - "version": "24.3.2", + "version": "24.3.3", "description": "Angular components for the NI Nimble Design System", "scripts": { "invoke-publish": "npm run invoke-publish:setup && cd ../dist/nimble-angular && npm publish", @@ -32,7 +32,7 @@ "@angular/forms": "^16.2.12", "@angular/localize": "^16.2.12", "@angular/router": "^16.2.12", - "@ni/nimble-components": "^29.1.5" + "@ni/nimble-components": "^29.1.6" }, "dependencies": { "tslib": "^2.2.0" diff --git a/packages/angular-workspace/spright-angular/CHANGELOG.json b/packages/angular-workspace/spright-angular/CHANGELOG.json index 777ef8a43d..867aa18fb5 100644 --- a/packages/angular-workspace/spright-angular/CHANGELOG.json +++ b/packages/angular-workspace/spright-angular/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/spright-angular", "entries": [ + { + "date": "Tue, 28 May 2024 20:13:14 GMT", + "version": "1.0.7", + "tag": "@ni/spright-angular_v1.0.7", + "comments": { + "patch": [ + { + "author": "beachball", + "package": "@ni/spright-angular", + "comment": "Bump @ni/spright-components to v1.0.7", + "commit": "not available" + } + ] + } + }, { "date": "Wed, 22 May 2024 18:32:15 GMT", "version": "1.0.6", diff --git a/packages/angular-workspace/spright-angular/CHANGELOG.md b/packages/angular-workspace/spright-angular/CHANGELOG.md index 48ad0e9884..3dc87d8058 100644 --- a/packages/angular-workspace/spright-angular/CHANGELOG.md +++ b/packages/angular-workspace/spright-angular/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/spright-angular -This log was last generated on Wed, 22 May 2024 18:32:15 GMT and should not be manually modified. +This log was last generated on Tue, 28 May 2024 20:13:14 GMT and should not be manually modified. <!-- Start content --> +## 1.0.7 + +Tue, 28 May 2024 20:13:14 GMT + +### Patches + +- Bump @ni/spright-components to v1.0.7 + ## 1.0.6 Wed, 22 May 2024 18:32:15 GMT diff --git a/packages/angular-workspace/spright-angular/package.json b/packages/angular-workspace/spright-angular/package.json index 470abf6567..5909d1db38 100644 --- a/packages/angular-workspace/spright-angular/package.json +++ b/packages/angular-workspace/spright-angular/package.json @@ -1,6 +1,6 @@ { "name": "@ni/spright-angular", - "version": "1.0.6", + "version": "1.0.7", "description": "Angular components for NI Spright", "scripts": { "invoke-publish": "npm run invoke-publish:setup && cd ../dist/spright-angular && npm publish", @@ -24,7 +24,7 @@ "peerDependencies": { "@angular/common": "^16.2.12", "@angular/core": "^16.2.12", - "@ni/spright-components": "^1.0.6" + "@ni/spright-components": "^1.0.7" }, "dependencies": { "tslib": "^2.2.0" diff --git a/packages/nimble-components/CHANGELOG.json b/packages/nimble-components/CHANGELOG.json index 05c40131ae..ec52e302bc 100644 --- a/packages/nimble-components/CHANGELOG.json +++ b/packages/nimble-components/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/nimble-components", "entries": [ + { + "date": "Tue, 28 May 2024 20:13:14 GMT", + "version": "29.1.6", + "tag": "@ni/nimble-components_v29.1.6", + "comments": { + "patch": [ + { + "author": "20542556+mollykreis@users.noreply.github.com", + "package": "@ni/nimble-components", + "commit": "2855db4fe58a8d1df112ea656215696d9582f9ea", + "comment": "Update banner styling to align with visual design spec" + } + ] + } + }, { "date": "Wed, 22 May 2024 18:32:15 GMT", "version": "29.1.5", diff --git a/packages/nimble-components/CHANGELOG.md b/packages/nimble-components/CHANGELOG.md index 68a3a438d4..12f886e796 100644 --- a/packages/nimble-components/CHANGELOG.md +++ b/packages/nimble-components/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/nimble-components -This log was last generated on Wed, 22 May 2024 18:32:15 GMT and should not be manually modified. +This log was last generated on Tue, 28 May 2024 20:13:14 GMT and should not be manually modified. <!-- Start content --> +## 29.1.6 + +Tue, 28 May 2024 20:13:14 GMT + +### Patches + +- Update banner styling to align with visual design spec ([ni/nimble@2855db4](https://github.com/ni/nimble/commit/2855db4fe58a8d1df112ea656215696d9582f9ea)) + ## 29.1.5 Wed, 22 May 2024 18:32:15 GMT diff --git a/packages/nimble-components/package.json b/packages/nimble-components/package.json index 16694478c4..c24e5bc6b8 100644 --- a/packages/nimble-components/package.json +++ b/packages/nimble-components/package.json @@ -1,6 +1,6 @@ { "name": "@ni/nimble-components", - "version": "29.1.5", + "version": "29.1.6", "description": "Styled web components for the NI Nimble Design System", "scripts": { "build": "npm run generate-icons && npm run generate-workers && npm run build-components && npm run bundle-components && npm run generate-scss", diff --git a/packages/spright-components/CHANGELOG.json b/packages/spright-components/CHANGELOG.json index 43524f3379..288a45496a 100644 --- a/packages/spright-components/CHANGELOG.json +++ b/packages/spright-components/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/spright-components", "entries": [ + { + "date": "Tue, 28 May 2024 20:13:14 GMT", + "version": "1.0.7", + "tag": "@ni/spright-components_v1.0.7", + "comments": { + "patch": [ + { + "author": "beachball", + "package": "@ni/spright-components", + "comment": "Bump @ni/nimble-components to v29.1.6", + "commit": "not available" + } + ] + } + }, { "date": "Wed, 22 May 2024 18:32:15 GMT", "version": "1.0.6", diff --git a/packages/spright-components/CHANGELOG.md b/packages/spright-components/CHANGELOG.md index d009bb41d1..a0fab71f30 100644 --- a/packages/spright-components/CHANGELOG.md +++ b/packages/spright-components/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/spright-components -This log was last generated on Wed, 22 May 2024 18:32:15 GMT and should not be manually modified. +This log was last generated on Tue, 28 May 2024 20:13:14 GMT and should not be manually modified. <!-- Start content --> +## 1.0.7 + +Tue, 28 May 2024 20:13:14 GMT + +### Patches + +- Bump @ni/nimble-components to v29.1.6 + ## 1.0.6 Wed, 22 May 2024 18:32:15 GMT diff --git a/packages/spright-components/package.json b/packages/spright-components/package.json index a7d3c47187..e1a9dda817 100644 --- a/packages/spright-components/package.json +++ b/packages/spright-components/package.json @@ -1,6 +1,6 @@ { "name": "@ni/spright-components", - "version": "1.0.6", + "version": "1.0.7", "description": "NI Spright Components", "scripts": { "build": "npm run build-components && npm run bundle-components", @@ -55,7 +55,7 @@ "@microsoft/fast-element": "^1.12.0", "@microsoft/fast-foundation": "^2.49.6", "@microsoft/fast-web-utilities": "^6.0.0", - "@ni/nimble-components": "29.1.5", + "@ni/nimble-components": "29.1.6", "@ni/nimble-tokens": "^6.13.6", "tslib": "^2.2.0" }, From 4557120b6fc24ebda3804754b2fa0cce04cef985 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Tue, 28 May 2024 17:38:36 -0500 Subject: [PATCH 7/8] API docs for additional components (#2135) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Pull Request ## ๐Ÿคจ Rationale Ongoing efforts towards #824. This PR builds on #2132 and covers these components: - tree - toolbar - icon - dialog - drawer - spinner - breadcrumb - theme provider ## ๐Ÿ‘ฉโ€๐Ÿ’ป Implementation Mostly following established patterns. Interesting bits: - moved a `nimble-components/src/dialog/tests/types.ts` to the `storybook` package since it iss only used by storybook - collapsed 2 controls into 1 in the dialog story - added a new table section called Styles for controls that impact CSS - removed "allowNavigation" capability from breadcrumb story because it was just showing native event behavior (i.e. how to cancel an event) and didn't have any documentation - moved "Target Configuration" section under the relevant component API section for several components. ## ๐Ÿงช Testing Storybook inspection ## โœ… 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. --- packages/storybook/.storybook/preview.js | 2 +- .../nimble/anchor-button/anchor-button.mdx | 8 +- .../src/nimble/anchor-tabs/anchor-tabs.mdx | 8 +- .../storybook/src/nimble/anchor/anchor.mdx | 8 +- .../storybook/src/nimble/banner/banner.mdx | 5 + .../src/nimble/breadcrumb/breadcrumb.mdx | 16 +++- .../nimble/breadcrumb/breadcrumb.stories.ts | 59 +++++++----- .../src/nimble/button/button.stories.ts | 2 +- .../nimble/card-button/card-button.stories.ts | 2 +- .../storybook/src/nimble/dialog/dialog.mdx | 11 ++- .../src/nimble/dialog/dialog.stories.ts | 77 +++++++++++---- .../src/nimble/dialog}/types.ts | 7 ++ .../storybook/src/nimble/drawer/drawer.mdx | 5 + .../src/nimble/drawer/drawer.stories.ts | 26 +++-- .../storybook/src/nimble/icon-base/icons.mdx | 5 + .../src/nimble/icon-base/icons.stories.ts | 4 +- .../nimble/menu-button/menu-button.stories.ts | 4 +- packages/storybook/src/nimble/menu/menu.mdx | 2 +- .../storybook/src/nimble/menu/menu.stories.ts | 2 +- .../users/rich-text-mention-users.stories.ts | 6 +- .../editor/rich-text-editor.stories.ts | 2 +- .../storybook/src/nimble/spinner/spinner.mdx | 14 ++- .../src/nimble/spinner/spinner.stories.ts | 8 +- .../anchor/table-column-anchor.mdx | 11 ++- .../storybook/src/nimble/tabs/tabs.stories.ts | 2 +- .../nimble/theme-provider/theme-provider.mdx | 5 + .../theme-provider/theme-provider.stories.ts | 11 ++- .../toggle-button/toggle-button.stories.ts | 2 +- .../storybook/src/nimble/toolbar/toolbar.mdx | 8 +- .../src/nimble/toolbar/toolbar.stories.ts | 23 ++++- .../src/nimble/tree-view/tree-view.mdx | 34 ++++--- .../src/nimble/tree-view/tree-view.stories.ts | 95 ++++++++++++++----- .../src/nimble/wafer-map/wafer-map.stories.ts | 2 +- packages/storybook/src/utilities/storybook.ts | 5 +- 34 files changed, 342 insertions(+), 139 deletions(-) rename packages/{nimble-components/src/dialog/tests => storybook/src/nimble/dialog}/types.ts (66%) diff --git a/packages/storybook/.storybook/preview.js b/packages/storybook/.storybook/preview.js index 99b228ab50..c9a45a56b8 100644 --- a/packages/storybook/.storybook/preview.js +++ b/packages/storybook/.storybook/preview.js @@ -105,5 +105,5 @@ configureActions({ depth: 1 }); -// Update the GUID on this line to trigger a turbosnap full rebuild: 354fdf0e-bdb4-4dd9-a6e4-21bf71c6efe6 +// Update the GUID on this line to trigger a turbosnap full rebuild: 354fdf0e-bdb4-4dd9-a6e5-21bf71c6efe6 // See https://www.chromatic.com/docs/turbosnap/#full-rebuilds diff --git a/packages/storybook/src/nimble/anchor-button/anchor-button.mdx b/packages/storybook/src/nimble/anchor-button/anchor-button.mdx index f1ec05a3ee..761ee20c88 100644 --- a/packages/storybook/src/nimble/anchor-button/anchor-button.mdx +++ b/packages/storybook/src/nimble/anchor-button/anchor-button.mdx @@ -29,6 +29,10 @@ If you want a button that triggers an action or event, use the <Tag name={button <ComponentApisLink /> +### Target Configuration + +<TargetDocs /> + ## Styling <StylingDocs components={{ Button: anchorButtonTag }} /> @@ -37,10 +41,6 @@ If you want a button that triggers an action or event, use the <Tag name={button {/* ## Examples */} -## Target Configuration - -<TargetDocs /> - ## Accessibility <ContentHiddenDocs buttonElement="nimble-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 9af6d97042..094d566c08 100644 --- a/packages/storybook/src/nimble/anchor-tabs/anchor-tabs.mdx +++ b/packages/storybook/src/nimble/anchor-tabs/anchor-tabs.mdx @@ -31,6 +31,10 @@ Use the <Tag name={anchorTabTag} /> child element to add new tabs to the <Tag na <Canvas of={anchorTabsStories.anchorTab} /> <Controls of={anchorTabsStories.anchorTab} /> +#### Target Configuration + +<TargetDocs /> + ### Tabs Toolbar Use the <Tag name={tabsToolbarTag} /> child element to add a toolbar next to the tabs. @@ -44,10 +48,6 @@ Use the <Tag name={tabsToolbarTag} /> child element to add a toolbar next to the {/* ## Examples */} -## Target Configuration - -<TargetDocs /> - ## Angular Usage In an Angular application, it is common to integrate with the router by setting `nimbleRouterLink` (rather than `href`) diff --git a/packages/storybook/src/nimble/anchor/anchor.mdx b/packages/storybook/src/nimble/anchor/anchor.mdx index 401187de3d..bdc1be6ad8 100644 --- a/packages/storybook/src/nimble/anchor/anchor.mdx +++ b/packages/storybook/src/nimble/anchor/anchor.mdx @@ -16,6 +16,10 @@ Per [W3C](https://www.w3.org/WAI/ARIA/apg/patterns/link/), an anchor/link widget <ComponentApisLink /> +### Target Configuration + +<TargetDocs /> + {/* ## Styling */} {/* ## Usage */} @@ -25,7 +29,3 @@ Per [W3C](https://www.w3.org/WAI/ARIA/apg/patterns/link/), an anchor/link widget {/* ## Accessibility */} {/* ## Resources */} - -## Target Configuration - -<TargetDocs /> diff --git a/packages/storybook/src/nimble/banner/banner.mdx b/packages/storybook/src/nimble/banner/banner.mdx index 6939d6a9c8..dc39d877e6 100644 --- a/packages/storybook/src/nimble/banner/banner.mdx +++ b/packages/storybook/src/nimble/banner/banner.mdx @@ -1,5 +1,6 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import { NimbleBanner } from './banner.react'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; import { bannerGapSize } from '../../../../nimble-components/src/theme-provider/design-tokens'; import * as bannerStories from './banner.stories'; @@ -14,7 +15,11 @@ location. Multiple banners may be stacked vertically in order of age, with the n should be spaced apart using the <code>{bannerGapSize.cssCustomProperty}</code> design token. <Canvas of={bannerStories._banner} /> + +## API + <Controls of={bannerStories._banner} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/breadcrumb/breadcrumb.mdx b/packages/storybook/src/nimble/breadcrumb/breadcrumb.mdx index e4be7375c9..0505a15cb6 100644 --- a/packages/storybook/src/nimble/breadcrumb/breadcrumb.mdx +++ b/packages/storybook/src/nimble/breadcrumb/breadcrumb.mdx @@ -1,6 +1,8 @@ import { Canvas, Meta, Stories, Controls, Title } from '@storybook/blocks'; import { NimbleBreadcrumb } from './breadcrumb.react'; import * as breadcrumbStories from './breadcrumb.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; +import TargetDocs from '../patterns/anchor/target-docs.mdx'; <Meta of={breadcrumbStories} /> <Title of={breadcrumbStories} /> @@ -12,8 +14,20 @@ See the [nimble-angular Readme](https://github.com/ni/nimble/blob/main/packages/ for information on using this component in Angular with RouterLink directives. <Canvas of={breadcrumbStories._standardBreadcrumb} /> + +## API + <Controls of={breadcrumbStories._standardBreadcrumb} /> -<Stories of={breadcrumbStories} /> +<ComponentApisLink /> + +### Breadcrumb Item + +<Canvas of={breadcrumbStories.breadcrumbItem} /> +<Controls of={breadcrumbStories.breadcrumbItem} /> + +#### Target Configuration + +<TargetDocs /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/breadcrumb/breadcrumb.stories.ts b/packages/storybook/src/nimble/breadcrumb/breadcrumb.stories.ts index 7b69c36000..510a7ba34b 100644 --- a/packages/storybook/src/nimble/breadcrumb/breadcrumb.stories.ts +++ b/packages/storybook/src/nimble/breadcrumb/breadcrumb.stories.ts @@ -1,35 +1,41 @@ -import type { Meta, StoryObj } from '@storybook/html'; +import type { HtmlRenderer, Meta, StoryObj } from '@storybook/html'; +import { withActions } from '@storybook/addon-actions/decorator'; import { html, repeat } from '@microsoft/fast-element'; import { breadcrumbItemTag } from '../../../../nimble-components/src/breadcrumb-item'; import { breadcrumbTag } from '../../../../nimble-components/src/breadcrumb'; import { BreadcrumbAppearance } from '../../../../nimble-components/src/breadcrumb/types'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, appearanceDescription, createUserSelectedThemeStory } from '../../utilities/storybook'; +import { hrefDescription } from '../patterns/anchor/anchor-docs'; interface BreadcrumbArgs { options: ItemArgs[]; appearance: keyof typeof BreadcrumbAppearance; - allowNavigation: boolean; } interface ItemArgs { href?: string; - target?: string; label: string; } interface BreadcrumbItemArgs extends ItemArgs { - allowNavigation: boolean; + click: undefined; } const metadata: Meta<BreadcrumbArgs> = { title: 'Components/Breadcrumb', + decorators: [withActions<HtmlRenderer>], parameters: { - actions: {} + actions: { + handles: ['click'] + } } }; export default metadata; +const defaultHrefDescription = hrefDescription({ componentName: 'breadcrumb item', includeDisable: false }); +const itemHrefDescription = `${defaultHrefDescription} If the last breadcrumb item represents the current page it should have no \`href\` set.`; + export const _standardBreadcrumb: StoryObj<BreadcrumbArgs> = { // prettier-ignore render: createUserSelectedThemeStory(html` @@ -39,8 +45,6 @@ export const _standardBreadcrumb: StoryObj<BreadcrumbArgs> = { ${repeat(x => x.options, html<ItemArgs, BreadcrumbArgs>` <${breadcrumbItemTag} href="${x => x.href}" - target="${x => x.target}" - @click="${(_x, c) => c.parent.allowNavigation}" > ${x => x.label} </${breadcrumbItemTag}> @@ -51,14 +55,18 @@ export const _standardBreadcrumb: StoryObj<BreadcrumbArgs> = { name: 'Standard Breadcrumb', argTypes: { options: { + name: 'default', description: - 'Nest one or more `<nimble-breadcrumb-item />`s inside `<nimble-breadcrumb />`. Each can optionally set `href`, `target`, etc. ' - + 'With a standard breadcrumb containing multiple items, the last breadcrumb represents the current page (with no `href` specified, ' - + 'rendering with a bold font).' + `The \`${breadcrumbItemTag}\` elements that populate this breadcrumb. + +With a standard breadcrumb containing multiple items, the last breadcrumb represents the current page.`, + table: { category: apiCategory.slots } }, appearance: { options: Object.keys(BreadcrumbAppearance), - control: { type: 'radio' } + description: appearanceDescription({ componentName: 'breadcrumb' }), + control: { type: 'radio' }, + table: { category: apiCategory.attributes } } }, args: { @@ -75,8 +83,7 @@ export const _standardBreadcrumb: StoryObj<BreadcrumbArgs> = { label: 'Current (No Link)' } ], - appearance: 'default', - allowNavigation: false + appearance: 'default' } }; @@ -85,28 +92,30 @@ export const breadcrumbItem: StoryObj<BreadcrumbItemArgs> = { <${breadcrumbTag}> <${breadcrumbItemTag} href="${x => x.href}" - target="${x => x.target}" - @click="${x => x.allowNavigation}" > - Breadcrumb Item + ${x => x.label} </${breadcrumbItemTag}> </${breadcrumbTag}> `), argTypes: { href: { - description: - '(Optional) The URL that this breadcrumb item/ link points to. Generally, the last breadcrumb item ' - + 'representing the current page has no `href` set.' + description: itemHrefDescription, + table: { category: apiCategory.attributes } }, - target: { - description: - '(Optional) Where to display the linked URL (destination browsing context): `_self`, `_blank`, etc.', - type: 'string' + label: { + name: 'default', + description: 'The text content of the breadcrumb item.', + type: 'string', + table: { category: apiCategory.slots } + }, + click: { + description: 'Event emitted when the user activates the breadcrumb item link, for example by clicking on it or pressing Enter while focused.', + control: false, + table: { category: apiCategory.events } } }, args: { href: 'http://www.ni.com', label: 'Breadcrumb Item', - allowNavigation: false } }; diff --git a/packages/storybook/src/nimble/button/button.stories.ts b/packages/storybook/src/nimble/button/button.stories.ts index b706797ab7..14697396a9 100644 --- a/packages/storybook/src/nimble/button/button.stories.ts +++ b/packages/storybook/src/nimble/button/button.stories.ts @@ -74,7 +74,7 @@ const metadata: Meta<ButtonArgs> = { }, click: { description: - 'Fires when the button is activated by either keyboard or mouse.', + 'Event emitted when the button is activated by either keyboard or mouse.', table: { category: apiCategory.events }, control: false } diff --git a/packages/storybook/src/nimble/card-button/card-button.stories.ts b/packages/storybook/src/nimble/card-button/card-button.stories.ts index e78da078da..ce2cd1b33d 100644 --- a/packages/storybook/src/nimble/card-button/card-button.stories.ts +++ b/packages/storybook/src/nimble/card-button/card-button.stories.ts @@ -72,7 +72,7 @@ const metadata: Meta<CardButtonArgs> = { }, click: { description: - 'Fires when the card button is activated by either keyboard or mouse.', + 'Event emitted when the card button is activated by either keyboard or mouse.', table: { category: apiCategory.events }, control: false } diff --git a/packages/storybook/src/nimble/dialog/dialog.mdx b/packages/storybook/src/nimble/dialog/dialog.mdx index aa90633baa..742da58de3 100644 --- a/packages/storybook/src/nimble/dialog/dialog.mdx +++ b/packages/storybook/src/nimble/dialog/dialog.mdx @@ -1,15 +1,18 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import * as dialogStories from './dialog.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; <Meta of={dialogStories} /> <Title of={dialogStories} /> A modal dialog that appears centered on top of all other windows, blocking other interaction until dismissed. -By default, the first focusable control gets focus when the dialog is opened. To focus a specific element instead, set the `autofocus` attribute on that element. - <Canvas of={dialogStories.dialog} /> + +## API + <Controls of={dialogStories.dialog} /> +<ComponentApisLink /> ## Styling @@ -38,7 +41,9 @@ nimble-dialog::part(control) { } ``` -{/* ## Usage */} +## Usage + +By default, the first focusable control gets focus when the dialog is opened. To focus a specific element instead, set the `autofocus` attribute on that element. {/* ## Examples */} diff --git a/packages/storybook/src/nimble/dialog/dialog.stories.ts b/packages/storybook/src/nimble/dialog/dialog.stories.ts index c25f53b72e..3de2033b38 100644 --- a/packages/storybook/src/nimble/dialog/dialog.stories.ts +++ b/packages/storybook/src/nimble/dialog/dialog.stories.ts @@ -4,6 +4,8 @@ import { TextField, textFieldTag } from '../../../../nimble-components/src/text- import { buttonTag } from '../../../../nimble-components/src/button'; import { checkboxTag } from '../../../../nimble-components/src/checkbox'; import { + bodyFont, + bodyFontColor, dialogLargeHeight, dialogLargeMaxHeight, dialogLargeWidth, @@ -12,8 +14,8 @@ import { dialogSmallWidth } from '../../../../nimble-components/src/theme-provider/design-tokens'; import { Dialog, dialogTag, UserDismissed } from '../../../../nimble-components/src/dialog'; -import { DialogSizeOptions, ExampleContentType } from '../../../../nimble-components/src/dialog/tests/types'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { DialogSizeOptions, ExampleContentType, ExampleFooterContentType } from './types'; +import { apiCategory, createUserSelectedThemeStory, preventDismissDescription } from '../../utilities/storybook'; import { loremIpsum } from '../../utilities/lorem-ipsum'; interface DialogArgs { @@ -21,9 +23,9 @@ interface DialogArgs { subtitle: string; headerHidden: boolean; footerHidden: boolean; - includeFooterButtons: boolean; preventDismiss: boolean; content: ExampleContentType; + footer: ExampleFooterContentType; size: DialogSizeOptions; show: undefined; close: undefined; @@ -55,7 +57,7 @@ const longContent = html` const content = { [ExampleContentType.shortContent]: shortContent, - [ExampleContentType.longContent]: longContent + [ExampleContentType.longContent]: longContent, } as const; const sizeDescription = ` @@ -94,6 +96,10 @@ const metadata: Meta<DialogArgs> = { max-height:${maxHeights[x.size]}; `} } + span[slot="footer"] { + font: var(${bodyFont.cssCustomProperty}); + color: var(${bodyFontColor.cssCustomProperty}); + } </style> <${dialogTag} ${ref('dialogRef')} @@ -106,7 +112,7 @@ const metadata: Meta<DialogArgs> = { ${x => content[x.content]} ${when( - x => x.includeFooterButtons, + x => x.footer === ExampleFooterContentType.buttons, html<DialogArgs>` <${buttonTag} @click="${x => x.dialogRef.close('Back pressed')}" @@ -130,6 +136,9 @@ const metadata: Meta<DialogArgs> = { > Continue </${buttonTag}> + `, + html<DialogArgs>` + <span slot="footer">${x => (x.preventDismiss ? 'Refresh the page to close the dialog.' : 'Press Esc to close the dialog.')}</span> ` )} </${dialogTag}> @@ -147,43 +156,66 @@ const metadata: Meta<DialogArgs> = { `), argTypes: { preventDismiss: { - name: 'prevent-dismiss' + name: 'prevent-dismiss', + description: preventDismissDescription({ componentName: 'dialog' }), + table: { category: apiCategory.attributes } }, title: { description: - 'Primary text that is displayed in the header when `header-hidden` is not set. Dialogs should **always include a title** even when `header-hidden` is set. The title is used to provide an accessible name to assistive technologies regardless of the value of `header-hidden`.<br><br>The title should be specified using an `inline` element, such as a `<span>`.' + 'Primary text that is displayed in the header when `header-hidden` is not set. Dialogs should **always include a title** even when `header-hidden` is set. The title is used to provide an accessible name to assistive technologies regardless of the value of `header-hidden`.<br><br>The title should be specified using an `inline` element, such as a `<span>`.', + table: { category: apiCategory.slots } }, subtitle: { description: - 'Secondary text that is displayed in the header when `header-hidden` is not set. If a dialog has an appropriate value to set for the subtitle, it should be included even when `header-hidden` is set. If the subtitle is set, it is used with the title to provide an accessible name to assistive technologies regardless of the value of `header-hidden`.<br><br>The subtitle should be specified using an `inline` element, such as a `<span>`.' + 'Secondary text that is displayed in the header when `header-hidden` is not set. If a dialog has an appropriate value to set for the subtitle, it should be included even when `header-hidden` is set. If the subtitle is set, it is used with the title to provide an accessible name to assistive technologies regardless of the value of `header-hidden`.<br><br>The subtitle should be specified using an `inline` element, such as a `<span>`.', + table: { category: apiCategory.slots } }, headerHidden: { name: 'header-hidden', description: - 'Setting `header-hidden` hides the title and subtitle of the dialog and allows the main content of the dialog to fill the space that would otherwise be reserved for the header. A title (and optionally a subtitle) should still be provided when `header-hidden` is set to ensure the dialog has a label that can be used by assistive technologies.' + 'Setting `header-hidden` hides the title and subtitle of the dialog and allows the main content of the dialog to fill the space that would otherwise be reserved for the header. A title (and optionally a subtitle) should still be provided when `header-hidden` is set to ensure the dialog has a label that can be used by assistive technologies.', + table: { category: apiCategory.attributes } + }, footerHidden: { name: 'footer-hidden', description: - 'Setting `footer-hidden` hides the footer of the dialog and any content that has been slotted within it. Setting `footer-hidden` also allows the main content of the dialog to fill the space that would otherwise be reserved for the footer.' - }, - includeFooterButtons: { - name: 'Include footer buttons' + 'Setting `footer-hidden` hides the footer of the dialog and any content that has been slotted within it. Setting `footer-hidden` also allows the main content of the dialog to fill the space that would otherwise be reserved for the footer.', + table: { category: apiCategory.attributes } }, content: { + name: 'default', options: [ ExampleContentType.shortContent, - ExampleContentType.longContent + ExampleContentType.longContent, ], control: { type: 'radio', labels: { [ExampleContentType.shortContent]: 'Short content', - [ExampleContentType.longContent]: 'Long content' + [ExampleContentType.longContent]: 'Long content', } - } + }, + description: 'The dialog content, which can be arbitrary HTML.', + table: { category: apiCategory.slots } + }, + footer: { + options: [ + ExampleFooterContentType.text, + ExampleFooterContentType.buttons, + ], + control: { + type: 'radio', + labels: { + [ExampleFooterContentType.text]: 'Text', + [ExampleFooterContentType.buttons]: 'Buttons', + } + }, + description: 'Content like buttons which appear at the bottom of the dialog.', + table: { category: apiCategory.slots } }, size: { + name: 'Dialog sizing', description: sizeDescription, options: [ DialogSizeOptions.smallGrowable, @@ -195,17 +227,20 @@ const metadata: Meta<DialogArgs> = { [DialogSizeOptions.smallGrowable]: 'Small growable', [DialogSizeOptions.largeFixed]: 'Large fixed' } - } + }, + table: { category: apiCategory.styles } }, show: { name: 'show()', description: - 'Call this member function to open the dialog. It returns a `Promise` that is resolved when the dialog is closed. The resolved value is either the reason passed to `close(...)` or the symbol `UserDismissed` if the dialog was dismissed via the ESC key.' + 'Call this member function to open the dialog. It returns a `Promise` that is resolved when the dialog is closed. The resolved value is either the reason passed to `close(...)` or the symbol `UserDismissed` if the dialog was dismissed via the `Esc` key.', + table: { category: apiCategory.methods } }, close: { name: 'close(reason)', description: - 'Call this member function to close the dialog. It takes an optional `reason` value which can be any type. This value is returned from `show()` via a `Promise`' + 'Call this member function to close the dialog. It takes an optional `reason` value which can be any type. This value is returned from `show()` via a `Promise`.', + table: { category: apiCategory.methods } }, openAndHandleResult: { table: { @@ -218,14 +253,14 @@ const metadata: Meta<DialogArgs> = { subtitle: 'Dialog subtitle', headerHidden: false, footerHidden: false, - includeFooterButtons: true, preventDismiss: false, content: ExampleContentType.shortContent, + footer: ExampleFooterContentType.buttons, size: DialogSizeOptions.smallGrowable, openAndHandleResult: (dialogRef, textFieldRef) => { void (async () => { const reason = await dialogRef.show(); - textFieldRef.value = reason === UserDismissed ? 'ESC pressed' : reason; + textFieldRef.value = reason === UserDismissed ? 'Esc pressed' : reason; })(); } } diff --git a/packages/nimble-components/src/dialog/tests/types.ts b/packages/storybook/src/nimble/dialog/types.ts similarity index 66% rename from packages/nimble-components/src/dialog/tests/types.ts rename to packages/storybook/src/nimble/dialog/types.ts index 7c5787c420..853f20fec3 100644 --- a/packages/nimble-components/src/dialog/tests/types.ts +++ b/packages/storybook/src/nimble/dialog/types.ts @@ -5,6 +5,13 @@ export const ExampleContentType = { export type ExampleContentType = (typeof ExampleContentType)[keyof typeof ExampleContentType]; +export const ExampleFooterContentType = { + text: 'text', + buttons: 'buttons' +} as const; +export type ExampleFooterContentType = + (typeof ExampleFooterContentType)[keyof typeof ExampleFooterContentType]; + export const DialogSizeOptions = { smallGrowable: 'Small growable', largeFixed: 'Large growable' diff --git a/packages/storybook/src/nimble/drawer/drawer.mdx b/packages/storybook/src/nimble/drawer/drawer.mdx index 47694b8bda..0dd9fd2f3d 100644 --- a/packages/storybook/src/nimble/drawer/drawer.mdx +++ b/packages/storybook/src/nimble/drawer/drawer.mdx @@ -1,5 +1,6 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import * as drawerStories from './drawer.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; <Meta of={drawerStories} /> <Title of={drawerStories} /> @@ -7,7 +8,11 @@ import * as drawerStories from './drawer.stories'; Specialized dialog designed to slide in from either side of the page. Typically used for a configuration pane. <Canvas of={drawerStories.drawer} /> + +## API + <Controls of={drawerStories.drawer} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/drawer/drawer.stories.ts b/packages/storybook/src/nimble/drawer/drawer.stories.ts index e3b6c34a5d..e2ccddec8c 100644 --- a/packages/storybook/src/nimble/drawer/drawer.stories.ts +++ b/packages/storybook/src/nimble/drawer/drawer.stories.ts @@ -19,8 +19,10 @@ import { DrawerLocation } from '../../../../nimble-components/src/drawer/types'; import { DrawerWidthOptions, ExampleContentType } from '../../../../nimble-components/src/drawer/tests/types'; import { + apiCategory, createUserSelectedThemeStory, - overrideWarning + overrideWarning, + preventDismissDescription } from '../../utilities/storybook'; interface DrawerArgs { @@ -149,12 +151,14 @@ const metadata: Meta<DrawerArgs> = { argTypes: { location: { options: [DrawerLocation.left, DrawerLocation.right], - control: { type: 'radio' } + control: { type: 'radio' }, + description: 'The side of the screen from which the drawer will slide in', + table: { category: apiCategory.attributes } }, preventDismiss: { name: 'prevent-dismiss', - description: - 'A boolean attribute to configure whether or not the drawer is dismissible via the `Esc` key, or any other dismiss action that is supported in the future' + description: preventDismissDescription({ componentName: 'drawer' }), + table: { category: apiCategory.attributes } }, content: { options: [ @@ -169,9 +173,12 @@ const metadata: Meta<DrawerArgs> = { [ExampleContentType.headerContentFooter]: 'Header/Content/Footer Example' } - } + }, + description: 'The drawer content, which can be arbitrary HTML.', + table: { category: apiCategory.slots } }, width: { + name: 'Drawer width', description: widthDescription, options: [ DrawerWidthOptions.default, @@ -189,17 +196,20 @@ const metadata: Meta<DrawerArgs> = { [DrawerWidthOptions.medium500]: 'Medium - 500px', [DrawerWidthOptions.fitContent]: 'fit-content' } - } + }, + table: { category: apiCategory.styles } }, show: { name: 'show()', description: - 'Call this member function to open the drawer. It returns a `Promise` that is resolved when the drawer is closed. The resolved value is either the reason passed to `close(...)` or the symbol `UserDismissed` if the drawer was dismissed via the `Esc` key.' + 'Call this member function to open the drawer. It returns a `Promise` that is resolved when the drawer is closed. The resolved value is either the reason passed to `close(...)` or the symbol `UserDismissed` if the drawer was dismissed via the `Esc` key.', + table: { category: apiCategory.methods } }, close: { name: 'close(reason)', description: - 'Call this member function to close the drawer. It takes an optional `reason` value which can be any type. This value is returned from `show()` via a `Promise`' + 'Call this member function to close the drawer. It takes an optional `reason` value which can be any type. This value is returned from `show()` via a `Promise`.', + table: { category: apiCategory.methods } }, drawerRef: { table: { diff --git a/packages/storybook/src/nimble/icon-base/icons.mdx b/packages/storybook/src/nimble/icon-base/icons.mdx index ec28df3efc..175b42e5a9 100644 --- a/packages/storybook/src/nimble/icon-base/icons.mdx +++ b/packages/storybook/src/nimble/icon-base/icons.mdx @@ -1,6 +1,7 @@ import { Meta, Controls, Canvas, Title } from '@storybook/blocks'; import * as iconsStories from './icons.stories'; import { iconAddTag } from '../../../../nimble-components/src/icons/add'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; <Meta of={iconsStories} /> <Title of={iconsStories} /> @@ -8,7 +9,11 @@ import { iconAddTag } from '../../../../nimble-components/src/icons/add'; Nimble icons can be slotted into other components or used independently. Each icon is available as a custom element. For example, <Tag name={iconAddTag} openClose/>. <Canvas of={iconsStories.icons} /> + +## API + <Controls of={iconsStories.icons} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/icon-base/icons.stories.ts b/packages/storybook/src/nimble/icon-base/icons.stories.ts index 05276e8f0a..63fe551a8e 100644 --- a/packages/storybook/src/nimble/icon-base/icons.stories.ts +++ b/packages/storybook/src/nimble/icon-base/icons.stories.ts @@ -13,6 +13,7 @@ import { tableColumnTextTag } from '../../../../nimble-components/src/table-colu import { IconSeverity } from '../../../../nimble-components/src/icon-base/types'; import { iconMetadata } from '../../../../nimble-components/src/icon-base/tests/icon-metadata'; import { + apiCategory, createUserSelectedThemeStory, fastParameters, overrideWarning @@ -71,7 +72,8 @@ export const icons: StoryObj<IconArgs> = { severity: { options: Object.keys(IconSeverity), control: { type: 'radio' }, - description: severityDescription + description: severityDescription, + table: { category: apiCategory.attributes } }, tableRef: { table: { diff --git a/packages/storybook/src/nimble/menu-button/menu-button.stories.ts b/packages/storybook/src/nimble/menu-button/menu-button.stories.ts index 1a28c1ab5a..fcfa2ea269 100644 --- a/packages/storybook/src/nimble/menu-button/menu-button.stories.ts +++ b/packages/storybook/src/nimble/menu-button/menu-button.stories.ts @@ -111,13 +111,13 @@ const metadata: Meta<MenuButtonArgs> = { table: { category: apiCategory.attributes } }, toggle: { - description: 'Fires after the menu button is toggled.', + description: 'Event emitted after the menu button is toggled.', table: { category: apiCategory.events }, control: false }, beforetoggle: { description: - 'Fires before the menu button is toggled. This can be used to populate the menu before it is opened.', + 'Event emitted before the menu button is toggled. This can be used to populate the menu before it is opened.', table: { category: apiCategory.events }, control: false } diff --git a/packages/storybook/src/nimble/menu/menu.mdx b/packages/storybook/src/nimble/menu/menu.mdx index 6fef9cb4c1..1533ec2ca3 100644 --- a/packages/storybook/src/nimble/menu/menu.mdx +++ b/packages/storybook/src/nimble/menu/menu.mdx @@ -38,7 +38,7 @@ Use the <Tag name={anchorMenuItemTag} /> child element to navigate to a URL when <Canvas of={menuStories.anchorMenuItem} /> <Controls of={menuStories.anchorMenuItem} /> -#### Anchor Menu Item Target Configuration +#### Target Configuration <TargetDocs /> diff --git a/packages/storybook/src/nimble/menu/menu.stories.ts b/packages/storybook/src/nimble/menu/menu.stories.ts index e4ad39ead2..c6a0c5a351 100644 --- a/packages/storybook/src/nimble/menu/menu.stories.ts +++ b/packages/storybook/src/nimble/menu/menu.stories.ts @@ -175,7 +175,7 @@ export const menuItem: StoryObj<MenuItemArgs> = { table: { category: apiCategory.attributes } }, change: { - description: 'Fires after the menu item is selected.', + description: 'Event emitted after the menu item is selected.', table: { category: apiCategory.events }, control: false } diff --git a/packages/storybook/src/nimble/rich-text-mention/users/rich-text-mention-users.stories.ts b/packages/storybook/src/nimble/rich-text-mention/users/rich-text-mention-users.stories.ts index 9dea4564c4..cdd19d725c 100644 --- a/packages/storybook/src/nimble/rich-text-mention/users/rich-text-mention-users.stories.ts +++ b/packages/storybook/src/nimble/rich-text-mention/users/rich-text-mention-users.stories.ts @@ -25,15 +25,15 @@ The object's type is \`RichTextMentionValidity\`, and it contains the following - \`missingDisplayNameValue\`: \`true\` when a mapping has no \`display-name\` value `; -const mentionUpdateEventDescription = `For the editor, This event will be fired on following action: +const mentionUpdateEventDescription = `For the editor, This event will be emitted on following action: - Whenever the \`@\` character is entered into the editor - When the user types any character after \`@\` into the editor -This fires with the \`eventData\` containing the current text that is added after the \`@\` character and before the current position of the +This emits with the \`eventData\` containing the current text that is added after the \`@\` character and before the current position of the text cursor. -For the viewer, this event will never be fired. +For the viewer, this event will never be emitted. `; const metadata: Meta = { diff --git a/packages/storybook/src/nimble/rich-text/editor/rich-text-editor.stories.ts b/packages/storybook/src/nimble/rich-text/editor/rich-text-editor.stories.ts index fddcd9ad87..f94d7dcf60 100644 --- a/packages/storybook/src/nimble/rich-text/editor/rich-text-editor.stories.ts +++ b/packages/storybook/src/nimble/rich-text/editor/rich-text-editor.stories.ts @@ -202,7 +202,7 @@ const metadata: Meta<RichTextEditorArgs> = { input: { name: 'input', description: - 'This event is fired when there is a change in the content of the editor.', + 'Event emitted when there is a change in the content of the editor.', control: false }, validity: { diff --git a/packages/storybook/src/nimble/spinner/spinner.mdx b/packages/storybook/src/nimble/spinner/spinner.mdx index ff5ef89734..629b1be1fb 100644 --- a/packages/storybook/src/nimble/spinner/spinner.mdx +++ b/packages/storybook/src/nimble/spinner/spinner.mdx @@ -1,5 +1,6 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import * as spinnerStories from './spinner.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; import { spinnerTag } from '../../../../nimble-components/src/spinner'; <Meta of={spinnerStories} /> @@ -9,13 +10,16 @@ import { spinnerTag } from '../../../../nimble-components/src/spinner'; particular region of a page to represent loading progress, or an ongoing operation, of an indeterminate / unknown duration. - It has 3 sizes (64px, 32px, and 16px) and 2 appearance types (default and - accent). - <Canvas of={spinnerStories.spinner} /> + +## API + <Controls of={spinnerStories.spinner} /> +<ComponentApisLink /> + +## Styling -## Sizing +### Sizing The 64px spinner is a less commonly used size reserved for large negative empty space. Only one 64px spinner should be used on a single screen at one time. @@ -25,7 +29,7 @@ The 16px spinner is the most compact option for tight spaces such as grid cells Multiple 16px spinners can be used on a single screen at one time. -## Styling / Theme +### Appearances Use the `default` appearance and Color theme for UIs with a strong background color. Do not use the `accent` appearance with the Color theme. diff --git a/packages/storybook/src/nimble/spinner/spinner.stories.ts b/packages/storybook/src/nimble/spinner/spinner.stories.ts index 6b07a709ac..a97a346e9f 100644 --- a/packages/storybook/src/nimble/spinner/spinner.stories.ts +++ b/packages/storybook/src/nimble/spinner/spinner.stories.ts @@ -13,7 +13,7 @@ import { spinnerTag } from '../../../../nimble-components/src/spinner'; import { SpinnerAppearance } from '../../../../nimble-components/src/spinner/types'; import { isChromatic } from '../../utilities/isChromatic'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../utilities/storybook'; const spinnerSize = { small: null, @@ -31,6 +31,7 @@ const metadata: Meta<SpinnerArgs> = { parameters: {}, argTypes: { size: { + name: 'Spinner sizing', description: '<p>Size of the spinner component.</p><details><summary>Usage details</summary>To customize its size, set its CSS ' + '<span style="font-family: monospace;">height</span> to a design token, and its width will automatically match its height. Each size will also require minimum pixel margins.<br/><ul>' @@ -53,7 +54,7 @@ const metadata: Meta<SpinnerArgs> = { Requires 64px minimum margins. </li></ul></details>`, options: Object.keys(spinnerSize), - table: { defaultValue: { summary: 'Small (16x16)' } }, + table: { category: apiCategory.styles }, control: { type: 'radio', labels: { @@ -81,7 +82,8 @@ const metadata: Meta<SpinnerArgs> = { + `<li>For appearance \`accent\`:<br/> Use for promoting NI branding and adding a splash of color in a monochromatic setting. Common places to use is home screens, licensing, dialogs and any instances where there will not be a conflict with green representing status.<br/> The green version is not intended to represent โ€œGoodโ€ or โ€œSuccessโ€. - </li></ul></details>` + </li></ul></details>`, + table: { category: apiCategory.attributes } } }, // Disable animation in Chromatic because it intermittently causes shapshot differences diff --git a/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.mdx b/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.mdx index bc4a08c8e1..114aada9ff 100644 --- a/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.mdx +++ b/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.mdx @@ -10,8 +10,15 @@ import { tableTag } from '../../../../../nimble-components/src/table'; The <Tag name={tableColumnAnchorTag}/> column is used to display string fields as links or text in the <Tag name={tableTag}/>. If a row provides an href for a link, that cell will display a link, otherwise it will display plain text. <Canvas of={tableColumnAnchorStories.anchorColumn} /> + +## API + <Controls of={tableColumnAnchorStories.anchorColumn} /> +### Target Configuration + +<TargetDocs /> + ## Usage ### Best Practices @@ -22,10 +29,6 @@ The <Tag name={tableColumnAnchorTag}/> column is used to display string fields a - If a label is not available or known for a url, the url itself may be explicitly provided for the label to ensure each distinct url has a distinct label. As grouping is done by label value, this prevents unrelated URLs from being grouped together. - For records without a url, the label may also be omitted. All omitted labels should consistently use `null`, `undefined`, or empty string but not a combination of those values. -### Target Configuration - -<TargetDocs /> - ### Angular Usage In an Angular app, you can configure a callback to intercept clicks so that you may invoke the router to perform the navigation instead of the default handler: diff --git a/packages/storybook/src/nimble/tabs/tabs.stories.ts b/packages/storybook/src/nimble/tabs/tabs.stories.ts index d665191de2..0f438969c7 100644 --- a/packages/storybook/src/nimble/tabs/tabs.stories.ts +++ b/packages/storybook/src/nimble/tabs/tabs.stories.ts @@ -66,7 +66,7 @@ export const tabs: StoryObj<TabsArgs> = { table: { category: apiCategory.slots } }, change: { - description: 'Fires when the active tab is changed', + description: 'Event emitted when the active tab is changed', control: false, table: { category: apiCategory.events } } diff --git a/packages/storybook/src/nimble/theme-provider/theme-provider.mdx b/packages/storybook/src/nimble/theme-provider/theme-provider.mdx index 4161adc422..f45539697c 100644 --- a/packages/storybook/src/nimble/theme-provider/theme-provider.mdx +++ b/packages/storybook/src/nimble/theme-provider/theme-provider.mdx @@ -1,5 +1,6 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import { themeProvider } from './theme-provider.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; <Meta title="Tokens/Theme Provider" /> <Title>Theme Provider @@ -7,4 +8,8 @@ import { themeProvider } from './theme-provider.stories'; The theme provider element allows configuring certain token values for the contained HTML tree. + +## API + + diff --git a/packages/storybook/src/nimble/theme-provider/theme-provider.stories.ts b/packages/storybook/src/nimble/theme-provider/theme-provider.stories.ts index 336817b0e5..8e80c0bcd1 100644 --- a/packages/storybook/src/nimble/theme-provider/theme-provider.stories.ts +++ b/packages/storybook/src/nimble/theme-provider/theme-provider.stories.ts @@ -9,7 +9,7 @@ import { type SharedTableArgs, sharedTableArgs } from '../table-column/base/table-column-stories-utils'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../utilities/storybook'; const simpleData = [ { @@ -88,7 +88,8 @@ export const themeProvider: StoryObj = { summary: '"light"' }, options: Object.keys(Theme), - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes } }, lang: { description: langDescription, @@ -97,7 +98,8 @@ export const themeProvider: StoryObj = { '`lang` of the document element if set, otherwise "en-US".' }, options: ['en-US', 'fr-FR', 'de-DE'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes } }, direction: { description: @@ -106,7 +108,8 @@ export const themeProvider: StoryObj = { summary: '"ltr"' }, options: Object.keys(Direction), - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes } } }, args: { diff --git a/packages/storybook/src/nimble/toggle-button/toggle-button.stories.ts b/packages/storybook/src/nimble/toggle-button/toggle-button.stories.ts index 64ca61d926..27d39ca540 100644 --- a/packages/storybook/src/nimble/toggle-button/toggle-button.stories.ts +++ b/packages/storybook/src/nimble/toggle-button/toggle-button.stories.ts @@ -82,7 +82,7 @@ const metadata: Meta = { table: { category: apiCategory.slots } }, change: { - description: 'Fires when the toggle button is pressed via mouse or keyboard.', + description: 'Event emitted when the toggle button is pressed via mouse or keyboard.', table: { category: apiCategory.events }, control: false } diff --git a/packages/storybook/src/nimble/toolbar/toolbar.mdx b/packages/storybook/src/nimble/toolbar/toolbar.mdx index b42fa79ccc..3d05edaadf 100644 --- a/packages/storybook/src/nimble/toolbar/toolbar.mdx +++ b/packages/storybook/src/nimble/toolbar/toolbar.mdx @@ -1,6 +1,7 @@ -import { Canvas, Meta, Title } from '@storybook/blocks'; +import { Canvas, Controls, Meta, Title } from '@storybook/blocks'; import { NimbleToolbar } from './toolbar.react'; import * as toolbarStories from './toolbar.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; @@ -22,6 +23,11 @@ nimble-toolbar::part(positioning-region) { <Canvas of={toolbarStories.toolbar} /> +## API + +<Controls of={toolbarStories.toolbar} /> + + {/* ## Styling */} {/* ## Usage */} diff --git a/packages/storybook/src/nimble/toolbar/toolbar.stories.ts b/packages/storybook/src/nimble/toolbar/toolbar.stories.ts index 5957d921e3..639593cc88 100644 --- a/packages/storybook/src/nimble/toolbar/toolbar.stories.ts +++ b/packages/storybook/src/nimble/toolbar/toolbar.stories.ts @@ -7,9 +7,14 @@ import { iconFilterTag } from '../../../../nimble-components/src/icons/filter'; import { iconPencilTag } from '../../../../nimble-components/src/icons/pencil'; import { iconTrashTag } from '../../../../nimble-components/src/icons/trash'; import { toolbarTag } from '../../../../nimble-components/src/toolbar'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../utilities/storybook'; -const metadata: Meta = { +interface ToolbarArgs { + start: undefined; + end: undefined; +} + +const metadata: Meta<ToolbarArgs> = { title: 'Components/Toolbar', parameters: {}, // prettier-ignore @@ -37,7 +42,19 @@ const metadata: Meta = { Filter </${buttonTag}> </${toolbarTag}> - `) + `), + argTypes: { + start: { + description: 'Content which will be positioned at the start of the toolbar.', + control: false, + table: { category: apiCategory.slots } + }, + end: { + description: 'Content which will be positioned at the end of the toolbar.', + control: false, + table: { category: apiCategory.slots } + }, + } }; export default metadata; diff --git a/packages/storybook/src/nimble/tree-view/tree-view.mdx b/packages/storybook/src/nimble/tree-view/tree-view.mdx index c2ae905d1f..8b6865d83b 100644 --- a/packages/storybook/src/nimble/tree-view/tree-view.mdx +++ b/packages/storybook/src/nimble/tree-view/tree-view.mdx @@ -1,6 +1,7 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import TargetDocs from '../patterns/anchor/target-docs.mdx'; import * as treeViewStories from './tree-view.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; import { treeViewTag } from '../../../../nimble-components/src/tree-view'; import { treeItemTag } from '../../../../nimble-components/src/tree-item'; import { anchorTreeItemTag } from '../../../../nimble-components/src/anchor-tree-item'; @@ -17,26 +18,37 @@ expanded to reveal the contents of the folder, which may be files, folders, or b The <Tag name={treeViewTag}/> supports standard <Tag name={treeItemTag}/> and <Tag name={anchorTreeItemTag}/>, which navigate to a url upon activation. Both types of tree items support icons as slotted content. +<Canvas of={treeViewStories.multipleTreeItems} /> + +## API + +<Controls of={treeViewStories.multipleTreeItems} /> +<ComponentApisLink /> + +### Tree Item + +Use a <Tag name={treeItemTag} /> child element if you want a tree item that calls a callback, has a value, and/or has child items. + <Canvas of={treeViewStories.treeItem} /> <Controls of={treeViewStories.treeItem} /> -{/* ## Styling */} +### Anchor Tree Item -{/* ## Usage */} +Use a <Tag name={anchorTreeItemTag} /> child element to navigate to a URL when the item is activated. -{/* ## Examples */} +<Canvas of={treeViewStories.anchorTreeItem} /> +<Controls of={treeViewStories.anchorTreeItem} /> -### Child Elements +#### Anchor Tree Item Target Configuration -- <Tag name={treeItemTag} /> - Use a this child element if you want a tree item - that calls a callback, has a value, and/or has child items. -- <Tag name={anchorTreeItemTag} /> - Use this child element to navigate to a URL - when the item is activated. +<TargetDocs /> -## Accessibility +{/* ## Styling */} -### Anchor Tree Item Target Configuration +{/* ## Usage */} -<TargetDocs /> +{/* ## Examples */} + +{/* ## Accessibility */} {/* ## Resources */} diff --git a/packages/storybook/src/nimble/tree-view/tree-view.stories.ts b/packages/storybook/src/nimble/tree-view/tree-view.stories.ts index 6f99966b78..e12ef8e9b3 100644 --- a/packages/storybook/src/nimble/tree-view/tree-view.stories.ts +++ b/packages/storybook/src/nimble/tree-view/tree-view.stories.ts @@ -7,12 +7,14 @@ import { treeItemTag } from '../../../../nimble-components/src/tree-item'; import { anchorTreeItemTag } from '../../../../nimble-components/src/anchor-tree-item'; import { treeViewTag } from '../../../../nimble-components/src/tree-view'; import { TreeViewSelectionMode } from '../../../../nimble-components/src/tree-view/types'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory, disabledDescription, iconDescription, textContentDescription } from '../../utilities/storybook'; import { hrefDescription } from '../patterns/anchor/anchor-docs'; interface TreeArgs { selectionMode: TreeViewSelectionMode; options: ItemArgs[]; + expandedChange: undefined; + selectedChange: undefined; } interface ItemArgs { @@ -33,9 +35,9 @@ interface AnchorItemArgs { } const selectionModeDescription = ` -<li>All: all items in the tree are selectable through user interaction</li> -<li>Leaves only: only the leaf items in the tree are selectable through user interaction</li> -<li>None: no items in the tree are selectable through user interaction</li> +<li>all: All items in the tree are selectable through user interaction</li> +<li>leaves-only: Only the leaf items in the tree are selectable through user interaction</li> +<li>none: No items in the tree are selectable through user interaction</li> <br> Note: Changing the selection mode does not affect which items can be selected programmatically. `; @@ -47,11 +49,6 @@ const metadata: Meta<TreeArgs> = { actions: { handles: ['expanded-change', 'selected-change'] } - }, - argTypes: { - selectionMode: { - description: selectionModeDescription - } } }; @@ -66,10 +63,32 @@ export const treeItem: StoryObj<ItemArgs> = { } }, argTypes: { + label: { + name: 'default', + description: `${textContentDescription({ componentName: 'tree item' })} Tree items can also contain child tree items to establish hierarchy.`, + table: { category: apiCategory.slots } + }, + value: { + description: 'A value for this tree item that can be used to identify the item when handling tree events.', + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'tree item' }), + table: { category: apiCategory.attributes } + }, icon: { - description: - 'When including an icon, set `slot="start"` on the icon to ensure proper styling.' - } + name: 'start', + description: iconDescription, + table: { category: apiCategory.slots } + }, + selected: { + description: 'Whether this item is selected.', + table: { category: apiCategory.attributes } + }, + expanded: { + description: 'Whether this item is expanded.', + table: { category: apiCategory.attributes } + }, }, // prettier-ignore render: createUserSelectedThemeStory(html` @@ -97,22 +116,34 @@ export const anchorTreeItem: StoryObj<AnchorItemArgs> = { parameters: { docs: { description: { - story: 'Use a `nimble-anchor-tree-item` to navigate to a URL from a `nimble-tree-view`. If you want a tree item that can have a value and/or child items, use a `nimble-tree-item` instead.' + story: `Use a \`${anchorTreeItemTag}\` to navigate to a URL from a \`${treeViewTag}\`. If you want a tree item that can have a value and/or child items, use a \`${treeItemTag}\` instead.` } } }, argTypes: { - icon: { - description: - 'When including an icon, set `slot="start"` on the icon to ensure proper styling.' + label: { + name: 'default', + description: textContentDescription({ componentName: 'anchor tree item' }), + table: { category: apiCategory.slots } + }, + href: { + description: hrefDescription({ componentName: 'anchor tree item', includeDisable: false }), + table: { category: apiCategory.attributes } + }, + disabled: { + description: disabledDescription({ componentName: 'tree item' }), + table: { category: apiCategory.attributes } }, selected: { description: - 'Cannot be selected interactively, as click/Enter causes navigation.' + 'Set this attribute programmatically to render the item as selected. It cannot be selected interactively, as click/Enter causes navigation.', + table: { category: apiCategory.attributes } + }, + icon: { + name: 'start', + description: iconDescription, + table: { category: apiCategory.slots } }, - href: { - description: hrefDescription({ componentName: 'anchor tree item', includeDisable: false }) - } }, // prettier-ignore render: createUserSelectedThemeStory(html` @@ -135,9 +166,29 @@ export const anchorTreeItem: StoryObj<AnchorItemArgs> = { export const multipleTreeItems: StoryObj<TreeArgs> = { argTypes: { selectionMode: { + name: 'selection-mode', options: Object.values(TreeViewSelectionMode), - control: { type: 'radio' } - } + control: { type: 'radio' }, + description: selectionModeDescription, + table: { category: apiCategory.attributes } + + }, + options: { + name: 'default', + description: + `One or more \`${treeItemTag}\` or \`${anchorTreeItemTag}\` elements which populate the tree. Nest items to establish tree hierarchy.`, + table: { category: apiCategory.slots } + }, + expandedChange: { + name: 'expanded-change', + description: 'Event emitted when an item is expanded or collapsed.', + table: { category: apiCategory.events } + }, + selectedChange: { + name: 'selected-change', + description: 'Event emitted when an item is selected or deselected.', + table: { category: apiCategory.events } + }, }, // prettier-ignore render: createUserSelectedThemeStory(html` diff --git a/packages/storybook/src/nimble/wafer-map/wafer-map.stories.ts b/packages/storybook/src/nimble/wafer-map/wafer-map.stories.ts index b0cedf6337..19d8ce2670 100644 --- a/packages/storybook/src/nimble/wafer-map/wafer-map.stories.ts +++ b/packages/storybook/src/nimble/wafer-map/wafer-map.stories.ts @@ -382,7 +382,7 @@ const metadata: Meta<WaferMapArgs> = { dieHover: { name: 'die-hover', description: - 'The event is fired whenever the mouse enters or leaves a die. In the event data, `detail.currentDie` will be set to the `WaferMapDie` element of the `dies` array that is being hovered or `undefined` if the mouse is leaving a die.' + 'Event emitted whenever the mouse enters or leaves a die. In the event data, `detail.currentDie` will be set to the `WaferMapDie` element of the `dies` array that is being hovered or `undefined` if the mouse is leaving a die.' }, validity: { description: `Readonly object of boolean values that represents the validity states that the wafer map's configuration can be in. diff --git a/packages/storybook/src/utilities/storybook.ts b/packages/storybook/src/utilities/storybook.ts index 5e94feaff8..733b14a251 100644 --- a/packages/storybook/src/utilities/storybook.ts +++ b/packages/storybook/src/utilities/storybook.ts @@ -169,7 +169,8 @@ export const apiCategory = { localizableLabels: 'Localizable Labels', methods: 'Methods', nonAttributeProperties: 'Properties', - slots: 'Slots' + slots: 'Slots', + styles: 'Styles' } as const; export const appearanceDescription = (options: { componentName: string }): string => `This attribute affects the appearance of the ${options.componentName}.`; @@ -184,3 +185,5 @@ export const errorVisibleDescription = 'When set to `true`, the `error-text` mes export const dropdownPositionDescription = (options: { componentName: string }): string => `Controls the position of the dropdown relative to the ${options.componentName}.`; export const optionsDescription = `The \`${listOptionTag}\` items for the user to select from.`; + +export const preventDismissDescription = (options: { componentName: string }): string => `Prevents the \`Esc\` key from closing the ${options.componentName}.`; From aca764d1490ba5f13feac228fb25b4acc9d98222 Mon Sep 17 00:00:00 2001 From: Jesse Attas <jattasNI@users.noreply.github.com> Date: Thu, 30 May 2024 08:51:09 -0500 Subject: [PATCH 8/8] Improve API documentation of table components (#2140) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Pull Request ## ๐Ÿคจ Rationale Ongoing efforts towards #824. This PR covers the table and its columns. ## ๐Ÿ‘ฉโ€๐Ÿ’ป Implementation Mostly following established patterns. Some interesting notes: 1. For the Table Column Configuration doc, we had divided the documentation into separate targeted stories. I decided these were useful but we also should have a single table describing the whole API of a column. I created the latter under the API section and moved the targeted stories to an Examples section. Let me know if it feels right! 2. The above resulted in a renamed story which appears as a Chromatic diff. ## ๐Ÿงช Testing Interacting with the built Storybook. ## โœ… 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. --- packages/storybook/.storybook/preview.js | 2 +- .../mapping/empty/mapping-empty.stories.ts | 8 +- .../mapping/icon/mapping-icon.stories.ts | 17 ++- .../spinner/mapping-spinner.stories.ts | 11 +- .../mapping/text/mapping-text.stories.ts | 8 +- .../mapping/user/mapping-user.stories.ts | 10 +- .../anchor/table-column-anchor.mdx | 2 + .../anchor/table-column-anchor.stories.ts | 17 ++- .../nimble/table-column/base/table-column.mdx | 26 ++-- .../table-column/base/table-column.stories.ts | 112 +++++++++++++++--- .../date-text/table-column-date-text.mdx | 5 + .../table-column-date-text.stories.ts | 77 ++++++++---- .../table-column-duration-text.mdx | 5 + .../table-column-duration-text.stories.ts | 8 +- .../mapping/table-column-mapping.mdx | 37 +++--- .../mapping/table-column-mapping.stories.ts | 25 +++- .../number-text/table-column-number-text.mdx | 5 + .../table-column-number-text.stories.ts | 32 +++-- .../table-column/text/table-column-text.mdx | 5 + .../text/table-column-text.stories.ts | 8 +- packages/storybook/src/nimble/table/table.mdx | 34 +++--- .../src/nimble/table/table.stories.ts | 101 ++++++++++++---- packages/storybook/src/utilities/storybook.ts | 2 + 23 files changed, 405 insertions(+), 152 deletions(-) diff --git a/packages/storybook/.storybook/preview.js b/packages/storybook/.storybook/preview.js index c9a45a56b8..c8039aaba8 100644 --- a/packages/storybook/.storybook/preview.js +++ b/packages/storybook/.storybook/preview.js @@ -105,5 +105,5 @@ configureActions({ depth: 1 }); -// Update the GUID on this line to trigger a turbosnap full rebuild: 354fdf0e-bdb4-4dd9-a6e5-21bf71c6efe6 +// Update the GUID on this line to trigger a turbosnap full rebuild: 354fdf0f-bdb4-4dd9-a6e5-21bf71c6efe6 // See https://www.chromatic.com/docs/turbosnap/#full-rebuilds diff --git a/packages/storybook/src/nimble/mapping/empty/mapping-empty.stories.ts b/packages/storybook/src/nimble/mapping/empty/mapping-empty.stories.ts index a818334157..5a053d9be8 100644 --- a/packages/storybook/src/nimble/mapping/empty/mapping-empty.stories.ts +++ b/packages/storybook/src/nimble/mapping/empty/mapping-empty.stories.ts @@ -1,7 +1,7 @@ import { html } from '@microsoft/fast-element'; import type { Meta, StoryObj } from '@storybook/html'; import { mappingKeyDescription } from '../base/story-helpers'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../../utilities/storybook'; import { hiddenWrapper } from '../../../utilities/hidden'; const metadata: Meta = { @@ -25,11 +25,13 @@ export const emptyMapping: StoryObj = { argTypes: { key: { control: false, - description: mappingKeyDescription('nothing') + description: mappingKeyDescription('nothing'), + table: { category: apiCategory.attributes }, }, text: { control: false, - description: 'A textual description of the value. This value will be displayed in group rows, but table cells will be empty. This attribute is required.' + description: 'A textual description of the value. This value will be displayed in group rows, but table cells will be empty. This attribute is required.', + table: { category: apiCategory.attributes }, } }, args: {} diff --git a/packages/storybook/src/nimble/mapping/icon/mapping-icon.stories.ts b/packages/storybook/src/nimble/mapping/icon/mapping-icon.stories.ts index 818af643b6..9c1452554a 100644 --- a/packages/storybook/src/nimble/mapping/icon/mapping-icon.stories.ts +++ b/packages/storybook/src/nimble/mapping/icon/mapping-icon.stories.ts @@ -1,7 +1,7 @@ import { html } from '@microsoft/fast-element'; import type { Meta, StoryObj } from '@storybook/html'; import { mappingKeyDescription } from '../base/story-helpers'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../../utilities/storybook'; import { hiddenWrapper } from '../../../utilities/hidden'; const metadata: Meta = { @@ -23,28 +23,33 @@ export const iconMapping: StoryObj = { argTypes: { key: { description: mappingKeyDescription('the mapped icon'), - control: false + control: false, + table: { category: apiCategory.attributes }, }, icon: { control: false, - description: 'The tag name of the Nimble icon to render, e.g. `nimble-icon-check`.' + description: 'The tag name of the Nimble icon to render, e.g. `nimble-icon-check`.', + table: { category: apiCategory.attributes }, }, severity: { control: false, description: - 'Must be one of the values in the `IconSeverity` enum. Controls the color of the icon.' + 'Must be one of the values in the `IconSeverity` enum. Controls the color of the icon.', + table: { category: apiCategory.attributes }, }, text: { control: false, description: `A textual description of the value. The text will be displayed next to the icon in a cell if \`text-hidden\` is not set, or as the tooltip and accessible name of the icon if \`text-hidden\` is set. The text is also displayed next to the icon - in a group header. This attribute is required.` + in a group header. This attribute is required.`, + table: { category: apiCategory.attributes }, }, textHidden: { control: false, name: 'text-hidden', description: - "When set, the text is hidden within the table's cells. When unset, the text is rendered next to the icon within the cell." + "When set, the text is hidden within the table's cells. When unset, the text is rendered next to the icon within the cell.", + table: { category: apiCategory.attributes }, } }, args: {} diff --git a/packages/storybook/src/nimble/mapping/spinner/mapping-spinner.stories.ts b/packages/storybook/src/nimble/mapping/spinner/mapping-spinner.stories.ts index f07098343a..9476d03dba 100644 --- a/packages/storybook/src/nimble/mapping/spinner/mapping-spinner.stories.ts +++ b/packages/storybook/src/nimble/mapping/spinner/mapping-spinner.stories.ts @@ -1,7 +1,7 @@ import { html } from '@microsoft/fast-element'; import type { Meta, StoryObj } from '@storybook/html'; import { mappingKeyDescription } from '../base/story-helpers'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../../utilities/storybook'; import { hiddenWrapper } from '../../../utilities/hidden'; const metadata: Meta = { @@ -23,19 +23,22 @@ export const spinnerMapping: StoryObj = { argTypes: { key: { description: mappingKeyDescription('a spinner'), - control: false + control: false, + table: { category: apiCategory.attributes }, }, text: { control: false, description: `A textual description of the value. The text will be displayed next to the spinner in a cell if \`text-hidden\` is not set, or as the tooltip and accessible name of the spinner if \`text-hidden\` is set. The text is also displayed next to the spinner - in a group header. This attribute is required.` + in a group header. This attribute is required.`, + table: { category: apiCategory.attributes }, }, textHidden: { control: false, name: 'text-hidden', description: - "When set, the text is hidden within the table's cells. When unset, the text is rendered next to the spinner within the cell." + "When set, the text is hidden within the table's cells. When unset, the text is rendered next to the spinner within the cell.", + table: { category: apiCategory.attributes }, } }, args: {} diff --git a/packages/storybook/src/nimble/mapping/text/mapping-text.stories.ts b/packages/storybook/src/nimble/mapping/text/mapping-text.stories.ts index ea8d34b752..38a1c62cb7 100644 --- a/packages/storybook/src/nimble/mapping/text/mapping-text.stories.ts +++ b/packages/storybook/src/nimble/mapping/text/mapping-text.stories.ts @@ -1,7 +1,7 @@ import { html } from '@microsoft/fast-element'; import type { Meta, StoryObj } from '@storybook/html'; import { mappingKeyDescription } from '../base/story-helpers'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../../utilities/storybook'; import { hiddenWrapper } from '../../../utilities/hidden'; const metadata: Meta = { @@ -23,10 +23,12 @@ export const textMapping: StoryObj = { argTypes: { key: { description: mappingKeyDescription('the mapped display text'), - control: false + control: false, + table: { category: apiCategory.attributes }, }, text: { - description: 'The display text.' + description: 'The display text.', + table: { category: apiCategory.attributes }, } }, args: {} diff --git a/packages/storybook/src/nimble/mapping/user/mapping-user.stories.ts b/packages/storybook/src/nimble/mapping/user/mapping-user.stories.ts index 87b3c44f42..3107486c55 100644 --- a/packages/storybook/src/nimble/mapping/user/mapping-user.stories.ts +++ b/packages/storybook/src/nimble/mapping/user/mapping-user.stories.ts @@ -1,6 +1,6 @@ import { html } from '@microsoft/fast-element'; import type { Meta, StoryObj } from '@storybook/html'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../../utilities/storybook'; import { hiddenWrapper } from '../../../utilities/hidden'; const metadata: Meta = { @@ -21,13 +21,15 @@ export const userMapping: StoryObj = { render: createUserSelectedThemeStory(hiddenWrapper(html`<style></style>`)), argTypes: { key: { - description: 'A key (url) for each user that maps to a user', - control: false + description: 'A URL that uniquely identifies the user, e.g. `user:1234`.', + control: false, + table: { category: apiCategory.attributes }, }, displayName: { name: 'display-name', description: - 'A string which renders the textual representation of user name' + 'The display name to render for the user, e.g. `Oscar Meyer ๐ŸŒญ`.', + table: { category: apiCategory.attributes }, } }, args: {} diff --git a/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.mdx b/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.mdx index 114aada9ff..2038ebfdbd 100644 --- a/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.mdx +++ b/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.mdx @@ -1,6 +1,7 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import TargetDocs from '../../patterns/anchor/target-docs.mdx'; import * as tableColumnAnchorStories from './table-column-anchor.stories'; +import ComponentApisLink from '../../../docs/component-apis-link.mdx'; import { tableColumnAnchorTag } from '../../../../../nimble-components/src/table-column/anchor'; import { tableTag } from '../../../../../nimble-components/src/table'; @@ -14,6 +15,7 @@ The <Tag name={tableColumnAnchorTag}/> column is used to display string fields a ## API <Controls of={tableColumnAnchorStories.anchorColumn} /> +<ComponentApisLink /> ### Target Configuration diff --git a/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.stories.ts b/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.stories.ts index f9362f28a3..8b63688a83 100644 --- a/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.stories.ts +++ b/packages/storybook/src/nimble/table-column/anchor/table-column-anchor.stories.ts @@ -11,7 +11,7 @@ import { sharedTableArgs, sharedTableArgTypes } from '../base/table-column-stories-utils'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../../utilities/storybook'; const metadata: Meta<SharedTableArgs> = { title: 'Components/Table Column: Anchor', @@ -102,28 +102,33 @@ export const anchorColumn: StoryObj<AnchorColumnTableArgs> = { description: 'Set this attribute to identify which field in the data record contains the visible text value for each cell in the column. The field values must be of type `string`. If a given row does not define a property with this name, that row will use the url as the label.', options: ['firstName', 'lastName'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, hrefFieldName: { name: 'href-field-name', description: 'Set this attribute to identify which field in the data record contains the link url for each cell in the column. If the field is not defined in a particular record, that cell will be displayed as plain text instead of a link. The field values must be of type `string`.', - control: false + control: false, + 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. This has no effect under the Color theme.' + 'Set to `prominent` to make the anchor appear in a different color than normal text. This has no effect under the Color theme.', + table: { category: apiCategory.attributes }, }, underlineHidden: { name: 'underline-hidden', defaultValue: { summary: 'false' }, - description: 'Causes the underline to be hidden except on hover.' + description: 'Causes the underline to be hidden except on hover.', + table: { category: apiCategory.attributes }, }, placeholder: { description: - 'The placeholder text to display when the label and href are both `undefined` or `null` for a record.' + 'The placeholder text to display when the label and href are both `undefined` or `null` for a record.', + table: { category: apiCategory.attributes }, } }, args: { diff --git a/packages/storybook/src/nimble/table-column/base/table-column.mdx b/packages/storybook/src/nimble/table-column/base/table-column.mdx index ab236f23fb..bcadafaab3 100644 --- a/packages/storybook/src/nimble/table-column/base/table-column.mdx +++ b/packages/storybook/src/nimble/table-column/base/table-column.mdx @@ -1,41 +1,49 @@ import { Controls, Canvas, Meta, Title, Description } from '@storybook/blocks'; import * as tableColumnStories from './table-column.stories'; +import ComponentApisLink from '../../../docs/component-apis-link.mdx'; <Meta of={tableColumnStories} /> <Title of={tableColumnStories} /> <Description of={tableColumnStories} /> -## Adding columns +## API + +<Controls of={tableColumnStories.api} /> +<ComponentApisLink /> + +## Examples + +### Adding columns <Description of={tableColumnStories.addingColumns} /> <Canvas of={tableColumnStories.addingColumns} /> <Controls of={tableColumnStories.addingColumns} /> -## Setting header content +### Setting header content <Description of={tableColumnStories.headerContent} /> <Canvas of={tableColumnStories.headerContent} /> <Controls of={tableColumnStories.headerContent} /> -## Configuring common attributes +### Hiding -<Description of={tableColumnStories.commonAttributes} /> -<Canvas of={tableColumnStories.commonAttributes} /> -<Controls of={tableColumnStories.commonAttributes} /> +<Description of={tableColumnStories.columnHidden} /> +<Canvas of={tableColumnStories.columnHidden} /> +<Controls of={tableColumnStories.columnHidden} /> -## Sorting +### Sorting <Description of={tableColumnStories.sorting} /> <Canvas of={tableColumnStories.sorting} /> <Controls of={tableColumnStories.sorting} /> -## Grouping +### Grouping <Description of={tableColumnStories.grouping} /> <Canvas of={tableColumnStories.grouping} /> <Controls of={tableColumnStories.grouping} /> -## Column Width +### Column width <Description of={tableColumnStories.width} /> <Canvas of={tableColumnStories.width} /> diff --git a/packages/storybook/src/nimble/table-column/base/table-column.stories.ts b/packages/storybook/src/nimble/table-column/base/table-column.stories.ts index e463532081..0680c82b42 100644 --- a/packages/storybook/src/nimble/table-column/base/table-column.stories.ts +++ b/packages/storybook/src/nimble/table-column/base/table-column.stories.ts @@ -21,7 +21,7 @@ import { sharedTableArgTypes, sharedTableArgs } from './table-column-stories-utils'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../../utilities/storybook'; const simpleData = [ { @@ -74,7 +74,7 @@ const simpleData = [ ] as const; const overviewText = `This page contains information about configuring the columns of a \`nimble-table\`. -See **Table** for information about configuring the table itself and the **Table Column** specific docs for +See [Table](?path=/docs/components-table--docs) for information about configuring the table itself and the **Table Column** pages for information about specific types of column.`; const metadata: Meta<SharedTableArgs> = { @@ -136,6 +136,96 @@ const metadata: Meta<SharedTableArgs> = { export default metadata; +interface ApiTableArgs extends SharedTableArgs { + content: undefined; + columnHidden: undefined; + columnId: undefined; + actionMenuSlot: undefined; + actionMenuLabel: undefined; + sortDirection: undefined; + sortIndex: undefined; + groupIndex: undefined; + groupingDisabled: undefined; + fractionalWidth: undefined; + minPixelWidth: undefined; +} + +export const api: StoryObj<ApiTableArgs> = { + parameters: { + // Story used by documentation, not needed for visual comparison. + chromatic: { disableSnapshot: true } + }, + argTypes: { + content: { + name: 'default', + description: 'Text or an icon added to the default slot of the column will be placed in the column header. See **Setting header content** for more information.', + table: { category: apiCategory.slots }, + control: false + }, + columnHidden: { + name: 'column-hidden', + description: 'Whether the column is hidden from display. See **Hiding** for more information.', + table: { category: apiCategory.attributes }, + control: false + }, + columnId: { + name: 'column-id', + description: + "Optionally use the `column-id` attribute to uniquely identify a column for features like adding an action menu. If you aren't using features that require a column id you may leave it unset for all columns. If you provide `column-id` for any column within a table then you must provide it for all and they must be unique strings.", + table: { category: apiCategory.attributes }, + control: false + }, + actionMenuSlot: { + name: 'action-menu-slot', + description: 'Configure this column to have an action menu by setting this attribute to the name of a slot in the table that contains the menu.', + table: { category: apiCategory.attributes }, + control: false + }, + actionMenuLabel: { + name: 'action-menu-label', + description: 'Configures the title and accessible label of the action menu button for this column.', + table: { category: apiCategory.attributes }, + control: false + }, + sortDirection: { + name: 'sort-direction', + description: 'The direction to sort the data in the column. See **Sorting** for more information.', + table: { category: apiCategory.attributes }, + control: false + }, + sortIndex: { + name: 'sort-index', + description: 'Specifies the sort precedence of the column within the set of all sorted columns. See **Sorting** for more information.', + table: { category: apiCategory.attributes }, + control: false + }, + groupIndex: { + name: 'group-index', + description: 'Specifies the group precedence of the column within the set of all grouped columns. See **Grouping** for more information.', + table: { category: apiCategory.attributes }, + control: false + }, + groupingDisabled: { + name: 'grouping-disabled', + description: 'Prevents the column from participating in grouping. See **Grouping** for more information.', + table: { category: apiCategory.attributes }, + control: false + }, + fractionalWidth: { + name: 'fractional-width', + description: 'Configures the proportion of the table width that this column should occupy initially. See **Column width** for more information.', + table: { category: apiCategory.attributes }, + control: false + }, + minPixelWidth: { + name: 'min-pixel-width', + description: 'Configures the minimum width that the column can be interactively resized to. See **Column width** for more information.', + table: { category: apiCategory.attributes }, + control: false + }, + } +}; + type ColumnOrderOption = 'FirstName, LastName' | 'LastName, FirstName'; interface ColumnOrderTableArgs extends SharedTableArgs { @@ -270,23 +360,22 @@ export const headerContent: StoryObj<HeaderContentTableArgs> = { } }; -const commonColumnAttributes = 'In addition to the attributes described in other stories there are other attributes available on all column types.'; +const columnHiddenDescription = 'Columns can be added to the table but hidden from display. One use case for this is to sort by a field but not display its value.'; -interface CommonAttributesTableArgs extends SharedTableArgs { +interface ColumnHiddenTableArgs extends SharedTableArgs { columnHidden: boolean; - columnId: string; } -export const commonAttributes: StoryObj<CommonAttributesTableArgs> = { +export const columnHidden: StoryObj<ColumnHiddenTableArgs> = { parameters: { docs: { description: { - story: commonColumnAttributes + story: columnHiddenDescription } } }, // prettier-ignore - render: createUserSelectedThemeStory(html<CommonAttributesTableArgs>` + render: createUserSelectedThemeStory(html<ColumnHiddenTableArgs>` <${tableTag} ${ref('tableRef')} data-unused="${x => x.updateData(x)}" @@ -319,13 +408,8 @@ export const commonAttributes: StoryObj<CommonAttributesTableArgs> = { columnHidden: { name: 'column-hidden', description: - 'Add the `column-hidden` attribute to hide a column from display. One use case for this is to sort by a field but not display its value.' + 'Add the `column-hidden` attribute to hide a column from display.' }, - columnId: { - name: 'column-id', - description: - "Optionally use the `column-id` attribute to uniquely identify a column for features like adding an action menu. If you aren't using features that require a column id you may leave it unset for all columns. If you provide `column-id` for any column within a table then you must provide it for all and they must be unique strings." - } }, args: { columnHidden: false diff --git a/packages/storybook/src/nimble/table-column/date-text/table-column-date-text.mdx b/packages/storybook/src/nimble/table-column/date-text/table-column-date-text.mdx index fa7d123f81..5a971395fe 100644 --- a/packages/storybook/src/nimble/table-column/date-text/table-column-date-text.mdx +++ b/packages/storybook/src/nimble/table-column/date-text/table-column-date-text.mdx @@ -1,6 +1,7 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import { NimbleTableColumnDateText } from './table-column-date-text.react'; import * as tableColumnDateTextStories from './table-column-date-text.stories'; +import ComponentApisLink from '../../../docs/component-apis-link.mdx'; import { tableColumnDateTextTag } from '../../../../../nimble-components/src/table-column/date-text'; import { tableTag } from '../../../../../nimble-components/src/table'; import NoNullAndUndefinedBestPractice from '../../patterns/table-column/no-null-and-undefined-best-practice-docs.mdx'; @@ -11,7 +12,11 @@ import NoNullAndUndefinedBestPractice from '../../patterns/table-column/no-null- The <Tag name={tableColumnDateTextTag}/> column is used to display date-time fields as text in the <Tag name={tableTag}/>. The date-time values must be of type `number` and represent the number of milliseconds since January 1, 1970 UTC. This is the representation used by the [JavaScript `Date` type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date). Dates are formatted in a locale-specific way based on the value of the `lang` token, which can be set via the [nimble-theme-provider](?path=/docs/tokens-theme-provider--docs). <Canvas of={tableColumnDateTextStories.dateTextColumn} /> + +## API + <Controls of={tableColumnDateTextStories.dateTextColumn} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/table-column/date-text/table-column-date-text.stories.ts b/packages/storybook/src/nimble/table-column/date-text/table-column-date-text.stories.ts index c1c0d425c9..dae862ffc3 100644 --- a/packages/storybook/src/nimble/table-column/date-text/table-column-date-text.stories.ts +++ b/packages/storybook/src/nimble/table-column/date-text/table-column-date-text.stories.ts @@ -28,7 +28,7 @@ import { sharedTableArgTypes, sharedTableArgs } from '../base/table-column-stories-utils'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, checkValidityDescription, createUserSelectedThemeStory } from '../../../utilities/storybook'; const simpleData = [ { @@ -163,44 +163,51 @@ export const dateTextColumn: StoryObj<TextColumnTableArgs> = { name: 'field-name', description: 'Set this attribute to identify which field in the data record should be displayed in each column. The field values must be of type `number` and represent the number of milliseconds since January 1, 1970 UTC. This is the representation used by the `Date` type.', - control: false + control: false, + table: { category: apiCategory.attributes }, }, placeholder: { description: - 'The placeholder text to display when the field value is `undefined` or `null` for a record.' + 'The placeholder text to display when the field value is `undefined` or `null` for a record.', + table: { category: apiCategory.attributes }, }, format: { description: formatDescription, options: Object.keys(DateTextFormat), - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customDateStyle: { name: 'custom-date-style', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'full', 'long', 'medium', 'short'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customTimeStyle: { name: 'custom-time-style', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'full', 'long', 'medium', 'short'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customWeekday: { name: 'custom-weekday', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'long', 'short', 'narrow'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customDay: { name: 'custom-day', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'numeric', '2-digit'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customMonth: { name: 'custom-month', @@ -214,56 +221,64 @@ export const dateTextColumn: StoryObj<TextColumnTableArgs> = { 'short', 'narrow' ], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customYear: { name: 'custom-year', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'numeric', '2-digit'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customEra: { name: 'custom-era', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'long', 'short', 'narrow'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customHour: { name: 'custom-hour', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'numeric', '2-digit'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customMinute: { name: 'custom-minute', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'numeric', '2-digit'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customSecond: { name: 'custom-second', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'numeric', '2-digit'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customHour12: { name: 'custom-hour12', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, true, false], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customHourCycle: { name: 'custom-hour-cycle', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'h11', 'h12', 'h23', 'h24'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customTimeZoneName: { name: 'custom-time-zone-name', @@ -278,7 +293,8 @@ export const dateTextColumn: StoryObj<TextColumnTableArgs> = { 'longGeneric', 'shortGeneric' ], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customTimeZone: { name: 'custom-time-zone', @@ -291,14 +307,16 @@ export const dateTextColumn: StoryObj<TextColumnTableArgs> = { 'America/New York', 'Europe/Paris' ], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customDayPeriod: { name: 'custom-day-period', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'narrow', 'short', 'long'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customCalendar: { name: 'custom-calendar', @@ -312,36 +330,43 @@ export const dateTextColumn: StoryObj<TextColumnTableArgs> = { 'hebrew', 'islamic-civil' ], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customNumberingSystem: { name: 'custom-numbering-system', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat). The values presented here are not a comprehensive list.', options: [undefined, 'arab', 'fullwide', 'latn', 'tamldec'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customFormatMatcher: { name: 'custom-format-matcher', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'basic', 'best-fit'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, customLocaleMatcher: { name: 'custom-locale-matcher', description: 'Refer to the option [documentation for the `Intl.DateTimeFormat()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat).', options: [undefined, 'lookup', 'best-fit'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, checkValidity: { name: 'checkValidity()', - description: - 'Returns `true` if the column configuration is valid, otherwise `false`.' + description: checkValidityDescription({ componentName: 'date text column' }), + table: { category: apiCategory.methods }, + control: false, }, validity: { - description: validityDescription + description: validityDescription, + table: { category: apiCategory.nonAttributeProperties }, + control: false, } }, args: { diff --git a/packages/storybook/src/nimble/table-column/duration-text/table-column-duration-text.mdx b/packages/storybook/src/nimble/table-column/duration-text/table-column-duration-text.mdx index f99ccef9c3..a91da858f5 100644 --- a/packages/storybook/src/nimble/table-column/duration-text/table-column-duration-text.mdx +++ b/packages/storybook/src/nimble/table-column/duration-text/table-column-duration-text.mdx @@ -1,5 +1,6 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import * as tableColumnDurationTextStories from './table-column-duration-text.stories'; +import ComponentApisLink from '../../../docs/component-apis-link.mdx'; import { tableColumnDurationTextTag } from '../../../../../nimble-components/src/table-column/duration-text'; import { tableTag } from '../../../../../nimble-components/src/table'; import NoNullAndUndefinedBestPractice from '../../patterns/table-column/no-null-and-undefined-best-practice-docs.mdx'; @@ -13,7 +14,11 @@ The <Tag name={tableColumnDurationTextTag}/> column is used to display a period of={tableColumnDurationTextStories.durationTextColumn} expanded={false} /> + +## API + <Controls of={tableColumnDurationTextStories.durationTextColumn} /> +<ComponentApisLink /> ## Usage diff --git a/packages/storybook/src/nimble/table-column/duration-text/table-column-duration-text.stories.ts b/packages/storybook/src/nimble/table-column/duration-text/table-column-duration-text.stories.ts index 4216a4b252..ac018b23d3 100644 --- a/packages/storybook/src/nimble/table-column/duration-text/table-column-duration-text.stories.ts +++ b/packages/storybook/src/nimble/table-column/duration-text/table-column-duration-text.stories.ts @@ -10,7 +10,7 @@ import { sharedTableArgTypes, sharedTableArgs } from '../base/table-column-stories-utils'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../../utilities/storybook'; const simpleData = [ { @@ -95,11 +95,13 @@ export const durationTextColumn: StoryObj<TextColumnTableArgs> = { name: 'field-name', description: 'Set this attribute to identify which field in the data record should be displayed in each column. The field values must be of type `number` and represent a total number of milliseconds.', - control: false + control: false, + table: { category: apiCategory.attributes }, }, placeholder: { description: - 'The placeholder text to display when the field value is `undefined` or `null` for a record.' + 'The placeholder text to display when the field value is `undefined` or `null` for a record.', + table: { category: apiCategory.attributes }, } }, args: { diff --git a/packages/storybook/src/nimble/table-column/mapping/table-column-mapping.mdx b/packages/storybook/src/nimble/table-column/mapping/table-column-mapping.mdx index 68434deb76..e94d0e63c0 100644 --- a/packages/storybook/src/nimble/table-column/mapping/table-column-mapping.mdx +++ b/packages/storybook/src/nimble/table-column/mapping/table-column-mapping.mdx @@ -5,6 +5,7 @@ import * as emptyMappingStories from '../../mapping/empty/mapping-empty.stories' import * as iconMappingStories from '../../mapping/icon/mapping-icon.stories'; import * as spinnerMappingStories from '../../mapping/spinner/mapping-spinner.stories'; import * as textMappingStories from '../../mapping/text/mapping-text.stories'; +import ComponentApisLink from '../../../docs/component-apis-link.mdx'; import { tableColumnMappingTag } from '../../../../../nimble-components/src/table-column/mapping'; import { mappingEmptyTag } from '../../../../../nimble-components/src/mapping/empty'; import { tableTag } from '../../../../../nimble-components/src/table'; @@ -18,37 +19,41 @@ The <Tag name={tableColumnMappingTag}/> renders specific number, boolean, or str <p>{columnOperationBehavior}</p> <Canvas of={tableColumnMappingStories.mappingColumn} /> -<Controls of={tableColumnMappingStories.mappingColumn} /> - -## Usage -### Best Practices +## API -- Provide a mapping for every expected record value. Because grouping is performed on the record value, non-mapped record values can result in multiple groups without group labels. - - To improve grouping behavior of a value that shouldn't be rendered in table cells, use a <Tag name={mappingEmptyTag}/> element to provide text for that value's group row. -- Avoid having multiple values that map to the same text because grouping and sorting is done on the record value rather than the mapped text. - -### Blazor Usage - -When setting a child mapping element's `Key` value to a string, you must wrap it in `@()` so that the compiler treats it as a string, e.g. -`<NimbleMappingIcon Key=@("foo") ...>` +<Controls of={tableColumnMappingStories.mappingColumn} /> +<ComponentApisLink /> -## Icon Mapping +### Icon Mapping <Description of={iconMappingStories} /> <Controls of={iconMappingStories.iconMapping} /> -## Spinner Mapping +### Spinner Mapping <Description of={spinnerMappingStories} /> <Controls of={spinnerMappingStories.spinnerMapping} /> -## Text Mapping +### Text Mapping <Description of={textMappingStories} /> <Controls of={textMappingStories.textMapping} /> -## Empty Mapping +### Empty Mapping <Description of={emptyMappingStories} /> <Controls of={emptyMappingStories.emptyMapping} /> + +## Usage + +### Best Practices + +- Provide a mapping for every expected record value. Because grouping is performed on the record value, non-mapped record values can result in multiple groups without group labels. + - To improve grouping behavior of a value that shouldn't be rendered in table cells, use a <Tag name={mappingEmptyTag}/> element to provide text for that value's group row. +- Avoid having multiple values that map to the same text because grouping and sorting is done on the record value rather than the mapped text. + +### Blazor Usage + +When setting a child mapping element's `Key` value to a string, you must wrap it in `@()` so that the compiler treats it as a string, e.g. +`<NimbleMappingIcon Key=@("foo") ...>` diff --git a/packages/storybook/src/nimble/table-column/mapping/table-column-mapping.stories.ts b/packages/storybook/src/nimble/table-column/mapping/table-column-mapping.stories.ts index 861c13fa45..ea3d3534b2 100644 --- a/packages/storybook/src/nimble/table-column/mapping/table-column-mapping.stories.ts +++ b/packages/storybook/src/nimble/table-column/mapping/table-column-mapping.stories.ts @@ -18,7 +18,7 @@ import { sharedTableArgs } from '../base/table-column-stories-utils'; import { isChromatic } from '../../../utilities/isChromatic'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, checkValidityDescription, createUserSelectedThemeStory } from '../../../utilities/storybook'; const simpleData = [ { @@ -71,6 +71,7 @@ interface MappingColumnTableArgs extends SharedTableArgs { widthMode: keyof typeof TableColumnMappingWidthMode; checkValidity: () => void; validity: () => void; + content: undefined; } const widthModeDescription = `When set to \`iconSize\`, the column will have a fixed width that makes the column the appropriate width to render only a single icon in the cell. @@ -124,6 +125,7 @@ export const mappingColumn: StoryObj<MappingColumnTableArgs> = { name: 'field-name', description: "Set this attribute to identify which field in the data record contains the value for each cell in the column. The field values' type must match the type specified by the `key-type` attribute.", + table: { category: apiCategory.attributes }, control: false }, keyType: { @@ -131,21 +133,32 @@ export const mappingColumn: StoryObj<MappingColumnTableArgs> = { control: false, defaultValue: { summary: '"string"' }, description: - 'The data type of the key values used for this column. Must be one of `"string"`, `"number"`, or `"boolean"`. Defaults to `"string"` if unspecified.' + 'The data type of the key values used for this column. Must be one of `"string"`, `"number"`, or `"boolean"`. Defaults to `"string"` if unspecified.', + table: { category: apiCategory.attributes }, }, widthMode: { name: 'width-mode', options: Object.keys(TableColumnMappingWidthMode), control: { type: 'radio' }, - description: widthModeDescription + description: widthModeDescription, + table: { category: apiCategory.attributes }, }, checkValidity: { name: 'checkValidity()', - description: - 'Returns `true` if the column configuration is valid, otherwise `false`.' + description: checkValidityDescription({ componentName: 'mapping column' }), + table: { category: apiCategory.methods }, + control: false }, validity: { - description: validityDescription + description: validityDescription, + table: { category: apiCategory.nonAttributeProperties }, + control: false + }, + content: { + name: 'default', + description: 'One or more mapping elements which specify how to render each possible data value.', + table: { category: apiCategory.slots }, + control: false } }, args: { diff --git a/packages/storybook/src/nimble/table-column/number-text/table-column-number-text.mdx b/packages/storybook/src/nimble/table-column/number-text/table-column-number-text.mdx index 8891609932..f33eddf679 100644 --- a/packages/storybook/src/nimble/table-column/number-text/table-column-number-text.mdx +++ b/packages/storybook/src/nimble/table-column/number-text/table-column-number-text.mdx @@ -5,6 +5,7 @@ import { noNullAndUndefinedBestPractice } from '../base/table-column-stories-utils'; import * as tableColumnNumberTextStories from './table-column-number-text.stories'; +import ComponentApisLink from '../../../docs/component-apis-link.mdx'; import { tableColumnNumberTextTag } from '../../../../../nimble-components/src/table-column/number-text'; import { tableTag } from '../../../../../nimble-components/src/table'; import NoNullAndUndefinedBestPractice from '../../patterns/table-column/no-null-and-undefined-best-practice-docs.mdx'; @@ -18,7 +19,11 @@ based on the value of the `lang` token, which can be set via the [nimble-theme-p <p>{columnOperationBehavior}</p> <Canvas of={tableColumnNumberTextStories.numberTextColumn} /> + +## API + <Controls of={tableColumnNumberTextStories.numberTextColumn} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/table-column/number-text/table-column-number-text.stories.ts b/packages/storybook/src/nimble/table-column/number-text/table-column-number-text.stories.ts index f19898ff3e..1d49175f92 100644 --- a/packages/storybook/src/nimble/table-column/number-text/table-column-number-text.stories.ts +++ b/packages/storybook/src/nimble/table-column/number-text/table-column-number-text.stories.ts @@ -15,7 +15,7 @@ import { sharedTableArgTypes, sharedTableArgs } from '../base/table-column-stories-utils'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, checkValidityDescription, createUserSelectedThemeStory } from '../../../utilities/storybook'; const simpleData = [ { @@ -186,48 +186,58 @@ export const numberTextColumn: StoryObj<NumberTextColumnTableArgs> = { name: 'field-name', description: 'Set this attribute to identify which field in the data record should be displayed in each column. The field values must be of type `number`.', - control: false + control: false, + table: { category: apiCategory.attributes }, }, placeholder: { description: - 'The placeholder text to display when the field value is `undefined` or `null` for a record.' + 'The placeholder text to display when the field value is `undefined` or `null` for a record.', + table: { category: apiCategory.attributes }, }, format: { description: formatDescription, options: Object.keys(NumberTextFormat), - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, alignment: { description: alignmentDescription, options: Object.keys(NumberTextAlignment), - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, decimalDigits: { name: 'decimal-digits', description: "The number of decimal places to format values to when the column's `format` is configured to be `decimal`. If neither `decimal-digits` or `decimal-maximum-digits` are set, a default value of `2` is used. `decimal-digits` and `decimal-maximum-digits` cannot both be set at the same time. The value must be in the range 0 - 20 (inclusive).", options: [undefined, 0, 1, 2, 3], - control: { type: 'select' } + control: { type: 'select' }, + table: { category: apiCategory.attributes }, }, decimalMaximumDigits: { name: 'decimal-maximum-digits', description: "The maximum number of decimal places to format values to when the column's `format` is configured to be `decimal`. This differs from `decimal-digits` in that trailing zeros are omitted. `decimal-digits` and `decimal-maximum-digits` cannot both be set at the same time. The value must be in the range 0 - 20 (inclusive).", options: [undefined, 0, 1, 2, 3, 20], - control: { type: 'select' } + control: { type: 'select' }, + table: { category: apiCategory.attributes }, }, unit: { description: unitDescription, options: ['default', 'byte', 'byte (1024)', 'degrees Celsius', 'degrees Fahrenheit', 'volt'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, checkValidity: { name: 'checkValidity()', - description: - 'Returns `true` if the column configuration is valid, otherwise `false`.' + description: checkValidityDescription({ componentName: 'number text column' }), + control: false, + table: { category: apiCategory.methods }, }, validity: { - description: validityDescription + description: validityDescription, + control: false, + table: { category: apiCategory.nonAttributeProperties }, } }, args: { diff --git a/packages/storybook/src/nimble/table-column/text/table-column-text.mdx b/packages/storybook/src/nimble/table-column/text/table-column-text.mdx index def6b24236..9b778f2c5a 100644 --- a/packages/storybook/src/nimble/table-column/text/table-column-text.mdx +++ b/packages/storybook/src/nimble/table-column/text/table-column-text.mdx @@ -1,6 +1,7 @@ import { Canvas, Meta, Controls, Title } from '@storybook/blocks'; import { NimbleTableColumnText } from './table-column-text.react'; import * as tableColumnTextStories from './table-column-text.stories'; +import ComponentApisLink from '../../../docs/component-apis-link.mdx'; import { tableColumnTextTag } from '../../../../../nimble-components/src/table-column/text'; import { tableTag } from '../../../../../nimble-components/src/table'; import NoNullAndUndefinedBestPractice from '../../patterns/table-column/no-null-and-undefined-best-practice-docs.mdx'; @@ -11,7 +12,11 @@ import NoNullAndUndefinedBestPractice from '../../patterns/table-column/no-null- The <Tag name={tableColumnTextTag}/> column is used to display string fields as text in the <Tag name={tableTag}/>. <Canvas of={tableColumnTextStories.textColumn} /> + +## API + <Controls of={tableColumnTextStories.textColumn} /> +<ComponentApisLink /> {/* ## Styling */} diff --git a/packages/storybook/src/nimble/table-column/text/table-column-text.stories.ts b/packages/storybook/src/nimble/table-column/text/table-column-text.stories.ts index 6af7db88cf..fee7759fe6 100644 --- a/packages/storybook/src/nimble/table-column/text/table-column-text.stories.ts +++ b/packages/storybook/src/nimble/table-column/text/table-column-text.stories.ts @@ -9,7 +9,7 @@ import { sharedTableArgTypes, sharedTableArgs } from '../base/table-column-stories-utils'; -import { createUserSelectedThemeStory } from '../../../utilities/storybook'; +import { apiCategory, createUserSelectedThemeStory } from '../../../utilities/storybook'; const simpleData = [ { @@ -95,11 +95,13 @@ export const textColumn: StoryObj<TextColumnTableArgs> = { description: 'Set this attribute to identify which field in the data record should be displayed in each column. The field values must be of type `string`.', options: ['firstName', 'lastName'], - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, placeholder: { description: - 'The placeholder text to display when the field value is `undefined` or `null` for a record.' + 'The placeholder text to display when the field value is `undefined` or `null` for a record.', + table: { category: apiCategory.attributes }, } }, args: { diff --git a/packages/storybook/src/nimble/table/table.mdx b/packages/storybook/src/nimble/table/table.mdx index f2fe197fea..73aab1501a 100644 --- a/packages/storybook/src/nimble/table/table.mdx +++ b/packages/storybook/src/nimble/table/table.mdx @@ -1,17 +1,33 @@ import { Controls, Canvas, Meta, Title } from '@storybook/blocks'; import * as tableStories from './table.stories'; +import ComponentApisLink from '../../docs/component-apis-link.mdx'; import { tableTag } from '../../../../nimble-components/src/table'; <Meta of={tableStories} /> <Title of={tableStories} /> The <Tag name={tableTag}/> is a component that offers a way to render tabular data in a variety of ways in each column. -For information about configuring table columns, see **Table Column Configuration** and **Table Column Types**. +For information about configuring table columns, see [Table Column Configuration](?path=/docs/components-table-column-configuration--docs) +and the **Table Column** pages for individual table column types. <Canvas of={tableStories.table} /> + +## API + <Controls of={tableStories.table} /> +<ComponentApisLink /> + +## Styling + +### Sizing + +The <Tag name={tableTag}/> should be sized explicitly or sized to fill the space of a parent container. The <Tag name={tableTag}/> does not currently support being styled with `height: auto`. The ability to auto size the table is tracked with [issue 1624](https://github.com/ni/nimble/issues/1624). + +{/* ## Usage */} -## Delay-loaded Hierarchy +## Examples + +### Delay-loaded hierarchy In some cases, it may be known that a record has children, but the records for those children are not known. For performance reasons, it may be preferred to load the children on demand when a user expands the parent row. To accomplish this, use the `setRecordHierarchyOptions()` function on the table to set the hierarchy @@ -20,7 +36,7 @@ options associated with records in the data. <Canvas of={tableStories.delayedHierarchy} /> <Controls of={tableStories.delayedHierarchy} /> -### Delay-loaded Hierarchy Usage +#### Using delay-loaded hierarchy The expected usage of the dynamically loaded hierarchy is as follows: @@ -39,7 +55,7 @@ The expected usage of the dynamically loaded hierarchy is as follows: - If loading the data determines that the row doesn't actually have children: 1. Call `setRecordHierarchyOptions` to change the row state to `{ delayedHierarchyState: TableRecordDelayedHierarchyState.none }`. This call must include the current state of any records not in the default state. -### setRecordHierarchyOptions Behavior +#### Behavior of setRecordHierarchyOptions `setRecordHierarchyOptions()` has the following behavior: @@ -49,16 +65,6 @@ The expected usage of the dynamically loaded hierarchy is as follows: - the table will not render delayed hierarchy state (loading or expandable) if the table's `parentIdFieldName` is not configured; however, the options will remain cached within the table if the `parentIdFieldName` becomes `undefined`, and that cached configuration will render in the table if the table's `parentIdFieldName` is changed back to a non-`undefined` value - calling `setData` will clear options associated with IDs that are no longer present in the data -## Styling - -### Sizing - -The <Tag name={tableTag}/> should be sized explicitly or sized to fill the space of a parent container. The <Tag name={tableTag}/> does not currently support being styled with `height: auto`. The ability to auto size the table is tracked with [issue 1624](https://github.com/ni/nimble/issues/1624). - -{/* ## Usage */} - -{/* ## Examples */} - {/* ## Accessibility */} {/* ## Resources */} diff --git a/packages/storybook/src/nimble/table/table.stories.ts b/packages/storybook/src/nimble/table/table.stories.ts index 0bee5c0971..a663b57b92 100644 --- a/packages/storybook/src/nimble/table/table.stories.ts +++ b/packages/storybook/src/nimble/table/table.stories.ts @@ -14,7 +14,7 @@ import { addLabelUseMetadata, type LabelUserArgs } from '../label-provider/base/label-user-stories-utils'; -import { createUserSelectedThemeStory } from '../../utilities/storybook'; +import { apiCategory, checkValidityDescription, createUserSelectedThemeStory } from '../../utilities/storybook'; import { isChromatic } from '../../utilities/isChromatic'; interface BaseTableArgs extends LabelUserArgs { @@ -62,6 +62,14 @@ interface TableArgs extends BaseTableArgs { setSelectedRecordIds: undefined; getSelectedRecordIds: undefined; data: ExampleDataType; + setRecordHierarchyOptions: undefined; + defaultSlot: undefined; + actionMenuSlot: undefined; + actionMenuBeforetoggle: undefined; + actionMenuToggle: undefined; + selectionChange: undefined; + columnConfigurationChange: undefined; + rowExpandToggle: undefined; } const simpleData = [ @@ -205,7 +213,7 @@ const dataSets = { [ExampleDataType.hierarchicalDataSet]: hierarchicalData } as const; -const dataDescription = `To set the data on the table, call \`setData()\` with an array data records. Each record is made up of fields, +const dataDescription = `To set the data on the table, call \`setData()\` with an array of data records. Each record is made up of fields, which are key/value pairs. The key in each pair must be of type \`string\`, which is defined by the type \`TableFieldName\`. The value in each pair must be of type \`string\`, \`number\`, \`boolean\`, \`null\`, or \`undefined\`, which is defined by the type \`TableFieldValue\`. @@ -236,7 +244,7 @@ The attribute is invalid in the following conditions: const parentIdFieldNameDescription = `An optional string attribute that specifies the field name within a row's record to use as a row's parent ID, which, when used in combination with the \`id-field-name\` attribute, will display the table data in a hierarchical fashion. If the attribute is not specified, the -data in the table will always be presented without hierarchy. +data in the table will be presented without hierarchy. To configure hierarchy dynamically instead, see \`setRecordHierarchyOptions()\`. The attribute is invalid in the following conditions: - When this attribute is set, but \`id-field-name\` is unset. This will cause \`validity.idFieldNameNotConfigured\` to be \`true\`. @@ -326,54 +334,101 @@ export const table: StoryObj<TableArgs> = { [ExampleDataType.largeDataSet]: 'Large data set (10k rows)', [ExampleDataType.hierarchicalDataSet]: 'Hierarchical data' } - } + }, + table: { category: apiCategory.methods }, }, selectionMode: { - table: { - defaultValue: { summary: 'none' } - }, + name: 'selection-mode', options: Object.keys(TableRowSelectionMode), description: 'Controls whether the table supports selecting a single row at a time, multiple rows at a time, or no rows. When selection is enabled, `id-field-name` must be specified.', - control: { type: 'radio' } + control: { type: 'radio' }, + table: { category: apiCategory.attributes }, }, getSelectedRecordIds: { name: 'getSelectedRecordIds()', description: 'A function that returns an array of record IDs that represent the selected row(s) in the table.', - control: false + control: false, + table: { category: apiCategory.methods }, }, setSelectedRecordIds: { name: 'setSelectedRecordIds()', description: setSelectedRecordIdsDescription, - control: false + control: false, + table: { category: apiCategory.methods }, }, idFieldName: { name: 'id-field-name', - table: { - defaultValue: { summary: 'undefined' } - }, description: idFieldNameDescription, - control: false + control: false, + table: { category: apiCategory.attributes }, }, parentIdFieldName: { name: 'parent-id-field-name', - table: { - defaultValue: { summary: 'undefined' } - }, description: parentIdFieldNameDescription, - control: false + control: false, + table: { category: apiCategory.attributes }, }, validity: { description: validityDescription, - control: false + control: false, + table: { category: apiCategory.nonAttributeProperties }, }, checkValidity: { name: 'checkValidity()', - description: - 'A function that returns `true` if the configuration of the table is valid and `false` if the configuration of the table is not valid.', - control: false - } + description: checkValidityDescription({ componentName: 'table' }), + control: false, + table: { category: apiCategory.methods }, + }, + setRecordHierarchyOptions: { + name: 'setRecordHierarchyOptions()', + description: 'Used to configure the hierarchy state of rows dynamically. To set static hierarchy, use `parent-id-field-name` instead. See the **Delay-loaded Hierarchy** section for more information.', + control: false, + table: { category: apiCategory.methods }, + }, + defaultSlot: { + name: 'default', + description: 'Configure table columns by adding them as child elements in the default slot. See **Table Column Configuration** for more information.', + control: false, + table: { category: apiCategory.slots }, + }, + actionMenuSlot: { + name: 'Action menus', + description: `To add an action menu to a column, add a \`${menuTag}\` element as a child of the table and set its slot attribute to a custom value. Then configure the column's \`action-menu-slot\` attribute to the same value. You can configure different action menus for multiple columns by giving them unique slot names.`, + control: false, + table: { category: apiCategory.slots }, + }, + actionMenuBeforetoggle: { + name: 'action-menu-beforetoggle', + description: 'Event emitted before an action menu opens or closes. This can be used to populate the menu before it is visible.', + control: false, + table: { category: apiCategory.events }, + }, + actionMenuToggle: { + name: 'action-menu-toggle', + description: 'Event emitted after an action menu opens or closes.', + control: false, + table: { category: apiCategory.events }, + }, + selectionChange: { + name: 'selection-change', + description: 'Event emitted when the user changes which rows are selected.', + control: false, + table: { category: apiCategory.events }, + }, + columnConfigurationChange: { + name: 'column-configuration-change', + description: 'Event emitted when the user changes a column\'s width or sort order.', + control: false, + table: { category: apiCategory.events }, + }, + rowExpandToggle: { + name: 'row-expand-toggle', + description: 'Event emitted when the user expands or collapses a row in a table with hierarchy. This does not emit when group rows are expanded or collapsed.', + control: false, + table: { category: apiCategory.events }, + }, }, args: { data: ExampleDataType.simpleData, diff --git a/packages/storybook/src/utilities/storybook.ts b/packages/storybook/src/utilities/storybook.ts index 733b14a251..84cbc80a15 100644 --- a/packages/storybook/src/utilities/storybook.ts +++ b/packages/storybook/src/utilities/storybook.ts @@ -187,3 +187,5 @@ export const dropdownPositionDescription = (options: { componentName: string }): export const optionsDescription = `The \`${listOptionTag}\` items for the user to select from.`; export const preventDismissDescription = (options: { componentName: string }): string => `Prevents the \`Esc\` key from closing the ${options.componentName}.`; + +export const checkValidityDescription = (options: { componentName: string }): string => `Returns \`true\` if the configuration of the ${options.componentName} is valid, otherwise \`false\`.`;