From cbad094278212f7d3214270ce5595455e51d104f Mon Sep 17 00:00:00 2001 From: rajsite Date: Fri, 5 Aug 2022 00:13:04 -0500 Subject: [PATCH 01/43] prototype --- .../.storybook/transformSource.js | 13 +++++++++ packages/nimble-components/CONTRIBUTING.md | 22 ++++++++++++++- .../nimble-components/docs/css-guidelines.md | 4 +-- .../nimble-components/src/breadcrumb/index.ts | 7 ++++- .../src/breadcrumb/styles.ts | 8 +++--- .../tests/breadcrumb-matrix.stories.ts | 23 +++++++-------- .../breadcrumb/tests/breadcrumb.stories.ts | 16 +++++------ .../nimble-components/src/breadcrumb/types.ts | 9 ++++++ .../nimble-components/src/button/index.ts | 14 ++++++++-- .../nimble-components/src/button/styles.ts | 28 +++++++++---------- .../src/button/tests/button.stories.ts | 2 +- .../nimble-components/src/button/types.ts | 12 +++++++- .../nimble-components/src/combobox/index.ts | 17 +++++------ .../nimble-components/src/combobox/styles.ts | 4 +-- .../nimble-components/src/drawer/styles.ts | 4 --- .../nimble-components/src/icon-base/index.ts | 12 +++++++- .../nimble-components/src/icon-base/styles.ts | 8 +++--- .../icon-base/tests/icon-matrix.stories.ts | 17 +++++------ .../src/icon-base/tests/icons.stories.ts | 12 ++++---- .../src/icon-base/tests/types.spec.ts | 5 ++-- .../nimble-components/src/icon-base/types.ts | 12 ++++---- .../src/menu-button/index.ts | 10 +++---- .../src/number-field/index.ts | 8 ++++-- .../src/number-field/styles.ts | 9 +++--- .../src/patterns/button/types.ts | 2 +- .../src/patterns/dropdown/styles.ts | 4 +-- .../src/patterns/error/styles.ts | 8 +++--- .../src/patterns/error/template.ts | 4 +-- .../src/patterns/error/types.ts | 13 ++++++--- .../nimble-components/src/select/styles.ts | 2 +- .../nimble-components/src/text-field/index.ts | 12 ++++++-- .../src/text-field/styles.ts | 12 ++++---- .../src/toggle-button/index.ts | 4 +-- .../nimble-components/src/tooltip/index.ts | 15 +++++++++- .../nimble-components/src/tooltip/styles.ts | 17 ++++++----- .../nimble-components/src/tooltip/template.ts | 10 +++++-- .../src/tooltip/tests/tooltip.stories.ts | 8 +++--- .../src/tooltip/tests/types.spec.ts | 2 +- .../nimble-components/src/tooltip/types.ts | 8 +++--- 39 files changed, 251 insertions(+), 146 deletions(-) create mode 100644 packages/nimble-components/src/breadcrumb/types.ts diff --git a/packages/nimble-components/.storybook/transformSource.js b/packages/nimble-components/.storybook/transformSource.js index 64f750d74e..2bbd6497d7 100644 --- a/packages/nimble-components/.storybook/transformSource.js +++ b/packages/nimble-components/.storybook/transformSource.js @@ -44,6 +44,18 @@ const removeCommentNodes = node => { } }; +const removeClassAttributes = node => { + if (node.hasChildNodes()) { + const nodes = Array.from(node.childNodes); + nodes.forEach(child => removeClassAttributes(child)); + } + // Assume that all class attributes added to nimble elements were added by FAST + // and are not part of the control api + if (node instanceof HTMLElement && node.tagName.toLowerCase().startsWith('nimble-')) { + node.removeAttribute('class'); + } +}; + const removeBlankLines = html => html .split('\n') .filter(line => line.trim() !== '') @@ -61,6 +73,7 @@ export const transformSource = source => { removeCommentNodes(fragment); removeCodeHideNodes(fragment); removeCodeHideTopContainerNode(fragment); + removeClassAttributes(fragment); const html = createHTMLFromFragment(fragment); const trimmedHTML = removeBlankLines(html); diff --git a/packages/nimble-components/CONTRIBUTING.md b/packages/nimble-components/CONTRIBUTING.md index 0efd9ae305..f85d8f35a2 100644 --- a/packages/nimble-components/CONTRIBUTING.md +++ b/packages/nimble-components/CONTRIBUTING.md @@ -131,7 +131,9 @@ Use the `html` tagged template helper to define your custom template. See [Decla This package follows the [NI JavaScript and TypeScript Styleguide](https://github.com/ni/javascript-styleguide) with some exceptions listed in [Coding Conventions](/packages/nimble-components/docs/coding-conventions.md). -#### API naming +#### API + +##### API naming Use lower-kebab-case for attributes and enum values that are part of a component's public API. @@ -140,6 +142,24 @@ Use lower-kebab-case for attributes and enum values that are part of a component public errorText: string | undefined; ``` +##### Attributes for alternative states + +https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes#content_versus_idl_attributes + +error-visible +appear-invalid + +:valid +:invalid +novalidate attribute +checkValidity +reportValidity +setCustomValidity +:required +:optional + +todo check that appearance behavior works for undefined values, looks like it should + #### CSS Component CSS should follow the patterns described in [CSS Guidelines](/packages/nimble-components/docs/css-guidelines.md). diff --git a/packages/nimble-components/docs/css-guidelines.md b/packages/nimble-components/docs/css-guidelines.md index ed89e47f3b..38a2b7cc45 100644 --- a/packages/nimble-components/docs/css-guidelines.md +++ b/packages/nimble-components/docs/css-guidelines.md @@ -120,7 +120,7 @@ For example: :host(${focusVisible}) {} /* focusVisible is specific to FAST */ :host(:active) {} :host(:invalid) {} -:host(.custom-state) {} +:host(.custom-state) {} TODO :host\(.*\.[\w]+.*\) :host([disabled]) {} /* disabled styles override all others in the cascade*/ ``` @@ -161,7 +161,7 @@ const styles = css` When styling the invalid state of a form component, it may seem natural to use `:host(:invalid)` in the CSS selector. `:invalid` applies when the form validation has run (generally happens immediately) and failed on that component. The problem with styling based on this pseudo-class is that it prevents a client from having control over when the invalid styling is displayed. For example, if a required input is initially empty, it is common not to show the error styling until the user has changed the value (and subsequently left it empty). -Instead of styling based on `:invalid`, use the class `invalid`. Then the client can create a binding to apply the `invalid` class based on the associated `FormControl`'s status properties, like `invalid`, `dirty`, and `touched`. +Instead of styling based on `:invalid`, use the TODO class `invalid`. Then the client can create a binding to apply the `invalid` class based on the associated `FormControl`'s status properties, like `invalid`, `dirty`, and `touched`. ## Use FAST's `display` utility for styling host element diff --git a/packages/nimble-components/src/breadcrumb/index.ts b/packages/nimble-components/src/breadcrumb/index.ts index dec941fff8..d626452c6c 100644 --- a/packages/nimble-components/src/breadcrumb/index.ts +++ b/packages/nimble-components/src/breadcrumb/index.ts @@ -1,9 +1,11 @@ +import { attr } from '@microsoft/fast-element'; import { DesignSystem, Breadcrumb as FoundationBreadcrumb, breadcrumbTemplate as template } from '@microsoft/fast-foundation'; import { styles } from './styles'; +import type { BreadcrumbAppearance } from './types'; declare global { interface HTMLElementTagNameMap { @@ -14,7 +16,10 @@ declare global { /** * A nimble-styled breadcrumb */ -export class Breadcrumb extends FoundationBreadcrumb {} +export class Breadcrumb extends FoundationBreadcrumb { + @attr + public appearance: BreadcrumbAppearance; +} const nimbleBreadcrumb = Breadcrumb.compose({ baseName: 'breadcrumb', diff --git a/packages/nimble-components/src/breadcrumb/styles.ts b/packages/nimble-components/src/breadcrumb/styles.ts index 120bbad122..7471bbb49e 100644 --- a/packages/nimble-components/src/breadcrumb/styles.ts +++ b/packages/nimble-components/src/breadcrumb/styles.ts @@ -27,7 +27,7 @@ export const styles = css` flex-wrap: wrap; } - :host(.prominent-links) { + :host([appearance="prominent"]) { --ni-private-breadcrumb-link-active-font-color: ${bodyFontColor}; } @@ -46,7 +46,7 @@ export const styles = css` --ni-private-breadcrumb-link-active-font-color: ${DigitalGreenDark}; } - :host(.prominent-links) { + :host([appearance="prominent"]) { --ni-private-breadcrumb-link-font-color: ${DigitalGreenDark}; } `, @@ -56,7 +56,7 @@ export const styles = css` --ni-private-breadcrumb-link-active-font-color: ${PowerGreen}; } - :host(.prominent-links) { + :host([appearance="prominent"]) { --ni-private-breadcrumb-link-font-color: ${PowerGreen}; } `, @@ -69,7 +69,7 @@ export const styles = css` )}; } - :host(.prominent-links) { + :host([appearance="prominent"]) { --ni-private-breadcrumb-link-font-color: ${PowerGreen}; } ` diff --git a/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts b/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts index f5f0f7c6b9..1b415f1f2b 100644 --- a/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts +++ b/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts @@ -1,6 +1,7 @@ import type { Story, Meta } from '@storybook/html'; import { withXD } from 'storybook-addon-xd-designs'; import { html, ViewTemplate } from '@microsoft/fast-element'; +import { pascalCase } from '@microsoft/fast-web-utilities'; import { createMatrixThemeStory, createStory @@ -11,6 +12,7 @@ import { } from '../../utilities/tests/matrix'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; +import { BreadcrumbAppearance } from '../types'; const metadata: Meta = { title: 'Tests/Breadcrumb', @@ -26,25 +28,24 @@ const metadata: Meta = { export default metadata; -const breadcrumbStyleStates = [ - ['', ''], - [' (Prominent Links style)', 'prominent-links'] -] as const; -type BreadcrumbStyleState = typeof breadcrumbStyleStates[number]; +const breadcrumbAppearanceStates: [string, string | undefined][] = Object.entries(BreadcrumbAppearance).map( + ([key, value]) => [pascalCase(key), value] +); +type BreadcrumbAppearanceState = typeof breadcrumbAppearanceStates[number]; const component = ([ - styleStateName, - style -]: BreadcrumbStyleState): ViewTemplate => html` - + appearanceName, + appearance +]: BreadcrumbAppearanceState): ViewTemplate => html` + - ${() => `Breadcrumb${styleStateName} - Link`} + ${() => `Breadcrumb (${appearanceName}) - Link`} Current (No Link) `; export const breadcrumbThemeMatrix: Story = createMatrixThemeStory( - createMatrix(component, [breadcrumbStyleStates]) + createMatrix(component, [breadcrumbAppearanceStates]) ); export const hiddenBreadcrumb: Story = createStory( diff --git a/packages/nimble-components/src/breadcrumb/tests/breadcrumb.stories.ts b/packages/nimble-components/src/breadcrumb/tests/breadcrumb.stories.ts index f663e29d6f..b6384887ad 100644 --- a/packages/nimble-components/src/breadcrumb/tests/breadcrumb.stories.ts +++ b/packages/nimble-components/src/breadcrumb/tests/breadcrumb.stories.ts @@ -3,10 +3,11 @@ import { withXD } from 'storybook-addon-xd-designs'; import { html, repeat } from '@microsoft/fast-element'; import { createUserSelectedThemeStory } from '../../utilities/tests/storybook'; import '../../all-components'; +import { BreadcrumbAppearance } from '../types'; interface BreadcrumbArgs { options: ItemArgs[]; - useProminentLinksStyle: boolean; + appearance: keyof typeof BreadcrumbAppearance; allowNavigation: boolean; } @@ -49,7 +50,7 @@ export const _standardBreadcrumb: StoryObj = { // prettier-ignore render: createUserSelectedThemeStory(html` ${repeat(x => x.options, html` = { + 'With a standard breadcrumb containing multiple items, the last breadcrumb represents the current page (with no `href` specified, ' + 'rendering with a bold font).' }, - useProminentLinksStyle: { - description: - 'To use the alternate (Prominent Links) style (which swaps the default and active/mouseover link colors), add the CSS class `prominent-links` to the ' - + '`` element.' - } + appearance: { + options: Object.keys(BreadcrumbAppearance), + control: { type: 'radio' } + }, }, args: { options: [ @@ -90,7 +90,7 @@ export const _standardBreadcrumb: StoryObj = { label: 'Current (No Link)' } ], - useProminentLinksStyle: false, + appearance: 'default', allowNavigation: false } }; diff --git a/packages/nimble-components/src/breadcrumb/types.ts b/packages/nimble-components/src/breadcrumb/types.ts new file mode 100644 index 0000000000..e59996c187 --- /dev/null +++ b/packages/nimble-components/src/breadcrumb/types.ts @@ -0,0 +1,9 @@ +/** + * Predefined icon appearance states + * @public + */ +export const BreadcrumbAppearance = { + default: undefined, + prominent: 'prominent' +} as const; +export type BreadcrumbAppearance = typeof BreadcrumbAppearance[keyof typeof BreadcrumbAppearance]; diff --git a/packages/nimble-components/src/button/index.ts b/packages/nimble-components/src/button/index.ts index 18c4965c54..62c001f2db 100644 --- a/packages/nimble-components/src/button/index.ts +++ b/packages/nimble-components/src/button/index.ts @@ -5,9 +5,9 @@ import { buttonTemplate as template, DesignSystem } from '@microsoft/fast-foundation'; -import type { IButton } from '../patterns/button/types'; +import type { ButtonPattern } from '../patterns/button/types'; import { styles } from './styles'; -import { ButtonAppearance } from './types'; +import { ButtonAppearance, ButtonAppearanceVariant } from './types'; declare global { interface HTMLElementTagNameMap { @@ -18,7 +18,7 @@ declare global { /** * A nimble-styled HTML button */ -export class Button extends FoundationButton implements IButton { +export class Button extends FoundationButton implements ButtonPattern { /** * @public * @remarks @@ -27,6 +27,14 @@ export class Button extends FoundationButton implements IButton { @attr public appearance: ButtonAppearance = ButtonAppearance.outline; + /** + * @public + * @remarks + * HTML Attribute: appearance-variant + */ + @attr({ attribute: 'appearance-variant' }) + public appearanceVariant: ButtonAppearanceVariant; + /** * @public * @remarks diff --git a/packages/nimble-components/src/button/styles.ts b/packages/nimble-components/src/button/styles.ts index 4d5895533f..9cd169d509 100644 --- a/packages/nimble-components/src/button/styles.ts +++ b/packages/nimble-components/src/button/styles.ts @@ -18,23 +18,23 @@ export const styles = buttonStyles appearanceBehavior( ButtonAppearance.outline, css` - :host(.primary) .control { + :host([appearance-variant="primary"]) .control { box-shadow: 0px 0px 0px ${borderWidth} rgba(${actionRgbPartialColor}, 0.3) inset; } - :host(.primary) .control:hover { + :host([appearance-variant="primary"]) .control:hover { box-shadow: 0px 0px 0px ${borderWidth} ${borderHoverColor} inset; } - :host(.primary) .control${focusVisible} { + :host([appearance-variant="primary"]) .control${focusVisible} { box-shadow: 0px 0px 0px ${borderWidth} ${borderHoverColor} inset; } - :host(.primary) .control:active { + :host([appearance-variant="primary"]) .control:active { box-shadow: none; } - :host(.primary) .control[disabled] { + :host([appearance-variant="primary"]) .control[disabled] { box-shadow: none; } ` @@ -42,23 +42,23 @@ export const styles = buttonStyles appearanceBehavior( ButtonAppearance.block, css` - :host(.primary) .control { + :host([appearance-variant="primary"]) .control { background-clip: padding-box; border-color: rgba(${actionRgbPartialColor}, 0.3); border-width: calc(2 * ${borderWidth}); padding: 0 calc(${standardPadding} - ${borderWidth}); } - :host(.primary[content-hidden]) .control { + :host([appearance-variant="primary"][content-hidden]) .control { padding: 0px; } - :host(.primary) .control:hover { + :host([appearance-variant="primary"]) .control:hover { border-color: ${borderHoverColor}; box-shadow: none; } - :host(.primary) .control${focusVisible} { + :host([appearance-variant="primary"]) .control${focusVisible} { background-clip: border-box; border-color: ${borderHoverColor}; border-width: ${borderWidth}; @@ -66,11 +66,11 @@ export const styles = buttonStyles padding: 0 ${standardPadding}; } - :host(.primary[content-hidden]) .control${focusVisible} { + :host([appearance-variant="primary"][content-hidden]) .control${focusVisible} { padding: 0px; } - :host(.primary) .control:active { + :host([appearance-variant="primary"]) .control:active { background-clip: border-box; border-color: ${fillSelectedColor}; border-width: ${borderWidth}; @@ -78,11 +78,11 @@ export const styles = buttonStyles padding: 0 ${standardPadding}; } - :host(.primary[content-hidden]) .control:active { + :host([appearance-variant="primary"][content-hidden]) .control:active { padding: 0px; } - :host(.primary) .control[disabled] { + :host([appearance-variant="primary"]) .control[disabled] { background-clip: border-box; border-color: transparent; border-width: ${borderWidth}; @@ -90,7 +90,7 @@ export const styles = buttonStyles padding: 0 ${standardPadding}; } - :host(.primary[content-hidden]) .control[disabled] { + :host([appearance-variant="primary"][content-hidden]) .control[disabled] { padding: 0px; } ` diff --git a/packages/nimble-components/src/button/tests/button.stories.ts b/packages/nimble-components/src/button/tests/button.stories.ts index a18c2c636c..1ae0b1eb3a 100644 --- a/packages/nimble-components/src/button/tests/button.stories.ts +++ b/packages/nimble-components/src/button/tests/button.stories.ts @@ -7,7 +7,7 @@ import '../../all-components'; interface ButtonArgs { label: string; - appearance: string; + appearance: ButtonAppearance; primary: boolean; disabled: boolean; icon: boolean; diff --git a/packages/nimble-components/src/button/types.ts b/packages/nimble-components/src/button/types.ts index 5b528e9911..d58d68a587 100644 --- a/packages/nimble-components/src/button/types.ts +++ b/packages/nimble-components/src/button/types.ts @@ -5,5 +5,15 @@ import type { Button } from '@microsoft/fast-foundation'; export { ButtonAppearance } from '../patterns/button/types'; - export type ButtonType = Button['type']; + +/** + * Types of button appearance variants. + * @public + */ +export const ButtonAppearanceVariant = { + default: undefined, + primary: 'primary' +} as const; +export type ButtonAppearanceVariant = + typeof ButtonAppearanceVariant[keyof typeof ButtonAppearanceVariant]; diff --git a/packages/nimble-components/src/combobox/index.ts b/packages/nimble-components/src/combobox/index.ts index a1ab9431df..8244b31341 100644 --- a/packages/nimble-components/src/combobox/index.ts +++ b/packages/nimble-components/src/combobox/index.ts @@ -17,7 +17,7 @@ import '../icons/exclamation-mark'; import '../icons/arrow-expander-down'; import { styles } from './styles'; -import type { IHasErrorText } from '../patterns/error/types'; +import type { ErrorPattern } from '../patterns/error/types'; declare global { interface HTMLElementTagNameMap { @@ -28,14 +28,14 @@ declare global { /** * A nimble-styed HTML combobox */ -export class Combobox extends FoundationCombobox implements IHasErrorText { +export class Combobox extends FoundationCombobox implements ErrorPattern { /** * The ref to the internal dropdown button element. * * @internal */ @observable - public readonly dropdownButton: ToggleButton | undefined; + public readonly dropdownButton!: ToggleButton; /** * A message explaining why the value is invalid. @@ -45,7 +45,10 @@ export class Combobox extends FoundationCombobox implements IHasErrorText { * HTML Attribute: error-text */ @attr({ attribute: 'error-text' }) - public errorText: string | undefined; + public errorText?: string; + + @attr({ attribute: 'error-visible', mode: 'boolean' }) + public errorVisible = false; // Workaround for https://github.com/microsoft/fast/issues/5123 public override setPositioning(): void { @@ -87,7 +90,7 @@ export class Combobox extends FoundationCombobox implements IHasErrorText { } public toggleButtonChangeHandler(e: Event): void { - this.open = this.dropdownButton!.checked; + this.open = this.dropdownButton.checked; e.stopImmediatePropagation(); } @@ -113,9 +116,7 @@ export class Combobox extends FoundationCombobox implements IHasErrorText { protected override openChanged(): void { super.openChanged(); - if (this.dropdownButton) { - this.dropdownButton.checked = this.open; - } + this.dropdownButton.checked = this.open; } // Workaround for https://github.com/microsoft/fast/issues/6041. diff --git a/packages/nimble-components/src/combobox/styles.ts b/packages/nimble-components/src/combobox/styles.ts index 3f19ac401d..045d8eee15 100644 --- a/packages/nimble-components/src/combobox/styles.ts +++ b/packages/nimble-components/src/combobox/styles.ts @@ -35,7 +35,7 @@ export const styles = css` border-bottom-color: ${borderHoverColor}; } - :host(.invalid) .control { + :host([error-visible]) .control { border-bottom: var(--ni-private-bottom-border-width) solid ${failColor}; } @@ -43,7 +43,7 @@ export const styles = css` border-color: rgba(${borderRgbPartialColor}, 0.1); } - :host(.invalid[disabled]) .control { + :host([error-visible][disabled]) .control { border-color: ${failColor}; } diff --git a/packages/nimble-components/src/drawer/styles.ts b/packages/nimble-components/src/drawer/styles.ts index 9699b7823e..4302e0656f 100644 --- a/packages/nimble-components/src/drawer/styles.ts +++ b/packages/nimble-components/src/drawer/styles.ts @@ -82,10 +82,6 @@ export const styles = css` height: 100%; } - :host(.hidden) .control { - visibility: hidden; - } - :host([location='left']) .control { left: 0px; border-right: ${borderWidth} solid ${popupBoxShadowColor}; diff --git a/packages/nimble-components/src/icon-base/index.ts b/packages/nimble-components/src/icon-base/index.ts index 5cdb6c6c90..5d875f7a9f 100644 --- a/packages/nimble-components/src/icon-base/index.ts +++ b/packages/nimble-components/src/icon-base/index.ts @@ -1,13 +1,23 @@ +import { attr } from '@microsoft/fast-element'; import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; import type { NimbleIcon } from '@ni/nimble-tokens/dist/icons/js'; import { template } from './template'; import { styles } from './styles'; +import type { IconAppearance } from './types'; /** * The base class for icon components */ export class Icon extends FoundationElement { - public constructor(public icon: NimbleIcon) { + /** + * @public + * @remarks + * HTML Attribute: appearance + */ + @attr + public appearance: IconAppearance; + + public constructor(/** @internal */ public readonly icon: NimbleIcon) { super(); } } diff --git a/packages/nimble-components/src/icon-base/styles.ts b/packages/nimble-components/src/icon-base/styles.ts index 59a9c1d8cf..1d65fa90f8 100644 --- a/packages/nimble-components/src/icon-base/styles.ts +++ b/packages/nimble-components/src/icon-base/styles.ts @@ -24,19 +24,19 @@ export const styles = css` height: 100%; } - :host(.fail) { + :host([appearance="error"]) { ${iconColor.cssCustomProperty}: ${failColor}; } - :host(.warning) { + :host([appearance="warning"]) { ${iconColor.cssCustomProperty}: ${warningColor}; } - :host(.pass) { + :host([appearance="success"]) { ${iconColor.cssCustomProperty}: ${passColor}; } - :host(.information) { + :host([appearance="information"]) { ${iconColor.cssCustomProperty}: ${informationColor}; } diff --git a/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts b/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts index fbfe35c9ea..540e75a134 100644 --- a/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts +++ b/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts @@ -1,5 +1,6 @@ import type { Story, Meta } from '@storybook/html'; import { html, ViewTemplate } from '@microsoft/fast-element'; +import { pascalCase } from '@microsoft/fast-web-utilities'; import { createMatrix, sharedMatrixParameters @@ -8,7 +9,7 @@ import { createMatrixThemeStory, createStory } from '../../utilities/tests/storybook'; -import { IconStatus } from '../types'; +import { IconAppearance } from '../types'; import { bodyFontColor } from '../../theme-provider/design-tokens'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; @@ -22,18 +23,14 @@ const metadata: Meta = { export default metadata; -const iconStatusStates = [ - ['Pass', IconStatus.pass], - ['Fail', IconStatus.fail], - ['Warning', IconStatus.warning], - ['Regular', IconStatus.regular], - ['Information', IconStatus.information] -] as const; +const iconStatusStates: [string, string | undefined][] = Object.entries(IconAppearance).map( + ([key, value]) => [pascalCase(key), value] +); type IconStatusState = typeof iconStatusStates[number]; const component = ([stateName, state]: IconStatusState): ViewTemplate => html` - ${stateName} - + ${() => stateName} + `; export const iconThemeMatrix: Story = createMatrixThemeStory( diff --git a/packages/nimble-components/src/icon-base/tests/icons.stories.ts b/packages/nimble-components/src/icon-base/tests/icons.stories.ts index 616ea4729f..0171c9d0d5 100644 --- a/packages/nimble-components/src/icon-base/tests/icons.stories.ts +++ b/packages/nimble-components/src/icon-base/tests/icons.stories.ts @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html, repeat } from '@microsoft/fast-element'; import { DesignSystem } from '@microsoft/fast-foundation'; import * as nimbleIconComponentsMap from '../../icons/all-icons'; -import { IconStatus } from '../types'; +import { IconAppearance } from '../types'; import { createUserSelectedThemeStory, overrideWarning @@ -16,7 +16,7 @@ import { const nimbleIconComponents = Object.values(nimbleIconComponentsMap); interface IconArgs { - status: IconStatus; + status: IconAppearance; } const metadata: Meta = { @@ -34,7 +34,7 @@ type IconClass = typeof Icon; const iconTemplate = html` ${(x, c) => html` <${DesignSystem.tagFor(x)} - class="${c.parent.status}" + appearance=${() => c.parent.status} title=${DesignSystem.tagFor(x)} > @@ -47,17 +47,17 @@ ${scssInternalPropertySetterMarkdown(tokenNames.iconColor, 'purple')} `; const statusDescription = ` -Set the \`pass\`, \`fail\`, \`warning\`, or \`information\` CSS class on the element to switch between the theme-aware color options. +Set appearance on the element to switch between the theme-aware color options. ${overrideWarning('Color', statusDescriptionOverride)} `; // prettier-ignore export const icons: StoryObj = { - args: { status: IconStatus.regular }, + args: { status: IconAppearance.default }, argTypes: { status: { - options: Object.values(IconStatus), + options: Object.values(IconAppearance), control: { type: 'radio' }, description: statusDescription } diff --git a/packages/nimble-components/src/icon-base/tests/types.spec.ts b/packages/nimble-components/src/icon-base/tests/types.spec.ts index cb1f13636b..cc8da8ab0a 100644 --- a/packages/nimble-components/src/icon-base/tests/types.spec.ts +++ b/packages/nimble-components/src/icon-base/tests/types.spec.ts @@ -1,9 +1,10 @@ -import type { IconStatus } from '../types'; +import type { IconAppearance } from '../types'; describe('Icon type', () => { it('IconStatus fails compile if assigning arbitrary string values', () => { // @ts-expect-error This expect will fail if the enum-like type is missing "as const" - const status: IconStatus = 'hello'; + const status: IconAppearance = 'hello'; + // @ts-expect-error This expect will fail if the enum-like type is missing "as const" expect(status).toEqual('hello'); }); }); diff --git a/packages/nimble-components/src/icon-base/types.ts b/packages/nimble-components/src/icon-base/types.ts index 2ee9ee0b65..9aa3424612 100644 --- a/packages/nimble-components/src/icon-base/types.ts +++ b/packages/nimble-components/src/icon-base/types.ts @@ -1,12 +1,12 @@ /** - * Predefined icon status states + * Predefined icon appearance states * @public */ -export const IconStatus = { - fail: 'fail', +export const IconAppearance = { + default: undefined, + error: 'error', warning: 'warning', - pass: 'pass', - regular: 'regular', + success: 'success', information: 'information' } as const; -export type IconStatus = typeof IconStatus[keyof typeof IconStatus]; +export type IconAppearance = typeof IconAppearance[keyof typeof IconAppearance]; diff --git a/packages/nimble-components/src/menu-button/index.ts b/packages/nimble-components/src/menu-button/index.ts index c49339abf2..0beb314b73 100644 --- a/packages/nimble-components/src/menu-button/index.ts +++ b/packages/nimble-components/src/menu-button/index.ts @@ -11,7 +11,7 @@ import type { ToggleButton } from '../toggle-button'; import { styles } from './styles'; import { template } from './template'; import { MenuButtonPosition } from './types'; -import type { IButton } from '../patterns/button/types'; +import type { ButtonPattern } from '../patterns/button/types'; import type { AnchoredRegion } from '../anchored-region'; declare global { @@ -23,7 +23,7 @@ declare global { /** * A nimble-styled menu button control. */ -export class MenuButton extends FoundationElement implements IButton { +export class MenuButton extends FoundationElement implements ButtonPattern { @attr public appearance: ButtonAppearance = ButtonAppearance.outline; @@ -47,15 +47,15 @@ export class MenuButton extends FoundationElement implements IButton { /** @internal */ @observable - public readonly toggleButton: ToggleButton | undefined; + public readonly toggleButton?: ToggleButton; /** @internal */ @observable - public readonly region: AnchoredRegion | undefined; + public readonly region?: AnchoredRegion; /** @internal */ @observable - public readonly slottedMenus: HTMLElement[] | undefined; + public readonly slottedMenus?: HTMLElement[]; /** * Used to maintain the internal state of whether the last menu item should be focused instead diff --git a/packages/nimble-components/src/number-field/index.ts b/packages/nimble-components/src/number-field/index.ts index e18fa6d0bf..2de35b1175 100644 --- a/packages/nimble-components/src/number-field/index.ts +++ b/packages/nimble-components/src/number-field/index.ts @@ -11,6 +11,7 @@ import { errorTextTemplate } from '../patterns/error/template'; import '../icons/add'; import '../icons/exclamation-mark'; import '../icons/minus-wide'; +import type { ErrorPattern } from '../patterns/error/types'; declare global { interface HTMLElementTagNameMap { @@ -21,7 +22,7 @@ declare global { /** * A nimble-styled HTML number input */ -export class NumberField extends FoundationNumberField { +export class NumberField extends FoundationNumberField implements ErrorPattern { @attr public appearance: NumberFieldAppearance = NumberFieldAppearance.underline; @@ -33,7 +34,10 @@ export class NumberField extends FoundationNumberField { * HTML Attribute: error-text */ @attr({ attribute: 'error-text' }) - public errorText: string | undefined; + public errorText?: string; + + @attr({ attribute: 'error-visible', mode: 'boolean' }) + public errorVisible = false; public override connectedCallback(): void { super.connectedCallback(); diff --git a/packages/nimble-components/src/number-field/styles.ts b/packages/nimble-components/src/number-field/styles.ts index 0babb7f2e8..1ff92493f7 100644 --- a/packages/nimble-components/src/number-field/styles.ts +++ b/packages/nimble-components/src/number-field/styles.ts @@ -72,7 +72,7 @@ export const styles = css` border-color: rgba(${borderRgbPartialColor}, 0.1); } - :host(.invalid) .root { + :host([error-visible]) .root { border-bottom-color: ${failColor}; } @@ -101,7 +101,7 @@ export const styles = css` } } - :host(.invalid) .root::after { + :host([error-visible]) .root::after { border-bottom-color: ${failColor}; } @@ -154,7 +154,8 @@ export const styles = css` } ${ - /* We are using flex `order` to define the visual ordering of the inc/dec buttons and the invalid icon because they are not "interactive" i.e. part of the tab order */ '' + /* We are using flex `order` to define the visual ordering of the inc/dec buttons + and the invalid icon because they are not "interactive" i.e. part of the tab order */ '' } .step-up { order: 3; @@ -195,7 +196,7 @@ export const styles = css` } .root:focus-within, - :host(.invalid) .root { + :host([error-visible]) .root { border-bottom-width: ${borderWidth}; padding-bottom: 0; } diff --git a/packages/nimble-components/src/patterns/button/types.ts b/packages/nimble-components/src/patterns/button/types.ts index 23d21cb2e2..18077e5e82 100644 --- a/packages/nimble-components/src/patterns/button/types.ts +++ b/packages/nimble-components/src/patterns/button/types.ts @@ -2,7 +2,7 @@ * The interface that buttons of various types implement. The properties in this interface * are leveraged by the shared button pattern css. */ -export interface IButton { +export interface ButtonPattern { /** * The appearance the button should have. */ diff --git a/packages/nimble-components/src/patterns/dropdown/styles.ts b/packages/nimble-components/src/patterns/dropdown/styles.ts index 88b110c4de..129b88ca99 100644 --- a/packages/nimble-components/src/patterns/dropdown/styles.ts +++ b/packages/nimble-components/src/patterns/dropdown/styles.ts @@ -71,7 +71,7 @@ export const styles = css` transition: width ${smallDelay} ease-in; } - :host(.invalid)::after { + :host([error-visible])::after { border-bottom-color: ${failColor}; } @@ -103,7 +103,7 @@ export const styles = css` padding-bottom: 1px; } - :host(.open:not(:hover)) .control { + :host([open]:not(:hover)) .control { border-bottom-color: ${borderHoverColor}; } diff --git a/packages/nimble-components/src/patterns/error/styles.ts b/packages/nimble-components/src/patterns/error/styles.ts index 5f45af0c68..a94c69b0a8 100644 --- a/packages/nimble-components/src/patterns/error/styles.ts +++ b/packages/nimble-components/src/patterns/error/styles.ts @@ -12,7 +12,7 @@ export const styles = css` display: none; } - :host(.invalid) .error-icon { + :host([error-visible]) .error-icon { display: inline-flex; width: ${iconSize}; height: ${iconSize}; @@ -23,7 +23,7 @@ export const styles = css` display: none; } - :host(.invalid) .error-text { + :host([error-visible]) .error-text { display: block; font: ${errorTextFont}; color: ${failColor}; @@ -36,11 +36,11 @@ export const styles = css` white-space: nowrap; } - :host(.invalid[readonly]:not([disabled])) .error-text { + :host([error-visible][readonly]:not([disabled])) .error-text { top: calc(${controlHeight} - ${borderWidth}); } - :host(.invalid) .error-text:empty { + :host([error-visible]) .error-text:empty { display: none; } `; diff --git a/packages/nimble-components/src/patterns/error/template.ts b/packages/nimble-components/src/patterns/error/template.ts index 440397bc58..4a61e0a3a3 100644 --- a/packages/nimble-components/src/patterns/error/template.ts +++ b/packages/nimble-components/src/patterns/error/template.ts @@ -1,7 +1,7 @@ import { html } from '@microsoft/fast-element'; -import type { IHasErrorText } from './types'; +import type { ErrorPattern } from './types'; -export const errorTextTemplate = html` +export const errorTextTemplate = html`
${x => x.errorText}
diff --git a/packages/nimble-components/src/patterns/error/types.ts b/packages/nimble-components/src/patterns/error/types.ts index 4d7a16ae65..a45244a560 100644 --- a/packages/nimble-components/src/patterns/error/types.ts +++ b/packages/nimble-components/src/patterns/error/types.ts @@ -1,9 +1,14 @@ /** - * This interface should be used by components that want to leverage the errorTextTemplate defined in templates.ts + * This interface should be used by components that want to leverage the error pattern */ -export interface IHasErrorText { +export interface ErrorPattern { /** - * The error text that will be displayed when a component has the 'invalid' class set + * The error text that will be displayed when a component is in the error appearance */ - errorText: string | undefined; + errorText?: string; + + /* + * Show the error appearance of the control + */ + errorVisible: boolean; } diff --git a/packages/nimble-components/src/select/styles.ts b/packages/nimble-components/src/select/styles.ts index 9e8f2e01b6..6d24ced26d 100644 --- a/packages/nimble-components/src/select/styles.ts +++ b/packages/nimble-components/src/select/styles.ts @@ -33,7 +33,7 @@ export const styles = css` border: ${borderWidth} solid rgba(${borderRgbPartialColor}, 0.3); } - :host(.invalid) .errortext { + :host([error-visible]) .errortext { top: calc(${controlHeight} - ${borderWidth}); } ` diff --git a/packages/nimble-components/src/text-field/index.ts b/packages/nimble-components/src/text-field/index.ts index 775cd9ee77..7f462a037c 100644 --- a/packages/nimble-components/src/text-field/index.ts +++ b/packages/nimble-components/src/text-field/index.ts @@ -9,7 +9,7 @@ import '../icons/exclamation-mark'; import { styles } from './styles'; import { TextFieldAppearance } from './types'; import { errorTextTemplate } from '../patterns/error/template'; -import type { IHasErrorText } from '../patterns/error/types'; +import type { ErrorPattern } from '../patterns/error/types'; declare global { interface HTMLElementTagNameMap { @@ -20,7 +20,7 @@ declare global { /** * A nimble-styed HTML text input */ -export class TextField extends FoundationTextField implements IHasErrorText { +export class TextField extends FoundationTextField implements ErrorPattern { /** * The appearance the text field should have. * @@ -39,7 +39,13 @@ export class TextField extends FoundationTextField implements IHasErrorText { * HTML Attribute: error-text */ @attr({ attribute: 'error-text' }) - public errorText: string | undefined; + public errorText?: string; + + @attr({ attribute: 'error-visible', mode: 'boolean' }) + public errorVisible = false; + + @attr({ attribute: 'edges-flush', mode: 'boolean' }) + public edgesFlush = false; public override connectedCallback(): void { super.connectedCallback(); diff --git a/packages/nimble-components/src/text-field/styles.ts b/packages/nimble-components/src/text-field/styles.ts index 77340a45c9..ab8f52803a 100644 --- a/packages/nimble-components/src/text-field/styles.ts +++ b/packages/nimble-components/src/text-field/styles.ts @@ -77,7 +77,7 @@ export const styles = css` border-color: rgba(${borderRgbPartialColor}, 0.1); } - :host(.invalid) .root { + :host([error-visible]) .root { border-bottom-color: ${failColor}; } @@ -85,7 +85,7 @@ export const styles = css` border-bottom-color: ${borderHoverColor}; } - :host([appearance='frameless'].clear-inline-padding) .root { + :host([appearance='frameless'][edges-flush]) .root { padding-left: 0px; padding-right: 0px; } @@ -98,7 +98,7 @@ export const styles = css` user-select: none; } - :host([appearance='frameless'].clear-inline-padding) .root::before { + :host([appearance='frameless'][edges-flush]) .root::before { display: none; } @@ -110,7 +110,7 @@ export const styles = css` user-select: none; } - :host([appearance='frameless'].clear-inline-padding) .root::after { + :host([appearance='frameless'][edges-flush]) .root::after { display: none; } @@ -186,7 +186,7 @@ export const styles = css` } } - :host(.invalid) [part='end']::after { + :host([error-visible]) [part='end']::after { border-bottom-color: ${failColor}; } @@ -229,7 +229,7 @@ export const styles = css` } .root:focus-within, - :host(.invalid) .root { + :host([error-visible]) .root { border-bottom-width: ${borderWidth}; padding-bottom: 0; } diff --git a/packages/nimble-components/src/toggle-button/index.ts b/packages/nimble-components/src/toggle-button/index.ts index 2843cb7982..4fa5a7d1f3 100644 --- a/packages/nimble-components/src/toggle-button/index.ts +++ b/packages/nimble-components/src/toggle-button/index.ts @@ -9,7 +9,7 @@ import { } from '@microsoft/fast-foundation'; import { styles } from './styles'; import { template } from './template'; -import type { IButton } from '../patterns/button/types'; +import type { ButtonPattern } from '../patterns/button/types'; import { ButtonAppearance } from './types'; declare global { @@ -21,7 +21,7 @@ declare global { /** * A nimble-styled toggle button control. */ -export class ToggleButton extends FoundationSwitch implements IButton { +export class ToggleButton extends FoundationSwitch implements ButtonPattern { /** * @public * @remarks diff --git a/packages/nimble-components/src/tooltip/index.ts b/packages/nimble-components/src/tooltip/index.ts index d5dcc251eb..dcb31d092d 100644 --- a/packages/nimble-components/src/tooltip/index.ts +++ b/packages/nimble-components/src/tooltip/index.ts @@ -1,9 +1,11 @@ +import { attr } from '@microsoft/fast-element'; import { DesignSystem, Tooltip as FoundationTooltip } from '@microsoft/fast-foundation'; import { styles } from './styles'; import { template } from './template'; +import type { TooltipAppearance } from './types'; declare global { interface HTMLElementTagNameMap { @@ -14,7 +16,18 @@ declare global { /** * A nimble-styled tooltip control. */ -export class Tooltip extends FoundationTooltip {} +export class Tooltip extends FoundationTooltip { + /** + * @public + * @remarks + * HTML Attribute: appearance + */ + @attr + public appearance: TooltipAppearance; + + @attr({ attribute: 'icon-visible', mode: 'boolean' }) + public iconVisible = false; +} const nimbleTooltip = Tooltip.compose({ baseName: 'tooltip', diff --git a/packages/nimble-components/src/tooltip/styles.ts b/packages/nimble-components/src/tooltip/styles.ts index e5248a13a9..10e7561467 100644 --- a/packages/nimble-components/src/tooltip/styles.ts +++ b/packages/nimble-components/src/tooltip/styles.ts @@ -53,26 +53,25 @@ export const styles = css` padding-right: 8px; } - :host(.fail.icon-visible) .fail { + :host([appearance="error"][icon-visible]) [appearance="error"] { display: flex; flex: 0 0 auto; } - :host(.information.icon-visible) .information { + :host([appearance="information"][icon-visible]) [appearance="information"] { display: flex; flex: 0 0 auto; } `.withBehaviors( - /* Local Theme Behaviors for tooltip borders and backgrounds */ themeBehavior( // Light Theme css` - :host(.fail) { + :host([appearance="error"]) { --ni-private-tooltip-border-color: ${BannerFail100DarkUi}; --ni-private-tooltip-background-color: ${White}; } - :host(.information) { + :host([appearance="information"]) { --ni-private-tooltip-border-color: ${Information100LightUi}; --ni-private-tooltip-background-color: ${White}; } @@ -87,11 +86,11 @@ export const styles = css` --ni-private-tooltip-background-color: ${Black85}; } - :host(.information) { + :host([appearance="information"]) { --ni-private-tooltip-border-color: ${Information100DarkUi}; } - :host(.fail) { + :host([appearance="error"]) { --ni-private-tooltip-border-color: ${BannerFail100DarkUi}; } `, @@ -112,11 +111,11 @@ export const styles = css` )}; } - :host(.fail) { + :host([appearance="error"]) { --ni-private-tooltip-border-color: ${White}; } - :host(.information) { + :host([appearance="information"]) { --ni-private-tooltip-border-color: ${White}; } diff --git a/packages/nimble-components/src/tooltip/template.ts b/packages/nimble-components/src/tooltip/template.ts index 47dd0ef0da..67b670bef7 100644 --- a/packages/nimble-components/src/tooltip/template.ts +++ b/packages/nimble-components/src/tooltip/template.ts @@ -29,8 +29,14 @@ export const template: FoundationElementTemplate> = contex ${ref('region')} > diff --git a/packages/nimble-components/src/tooltip/tests/tooltip.stories.ts b/packages/nimble-components/src/tooltip/tests/tooltip.stories.ts index c729477380..7034bd7138 100644 --- a/packages/nimble-components/src/tooltip/tests/tooltip.stories.ts +++ b/packages/nimble-components/src/tooltip/tests/tooltip.stories.ts @@ -9,11 +9,11 @@ import { bodyFont, bodyFontColor } from '../../theme-provider/design-tokens'; -import { TooltipStatus } from '../types'; +import { TooltipAppearance } from '../types'; interface TooltipArgs { visible: boolean; - state: keyof typeof TooltipStatus; + state: keyof typeof TooltipAppearance; delay: number; tooltip: string; autoUpdateMode: AutoUpdateMode; @@ -61,7 +61,7 @@ const metadata: Meta = { delay="${x => x.delay}" auto-update-mode="${x => x.autoUpdateMode}" id="ariaAnchor" - class="${x => TooltipStatus[x.state]} ${x => (x.icon ? 'icon-visible' : '')}" + class="${x => TooltipAppearance[x.state]} ${x => (x.icon ? 'icon-visible' : '')}" > ${x => x.tooltip} @@ -87,7 +87,7 @@ const metadata: Meta = { 'The delay in milliseconds before a tooltip is shown after a hover event' }, state: { - options: Object.keys(TooltipStatus), + options: Object.keys(TooltipAppearance), control: { type: 'radio' }, description: 'Set the `default`, `fail`, or `information` CSS class on the tooltip to switch between the theme-aware color options.' diff --git a/packages/nimble-components/src/tooltip/tests/types.spec.ts b/packages/nimble-components/src/tooltip/tests/types.spec.ts index 56e72cace5..3c02cbb45d 100644 --- a/packages/nimble-components/src/tooltip/tests/types.spec.ts +++ b/packages/nimble-components/src/tooltip/tests/types.spec.ts @@ -1,4 +1,4 @@ -import type { TooltipStatus } from '../types'; +import type { TooltipAppearance } from '../types'; describe('Tooltip type', () => { it('TooltipStatus fails compile if assigning arbitrary string values', () => { diff --git a/packages/nimble-components/src/tooltip/types.ts b/packages/nimble-components/src/tooltip/types.ts index 4c50b72f58..e2fa8fad1a 100644 --- a/packages/nimble-components/src/tooltip/types.ts +++ b/packages/nimble-components/src/tooltip/types.ts @@ -2,10 +2,10 @@ * Types of tooltip appearance. * @public */ -export const TooltipStatus = { - default: '', - fail: 'fail', +export const TooltipAppearance = { + default: undefined, + error: 'error', information: 'information' } as const; -export type TooltipStatus = typeof TooltipStatus[keyof typeof TooltipStatus]; +export type TooltipAppearance = typeof TooltipAppearance[keyof typeof TooltipAppearance]; From 2e3de26e1f535e152a528b27d61b0091d5db80a1 Mon Sep 17 00:00:00 2001 From: rajsite Date: Fri, 5 Aug 2022 17:21:28 -0500 Subject: [PATCH 02/43] prototype --- .../src/button/tests/button-matrix.stories.ts | 21 ++++++++++--------- .../src/button/tests/button.stories.ts | 18 ++++++++++++---- .../nimble-components/src/combobox/index.ts | 11 ++++++---- .../combobox/tests/combobox-matrix.stories.ts | 20 +++++++----------- .../src/combobox/tests/combobox.stories.ts | 9 ++++---- .../src/number-field/index.ts | 3 ++- .../tests/number-field-matrix.stories.ts | 19 ++++++----------- .../tests/number-field.stories.ts | 18 ++++++++++------ .../src/utilities/tests/states.ts | 9 ++++---- 9 files changed, 69 insertions(+), 59 deletions(-) diff --git a/packages/nimble-components/src/button/tests/button-matrix.stories.ts b/packages/nimble-components/src/button/tests/button-matrix.stories.ts index 3fbc26b560..35ac76531f 100644 --- a/packages/nimble-components/src/button/tests/button-matrix.stories.ts +++ b/packages/nimble-components/src/button/tests/button-matrix.stories.ts @@ -2,7 +2,7 @@ import type { Meta, Story } from '@storybook/html'; import { withXD } from 'storybook-addon-xd-designs'; import { html, ViewTemplate, when } from '@microsoft/fast-element'; import { pascalCase } from '@microsoft/fast-web-utilities'; -import { ButtonAppearance } from '../types'; +import { ButtonAppearance, ButtonAppearanceVariant } from '../types'; import { createMatrix, sharedMatrixParameters @@ -44,27 +44,28 @@ const appearanceStates = Object.entries(ButtonAppearance).map( ); type AppearanceState = typeof appearanceStates[number]; -const primaryStates = [ - ['Primary', 'primary'], - ['', ''] -] as const; -type PrimaryState = typeof primaryStates[number]; +const appearanceVariantStates: [string, string | undefined][] = Object + .entries(ButtonAppearanceVariant) + .map( + ([key, value]) => [pascalCase(key), value] + ); +type AppearanceVariantState = typeof appearanceVariantStates[number]; // prettier-ignore const component = ( [disabledName, disabled]: DisabledState, [appearanceName, appearance]: AppearanceState, - [primaryName, primaryClass]: PrimaryState, + [appearanceVariantName, appearanceVariant]: AppearanceVariantState, [iconVisible, labelVisible, endIconVisible]: PartVisibilityState, ): ViewTemplate => html` disabled} ?content-hidden=${() => !labelVisible} style="margin-right: 8px; margin-bottom: 8px;"> ${when(() => iconVisible, html``)} - ${() => `${primaryName} ${appearanceName!} Button ${disabledName}`} + ${() => `${appearanceVariantName} ${appearanceName!} Button ${disabledName}`} ${when(() => endIconVisible, html``)} `; @@ -73,7 +74,7 @@ export const buttonThemeMatrix: Story = createMatrixThemeStory( createMatrix(component, [ disabledStates, appearanceStates, - primaryStates, + appearanceVariantStates, partVisibilityStates ]) ); diff --git a/packages/nimble-components/src/button/tests/button.stories.ts b/packages/nimble-components/src/button/tests/button.stories.ts index 1ae0b1eb3a..2efc66e554 100644 --- a/packages/nimble-components/src/button/tests/button.stories.ts +++ b/packages/nimble-components/src/button/tests/button.stories.ts @@ -1,13 +1,14 @@ import type { Meta, StoryObj } from '@storybook/html'; import { withXD } from 'storybook-addon-xd-designs'; import { html, when } from '@microsoft/fast-element'; -import { ButtonAppearance } from '../types'; +import { ButtonAppearance, ButtonAppearanceVariant } from '../types'; import { createUserSelectedThemeStory } from '../../utilities/tests/storybook'; import '../../all-components'; interface ButtonArgs { label: string; appearance: ButtonAppearance; + appearanceVariant: keyof typeof ButtonAppearanceVariant; primary: boolean; disabled: boolean; icon: boolean; @@ -72,15 +73,24 @@ const metadata: Meta = { }, // prettier-ignore render: createUserSelectedThemeStory(html` - - ${when(x => x.icon, html``)} + + ${when(x => x.icon, html` + + `)} ${x => x.label} - ${when(x => x.endIcon, html``)} + ${when(x => x.endIcon, html` + + `)} `), args: { label: 'Ghost Button', appearance: 'ghost', + appearanceVariant: 'default', primary: false, icon: false, endIcon: false, diff --git a/packages/nimble-components/src/combobox/index.ts b/packages/nimble-components/src/combobox/index.ts index 8244b31341..57df39b38a 100644 --- a/packages/nimble-components/src/combobox/index.ts +++ b/packages/nimble-components/src/combobox/index.ts @@ -35,7 +35,7 @@ export class Combobox extends FoundationCombobox implements ErrorPattern { * @internal */ @observable - public readonly dropdownButton!: ToggleButton; + public readonly dropdownButton?: ToggleButton; /** * A message explaining why the value is invalid. @@ -90,7 +90,7 @@ export class Combobox extends FoundationCombobox implements ErrorPattern { } public toggleButtonChangeHandler(e: Event): void { - this.open = this.dropdownButton.checked; + this.open = this.dropdownButton!.checked; e.stopImmediatePropagation(); } @@ -116,7 +116,9 @@ export class Combobox extends FoundationCombobox implements ErrorPattern { protected override openChanged(): void { super.openChanged(); - this.dropdownButton.checked = this.open; + if (this.dropdownButton) { + this.dropdownButton.checked = this.open; + } } // Workaround for https://github.com/microsoft/fast/issues/6041. @@ -149,7 +151,8 @@ const nimbleCombobox = Combobox.compose({ end: html`
html` +
+ Option 1 @@ -55,7 +49,7 @@ const component = ( `; export const comboboxThemeMatrix: Story = createMatrixThemeStory( - createMatrix(component, [disabledStates, comboboxInvalidStates]) + createMatrix(component, [disabledStates, errorStates]) ); export const hiddenCombobox: Story = createStory( diff --git a/packages/nimble-components/src/combobox/tests/combobox.stories.ts b/packages/nimble-components/src/combobox/tests/combobox.stories.ts index 3ae706ef61..a83b3baed0 100644 --- a/packages/nimble-components/src/combobox/tests/combobox.stories.ts +++ b/packages/nimble-components/src/combobox/tests/combobox.stories.ts @@ -12,7 +12,7 @@ interface ComboboxArgs { dropDownPosition: DropdownPosition; autocomplete: ComboboxAutocomplete; options: OptionArgs[]; - invalid: boolean; + errorVisible: boolean; errorText: string; currentValue: string; } @@ -48,8 +48,9 @@ const metadata: Meta = { ?disabled="${x => x.disabled}" position="${x => x.dropDownPosition}" error-text="${x => x.errorText}" - class="${x => (x.invalid ? 'invalid' : '')}" - aria-invalid="${x => x.invalid}" + ?error-visible="${x => x.errorVisible}" + ${/* This should be handled by the error-visible attr */ ''} + aria-invalid="${x => x.errorVisible}" value="${x => x.currentValue}" > ${repeat(x => x.options, html` @@ -79,7 +80,7 @@ const metadata: Meta = { disabled: false, dropDownPosition: 'below', autocomplete: ComboboxAutocomplete.both, - invalid: false, + errorVisible: false, errorText: 'Value is invalid', currentValue: 'Joaquin', options: [ diff --git a/packages/nimble-components/src/number-field/index.ts b/packages/nimble-components/src/number-field/index.ts index 2de35b1175..a7509b6602 100644 --- a/packages/nimble-components/src/number-field/index.ts +++ b/packages/nimble-components/src/number-field/index.ts @@ -87,7 +87,8 @@ const nimbleNumberField = NumberField.compose({ `, end: html` ${errorTextTemplate} ` diff --git a/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts b/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts index 3a5fa922a7..a022a63f09 100644 --- a/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts +++ b/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts @@ -10,7 +10,7 @@ import { createMatrix, sharedMatrixParameters } from '../../utilities/tests/matrix'; -import { disabledStates, DisabledState } from '../../utilities/tests/states'; +import { disabledStates, DisabledState, errorStates, ErrorState } from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; import { NumberFieldAppearance } from '../types'; @@ -34,14 +34,6 @@ const valueStates = [ ] as const; type ValueState = typeof valueStates[number]; -/* array of state name, invalidClass, errorText */ -const invalidStates = [ - ['', '', 'This is not valid.'], - ['Invalid', 'invalid', ''], - ['Invalid w/ Error', 'invalid', 'This is not valid.'] -] as const; -type InvalidState = typeof invalidStates[number]; - const appearanceStates = Object.entries(NumberFieldAppearance).map( ([key, value]) => [pascalCase(key), value] ); @@ -50,19 +42,20 @@ type AppearanceState = typeof appearanceStates[number]; const component = ( [disabledName, disabled]: DisabledState, [valueName, valueValue, placeholderValue]: ValueState, - [invalidName, invalidClass, errorText]: InvalidState, + [errorName, errorVisible, errorText]: ErrorState, [appearanceName, appearance]: AppearanceState ): ViewTemplate => html` - ${() => invalidName} ${() => appearanceName} ${() => valueName} + ${() => errorName} ${() => appearanceName} ${() => valueName} ${() => disabledName} `; @@ -71,7 +64,7 @@ export const numberFieldThemeMatrix: Story = createMatrixThemeStory( createMatrix(component, [ disabledStates, valueStates, - invalidStates, + errorStates, appearanceStates ]) ); diff --git a/packages/nimble-components/src/number-field/tests/number-field.stories.ts b/packages/nimble-components/src/number-field/tests/number-field.stories.ts index 11fdb60509..a3ef85a334 100644 --- a/packages/nimble-components/src/number-field/tests/number-field.stories.ts +++ b/packages/nimble-components/src/number-field/tests/number-field.stories.ts @@ -10,8 +10,8 @@ interface NumberFieldArgs { value: number; appearance: NumberFieldAppearance; disabled: boolean; - invalid: boolean; - 'error-text': string; + errorVisible: boolean; + errorText: string; } const metadata: Meta = { @@ -38,8 +38,8 @@ const metadata: Meta = { value="${x => x.value}" appearance="${x => x.appearance}" ?disabled="${x => x.disabled}" - class="${x => (x.invalid ? 'invalid' : '')}" - error-text="${x => x['error-text']}" + ?error-visible="${x => x.errorVisible}" + error-text="${x => x.errorText}" > ${x => x.label} @@ -48,6 +48,12 @@ const metadata: Meta = { appearance: { options: Object.values(NumberFieldAppearance), control: { type: 'radio' } + }, + errorText: { + name: 'error-text' + }, + errorVisible: { + name: 'error-visible' } }, args: { @@ -55,8 +61,8 @@ const metadata: Meta = { value: 42, appearance: NumberFieldAppearance.underline, disabled: false, - invalid: false, - 'error-text': 'Value is invalid' + errorVisible: false, + errorText: 'Value is invalid' } }; diff --git a/packages/nimble-components/src/utilities/tests/states.ts b/packages/nimble-components/src/utilities/tests/states.ts index 0d75c1c4c3..2b0efd215d 100644 --- a/packages/nimble-components/src/utilities/tests/states.ts +++ b/packages/nimble-components/src/utilities/tests/states.ts @@ -26,11 +26,12 @@ export const disabledStates = [ ] as const; export type DisabledState = typeof disabledStates[number]; -export const invalidStates = [ - ['', ''], - ['Invalid', 'invalid'] +export const errorStates = [ + ['', false, ''], + ['Error Message', true, 'This is not valid.'], + ['Error No Message', true, ''] ] as const; -export type InvalidState = typeof invalidStates[number]; +export type ErrorState = typeof errorStates[number]; export const readOnlyStates = [ ['', false], From 5ad373142de5198c0f26040b4b6bf51d24768b35 Mon Sep 17 00:00:00 2001 From: rajsite Date: Sun, 7 Aug 2022 22:11:10 -0500 Subject: [PATCH 03/43] prototype --- .../tests/breadcrumb-matrix.stories.ts | 7 + .../src/button/tests/button-matrix.stories.ts | 19 ++- .../src/button/tests/button.stories.ts | 21 +-- .../checkbox/tests/checkbox-matrix.stories.ts | 7 + .../nimble-components/src/combobox/index.ts | 3 +- .../src/combobox/tests/combobox.stories.ts | 2 +- .../src/icon-base/tests/icons.stories.ts | 20 +-- .../src/menu/tests/menu-matrix.stories.ts | 11 ++ .../tests/number-field-matrix.stories.ts | 7 + .../src/patterns/dropdown/types.ts | 14 +- .../tests/text-customization.stories.ts | 48 ------ .../nimble-components/src/select/styles.ts | 5 - .../src/select/tests/select-matrix.stories.ts | 12 ++ .../src/select/tests/select.stories.ts | 12 +- .../src/tabs/tests/tabs-matrix.stories.ts | 13 ++ .../tests/text-area-matrix.stories.ts | 14 +- .../src/text-area/tests/text-area.stories.ts | 3 +- .../nimble-components/src/text-field/index.ts | 8 +- .../tests/text-field-matrix.stories.ts | 150 +++++++++--------- .../text-field/tests/text-field.stories.ts | 24 +-- .../tests/toggle-button-matrix.stories.ts | 11 +- .../tooltip/tests/tooltip-matrix.stories.ts | 44 ++--- .../src/tooltip/tests/tooltip.stories.ts | 38 +++-- .../tests/tree-view-matrix.stories.ts | 12 ++ .../src/utilities/tests/lorem-ipsum.ts | 1 + .../src/utilities/tests/text-customization.ts | 15 ++ 26 files changed, 298 insertions(+), 223 deletions(-) delete mode 100644 packages/nimble-components/src/patterns/tests/text-customization.stories.ts create mode 100644 packages/nimble-components/src/utilities/tests/lorem-ipsum.ts create mode 100644 packages/nimble-components/src/utilities/tests/text-customization.ts diff --git a/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts b/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts index 1b415f1f2b..d43c213729 100644 --- a/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts +++ b/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts @@ -13,6 +13,7 @@ import { import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; import { BreadcrumbAppearance } from '../types'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; const metadata: Meta = { title: 'Tests/Breadcrumb', @@ -56,3 +57,9 @@ export const hiddenBreadcrumb: Story = createStory( ` ) ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html`Breadcrumb item` + ) +); diff --git a/packages/nimble-components/src/button/tests/button-matrix.stories.ts b/packages/nimble-components/src/button/tests/button-matrix.stories.ts index 35ac76531f..213ac4196a 100644 --- a/packages/nimble-components/src/button/tests/button-matrix.stories.ts +++ b/packages/nimble-components/src/button/tests/button-matrix.stories.ts @@ -14,6 +14,7 @@ import { } from '../../utilities/tests/storybook'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; const metadata: Meta = { title: 'Tests/Button', @@ -39,16 +40,14 @@ const partVisibilityStates = [ ] as const; type PartVisibilityState = typeof partVisibilityStates[number]; -const appearanceStates = Object.entries(ButtonAppearance).map( - ([key, value]) => [pascalCase(key), value] -); +const appearanceStates: [string, string | undefined][] = Object + .entries(ButtonAppearance) + .map(([key, value]) => [pascalCase(key), value]); type AppearanceState = typeof appearanceStates[number]; const appearanceVariantStates: [string, string | undefined][] = Object .entries(ButtonAppearanceVariant) - .map( - ([key, value]) => [pascalCase(key), value] - ); + .map(([key, value]) => [pascalCase(key), value]); type AppearanceVariantState = typeof appearanceVariantStates[number]; // prettier-ignore @@ -65,7 +64,7 @@ const component = ( ?content-hidden=${() => !labelVisible} style="margin-right: 8px; margin-bottom: 8px;"> ${when(() => iconVisible, html``)} - ${() => `${appearanceVariantName} ${appearanceName!} Button ${disabledName}`} + ${() => `${appearanceVariantName} ${appearanceName} Button ${disabledName}`} ${when(() => endIconVisible, html``)} `; @@ -82,3 +81,9 @@ export const buttonThemeMatrix: Story = createMatrixThemeStory( export const hiddenButton: Story = createStory( hiddenWrapper(html``) ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html`Button` + ) +); diff --git a/packages/nimble-components/src/button/tests/button.stories.ts b/packages/nimble-components/src/button/tests/button.stories.ts index 2efc66e554..2ae9fcf8be 100644 --- a/packages/nimble-components/src/button/tests/button.stories.ts +++ b/packages/nimble-components/src/button/tests/button.stories.ts @@ -7,9 +7,8 @@ import '../../all-components'; interface ButtonArgs { label: string; - appearance: ButtonAppearance; + appearance: keyof typeof ButtonAppearance; appearanceVariant: keyof typeof ButtonAppearanceVariant; - primary: boolean; disabled: boolean; icon: boolean; contentHidden: boolean; @@ -21,7 +20,7 @@ enables users to trigger an action or event, such as submitting a form, opening action, or performing a delete operation. A common convention for informing users that a button launches a dialog is to append "…" (ellipsis) to the button label, e.g., "Save as…".`; -const primaryDescription = `Set the \`primary\` CSS class on the element to make a button primary. This class has no effect on buttons with a \`ghost\` appearance. +const appearanceVariantDescription = `This attribute has no effect on buttons with a \`ghost\` appearance.
Primary Button Usage @@ -57,11 +56,14 @@ const metadata: Meta = { }, argTypes: { appearance: { - options: Object.values(ButtonAppearance), + options: Object.keys(ButtonAppearance), control: { type: 'radio' } }, - primary: { - description: primaryDescription + appearanceVariant: { + name: 'appearance-variant', + options: Object.keys(ButtonAppearanceVariant), + control: { type: 'radio' }, + description: appearanceVariantDescription }, icon: { description: @@ -75,7 +77,7 @@ const metadata: Meta = { render: createUserSelectedThemeStory(html` ${when(x => x.icon, html` @@ -88,10 +90,9 @@ const metadata: Meta = { `), args: { - label: 'Ghost Button', - appearance: 'ghost', + label: 'Button', + appearance: 'outline', appearanceVariant: 'default', - primary: false, icon: false, endIcon: false, contentHidden: false, diff --git a/packages/nimble-components/src/checkbox/tests/checkbox-matrix.stories.ts b/packages/nimble-components/src/checkbox/tests/checkbox-matrix.stories.ts index d734341eb0..15dd28232e 100644 --- a/packages/nimble-components/src/checkbox/tests/checkbox-matrix.stories.ts +++ b/packages/nimble-components/src/checkbox/tests/checkbox-matrix.stories.ts @@ -12,6 +12,7 @@ import { } from '../../utilities/tests/storybook'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; const metadata: Meta = { title: 'Tests/Checkbox', @@ -64,3 +65,9 @@ export const hiddenCheckbox: Story = createStory( html`` ) ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html`Checkbox` + ) +); diff --git a/packages/nimble-components/src/combobox/index.ts b/packages/nimble-components/src/combobox/index.ts index 57df39b38a..801d1fb257 100644 --- a/packages/nimble-components/src/combobox/index.ts +++ b/packages/nimble-components/src/combobox/index.ts @@ -18,6 +18,7 @@ import '../icons/arrow-expander-down'; import { styles } from './styles'; import type { ErrorPattern } from '../patterns/error/types'; +import type { DropdownPattern } from '../patterns/dropdown/types'; declare global { interface HTMLElementTagNameMap { @@ -28,7 +29,7 @@ declare global { /** * A nimble-styed HTML combobox */ -export class Combobox extends FoundationCombobox implements ErrorPattern { +export class Combobox extends FoundationCombobox implements DropdownPattern, ErrorPattern { /** * The ref to the internal dropdown button element. * diff --git a/packages/nimble-components/src/combobox/tests/combobox.stories.ts b/packages/nimble-components/src/combobox/tests/combobox.stories.ts index a83b3baed0..6d3f5bc571 100644 --- a/packages/nimble-components/src/combobox/tests/combobox.stories.ts +++ b/packages/nimble-components/src/combobox/tests/combobox.stories.ts @@ -49,7 +49,7 @@ const metadata: Meta = { position="${x => x.dropDownPosition}" error-text="${x => x.errorText}" ?error-visible="${x => x.errorVisible}" - ${/* This should be handled by the error-visible attr */ ''} + ${/* TODO: This should be handled by the error-visible attr */ ''} aria-invalid="${x => x.errorVisible}" value="${x => x.currentValue}" > diff --git a/packages/nimble-components/src/icon-base/tests/icons.stories.ts b/packages/nimble-components/src/icon-base/tests/icons.stories.ts index 0171c9d0d5..d38a74c90e 100644 --- a/packages/nimble-components/src/icon-base/tests/icons.stories.ts +++ b/packages/nimble-components/src/icon-base/tests/icons.stories.ts @@ -16,7 +16,7 @@ import { const nimbleIconComponents = Object.values(nimbleIconComponentsMap); interface IconArgs { - status: IconAppearance; + appearance: keyof typeof IconAppearance; } const metadata: Meta = { @@ -34,32 +34,34 @@ type IconClass = typeof Icon; const iconTemplate = html` ${(x, c) => html` <${DesignSystem.tagFor(x)} - appearance=${() => c.parent.status} + appearance=${() => IconAppearance[c.parent.appearance]} title=${DesignSystem.tagFor(x)} > `} `; -const statusDescriptionOverride = ` +const appearanceDescriptionOverride = ` With SCSS properties, the icon color can be overriden. For example: ${scssInternalPropertySetterMarkdown(tokenNames.iconColor, 'purple')} `; -const statusDescription = ` +const appearanceDescription = ` Set appearance on the element to switch between the theme-aware color options. -${overrideWarning('Color', statusDescriptionOverride)} +${overrideWarning('Color', appearanceDescriptionOverride)} `; // prettier-ignore export const icons: StoryObj = { - args: { status: IconAppearance.default }, + args: { + appearance: 'default' + }, argTypes: { - status: { - options: Object.values(IconAppearance), + appearance: { + options: Object.keys(IconAppearance), control: { type: 'radio' }, - description: statusDescription + description: appearanceDescription } }, render: createUserSelectedThemeStory(html` diff --git a/packages/nimble-components/src/menu/tests/menu-matrix.stories.ts b/packages/nimble-components/src/menu/tests/menu-matrix.stories.ts index 724155807f..143eccd014 100644 --- a/packages/nimble-components/src/menu/tests/menu-matrix.stories.ts +++ b/packages/nimble-components/src/menu/tests/menu-matrix.stories.ts @@ -15,6 +15,7 @@ import { } from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; const metadata: Meta = { title: 'Tests/Menu', @@ -79,3 +80,13 @@ export const hiddenMenu: Story = createStory( ` ) ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html` + + Inner text + Menu item + ` + ) +); \ No newline at end of file diff --git a/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts b/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts index a022a63f09..06fe188986 100644 --- a/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts +++ b/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts @@ -14,6 +14,7 @@ import { disabledStates, DisabledState, errorStates, ErrorState } from '../../ut import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; import { NumberFieldAppearance } from '../types'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; const metadata: Meta = { title: 'Tests/Number Field', @@ -76,3 +77,9 @@ export const hiddenNumberField: Story = createStory( >` ) ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html`Number field` + ) +); diff --git a/packages/nimble-components/src/patterns/dropdown/types.ts b/packages/nimble-components/src/patterns/dropdown/types.ts index 0bc2ba82f9..39f134664f 100644 --- a/packages/nimble-components/src/patterns/dropdown/types.ts +++ b/packages/nimble-components/src/patterns/dropdown/types.ts @@ -1,8 +1,16 @@ -import { SelectPosition } from '@microsoft/fast-foundation'; +import type { ErrorPattern } from '../error/types'; + +/** + * The interface that dropdowns of various types implement. The properties in this interface + * are leveraged by the shared dropdown pattern css. + */ +export interface DropdownPattern extends ErrorPattern { + position?: DropdownPosition; +} export const DropdownPosition = { - above: SelectPosition.above, - below: SelectPosition.below + above: 'above', + below: 'below' } as const; export type DropdownPosition = typeof DropdownPosition[keyof typeof DropdownPosition]; diff --git a/packages/nimble-components/src/patterns/tests/text-customization.stories.ts b/packages/nimble-components/src/patterns/tests/text-customization.stories.ts deleted file mode 100644 index 368120e921..0000000000 --- a/packages/nimble-components/src/patterns/tests/text-customization.stories.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { Story, Meta } from '@storybook/html'; -import { html } from '@microsoft/fast-element'; -import { createUserSelectedThemeStory } from '../../utilities/tests/storybook'; -import { standardPadding } from '../../theme-provider/design-tokens'; - -const metadata: Meta = { - title: 'Tests/Text Customization' -}; - -export default metadata; - -// prettier-ignore -export const textCustomizationStory: Story = createUserSelectedThemeStory(html` -
- - Breadcrumb item - Button - Checkbox - - Inner text - Menu item - - Number field - - Inner text - Nimble select item - - - Inner text - Tabs toolbar - Tab - - Text area - Text field - Toggle button - - Inner text - Tree item - -
`); diff --git a/packages/nimble-components/src/select/styles.ts b/packages/nimble-components/src/select/styles.ts index 6d24ced26d..25fd13db7c 100644 --- a/packages/nimble-components/src/select/styles.ts +++ b/packages/nimble-components/src/select/styles.ts @@ -4,7 +4,6 @@ import { appearanceBehavior } from '../utilities/style/appearance'; import { DropdownAppearance } from '../patterns/dropdown/types'; import { borderWidth, - controlHeight, borderRgbPartialColor, standardPadding } from '../theme-provider/design-tokens'; @@ -32,10 +31,6 @@ export const styles = css` .control { border: ${borderWidth} solid rgba(${borderRgbPartialColor}, 0.3); } - - :host([error-visible]) .errortext { - top: calc(${controlHeight} - ${borderWidth}); - } ` ), appearanceBehavior( diff --git a/packages/nimble-components/src/select/tests/select-matrix.stories.ts b/packages/nimble-components/src/select/tests/select-matrix.stories.ts index 8562fe7260..ce8e2c1531 100644 --- a/packages/nimble-components/src/select/tests/select-matrix.stories.ts +++ b/packages/nimble-components/src/select/tests/select-matrix.stories.ts @@ -14,6 +14,7 @@ import { disabledStates, DisabledState } from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; import { DropdownAppearance } from '../../patterns/dropdown/types'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; const metadata: Meta = { title: 'Tests/Select', @@ -72,3 +73,14 @@ export const blankListOption: Story = createStory( ` ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html` + + Inner text + Nimble select item + + ` + ) +); diff --git a/packages/nimble-components/src/select/tests/select.stories.ts b/packages/nimble-components/src/select/tests/select.stories.ts index f9bb1dfac7..f6b83fe6e1 100644 --- a/packages/nimble-components/src/select/tests/select.stories.ts +++ b/packages/nimble-components/src/select/tests/select.stories.ts @@ -38,10 +38,16 @@ const metadata: Meta = { }, // prettier-ignore render: createUserSelectedThemeStory(html` - + ${repeat(x => x.options, html` - + ${x => x.label} `)} diff --git a/packages/nimble-components/src/tabs/tests/tabs-matrix.stories.ts b/packages/nimble-components/src/tabs/tests/tabs-matrix.stories.ts index 9fe0be38cb..ca6b2cf059 100644 --- a/packages/nimble-components/src/tabs/tests/tabs-matrix.stories.ts +++ b/packages/nimble-components/src/tabs/tests/tabs-matrix.stories.ts @@ -12,6 +12,7 @@ import { import { DisabledState, disabledStates } from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; const metadata: Meta = { title: 'Tests/Tabs', @@ -64,3 +65,15 @@ export const hiddenTabs: Story = createStory( ` ) ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html` + + Inner text + Tabs toolbar + Tab + + ` + ) +); diff --git a/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts b/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts index df4e81086b..d5fbe72525 100644 --- a/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts +++ b/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts @@ -19,6 +19,8 @@ import { } from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; +import { loremIpsum } from '../../utilities/tests/lorem-ipsum'; const metadata: Meta = { title: 'Tests/Text Area', @@ -39,7 +41,7 @@ const valueStates = [ ['Value', 'Hello', null], [ 'Long Value', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', + loremIpsum, null ] ] as const; @@ -86,7 +88,7 @@ const widthSizingTestCase = ( ${widthLabel} ${colsLabel} @@ -101,7 +103,7 @@ const heightSizingTestCase = ( ${heightLabel} ${rowsLabel} @@ -138,3 +140,9 @@ export const hiddenTextArea: Story = createStory( html`` ) ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html`Text area` + ) +); diff --git a/packages/nimble-components/src/text-area/tests/text-area.stories.ts b/packages/nimble-components/src/text-area/tests/text-area.stories.ts index 8bf7c9a066..7a984d1b6c 100644 --- a/packages/nimble-components/src/text-area/tests/text-area.stories.ts +++ b/packages/nimble-components/src/text-area/tests/text-area.stories.ts @@ -4,6 +4,7 @@ import { withXD } from 'storybook-addon-xd-designs'; import { createUserSelectedThemeStory } from '../../utilities/tests/storybook'; import { TextAreaAppearance, TextAreaResize } from '../types'; import '../../all-components'; +import { loremIpsum } from '../../utilities/tests/lorem-ipsum'; interface TextAreaArgs { appearance: TextAreaAppearance; @@ -88,7 +89,7 @@ const metadata: Meta = { appearance: TextAreaAppearance.outline, label: 'default label', placeholder: 'Placeholder', - value: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', + value: loremIpsum, readonly: false, disabled: false, spellcheck: false, diff --git a/packages/nimble-components/src/text-field/index.ts b/packages/nimble-components/src/text-field/index.ts index 7f462a037c..806c7e7eb0 100644 --- a/packages/nimble-components/src/text-field/index.ts +++ b/packages/nimble-components/src/text-field/index.ts @@ -46,11 +46,6 @@ export class TextField extends FoundationTextField implements ErrorPattern { @attr({ attribute: 'edges-flush', mode: 'boolean' }) public edgesFlush = false; - - public override connectedCallback(): void { - super.connectedCallback(); - this.control.setAttribute('aria-errormessage', 'errortext'); - } } const nimbleTextField = TextField.compose({ @@ -63,7 +58,8 @@ const nimbleTextField = TextField.compose({ }, end: html` diff --git a/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts b/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts index af98334774..db98286f8b 100644 --- a/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts +++ b/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts @@ -4,7 +4,8 @@ import { html, ViewTemplate, when } from '@microsoft/fast-element'; import { pascalCase } from '@microsoft/fast-web-utilities'; import { createStory, - createFixedThemeStory + createFixedThemeStory, + createMatrixThemeStory } from '../../utilities/tests/storybook'; import { TextFieldAppearance } from '../types'; import { @@ -16,10 +17,14 @@ import { DisabledState, ReadOnlyState, readOnlyStates, - backgroundStates + backgroundStates, + errorStates, + ErrorState } from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; +import { loremIpsum } from '../../utilities/tests/lorem-ipsum'; const metadata: Meta = { title: 'Tests/Text Field', @@ -70,55 +75,50 @@ const leftIconStates = [ ] as const; type LeftIconState = typeof leftIconStates[number]; -/* array of state name, invalidClass, errorText */ -const textFieldInvalidStates = [ - ['', '', 'This is not valid.'], - ['', '', ''], - ['Invalid w/ Error', 'invalid', 'This is not valid.'], - ['Invalid', 'invalid', ''] -] as const; -type TextFieldInvalidState = typeof textFieldInvalidStates[number]; - const appearanceStates = Object.entries(TextFieldAppearance).map( ([key, value]) => [pascalCase(key), value] ); type AppearanceState = typeof appearanceStates[number]; -const clearInlinePaddingStates = [ - ['', ''], - ['No Pad', 'clear-inline-padding'] +const edgesFlushStates = [ + ['', false], + ['Edges Flush', true] ] as const; -type ClearInlinePaddingState = typeof clearInlinePaddingStates[number]; +type EdgesFlushState = typeof edgesFlushStates[number]; // prettier-ignore const component = ( - [readOnlyName, readonly]: ReadOnlyState, + [_readOnlyName, readonly]: ReadOnlyState, [_disabledName, disabled]: DisabledState, - [showActionButtonsName, showActionButtons]: ActionButtonState, + [_showActionButtonsName, showActionButtons]: ActionButtonState, [showLeftIconName, showLeftIcon]: LeftIconState, - [invalidName, invalidClass, errorText]: TextFieldInvalidState, + [errorName, errorVisible, errorText]: ErrorState, [typeName, type]: TypeState, [appearanceName, appearance]: AppearanceState, - [noPadName, clearInlinePadding]: ClearInlinePaddingState, + [edgesFluashName, edgesFlush]: EdgesFlushState, [valueName, valueValue, placeholderValue]: ValueState ): ViewTemplate => html` ${when(() => showLeftIcon, html``)} - ${() => invalidName} ${() => typeName} - ${() => appearanceName} ${() => noPadName} ${() => valueName} - ${() => readOnlyName} ${() => showLeftIconName} ${() => showActionButtonsName} - + ${/* Only include states in label that are not expanded on page */ ''} + ${() => showLeftIconName} + ${() => errorName} + ${() => typeName} + ${() => appearanceName} + ${() => edgesFluashName} + ${() => valueName} ${when(() => showActionButtons, html` @@ -138,10 +138,10 @@ export const lightThemeEditableEnabledWithoutButtons: Story = createFixedThemeSt [disabledStates[0]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), lightThemeWhiteBackground @@ -153,10 +153,10 @@ export const lightThemeEditableEnabledWithButtons: Story = createFixedThemeStory [disabledStates[0]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), lightThemeWhiteBackground @@ -168,10 +168,10 @@ export const lightThemeEditableDisabledWithoutButtons: Story = createFixedThemeS [disabledStates[1]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), lightThemeWhiteBackground @@ -183,10 +183,10 @@ export const lightThemeEditableDisabledWithButtons: Story = createFixedThemeStor [disabledStates[1]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), lightThemeWhiteBackground @@ -198,10 +198,10 @@ export const lightThemeReadOnlyEnabledWithoutButtons: Story = createFixedThemeSt [disabledStates[0]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), lightThemeWhiteBackground @@ -213,10 +213,10 @@ export const lightThemeReadOnlyEnabledWithButtons: Story = createFixedThemeStory [disabledStates[0]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), lightThemeWhiteBackground @@ -228,10 +228,10 @@ export const lightThemeReadOnlyDisabledWithoutButtons: Story = createFixedThemeS [disabledStates[1]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), lightThemeWhiteBackground @@ -243,10 +243,10 @@ export const lightThemeReadOnlyDisabledWithButtons: Story = createFixedThemeStor [disabledStates[1]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), lightThemeWhiteBackground @@ -258,10 +258,10 @@ export const darkThemeEditableEnabledWithoutButtons: Story = createFixedThemeSto [disabledStates[0]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), darkThemeBlackBackground @@ -273,10 +273,10 @@ export const darkThemeEditableEnabledWithButtons: Story = createFixedThemeStory( [disabledStates[0]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), darkThemeBlackBackground @@ -288,10 +288,10 @@ export const darkThemeEditableDisabledWithoutButtons: Story = createFixedThemeSt [disabledStates[1]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), darkThemeBlackBackground @@ -303,10 +303,10 @@ export const darkThemeEditableDisabledWithButtons: Story = createFixedThemeStory [disabledStates[1]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), darkThemeBlackBackground @@ -318,10 +318,10 @@ export const darkThemeReadOnlyEnabledWithoutButtons: Story = createFixedThemeSto [disabledStates[0]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), darkThemeBlackBackground @@ -333,10 +333,10 @@ export const darkThemeReadOnlyEnabledWithButtons: Story = createFixedThemeStory( [disabledStates[0]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), darkThemeBlackBackground @@ -348,10 +348,10 @@ export const darkThemeReadOnlyDisabledWithoutButtons: Story = createFixedThemeSt [disabledStates[1]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), darkThemeBlackBackground @@ -363,10 +363,10 @@ export const darkThemeReadOnlyDisabledWithButtons: Story = createFixedThemeStory [disabledStates[1]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), darkThemeBlackBackground @@ -378,10 +378,10 @@ export const colorThemeEditableEnabledWithoutButtons: Story = createFixedThemeSt [disabledStates[0]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), colorThemeDarkGreenBackground @@ -393,10 +393,10 @@ export const colorThemeEditableEnabledWithButtons: Story = createFixedThemeStory [disabledStates[0]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), colorThemeDarkGreenBackground @@ -408,10 +408,10 @@ export const colorThemeEditableDisabledWithoutButtons: Story = createFixedThemeS [disabledStates[1]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), colorThemeDarkGreenBackground @@ -423,10 +423,10 @@ export const colorThemeEditableDisabledWithButtons: Story = createFixedThemeStor [disabledStates[1]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), colorThemeDarkGreenBackground @@ -438,10 +438,10 @@ export const colorThemeReadOnlyEnabledWithoutButtons: Story = createFixedThemeSt [disabledStates[0]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), colorThemeDarkGreenBackground @@ -453,10 +453,10 @@ export const colorThemeReadOnlyEnabledWithButtons: Story = createFixedThemeStory [disabledStates[0]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), colorThemeDarkGreenBackground @@ -468,10 +468,10 @@ export const colorThemeReadOnlyDisabledWithoutButtons: Story = createFixedThemeS [disabledStates[1]], [actionButtonStates[0]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), colorThemeDarkGreenBackground @@ -483,10 +483,10 @@ export const colorThemeReadOnlyDisabledWithButtons: Story = createFixedThemeStor [disabledStates[1]], [actionButtonStates[1]], leftIconStates, - textFieldInvalidStates, + errorStates, typeStates, appearanceStates, - clearInlinePaddingStates, + edgesFlushStates, valueStates ]), colorThemeDarkGreenBackground @@ -497,3 +497,9 @@ export const hiddenTextField: Story = createStory( html`` ) ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html`Text field` + ) +); diff --git a/packages/nimble-components/src/text-field/tests/text-field.stories.ts b/packages/nimble-components/src/text-field/tests/text-field.stories.ts index 359a6653a3..ac9d39a13d 100644 --- a/packages/nimble-components/src/text-field/tests/text-field.stories.ts +++ b/packages/nimble-components/src/text-field/tests/text-field.stories.ts @@ -9,12 +9,12 @@ interface TextFieldArgs { label: string; type: string; appearance: string; - 'clear-inline-padding': boolean; + edgesFlush: boolean; value: string; readonly: boolean; disabled: boolean; - invalid: boolean; - 'error-text': string; + errorVisible: boolean; + errorText: string; actionButton: boolean; leftIcon: boolean; } @@ -52,11 +52,13 @@ const metadata: Meta = { type="${x => x.type}" appearance="${x => x.appearance}" value="${x => x.value}" - class="${x => (x.invalid ? 'invalid' : '')} ${x => (x['clear-inline-padding'] ? 'clear-inline-padding' : '')}" - aria-invalid="${x => x.invalid}" + ${/* TODO: This should be handled by the error-visible attr */ ''} + aria-invalid="${x => x.errorVisible}" ?readonly="${x => x.readonly}" ?disabled="${x => x.disabled}" - error-text="${x => x['error-text']}" + error-text="${x => x.errorText}" + ?error-visible="${x => x.errorVisible}" + ?edges-flush="${x => x.edgesFlush}" > ${when(x => x.leftIcon, html` `)} @@ -79,11 +81,11 @@ const metadata: Meta = { options: Object.values(TextFieldAppearance), control: { type: 'radio' } }, - 'clear-inline-padding': { + edgesFlush: { description: 'Add the class `clear-inline-padding` to remove the start and end padding. Only affects the frameless appearance.' }, - 'error-text': { + errorText: { description: 'A message to be displayed when the text field is in the invalid state explaining why the value is invalid' }, @@ -98,12 +100,12 @@ const metadata: Meta = { label: 'default label', type: 'text', appearance: 'underline', - 'clear-inline-padding': false, + edgesFlush: false, value: '', readonly: false, disabled: false, - invalid: false, - 'error-text': 'Value is invalid', + errorVisible: false, + errorText: 'Value is invalid', actionButton: false, leftIcon: false } diff --git a/packages/nimble-components/src/toggle-button/tests/toggle-button-matrix.stories.ts b/packages/nimble-components/src/toggle-button/tests/toggle-button-matrix.stories.ts index 50178b8f00..82a4f54d11 100644 --- a/packages/nimble-components/src/toggle-button/tests/toggle-button-matrix.stories.ts +++ b/packages/nimble-components/src/toggle-button/tests/toggle-button-matrix.stories.ts @@ -14,6 +14,7 @@ import { } from '../../utilities/tests/storybook'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; const metadata: Meta = { title: 'Tests/Toggle Button', @@ -39,7 +40,7 @@ const partVisibilityStates = [ ] as const; type PartVisibilityState = typeof partVisibilityStates[number]; -const appearanceStates = Object.entries(ButtonAppearance).map( +const appearanceStates: [string, string | undefined][] = Object.entries(ButtonAppearance).map( ([key, value]) => [pascalCase(key), value] ); type AppearanceState = typeof appearanceStates[number]; @@ -64,7 +65,7 @@ const component = ( ?checked=${() => checked} style="margin-right: 8px; margin-bottom: 8px;"> ${when(() => iconVisible, html``)} - ${() => `${checkedName} ${appearanceName!} Toggle Button ${disabledName}`} + ${() => `${checkedName} ${appearanceName} Toggle Button ${disabledName}`} ${when(() => endIconVisible, html``)} `; @@ -85,3 +86,9 @@ export const hiddenButton: Story = createStory( >` ) ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html`Toggle button` + ) +); diff --git a/packages/nimble-components/src/tooltip/tests/tooltip-matrix.stories.ts b/packages/nimble-components/src/tooltip/tests/tooltip-matrix.stories.ts index eaef34069e..de915251a7 100644 --- a/packages/nimble-components/src/tooltip/tests/tooltip-matrix.stories.ts +++ b/packages/nimble-components/src/tooltip/tests/tooltip-matrix.stories.ts @@ -1,6 +1,7 @@ import type { Meta, Story } from '@storybook/html'; import { withXD } from 'storybook-addon-xd-designs'; import { html, ViewTemplate } from '@microsoft/fast-element'; +import { pascalCase } from '@microsoft/fast-web-utilities'; import { createMatrix, sharedMatrixParameters @@ -17,6 +18,8 @@ import { bodyFontColor, borderColor } from '../../theme-provider/design-tokens'; +import { loremIpsum } from '../../utilities/tests/lorem-ipsum'; +import { TooltipAppearance } from '../types'; const metadata: Meta = { title: 'Tests/Tooltip', @@ -36,28 +39,26 @@ const textStates = [ ['Short_Text', 'Hello'], [ 'Long_Text', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.' + loremIpsum ] ] as const; type TextState = typeof textStates[number]; -const statusStates = [ - ['Default', ''], - ['Fail', 'fail'], - ['Information', 'information'] -] as const; -type StatusState = typeof statusStates[number]; +const appearanceStates: [string, string | undefined][] = Object + .entries(TooltipAppearance) + .map(([key, value]) => [pascalCase(key), value]); +type AppearanceState = typeof appearanceStates[number]; -const iconStates = [ - ['No_Icon', ''], - ['Icon_Visible', 'icon-visible'] +const iconVisibleStates = [ + ['No_Icon', false], + ['Icon_Visible', true] ] as const; -type IconState = typeof iconStates[number]; +type IconVisibleState = typeof iconVisibleStates[number]; const component = ( [textName, text]: TextState, - [valueName, value]: StatusState, - [iconName, icon]: IconState + [appearanceName, appearance]: AppearanceState, + [iconVisibleName, iconVisible]: IconVisibleState ): ViewTemplate => html`
-
+
Text, Button, Icon, etc.
- ${x => x.tooltip} + ${x => x.value}
`), args: { visible: false, - state: 'default', - icon: false, - tooltip: 'Tooltip label', + appearance: 'default', + iconVisible: false, + value: 'Tooltip label', delay: 300, autoUpdateMode: 'anchor' }, @@ -86,15 +90,9 @@ const metadata: Meta = { description: 'The delay in milliseconds before a tooltip is shown after a hover event' }, - state: { + appearance: { options: Object.keys(TooltipAppearance), control: { type: 'radio' }, - description: - 'Set the `default`, `fail`, or `information` CSS class on the tooltip to switch between the theme-aware color options.' - }, - icon: { - description: - 'Add the `icon-visible` CSS class to the tooltip to show the icon corresponding to the tooltip state. The `default` state will not show an icon even if `icon-visible` is set.' } } }; diff --git a/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts b/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts index 245996f3c1..1e5979b61c 100644 --- a/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts +++ b/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts @@ -20,6 +20,7 @@ import { } from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; +import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; const metadata: Meta = { title: 'Tests/Tree View', @@ -82,3 +83,14 @@ export const hiddenTreeView: Story = createStory( ` ) ); + +export const textCustomized: Story = createMatrixThemeStory( + textCustomizationWrapper( + html` + + Inner text + Tree item + + ` + ) +); diff --git a/packages/nimble-components/src/utilities/tests/lorem-ipsum.ts b/packages/nimble-components/src/utilities/tests/lorem-ipsum.ts new file mode 100644 index 0000000000..c15fbe80c0 --- /dev/null +++ b/packages/nimble-components/src/utilities/tests/lorem-ipsum.ts @@ -0,0 +1 @@ +export const loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; \ No newline at end of file diff --git a/packages/nimble-components/src/utilities/tests/text-customization.ts b/packages/nimble-components/src/utilities/tests/text-customization.ts new file mode 100644 index 0000000000..3cbf875d1f --- /dev/null +++ b/packages/nimble-components/src/utilities/tests/text-customization.ts @@ -0,0 +1,15 @@ +import { html, ViewTemplate } from '@microsoft/fast-element'; + +/** + * Applies a style to customize text for all elements + */ +export const textCustomizationWrapper = (template: ViewTemplate): ViewTemplate => { + return html` + + ${template} + `; +}; From ad9a2479eb27df46049771152d8c05b45a5094dc Mon Sep 17 00:00:00 2001 From: rajsite Date: Sun, 7 Aug 2022 22:35:48 -0500 Subject: [PATCH 04/43] prototype --- .../nimble-components/src/breadcrumb/styles.ts | 8 ++++---- .../tests/breadcrumb-matrix.stories.ts | 17 ++++++++++------- .../src/breadcrumb/tests/breadcrumb.stories.ts | 2 +- .../nimble-components/src/breadcrumb/types.ts | 3 ++- .../src/button/tests/button-matrix.stories.ts | 16 +++++++--------- .../checkbox/tests/checkbox-matrix.stories.ts | 4 +--- .../nimble-components/src/combobox/index.ts | 4 +++- .../combobox/tests/combobox-matrix.stories.ts | 7 ++++++- .../nimble-components/src/icon-base/styles.ts | 8 ++++---- .../src/icon-base/tests/icon-matrix.stories.ts | 16 +++++++++------- .../src/menu/tests/menu-matrix.stories.ts | 5 ++--- .../tests/number-field-matrix.stories.ts | 15 +++++++++++---- .../src/patterns/error/types.ts | 4 ++-- .../src/select/tests/select-matrix.stories.ts | 8 ++++---- .../src/tabs/tests/tabs-matrix.stories.ts | 10 +++++----- .../text-area/tests/text-area-matrix.stories.ts | 10 ++++------ .../tests/text-field-matrix.stories.ts | 6 +++++- .../tests/toggle-button-matrix.stories.ts | 6 +++--- .../nimble-components/src/tooltip/styles.ts | 16 ++++++++-------- .../src/tooltip/tests/tooltip-matrix.stories.ts | 17 +++++++++-------- .../src/tooltip/tests/tooltip.stories.ts | 7 ++----- .../src/tooltip/tests/types.spec.ts | 5 +++-- packages/nimble-components/src/tooltip/types.ts | 3 ++- .../tree-view/tests/tree-view-matrix.stories.ts | 8 ++++---- .../src/utilities/tests/lorem-ipsum.ts | 2 +- .../src/utilities/tests/text-customization.ts | 16 +++++++++------- 26 files changed, 121 insertions(+), 102 deletions(-) diff --git a/packages/nimble-components/src/breadcrumb/styles.ts b/packages/nimble-components/src/breadcrumb/styles.ts index 7471bbb49e..fe3199fe0c 100644 --- a/packages/nimble-components/src/breadcrumb/styles.ts +++ b/packages/nimble-components/src/breadcrumb/styles.ts @@ -27,7 +27,7 @@ export const styles = css` flex-wrap: wrap; } - :host([appearance="prominent"]) { + :host([appearance='prominent']) { --ni-private-breadcrumb-link-active-font-color: ${bodyFontColor}; } @@ -46,7 +46,7 @@ export const styles = css` --ni-private-breadcrumb-link-active-font-color: ${DigitalGreenDark}; } - :host([appearance="prominent"]) { + :host([appearance='prominent']) { --ni-private-breadcrumb-link-font-color: ${DigitalGreenDark}; } `, @@ -56,7 +56,7 @@ export const styles = css` --ni-private-breadcrumb-link-active-font-color: ${PowerGreen}; } - :host([appearance="prominent"]) { + :host([appearance='prominent']) { --ni-private-breadcrumb-link-font-color: ${PowerGreen}; } `, @@ -69,7 +69,7 @@ export const styles = css` )}; } - :host([appearance="prominent"]) { + :host([appearance='prominent']) { --ni-private-breadcrumb-link-font-color: ${PowerGreen}; } ` diff --git a/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts b/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts index d43c213729..dea16bf1fd 100644 --- a/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts +++ b/packages/nimble-components/src/breadcrumb/tests/breadcrumb-matrix.stories.ts @@ -29,16 +29,19 @@ const metadata: Meta = { export default metadata; -const breadcrumbAppearanceStates: [string, string | undefined][] = Object.entries(BreadcrumbAppearance).map( - ([key, value]) => [pascalCase(key), value] -); -type BreadcrumbAppearanceState = typeof breadcrumbAppearanceStates[number]; +const appearanceStates: [string, string | undefined][] = Object.entries( + BreadcrumbAppearance +).map(([key, value]) => [pascalCase(key), value]); +type AppearanceState = typeof appearanceStates[number]; const component = ([ appearanceName, appearance -]: BreadcrumbAppearanceState): ViewTemplate => html` - +]: AppearanceState): ViewTemplate => html` + ${() => `Breadcrumb (${appearanceName}) - Link`} @@ -46,7 +49,7 @@ const component = ([ `; export const breadcrumbThemeMatrix: Story = createMatrixThemeStory( - createMatrix(component, [breadcrumbAppearanceStates]) + createMatrix(component, [appearanceStates]) ); export const hiddenBreadcrumb: Story = createStory( diff --git a/packages/nimble-components/src/breadcrumb/tests/breadcrumb.stories.ts b/packages/nimble-components/src/breadcrumb/tests/breadcrumb.stories.ts index b6384887ad..da831d34d7 100644 --- a/packages/nimble-components/src/breadcrumb/tests/breadcrumb.stories.ts +++ b/packages/nimble-components/src/breadcrumb/tests/breadcrumb.stories.ts @@ -74,7 +74,7 @@ export const _standardBreadcrumb: StoryObj = { appearance: { options: Object.keys(BreadcrumbAppearance), control: { type: 'radio' } - }, + } }, args: { options: [ diff --git a/packages/nimble-components/src/breadcrumb/types.ts b/packages/nimble-components/src/breadcrumb/types.ts index e59996c187..4a030121ca 100644 --- a/packages/nimble-components/src/breadcrumb/types.ts +++ b/packages/nimble-components/src/breadcrumb/types.ts @@ -6,4 +6,5 @@ export const BreadcrumbAppearance = { default: undefined, prominent: 'prominent' } as const; -export type BreadcrumbAppearance = typeof BreadcrumbAppearance[keyof typeof BreadcrumbAppearance]; +export type BreadcrumbAppearance = + typeof BreadcrumbAppearance[keyof typeof BreadcrumbAppearance]; diff --git a/packages/nimble-components/src/button/tests/button-matrix.stories.ts b/packages/nimble-components/src/button/tests/button-matrix.stories.ts index 213ac4196a..77049d93ce 100644 --- a/packages/nimble-components/src/button/tests/button-matrix.stories.ts +++ b/packages/nimble-components/src/button/tests/button-matrix.stories.ts @@ -40,14 +40,14 @@ const partVisibilityStates = [ ] as const; type PartVisibilityState = typeof partVisibilityStates[number]; -const appearanceStates: [string, string | undefined][] = Object - .entries(ButtonAppearance) - .map(([key, value]) => [pascalCase(key), value]); +const appearanceStates: [string, string | undefined][] = Object.entries( + ButtonAppearance +).map(([key, value]) => [pascalCase(key), value]); type AppearanceState = typeof appearanceStates[number]; -const appearanceVariantStates: [string, string | undefined][] = Object - .entries(ButtonAppearanceVariant) - .map(([key, value]) => [pascalCase(key), value]); +const appearanceVariantStates: [string, string | undefined][] = Object.entries( + ButtonAppearanceVariant +).map(([key, value]) => [pascalCase(key), value]); type AppearanceVariantState = typeof appearanceVariantStates[number]; // prettier-ignore @@ -83,7 +83,5 @@ export const hiddenButton: Story = createStory( ); export const textCustomized: Story = createMatrixThemeStory( - textCustomizationWrapper( - html`Button` - ) + textCustomizationWrapper(html`Button`) ); diff --git a/packages/nimble-components/src/checkbox/tests/checkbox-matrix.stories.ts b/packages/nimble-components/src/checkbox/tests/checkbox-matrix.stories.ts index 15dd28232e..0c7f7a5c32 100644 --- a/packages/nimble-components/src/checkbox/tests/checkbox-matrix.stories.ts +++ b/packages/nimble-components/src/checkbox/tests/checkbox-matrix.stories.ts @@ -67,7 +67,5 @@ export const hiddenCheckbox: Story = createStory( ); export const textCustomized: Story = createMatrixThemeStory( - textCustomizationWrapper( - html`Checkbox` - ) + textCustomizationWrapper(html`Checkbox`) ); diff --git a/packages/nimble-components/src/combobox/index.ts b/packages/nimble-components/src/combobox/index.ts index 801d1fb257..faff459642 100644 --- a/packages/nimble-components/src/combobox/index.ts +++ b/packages/nimble-components/src/combobox/index.ts @@ -29,7 +29,9 @@ declare global { /** * A nimble-styed HTML combobox */ -export class Combobox extends FoundationCombobox implements DropdownPattern, ErrorPattern { +export class Combobox + extends FoundationCombobox + implements DropdownPattern, ErrorPattern { /** * The ref to the internal dropdown button element. * diff --git a/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts b/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts index d9511b0010..e48c76a47d 100644 --- a/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts +++ b/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts @@ -10,7 +10,12 @@ import { sharedMatrixParameters } from '../../utilities/tests/matrix'; import '../../all-components'; -import { disabledStates, DisabledState, errorStates, ErrorState } from '../../utilities/tests/states'; +import { + disabledStates, + DisabledState, + errorStates, + ErrorState +} from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; const metadata: Meta = { diff --git a/packages/nimble-components/src/icon-base/styles.ts b/packages/nimble-components/src/icon-base/styles.ts index 1d65fa90f8..0a45431f5f 100644 --- a/packages/nimble-components/src/icon-base/styles.ts +++ b/packages/nimble-components/src/icon-base/styles.ts @@ -24,19 +24,19 @@ export const styles = css` height: 100%; } - :host([appearance="error"]) { + :host([appearance='error']) { ${iconColor.cssCustomProperty}: ${failColor}; } - :host([appearance="warning"]) { + :host([appearance='warning']) { ${iconColor.cssCustomProperty}: ${warningColor}; } - :host([appearance="success"]) { + :host([appearance='success']) { ${iconColor.cssCustomProperty}: ${passColor}; } - :host([appearance="information"]) { + :host([appearance='information']) { ${iconColor.cssCustomProperty}: ${informationColor}; } diff --git a/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts b/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts index 540e75a134..b3bef133e0 100644 --- a/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts +++ b/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts @@ -23,18 +23,20 @@ const metadata: Meta = { export default metadata; -const iconStatusStates: [string, string | undefined][] = Object.entries(IconAppearance).map( - ([key, value]) => [pascalCase(key), value] -); -type IconStatusState = typeof iconStatusStates[number]; +const appearanceStates: [string, string | undefined][] = Object.entries( + IconAppearance +).map(([key, value]) => [pascalCase(key), value]); +type AppearanceState = typeof appearanceStates[number]; -const component = ([stateName, state]: IconStatusState): ViewTemplate => html` - ${() => stateName} +const component = ([stateName, state]: AppearanceState): ViewTemplate => html` + + ${() => stateName} + `; export const iconThemeMatrix: Story = createMatrixThemeStory( - createMatrix(component, [iconStatusStates]) + createMatrix(component, [appearanceStates]) ); export const hiddenIcon: Story = createStory( diff --git a/packages/nimble-components/src/menu/tests/menu-matrix.stories.ts b/packages/nimble-components/src/menu/tests/menu-matrix.stories.ts index 143eccd014..518ac379e9 100644 --- a/packages/nimble-components/src/menu/tests/menu-matrix.stories.ts +++ b/packages/nimble-components/src/menu/tests/menu-matrix.stories.ts @@ -83,10 +83,9 @@ export const hiddenMenu: Story = createStory( export const textCustomized: Story = createMatrixThemeStory( textCustomizationWrapper( - html` - + html` Inner text Menu item ` ) -); \ No newline at end of file +); diff --git a/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts b/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts index 06fe188986..b6ca4feede 100644 --- a/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts +++ b/packages/nimble-components/src/number-field/tests/number-field-matrix.stories.ts @@ -10,7 +10,12 @@ import { createMatrix, sharedMatrixParameters } from '../../utilities/tests/matrix'; -import { disabledStates, DisabledState, errorStates, ErrorState } from '../../utilities/tests/states'; +import { + disabledStates, + DisabledState, + errorStates, + ErrorState +} from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; import { NumberFieldAppearance } from '../types'; @@ -72,9 +77,11 @@ export const numberFieldThemeMatrix: Story = createMatrixThemeStory( export const hiddenNumberField: Story = createStory( hiddenWrapper( - html`` + html` + + ` ) ); diff --git a/packages/nimble-components/src/patterns/error/types.ts b/packages/nimble-components/src/patterns/error/types.ts index a45244a560..0631f3b95c 100644 --- a/packages/nimble-components/src/patterns/error/types.ts +++ b/packages/nimble-components/src/patterns/error/types.ts @@ -8,7 +8,7 @@ export interface ErrorPattern { errorText?: string; /* - * Show the error appearance of the control - */ + * Show the error appearance of the control + */ errorVisible: boolean; } diff --git a/packages/nimble-components/src/select/tests/select-matrix.stories.ts b/packages/nimble-components/src/select/tests/select-matrix.stories.ts index ce8e2c1531..677c4ba663 100644 --- a/packages/nimble-components/src/select/tests/select-matrix.stories.ts +++ b/packages/nimble-components/src/select/tests/select-matrix.stories.ts @@ -77,10 +77,10 @@ export const blankListOption: Story = createStory( export const textCustomized: Story = createMatrixThemeStory( textCustomizationWrapper( html` - - Inner text - Nimble select item - + + Inner text + Nimble select item + ` ) ); diff --git a/packages/nimble-components/src/tabs/tests/tabs-matrix.stories.ts b/packages/nimble-components/src/tabs/tests/tabs-matrix.stories.ts index ca6b2cf059..f5f234b962 100644 --- a/packages/nimble-components/src/tabs/tests/tabs-matrix.stories.ts +++ b/packages/nimble-components/src/tabs/tests/tabs-matrix.stories.ts @@ -69,11 +69,11 @@ export const hiddenTabs: Story = createStory( export const textCustomized: Story = createMatrixThemeStory( textCustomizationWrapper( html` - - Inner text - Tabs toolbar - Tab - + + Inner text + Tabs toolbar + Tab + ` ) ); diff --git a/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts b/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts index d5fbe72525..945f0eb347 100644 --- a/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts +++ b/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts @@ -39,11 +39,7 @@ export default metadata; const valueStates = [ ['Placeholder', null, 'placeholder'], ['Value', 'Hello', null], - [ - 'Long Value', - loremIpsum, - null - ] + ['Long Value', loremIpsum, null] ] as const; type ValueState = typeof valueStates[number]; @@ -143,6 +139,8 @@ export const hiddenTextArea: Story = createStory( export const textCustomized: Story = createMatrixThemeStory( textCustomizationWrapper( - html`Text area` + html` + Text area + ` ) ); diff --git a/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts b/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts index db98286f8b..2a5e987b43 100644 --- a/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts +++ b/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts @@ -500,6 +500,10 @@ export const hiddenTextField: Story = createStory( export const textCustomized: Story = createMatrixThemeStory( textCustomizationWrapper( - html`Text field` + html` + + Text field + + ` ) ); diff --git a/packages/nimble-components/src/toggle-button/tests/toggle-button-matrix.stories.ts b/packages/nimble-components/src/toggle-button/tests/toggle-button-matrix.stories.ts index 82a4f54d11..9a2e66c60c 100644 --- a/packages/nimble-components/src/toggle-button/tests/toggle-button-matrix.stories.ts +++ b/packages/nimble-components/src/toggle-button/tests/toggle-button-matrix.stories.ts @@ -40,9 +40,9 @@ const partVisibilityStates = [ ] as const; type PartVisibilityState = typeof partVisibilityStates[number]; -const appearanceStates: [string, string | undefined][] = Object.entries(ButtonAppearance).map( - ([key, value]) => [pascalCase(key), value] -); +const appearanceStates: [string, string | undefined][] = Object.entries( + ButtonAppearance +).map(([key, value]) => [pascalCase(key), value]); type AppearanceState = typeof appearanceStates[number]; const checkedStates = [ diff --git a/packages/nimble-components/src/tooltip/styles.ts b/packages/nimble-components/src/tooltip/styles.ts index 10e7561467..a6589b0d03 100644 --- a/packages/nimble-components/src/tooltip/styles.ts +++ b/packages/nimble-components/src/tooltip/styles.ts @@ -53,12 +53,12 @@ export const styles = css` padding-right: 8px; } - :host([appearance="error"][icon-visible]) [appearance="error"] { + :host([appearance='error'][icon-visible]) [appearance='error'] { display: flex; flex: 0 0 auto; } - :host([appearance="information"][icon-visible]) [appearance="information"] { + :host([appearance='information'][icon-visible]) [appearance='information'] { display: flex; flex: 0 0 auto; } @@ -66,12 +66,12 @@ export const styles = css` themeBehavior( // Light Theme css` - :host([appearance="error"]) { + :host([appearance='error']) { --ni-private-tooltip-border-color: ${BannerFail100DarkUi}; --ni-private-tooltip-background-color: ${White}; } - :host([appearance="information"]) { + :host([appearance='information']) { --ni-private-tooltip-border-color: ${Information100LightUi}; --ni-private-tooltip-background-color: ${White}; } @@ -86,11 +86,11 @@ export const styles = css` --ni-private-tooltip-background-color: ${Black85}; } - :host([appearance="information"]) { + :host([appearance='information']) { --ni-private-tooltip-border-color: ${Information100DarkUi}; } - :host([appearance="error"]) { + :host([appearance='error']) { --ni-private-tooltip-border-color: ${BannerFail100DarkUi}; } `, @@ -111,11 +111,11 @@ export const styles = css` )}; } - :host([appearance="error"]) { + :host([appearance='error']) { --ni-private-tooltip-border-color: ${White}; } - :host([appearance="information"]) { + :host([appearance='information']) { --ni-private-tooltip-border-color: ${White}; } diff --git a/packages/nimble-components/src/tooltip/tests/tooltip-matrix.stories.ts b/packages/nimble-components/src/tooltip/tests/tooltip-matrix.stories.ts index de915251a7..bbf5a7bb59 100644 --- a/packages/nimble-components/src/tooltip/tests/tooltip-matrix.stories.ts +++ b/packages/nimble-components/src/tooltip/tests/tooltip-matrix.stories.ts @@ -37,16 +37,13 @@ export default metadata; const textStates = [ ['Short_Text', 'Hello'], - [ - 'Long_Text', - loremIpsum - ] + ['Long_Text', loremIpsum] ] as const; type TextState = typeof textStates[number]; -const appearanceStates: [string, string | undefined][] = Object - .entries(TooltipAppearance) - .map(([key, value]) => [pascalCase(key), value]); +const appearanceStates: [string, string | undefined][] = Object.entries( + TooltipAppearance +).map(([key, value]) => [pascalCase(key), value]); type AppearanceState = typeof appearanceStates[number]; const iconVisibleStates = [ @@ -112,7 +109,11 @@ export const tooltipLightThemeWhiteBackground: Story = createFixedThemeStory( ); export const tooltipColorThemeDarkGreenBackground: Story = createFixedThemeStory( - createMatrix(component, [textStates, appearanceStates, iconVisibleStates]), + createMatrix(component, [ + textStates, + appearanceStates, + iconVisibleStates + ]), colorThemeDarkGreenBackground ); diff --git a/packages/nimble-components/src/tooltip/tests/tooltip.stories.ts b/packages/nimble-components/src/tooltip/tests/tooltip.stories.ts index c14456dfa3..b2704349a1 100644 --- a/packages/nimble-components/src/tooltip/tests/tooltip.stories.ts +++ b/packages/nimble-components/src/tooltip/tests/tooltip.stories.ts @@ -52,10 +52,7 @@ const metadata: Meta = { }
-
+
Text, Button, Icon, etc.
= { }, appearance: { options: Object.keys(TooltipAppearance), - control: { type: 'radio' }, + control: { type: 'radio' } } } }; diff --git a/packages/nimble-components/src/tooltip/tests/types.spec.ts b/packages/nimble-components/src/tooltip/tests/types.spec.ts index 3c02cbb45d..234174d0e4 100644 --- a/packages/nimble-components/src/tooltip/tests/types.spec.ts +++ b/packages/nimble-components/src/tooltip/tests/types.spec.ts @@ -1,9 +1,10 @@ import type { TooltipAppearance } from '../types'; describe('Tooltip type', () => { - it('TooltipStatus fails compile if assigning arbitrary string values', () => { + it('TooltipAppearance fails compile if assigning arbitrary string values', () => { + // @ts-expect-error This expect will fail if the enum-like type is missing "as const" + const status: TooltipAppearance = 'hello'; // @ts-expect-error This expect will fail if the enum-like type is missing "as const" - const status: TooltipStatus = 'hello'; expect(status).toEqual('hello'); }); }); diff --git a/packages/nimble-components/src/tooltip/types.ts b/packages/nimble-components/src/tooltip/types.ts index e2fa8fad1a..0ccadeb735 100644 --- a/packages/nimble-components/src/tooltip/types.ts +++ b/packages/nimble-components/src/tooltip/types.ts @@ -8,4 +8,5 @@ export const TooltipAppearance = { information: 'information' } as const; -export type TooltipAppearance = typeof TooltipAppearance[keyof typeof TooltipAppearance]; +export type TooltipAppearance = + typeof TooltipAppearance[keyof typeof TooltipAppearance]; diff --git a/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts b/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts index 1e5979b61c..e2fe9fd6ab 100644 --- a/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts +++ b/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts @@ -87,10 +87,10 @@ export const hiddenTreeView: Story = createStory( export const textCustomized: Story = createMatrixThemeStory( textCustomizationWrapper( html` - - Inner text - Tree item - + + Inner text + Tree item + ` ) ); diff --git a/packages/nimble-components/src/utilities/tests/lorem-ipsum.ts b/packages/nimble-components/src/utilities/tests/lorem-ipsum.ts index c15fbe80c0..d0e62ef873 100644 --- a/packages/nimble-components/src/utilities/tests/lorem-ipsum.ts +++ b/packages/nimble-components/src/utilities/tests/lorem-ipsum.ts @@ -1 +1 @@ -export const loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; \ No newline at end of file +export const loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; diff --git a/packages/nimble-components/src/utilities/tests/text-customization.ts b/packages/nimble-components/src/utilities/tests/text-customization.ts index 3cbf875d1f..8b4579bada 100644 --- a/packages/nimble-components/src/utilities/tests/text-customization.ts +++ b/packages/nimble-components/src/utilities/tests/text-customization.ts @@ -3,13 +3,15 @@ import { html, ViewTemplate } from '@microsoft/fast-element'; /** * Applies a style to customize text for all elements */ -export const textCustomizationWrapper = (template: ViewTemplate): ViewTemplate => { +export const textCustomizationWrapper = ( + template: ViewTemplate +): ViewTemplate => { return html` - - ${template} + + ${template} `; }; From 43863ab45f4ac7bd20c3719b9d2e2b1df774f16c Mon Sep 17 00:00:00 2001 From: rajsite Date: Mon, 8 Aug 2022 22:22:30 -0500 Subject: [PATCH 05/43] prototype --- .../nimble-components/src/text-field/index.ts | 4 +- .../src/text-field/styles.ts | 6 +- .../tests/text-field-matrix.stories.ts | 60 +++++++++---------- .../text-field/tests/text-field.stories.ts | 10 ++-- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/packages/nimble-components/src/text-field/index.ts b/packages/nimble-components/src/text-field/index.ts index 806c7e7eb0..c58c2ae22a 100644 --- a/packages/nimble-components/src/text-field/index.ts +++ b/packages/nimble-components/src/text-field/index.ts @@ -44,8 +44,8 @@ export class TextField extends FoundationTextField implements ErrorPattern { @attr({ attribute: 'error-visible', mode: 'boolean' }) public errorVisible = false; - @attr({ attribute: 'edges-flush', mode: 'boolean' }) - public edgesFlush = false; + @attr({ attribute: 'full-bleed', mode: 'boolean' }) + public fullBleed = false; } const nimbleTextField = TextField.compose({ diff --git a/packages/nimble-components/src/text-field/styles.ts b/packages/nimble-components/src/text-field/styles.ts index ab8f52803a..d56807319b 100644 --- a/packages/nimble-components/src/text-field/styles.ts +++ b/packages/nimble-components/src/text-field/styles.ts @@ -85,7 +85,7 @@ export const styles = css` border-bottom-color: ${borderHoverColor}; } - :host([appearance='frameless'][edges-flush]) .root { + :host([appearance='frameless'][full-bleed]) .root { padding-left: 0px; padding-right: 0px; } @@ -98,7 +98,7 @@ export const styles = css` user-select: none; } - :host([appearance='frameless'][edges-flush]) .root::before { + :host([appearance='frameless'][full-bleed]) .root::before { display: none; } @@ -110,7 +110,7 @@ export const styles = css` user-select: none; } - :host([appearance='frameless'][edges-flush]) .root::after { + :host([appearance='frameless'][full-bleed]) .root::after { display: none; } diff --git a/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts b/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts index 2a5e987b43..196afe8943 100644 --- a/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts +++ b/packages/nimble-components/src/text-field/tests/text-field-matrix.stories.ts @@ -80,11 +80,11 @@ const appearanceStates = Object.entries(TextFieldAppearance).map( ); type AppearanceState = typeof appearanceStates[number]; -const edgesFlushStates = [ +const fullBleedStates = [ ['', false], - ['Edges Flush', true] + ['Full Bleed', true] ] as const; -type EdgesFlushState = typeof edgesFlushStates[number]; +type FullBleedState = typeof fullBleedStates[number]; // prettier-ignore const component = ( @@ -95,12 +95,12 @@ const component = ( [errorName, errorVisible, errorText]: ErrorState, [typeName, type]: TypeState, [appearanceName, appearance]: AppearanceState, - [edgesFluashName, edgesFlush]: EdgesFlushState, + [fullBleedName, fullBleed]: FullBleedState, [valueName, valueValue, placeholderValue]: ValueState ): ViewTemplate => html` errorName} ${() => typeName} ${() => appearanceName} - ${() => edgesFluashName} + ${() => fullBleedName} ${() => valueName} ${when(() => showActionButtons, html` @@ -141,7 +141,7 @@ export const lightThemeEditableEnabledWithoutButtons: Story = createFixedThemeSt errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), lightThemeWhiteBackground @@ -156,7 +156,7 @@ export const lightThemeEditableEnabledWithButtons: Story = createFixedThemeStory errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), lightThemeWhiteBackground @@ -171,7 +171,7 @@ export const lightThemeEditableDisabledWithoutButtons: Story = createFixedThemeS errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), lightThemeWhiteBackground @@ -186,7 +186,7 @@ export const lightThemeEditableDisabledWithButtons: Story = createFixedThemeStor errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), lightThemeWhiteBackground @@ -201,7 +201,7 @@ export const lightThemeReadOnlyEnabledWithoutButtons: Story = createFixedThemeSt errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), lightThemeWhiteBackground @@ -216,7 +216,7 @@ export const lightThemeReadOnlyEnabledWithButtons: Story = createFixedThemeStory errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), lightThemeWhiteBackground @@ -231,7 +231,7 @@ export const lightThemeReadOnlyDisabledWithoutButtons: Story = createFixedThemeS errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), lightThemeWhiteBackground @@ -246,7 +246,7 @@ export const lightThemeReadOnlyDisabledWithButtons: Story = createFixedThemeStor errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), lightThemeWhiteBackground @@ -261,7 +261,7 @@ export const darkThemeEditableEnabledWithoutButtons: Story = createFixedThemeSto errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), darkThemeBlackBackground @@ -276,7 +276,7 @@ export const darkThemeEditableEnabledWithButtons: Story = createFixedThemeStory( errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), darkThemeBlackBackground @@ -291,7 +291,7 @@ export const darkThemeEditableDisabledWithoutButtons: Story = createFixedThemeSt errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), darkThemeBlackBackground @@ -306,7 +306,7 @@ export const darkThemeEditableDisabledWithButtons: Story = createFixedThemeStory errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), darkThemeBlackBackground @@ -321,7 +321,7 @@ export const darkThemeReadOnlyEnabledWithoutButtons: Story = createFixedThemeSto errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), darkThemeBlackBackground @@ -336,7 +336,7 @@ export const darkThemeReadOnlyEnabledWithButtons: Story = createFixedThemeStory( errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), darkThemeBlackBackground @@ -351,7 +351,7 @@ export const darkThemeReadOnlyDisabledWithoutButtons: Story = createFixedThemeSt errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), darkThemeBlackBackground @@ -366,7 +366,7 @@ export const darkThemeReadOnlyDisabledWithButtons: Story = createFixedThemeStory errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), darkThemeBlackBackground @@ -381,7 +381,7 @@ export const colorThemeEditableEnabledWithoutButtons: Story = createFixedThemeSt errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), colorThemeDarkGreenBackground @@ -396,7 +396,7 @@ export const colorThemeEditableEnabledWithButtons: Story = createFixedThemeStory errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), colorThemeDarkGreenBackground @@ -411,7 +411,7 @@ export const colorThemeEditableDisabledWithoutButtons: Story = createFixedThemeS errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), colorThemeDarkGreenBackground @@ -426,7 +426,7 @@ export const colorThemeEditableDisabledWithButtons: Story = createFixedThemeStor errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), colorThemeDarkGreenBackground @@ -441,7 +441,7 @@ export const colorThemeReadOnlyEnabledWithoutButtons: Story = createFixedThemeSt errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), colorThemeDarkGreenBackground @@ -456,7 +456,7 @@ export const colorThemeReadOnlyEnabledWithButtons: Story = createFixedThemeStory errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), colorThemeDarkGreenBackground @@ -471,7 +471,7 @@ export const colorThemeReadOnlyDisabledWithoutButtons: Story = createFixedThemeS errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), colorThemeDarkGreenBackground @@ -486,7 +486,7 @@ export const colorThemeReadOnlyDisabledWithButtons: Story = createFixedThemeStor errorStates, typeStates, appearanceStates, - edgesFlushStates, + fullBleedStates, valueStates ]), colorThemeDarkGreenBackground diff --git a/packages/nimble-components/src/text-field/tests/text-field.stories.ts b/packages/nimble-components/src/text-field/tests/text-field.stories.ts index ac9d39a13d..eb2f191010 100644 --- a/packages/nimble-components/src/text-field/tests/text-field.stories.ts +++ b/packages/nimble-components/src/text-field/tests/text-field.stories.ts @@ -9,7 +9,7 @@ interface TextFieldArgs { label: string; type: string; appearance: string; - edgesFlush: boolean; + fullBleed: boolean; value: string; readonly: boolean; disabled: boolean; @@ -58,7 +58,7 @@ const metadata: Meta = { ?disabled="${x => x.disabled}" error-text="${x => x.errorText}" ?error-visible="${x => x.errorVisible}" - ?edges-flush="${x => x.edgesFlush}" + ?full-bleed="${x => x.fullBleed}" > ${when(x => x.leftIcon, html` `)} @@ -81,9 +81,9 @@ const metadata: Meta = { options: Object.values(TextFieldAppearance), control: { type: 'radio' } }, - edgesFlush: { + fullBleed: { description: - 'Add the class `clear-inline-padding` to remove the start and end padding. Only affects 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.' }, errorText: { description: @@ -100,7 +100,7 @@ const metadata: Meta = { label: 'default label', type: 'text', appearance: 'underline', - edgesFlush: false, + fullBleed: false, value: '', readonly: false, disabled: false, From 6187570b2c84cf886ac4a4c54472397850e34533 Mon Sep 17 00:00:00 2001 From: rajsite Date: Mon, 8 Aug 2022 22:59:57 -0500 Subject: [PATCH 06/43] prototype --- .../combobox/tests/combobox-matrix.stories.ts | 30 ++++++++++++------- .../src/select/tests/select-matrix.stories.ts | 27 ++++++++++------- .../tests/tree-view-matrix.stories.ts | 16 +++++++--- .../src/utilities/tests/states.ts | 12 -------- 4 files changed, 48 insertions(+), 37 deletions(-) diff --git a/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts b/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts index e48c76a47d..984b1de425 100644 --- a/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts +++ b/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts @@ -17,6 +17,7 @@ import { ErrorState } from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; +import { controlLabelFont, controlLabelFontColor, smallPadding } from '../../theme-provider/design-tokens'; const metadata: Meta = { title: 'Tests/Combobox', @@ -39,18 +40,25 @@ const component = ( [disabledName, disabled]: DisabledState, [errorName, errorVisible, errorText]: ErrorState, ): ViewTemplate => html` -
- - - Option 1 - Option 2 - Option 3 - - + + + Option 1 + Option 2 + Option 3 + + +
`; export const comboboxThemeMatrix: Story = createMatrixThemeStory( diff --git a/packages/nimble-components/src/select/tests/select-matrix.stories.ts b/packages/nimble-components/src/select/tests/select-matrix.stories.ts index 677c4ba663..889da2a2d3 100644 --- a/packages/nimble-components/src/select/tests/select-matrix.stories.ts +++ b/packages/nimble-components/src/select/tests/select-matrix.stories.ts @@ -15,6 +15,7 @@ import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; import { DropdownAppearance } from '../../patterns/dropdown/types'; import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; +import { controlLabelFont, controlLabelFontColor, smallPadding } from '../../theme-provider/design-tokens'; const metadata: Meta = { title: 'Tests/Select', @@ -41,17 +42,23 @@ const component = ( [disabledName, disabled]: DisabledState, [appearanceName, appearance]: AppearanceState ): ViewTemplate => html` -
- - - Option 1 - Option 2 - Option 3 - - + + + Option 1 + Option 2 + Option 3 + +
`; diff --git a/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts b/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts index e2fe9fd6ab..c7ad292f86 100644 --- a/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts +++ b/packages/nimble-components/src/tree-view/tests/tree-view-matrix.stories.ts @@ -11,10 +11,6 @@ import { import { disabledStates, DisabledState, - ExpandedState, - expandedStates, - SelectedState, - selectedStates, IconVisibleState, iconVisibleStates } from '../../utilities/tests/states'; @@ -29,6 +25,18 @@ const metadata: Meta = { } }; +const expandedStates = [ + ['Collapsed', false], + ['Expanded', true] +] as const; +type ExpandedState = typeof expandedStates[number]; + +const selectedStates = [ + ['Unselected', false], + ['Selected', true] +] as const; +type SelectedState = typeof selectedStates[number]; + // prettier-ignore const component = ( [disabledName, disabled]: DisabledState, diff --git a/packages/nimble-components/src/utilities/tests/states.ts b/packages/nimble-components/src/utilities/tests/states.ts index 2b0efd215d..885ebec074 100644 --- a/packages/nimble-components/src/utilities/tests/states.ts +++ b/packages/nimble-components/src/utilities/tests/states.ts @@ -41,15 +41,3 @@ export type ReadOnlyState = typeof readOnlyStates[number]; export const iconVisibleStates = [false, true] as const; export type IconVisibleState = typeof iconVisibleStates[number]; - -export const expandedStates = [ - ['Collapsed', false], - ['Expanded', true] -] as const; -export type ExpandedState = typeof expandedStates[number]; - -export const selectedStates = [ - ['Unselected', false], - ['Selected', true] -] as const; -export type SelectedState = typeof selectedStates[number]; From 2089e933f71e8a716bf47418c121b50691ac2603 Mon Sep 17 00:00:00 2001 From: rajsite Date: Mon, 8 Aug 2022 23:23:04 -0500 Subject: [PATCH 07/43] prototype --- .../combobox/tests/combobox-matrix.stories.ts | 21 +++++++++++++++---- .../src/select/tests/select-matrix.stories.ts | 4 ++-- .../tests/text-area-matrix.stories.ts | 4 +++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts b/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts index 984b1de425..f99dd4cb14 100644 --- a/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts +++ b/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts @@ -17,7 +17,13 @@ import { ErrorState } from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; -import { controlLabelFont, controlLabelFontColor, smallPadding } from '../../theme-provider/design-tokens'; +import { controlLabelFont, controlLabelFontColor, standardPadding } from '../../theme-provider/design-tokens'; + +const valueStates = [ + ['No Value', undefined, 'placeholder'], + ['Value', 'Hello', 'placeholder'] +] as const; +type ValueState = typeof valueStates[number]; const metadata: Meta = { title: 'Tests/Combobox', @@ -39,19 +45,26 @@ export default metadata; const component = ( [disabledName, disabled]: DisabledState, [errorName, errorVisible, errorText]: ErrorState, + [valueName, value, placeholder]: ValueState ): ViewTemplate => html`
- + Option 1 Option 2 @@ -62,7 +75,7 @@ const component = ( `; export const comboboxThemeMatrix: Story = createMatrixThemeStory( - createMatrix(component, [disabledStates, errorStates]) + createMatrix(component, [disabledStates, errorStates, valueStates]) ); export const hiddenCombobox: Story = createStory( diff --git a/packages/nimble-components/src/select/tests/select-matrix.stories.ts b/packages/nimble-components/src/select/tests/select-matrix.stories.ts index 889da2a2d3..a75ad5894c 100644 --- a/packages/nimble-components/src/select/tests/select-matrix.stories.ts +++ b/packages/nimble-components/src/select/tests/select-matrix.stories.ts @@ -15,7 +15,7 @@ import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; import { DropdownAppearance } from '../../patterns/dropdown/types'; import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; -import { controlLabelFont, controlLabelFontColor, smallPadding } from '../../theme-provider/design-tokens'; +import { controlLabelFont, controlLabelFontColor, standardPadding } from '../../theme-provider/design-tokens'; const metadata: Meta = { title: 'Tests/Select', @@ -45,7 +45,7 @@ const component = (
diff --git a/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts b/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts index 945f0eb347..e08d57afd2 100644 --- a/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts +++ b/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts @@ -62,7 +62,9 @@ const component = ( placeholder="${() => placeholderValue}" ?readonly="${() => readonly}" > - ${() => disabledName} ${() => appearanceName} ${() => valueName} + ${() => disabledName} + ${() => appearanceName} + ${() => valueName} ${() => readOnlyName} `; From 91283c77eb99b010acf345e21ec30707d79d565d Mon Sep 17 00:00:00 2001 From: rajsite Date: Tue, 9 Aug 2022 14:36:19 -0500 Subject: [PATCH 08/43] prototype --- .../src/directives/tooltip/nimble-tooltip.directive.ts | 4 ++-- .../tooltip/tests/nimble-tooltip.directive.spec.ts | 4 ++-- .../projects/ni/nimble-angular/src/public-api.ts | 2 +- .../src/combobox/tests/combobox-matrix.stories.ts | 6 +++++- .../src/select/tests/select-matrix.stories.ts | 6 +++++- .../src/text-area/tests/text-area-matrix.stories.ts | 4 +--- 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/tooltip/nimble-tooltip.directive.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/tooltip/nimble-tooltip.directive.ts index 06e65189a7..edf2fecf37 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/tooltip/nimble-tooltip.directive.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/tooltip/nimble-tooltip.directive.ts @@ -1,10 +1,10 @@ import { Directive, ElementRef, Input, Renderer2 } from '@angular/core'; import type { Tooltip } from '@ni/nimble-components/dist/esm/tooltip'; -import { TooltipStatus } from '@ni/nimble-components/dist/esm/tooltip/types'; +import { TooltipAppearance } from '@ni/nimble-components/dist/esm/tooltip/types'; import { NumberValueOrAttribute, toNumberProperty } from '../utilities/template-value-helpers'; export type { Tooltip }; -export { TooltipStatus }; +export { TooltipAppearance }; /** * Directive to provide Angular integration for the tooltip. diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/tooltip/tests/nimble-tooltip.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/tooltip/tests/nimble-tooltip.directive.spec.ts index f51f0a6e11..4bd8f23ad1 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/tooltip/tests/nimble-tooltip.directive.spec.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/tooltip/tests/nimble-tooltip.directive.spec.ts @@ -1,7 +1,7 @@ import { Component, ElementRef, ViewChild } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import type { NumberValueOrAttribute } from 'dist/ni/nimble-angular/directives/utilities/template-value-helpers'; -import { Tooltip, NimbleTooltipDirective, TooltipStatus } from '../nimble-tooltip.directive'; +import { Tooltip, NimbleTooltipDirective, TooltipAppearance } from '../nimble-tooltip.directive'; import { NimbleTooltipModule } from '../nimble-tooltip.module'; describe('Nimble tooltip', () => { @@ -21,7 +21,7 @@ describe('Nimble tooltip', () => { it('can use TooltipStatus values', () => { // Ensure TooltipStatus is exported correctly so that it can be used // as more than a type. - expect(TooltipStatus.information).toEqual(TooltipStatus.information); + expect(TooltipAppearance.information).toEqual(TooltipAppearance.information); }); }); diff --git a/angular-workspace/projects/ni/nimble-angular/src/public-api.ts b/angular-workspace/projects/ni/nimble-angular/src/public-api.ts index 30bdb8dc71..b5a3e352ca 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/public-api.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/public-api.ts @@ -71,4 +71,4 @@ export * from './testing/async-helpers'; // Export enums that are used by multiple components here to avoid exporting them multiple times. export { ButtonAppearance } from '@ni/nimble-components/dist/esm/patterns/button/types'; export { DropdownAppearance } from '@ni/nimble-components/dist/esm/patterns/dropdown/types'; -export { IconStatus } from '@ni/nimble-components/dist/esm/icon-base/types'; \ No newline at end of file +export { IconAppearance } from '@ni/nimble-components/dist/esm/icon-base/types'; \ No newline at end of file diff --git a/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts b/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts index f99dd4cb14..ff9e8712a5 100644 --- a/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts +++ b/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts @@ -17,7 +17,11 @@ import { ErrorState } from '../../utilities/tests/states'; import { hiddenWrapper } from '../../utilities/tests/hidden'; -import { controlLabelFont, controlLabelFontColor, standardPadding } from '../../theme-provider/design-tokens'; +import { + controlLabelFont, + controlLabelFontColor, + standardPadding +} from '../../theme-provider/design-tokens'; const valueStates = [ ['No Value', undefined, 'placeholder'], diff --git a/packages/nimble-components/src/select/tests/select-matrix.stories.ts b/packages/nimble-components/src/select/tests/select-matrix.stories.ts index a75ad5894c..2c07bd79a4 100644 --- a/packages/nimble-components/src/select/tests/select-matrix.stories.ts +++ b/packages/nimble-components/src/select/tests/select-matrix.stories.ts @@ -15,7 +15,11 @@ import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; import { DropdownAppearance } from '../../patterns/dropdown/types'; import { textCustomizationWrapper } from '../../utilities/tests/text-customization'; -import { controlLabelFont, controlLabelFontColor, standardPadding } from '../../theme-provider/design-tokens'; +import { + controlLabelFont, + controlLabelFontColor, + standardPadding +} from '../../theme-provider/design-tokens'; const metadata: Meta = { title: 'Tests/Select', diff --git a/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts b/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts index e08d57afd2..945f0eb347 100644 --- a/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts +++ b/packages/nimble-components/src/text-area/tests/text-area-matrix.stories.ts @@ -62,9 +62,7 @@ const component = ( placeholder="${() => placeholderValue}" ?readonly="${() => readonly}" > - ${() => disabledName} - ${() => appearanceName} - ${() => valueName} + ${() => disabledName} ${() => appearanceName} ${() => valueName} ${() => readOnlyName} `; From 873df4cf5df0d2130d5f4336f2e45c9dc25289e0 Mon Sep 17 00:00:00 2001 From: rajsite Date: Tue, 9 Aug 2022 14:36:46 -0500 Subject: [PATCH 09/43] Change files --- ...imble-angular-cfe8519a-4f32-4d76-ae82-9dee01fbe94d.json | 7 +++++++ ...le-components-b448e267-8129-44ea-a70d-3b6baa379bdf.json | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 change/@ni-nimble-angular-cfe8519a-4f32-4d76-ae82-9dee01fbe94d.json create mode 100644 change/@ni-nimble-components-b448e267-8129-44ea-a70d-3b6baa379bdf.json diff --git a/change/@ni-nimble-angular-cfe8519a-4f32-4d76-ae82-9dee01fbe94d.json b/change/@ni-nimble-angular-cfe8519a-4f32-4d76-ae82-9dee01fbe94d.json new file mode 100644 index 0000000000..f004819219 --- /dev/null +++ b/change/@ni-nimble-angular-cfe8519a-4f32-4d76-ae82-9dee01fbe94d.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "prototype", + "packageName": "@ni/nimble-angular", + "email": "rajsite@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/change/@ni-nimble-components-b448e267-8129-44ea-a70d-3b6baa379bdf.json b/change/@ni-nimble-components-b448e267-8129-44ea-a70d-3b6baa379bdf.json new file mode 100644 index 0000000000..1f8f56faad --- /dev/null +++ b/change/@ni-nimble-components-b448e267-8129-44ea-a70d-3b6baa379bdf.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "prototype", + "packageName": "@ni/nimble-components", + "email": "rajsite@users.noreply.github.com", + "dependentChangeType": "none" +} From 306841563c8da46685f690bf9cd45e92c0b092e3 Mon Sep 17 00:00:00 2001 From: rajsite Date: Tue, 9 Aug 2022 16:57:22 -0500 Subject: [PATCH 10/43] prototype --- .../src/tooltip/tests/tooltip.spec.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/nimble-components/src/tooltip/tests/tooltip.spec.ts b/packages/nimble-components/src/tooltip/tests/tooltip.spec.ts index b5f7cc855d..0979c11384 100644 --- a/packages/nimble-components/src/tooltip/tests/tooltip.spec.ts +++ b/packages/nimble-components/src/tooltip/tests/tooltip.spec.ts @@ -1,7 +1,8 @@ import { DesignSystem, TooltipPosition, - Tooltip as FoundationTooltip + Tooltip as FoundationTooltip, + ElementDisambiguation } from '@microsoft/fast-foundation'; import { DOM, html } from '@microsoft/fast-element'; import { fixture, Fixture } from '../../utilities/tests/fixture'; @@ -144,7 +145,7 @@ describe('Tooltip', () => { it('should render the default state when selected and not render an icon when true', async () => { element.visible = true; - element.classList.add('icon-visible'); + element.iconVisible = true; await connect(); await DOM.nextUpdate(); @@ -157,7 +158,7 @@ describe('Tooltip', () => { it('should render the error state when selected', async () => { element.visible = true; - element.classList.add('fail'); + element.appearance = 'error'; await connect(); await DOM.nextUpdate(); @@ -170,8 +171,8 @@ describe('Tooltip', () => { it('should render the error state when selected and render the corresponding icon when true', async () => { element.visible = true; - element.classList.add('fail'); - element.classList.add('icon-visible'); + element.appearance = 'error'; + element.iconVisible = true; await connect(); await DOM.nextUpdate(); @@ -184,7 +185,7 @@ describe('Tooltip', () => { it('should render the info state when selected', async () => { element.visible = true; - element.classList.add('information'); + element.appearance = 'information'; await connect(); await DOM.nextUpdate(); @@ -197,8 +198,8 @@ describe('Tooltip', () => { it('should render the information state when selected and render the corresponding icon when true', async () => { element.visible = true; - element.classList.add('information'); - element.classList.add('icon-visible'); + element.appearance = 'information'; + element.iconVisible = true; await connect(); await DOM.nextUpdate(); From a69b1852649e96279ec986808baae8b2364e40be Mon Sep 17 00:00:00 2001 From: rajsite Date: Tue, 9 Aug 2022 17:06:54 -0500 Subject: [PATCH 11/43] prototype --- packages/nimble-components/src/tooltip/tests/tooltip.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/nimble-components/src/tooltip/tests/tooltip.spec.ts b/packages/nimble-components/src/tooltip/tests/tooltip.spec.ts index 0979c11384..32fff54d7c 100644 --- a/packages/nimble-components/src/tooltip/tests/tooltip.spec.ts +++ b/packages/nimble-components/src/tooltip/tests/tooltip.spec.ts @@ -1,8 +1,7 @@ import { DesignSystem, TooltipPosition, - Tooltip as FoundationTooltip, - ElementDisambiguation + Tooltip as FoundationTooltip } from '@microsoft/fast-foundation'; import { DOM, html } from '@microsoft/fast-element'; import { fixture, Fixture } from '../../utilities/tests/fixture'; From 434c1b6e4eedbee173544eaef6d07040af5c9341 Mon Sep 17 00:00:00 2001 From: rajsite Date: Tue, 9 Aug 2022 17:56:49 -0500 Subject: [PATCH 12/43] prototype --- packages/nimble-components/CONTRIBUTING.md | 22 +------------------ .../nimble-components/docs/css-guidelines.md | 4 ++-- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/packages/nimble-components/CONTRIBUTING.md b/packages/nimble-components/CONTRIBUTING.md index f85d8f35a2..0efd9ae305 100644 --- a/packages/nimble-components/CONTRIBUTING.md +++ b/packages/nimble-components/CONTRIBUTING.md @@ -131,9 +131,7 @@ Use the `html` tagged template helper to define your custom template. See [Decla This package follows the [NI JavaScript and TypeScript Styleguide](https://github.com/ni/javascript-styleguide) with some exceptions listed in [Coding Conventions](/packages/nimble-components/docs/coding-conventions.md). -#### API - -##### API naming +#### API naming Use lower-kebab-case for attributes and enum values that are part of a component's public API. @@ -142,24 +140,6 @@ Use lower-kebab-case for attributes and enum values that are part of a component public errorText: string | undefined; ``` -##### Attributes for alternative states - -https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes#content_versus_idl_attributes - -error-visible -appear-invalid - -:valid -:invalid -novalidate attribute -checkValidity -reportValidity -setCustomValidity -:required -:optional - -todo check that appearance behavior works for undefined values, looks like it should - #### CSS Component CSS should follow the patterns described in [CSS Guidelines](/packages/nimble-components/docs/css-guidelines.md). diff --git a/packages/nimble-components/docs/css-guidelines.md b/packages/nimble-components/docs/css-guidelines.md index 38a2b7cc45..ed89e47f3b 100644 --- a/packages/nimble-components/docs/css-guidelines.md +++ b/packages/nimble-components/docs/css-guidelines.md @@ -120,7 +120,7 @@ For example: :host(${focusVisible}) {} /* focusVisible is specific to FAST */ :host(:active) {} :host(:invalid) {} -:host(.custom-state) {} TODO :host\(.*\.[\w]+.*\) +:host(.custom-state) {} :host([disabled]) {} /* disabled styles override all others in the cascade*/ ``` @@ -161,7 +161,7 @@ const styles = css` When styling the invalid state of a form component, it may seem natural to use `:host(:invalid)` in the CSS selector. `:invalid` applies when the form validation has run (generally happens immediately) and failed on that component. The problem with styling based on this pseudo-class is that it prevents a client from having control over when the invalid styling is displayed. For example, if a required input is initially empty, it is common not to show the error styling until the user has changed the value (and subsequently left it empty). -Instead of styling based on `:invalid`, use the TODO class `invalid`. Then the client can create a binding to apply the `invalid` class based on the associated `FormControl`'s status properties, like `invalid`, `dirty`, and `touched`. +Instead of styling based on `:invalid`, use the class `invalid`. Then the client can create a binding to apply the `invalid` class based on the associated `FormControl`'s status properties, like `invalid`, `dirty`, and `touched`. ## Use FAST's `display` utility for styling host element From 06db2c418c48d566ec9d6ca28c223eab43a67c44 Mon Sep 17 00:00:00 2001 From: rajsite Date: Wed, 31 Aug 2022 15:34:22 -0500 Subject: [PATCH 13/43] Merge woopsies --- packages/nimble-components/src/utilities/tests/states.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/nimble-components/src/utilities/tests/states.ts b/packages/nimble-components/src/utilities/tests/states.ts index 75bd0c1516..885ebec074 100644 --- a/packages/nimble-components/src/utilities/tests/states.ts +++ b/packages/nimble-components/src/utilities/tests/states.ts @@ -41,5 +41,3 @@ export type ReadOnlyState = typeof readOnlyStates[number]; export const iconVisibleStates = [false, true] as const; export type IconVisibleState = typeof iconVisibleStates[number]; -<<<<<<< HEAD -======= From 0cdd7214a5d622b2cebeb3cca617cb6d295c3ead Mon Sep 17 00:00:00 2001 From: rajsite Date: Wed, 31 Aug 2022 15:41:04 -0500 Subject: [PATCH 14/43] Lint --- .../src/combobox/tests/combobox-matrix.stories.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts b/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts index 53fa9dc05d..84a5525094 100644 --- a/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts +++ b/packages/nimble-components/src/combobox/tests/combobox-matrix.stories.ts @@ -90,7 +90,12 @@ const component = ( `; export const comboboxThemeMatrix: Story = createMatrixThemeStory( - createMatrix(component, [disabledStates, appearanceStates, errorStates, valueStates]) + createMatrix(component, [ + disabledStates, + appearanceStates, + errorStates, + valueStates + ]) ); export const hiddenCombobox: Story = createStory( From 4b53eb75c5b4d093fca5f19f94066c0c42adf167 Mon Sep 17 00:00:00 2001 From: rajsite Date: Wed, 31 Aug 2022 19:53:48 -0500 Subject: [PATCH 15/43] merge commit updates --- packages/nimble-components/src/combobox/styles.ts | 6 +++--- packages/nimble-components/src/list-option/styles.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/nimble-components/src/combobox/styles.ts b/packages/nimble-components/src/combobox/styles.ts index 72c4321942..27a9145d68 100644 --- a/packages/nimble-components/src/combobox/styles.ts +++ b/packages/nimble-components/src/combobox/styles.ts @@ -33,7 +33,7 @@ export const styles = css` color: ${bodyDisabledFontColor}; } - :host(.invalid)::after { + :host([error-visible])::after { border-bottom-color: ${failColor}; } @@ -54,7 +54,7 @@ export const styles = css` } :host([error-visible][disabled]) .control, - :host([error-visible].open) .control { + :host([error-visible][open]) .control { border-bottom-color: ${failColor}; } @@ -111,7 +111,7 @@ export const styles = css` appearanceBehavior( DropdownAppearance.block, css` - :host(.invalid) .control { + :host([error-visible]) .control { border-bottom-width: ${borderWidth}; padding-bottom: 0; } diff --git a/packages/nimble-components/src/list-option/styles.ts b/packages/nimble-components/src/list-option/styles.ts index 40a1c9a451..2b5a04c678 100644 --- a/packages/nimble-components/src/list-option/styles.ts +++ b/packages/nimble-components/src/list-option/styles.ts @@ -26,13 +26,13 @@ export const styles = css` padding: 8px 4px; } - :host(.selected) { + :host([aria-selected="true"]) { box-shadow: none; outline: none; background-color: ${fillSelectedColor}; } - :host(:hover.selected) { + :host([aria-selected="true"]:hover) { background-color: ${fillHoverSelectedColor}; } From 4f1d9099a5f9d9e80f49d68354c32c0b94edb7c1 Mon Sep 17 00:00:00 2001 From: rajsite Date: Wed, 31 Aug 2022 20:06:44 -0500 Subject: [PATCH 16/43] remove login page --- .../example-client-app/src/app/app.module.ts | 5 +--- .../src/app/header/header.component.html | 1 - .../src/app/header/header.component.ts | 5 ---- .../src/app/login/login.component.html | 24 ------------------ .../src/app/login/login.component.scss | 25 ------------------- .../src/app/login/login.component.ts | 22 ---------------- 6 files changed, 1 insertion(+), 81 deletions(-) delete mode 100644 angular-workspace/projects/example-client-app/src/app/login/login.component.html delete mode 100644 angular-workspace/projects/example-client-app/src/app/login/login.component.scss delete mode 100644 angular-workspace/projects/example-client-app/src/app/login/login.component.ts diff --git a/angular-workspace/projects/example-client-app/src/app/app.module.ts b/angular-workspace/projects/example-client-app/src/app/app.module.ts index 17421a7460..948fa7a673 100644 --- a/angular-workspace/projects/example-client-app/src/app/app.module.ts +++ b/angular-workspace/projects/example-client-app/src/app/app.module.ts @@ -10,14 +10,12 @@ import { NimbleTextAreaModule, NimbleTextFieldModule, NimbleNumberFieldModule, N NimbleCardButtonModule, NimbleDialogModule } from '@ni/nimble-angular'; import { AppComponent } from './app.component'; import { CustomAppComponent } from './customapp/customapp.component'; -import { LoginComponent } from './login/login.component'; import { HeaderComponent } from './header/header.component'; import { NavDrawerComponent } from './nav-drawer/nav-drawer.component'; @NgModule({ declarations: [ AppComponent, - LoginComponent, HeaderComponent, NavDrawerComponent, CustomAppComponent @@ -55,8 +53,7 @@ import { NavDrawerComponent } from './nav-drawer/nav-drawer.component'; NimbleCardButtonModule, NimbleDialogModule, RouterModule.forRoot([ - { path: '', redirectTo: '/login', pathMatch: 'full' }, - { path: 'login', component: LoginComponent }, + { path: '', redirectTo: '/customapp', pathMatch: 'full' }, { path: 'customapp', component: CustomAppComponent } ], { useHash: true }) diff --git a/angular-workspace/projects/example-client-app/src/app/header/header.component.html b/angular-workspace/projects/example-client-app/src/app/header/header.component.html index f95eda59fe..92dc954dc3 100644 --- a/angular-workspace/projects/example-client-app/src/app/header/header.component.html +++ b/angular-workspace/projects/example-client-app/src/app/header/header.component.html @@ -13,7 +13,6 @@

User settings

Menu User Settings - Logout
diff --git a/angular-workspace/projects/example-client-app/src/app/header/header.component.ts b/angular-workspace/projects/example-client-app/src/app/header/header.component.ts index 24c4623c6e..38aa1f55c9 100644 --- a/angular-workspace/projects/example-client-app/src/app/header/header.component.ts +++ b/angular-workspace/projects/example-client-app/src/app/header/header.component.ts @@ -36,11 +36,6 @@ export class HeaderComponent { this.userSettingsDrawer.hide(); } - public onLogoutSelected(): void { - this.toggleMenuHidden(); - void this.router.navigate(['/login']); - } - private toggleMenuHidden(): void { this.hideMenu = !this.hideMenu; } diff --git a/angular-workspace/projects/example-client-app/src/app/login/login.component.html b/angular-workspace/projects/example-client-app/src/app/login/login.component.html deleted file mode 100644 index cdca4f757a..0000000000 --- a/angular-workspace/projects/example-client-app/src/app/login/login.component.html +++ /dev/null @@ -1,24 +0,0 @@ -
- -
diff --git a/angular-workspace/projects/example-client-app/src/app/login/login.component.scss b/angular-workspace/projects/example-client-app/src/app/login/login.component.scss deleted file mode 100644 index 6c9ee0a34f..0000000000 --- a/angular-workspace/projects/example-client-app/src/app/login/login.component.scss +++ /dev/null @@ -1,25 +0,0 @@ -@import '~@ni/nimble-angular/styles/tokens'; - -:host { - background-color: $ni-nimble-application-background-color; - display: flex; - flex: auto; - justify-content: center; - align-items: center; - height: 100%; -} - -.login-container { - display: flex; - flex-direction: column; -} - -nimble-button { - margin-bottom: 12px; - width: fit-content; -} - -nimble-text-field { - width: 150px; - margin-bottom: 12px; -} diff --git a/angular-workspace/projects/example-client-app/src/app/login/login.component.ts b/angular-workspace/projects/example-client-app/src/app/login/login.component.ts deleted file mode 100644 index f006b2cd3b..0000000000 --- a/angular-workspace/projects/example-client-app/src/app/login/login.component.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Component, Inject } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Router } from '@angular/router'; - -@Component({ - selector: 'example-login', - templateUrl: './login.component.html', - styleUrls: ['./login.component.scss'] -}) -export class LoginComponent { - public loginForm: FormGroup; - public constructor(private readonly formBuilder: FormBuilder, @Inject(Router) private readonly router: Router) { - this.loginForm = this.formBuilder.group({ - username: ['someuser', Validators.required], - password: ['password', Validators.required] - }); - } - - public onSubmit(): void { - void this.router.navigate(['/customapp']); - } -} From db540557dc6811528552a8dc750d92730c6787c6 Mon Sep 17 00:00:00 2001 From: rajsite Date: Fri, 2 Sep 2022 18:37:27 -0500 Subject: [PATCH 17/43] remove aria-invalid todo, split to separate PR --- .../nimble-components/src/combobox/tests/combobox.stories.ts | 2 -- .../src/text-field/tests/text-field.stories.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/packages/nimble-components/src/combobox/tests/combobox.stories.ts b/packages/nimble-components/src/combobox/tests/combobox.stories.ts index dc48fc885a..c377aead6f 100644 --- a/packages/nimble-components/src/combobox/tests/combobox.stories.ts +++ b/packages/nimble-components/src/combobox/tests/combobox.stories.ts @@ -54,8 +54,6 @@ const metadata: Meta = { position="${x => x.dropDownPosition}" error-text="${x => x.errorText}" ?error-visible="${x => x.errorVisible}" - ${/* TODO: This should be handled by the error-visible attr */ ''} - aria-invalid="${x => x.errorVisible}" appearance="${x => x.appearance}" value="${x => x.currentValue}" placeholder="${x => x.placeholder}" diff --git a/packages/nimble-components/src/text-field/tests/text-field.stories.ts b/packages/nimble-components/src/text-field/tests/text-field.stories.ts index eb2f191010..b7add550b7 100644 --- a/packages/nimble-components/src/text-field/tests/text-field.stories.ts +++ b/packages/nimble-components/src/text-field/tests/text-field.stories.ts @@ -52,8 +52,6 @@ const metadata: Meta = { type="${x => x.type}" appearance="${x => x.appearance}" value="${x => x.value}" - ${/* TODO: This should be handled by the error-visible attr */ ''} - aria-invalid="${x => x.errorVisible}" ?readonly="${x => x.readonly}" ?disabled="${x => x.disabled}" error-text="${x => x.errorText}" From 44e44f419241a8f96aed74494b8e7a249de88450 Mon Sep 17 00:00:00 2001 From: rajsite Date: Fri, 2 Sep 2022 18:39:42 -0500 Subject: [PATCH 18/43] lint --- packages/nimble-components/src/list-option/styles.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nimble-components/src/list-option/styles.ts b/packages/nimble-components/src/list-option/styles.ts index 2b5a04c678..6a53b95187 100644 --- a/packages/nimble-components/src/list-option/styles.ts +++ b/packages/nimble-components/src/list-option/styles.ts @@ -26,13 +26,13 @@ export const styles = css` padding: 8px 4px; } - :host([aria-selected="true"]) { + :host([aria-selected='true']) { box-shadow: none; outline: none; background-color: ${fillSelectedColor}; } - :host([aria-selected="true"]:hover) { + :host([aria-selected='true']:hover) { background-color: ${fillHoverSelectedColor}; } From 877d6ac86fde07485abfe6c4052f03f5e2781d76 Mon Sep 17 00:00:00 2001 From: rajsite Date: Mon, 5 Sep 2022 16:47:26 -0500 Subject: [PATCH 19/43] error-visible angular --- .../combobox/nimble-combobox.directive.ts | 10 ++++ .../tests/nimble-combobox.directive.spec.ts | 52 +++++++++++++++++-- .../nimble-number-field.directive.ts | 10 ++++ .../nimble-number-field.directive.spec.ts | 52 +++++++++++++++++-- .../text-field/nimble-text-field.directive.ts | 10 ++++ .../tests/nimble-text-field.directive.spec.ts | 52 +++++++++++++++++-- 6 files changed, 177 insertions(+), 9 deletions(-) diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.directive.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.directive.ts index 2f48e8b7e7..2277b6b7b1 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.directive.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.directive.ts @@ -56,5 +56,15 @@ export class NimbleComboboxDirective { this.renderer.setProperty(this.elementRef.nativeElement, 'errorText', value); } + public get errorVisible(): boolean { + return this.elementRef.nativeElement.errorVisible; + } + + // Renaming because property should have camel casing, but attribute should not + // eslint-disable-next-line @angular-eslint/no-input-rename + @Input('error-visible') public set errorVisible(value: BooleanValueOrAttribute) { + this.renderer.setProperty(this.elementRef.nativeElement, 'errorVisible', toBooleanProperty(value)); + } + public constructor(private readonly renderer: Renderer2, private readonly elementRef: ElementRef) {} } diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/tests/nimble-combobox.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/tests/nimble-combobox.directive.spec.ts index fecba2cfab..90d905abd0 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/tests/nimble-combobox.directive.spec.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/tests/nimble-combobox.directive.spec.ts @@ -66,6 +66,17 @@ describe('Nimble combobox', () => { directive.errorText = 'new value'; expect(nativeElement.errorText).toBe('new value'); }); + + it('has expected defaults for errorVisible', () => { + expect(directive.errorVisible).toBeFalse(); + expect(nativeElement.errorVisible).toBeFalse(); + }); + + it('can use the directive to set errorVisible', () => { + directive.errorVisible = true; + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); }); describe('with template string values', () => { @@ -75,8 +86,10 @@ describe('Nimble combobox', () => { disabled autocomplete="inline" appearance="outline" + placeholder="Enter value:" error-text="error text" - placeholder="Enter value:"> + error-visible + > ` }) class TestHostComponent { @@ -123,6 +136,11 @@ describe('Nimble combobox', () => { expect(directive.errorText).toBe('error text'); expect(nativeElement.errorText).toBe('error text'); }); + + it('will use template string values for errorVisible', () => { + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); }); describe('with property bound values', () => { @@ -132,8 +150,10 @@ describe('Nimble combobox', () => { [disabled]="disabled" [autocomplete]="autocomplete" [appearance]="appearance" + [placeholder]="placeholder" [error-text]="errorText" - [placeholder]="placeholder"> + [error-visible]="errorVisible" + > ` }) @@ -145,6 +165,7 @@ describe('Nimble combobox', () => { public appearance: DropdownAppearance = DropdownAppearance.outline; public errorText = 'initial value'; public placeholder = 'Enter value:'; + public errorVisible = false; } let fixture: ComponentFixture; @@ -217,6 +238,17 @@ describe('Nimble combobox', () => { expect(directive.errorText).toBe('new value'); expect(nativeElement.errorText).toBe('new value'); }); + + it('can be configured with property binding for errorVisible', () => { + expect(directive.errorVisible).toBeFalse(); + expect(nativeElement.errorVisible).toBeFalse(); + + fixture.componentInstance.errorVisible = true; + fixture.detectChanges(); + + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); }); describe('with attribute bound values', () => { @@ -227,7 +259,9 @@ describe('Nimble combobox', () => { [attr.autocomplete]="autocomplete" [attr.appearance]="appearance" [attr.placeholder]="placeholder" - [attr.error-text]="errorText"> + [attr.error-text]="errorText" + [attr.error-visible]="errorVisible" + > ` }) @@ -239,6 +273,7 @@ describe('Nimble combobox', () => { public appearance: DropdownAppearance = DropdownAppearance.underline; public placeholder = 'Enter value:'; public errorText = 'initial value'; + public errorVisible: BooleanValueOrAttribute = null; } let fixture: ComponentFixture; @@ -311,5 +346,16 @@ describe('Nimble combobox', () => { expect(directive.errorText).toBe('new value'); expect(nativeElement.errorText).toBe('new value'); }); + + it('can be configured with attribute binding for errorVisible', () => { + expect(directive.errorVisible).toBeFalse(); + expect(nativeElement.errorVisible).toBeFalse(); + + fixture.componentInstance.errorVisible = ''; + fixture.detectChanges(); + + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); }); }); diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/nimble-number-field.directive.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/nimble-number-field.directive.ts index d9f088ca26..539ed6f372 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/nimble-number-field.directive.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/nimble-number-field.directive.ts @@ -74,5 +74,15 @@ export class NimbleNumberFieldDirective { this.renderer.setProperty(this.elementRef.nativeElement, 'errorText', value); } + public get errorVisible(): boolean { + return this.elementRef.nativeElement.errorVisible; + } + + // Renaming because property should have camel casing, but attribute should not + // eslint-disable-next-line @angular-eslint/no-input-rename + @Input('error-visible') public set errorVisible(value: BooleanValueOrAttribute) { + this.renderer.setProperty(this.elementRef.nativeElement, 'errorVisible', toBooleanProperty(value)); + } + public constructor(private readonly renderer: Renderer2, private readonly elementRef: ElementRef) {} } diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/tests/nimble-number-field.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/tests/nimble-number-field.directive.spec.ts index e45d2b6d31..e7d1b9d849 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/tests/nimble-number-field.directive.spec.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/tests/nimble-number-field.directive.spec.ts @@ -110,6 +110,17 @@ describe('Nimble number field', () => { directive.errorText = 'new value'; expect(nativeElement.errorText).toBe('new value'); }); + + it('has expected defaults for errorVisible', () => { + expect(directive.errorVisible).toBeFalse(); + expect(nativeElement.errorVisible).toBeFalse(); + }); + + it('can use the directive to set errorVisible', () => { + directive.errorVisible = true; + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); }); describe('with template string values', () => { @@ -122,7 +133,9 @@ describe('Nimble number field', () => { max=20 step=2 placeholder="Placeholder value" - error-text="error text"> + error-text="error text" + error-visible + > ` }) class TestHostComponent { @@ -179,6 +192,11 @@ describe('Nimble number field', () => { expect(directive.errorText).toBe('error text'); expect(nativeElement.errorText).toBe('error text'); }); + + it('will use template string values for errorVisible', () => { + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); }); describe('with property bound values', () => { @@ -191,7 +209,9 @@ describe('Nimble number field', () => { [max]="max" [step]="step" [placeholder]="placeholder" - [error-text]="errorText"> + [error-text]="errorText" + [error-visible]="errorVisible" + > ` }) class TestHostComponent { @@ -204,6 +224,7 @@ describe('Nimble number field', () => { public step = 2; public placeholder = 'initial'; public errorText = 'initial value'; + public errorVisible = false; } let fixture: ComponentFixture; @@ -297,6 +318,17 @@ describe('Nimble number field', () => { expect(directive.errorText).toBe('new value'); expect(nativeElement.errorText).toBe('new value'); }); + + it('can be configured with property binding for errorVisible', () => { + expect(directive.errorVisible).toBeFalse(); + expect(nativeElement.errorVisible).toBeFalse(); + + fixture.componentInstance.errorVisible = true; + fixture.detectChanges(); + + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); }); describe('with attribute bound values', () => { @@ -309,7 +341,9 @@ describe('Nimble number field', () => { [attr.max]="max" [attr.step]="step" [attr.placeholder]="placeholder" - [attr.error-text]="errorText"> + [attr.error-text]="errorText" + [attr.error-visible]="errorVisible" + > ` }) class TestHostComponent { @@ -322,6 +356,7 @@ describe('Nimble number field', () => { public step: NumberValueOrAttribute = 2; public placeholder = 'initial'; public errorText = 'initial value'; + public errorVisible: BooleanValueOrAttribute = null; } let fixture: ComponentFixture; @@ -415,5 +450,16 @@ describe('Nimble number field', () => { expect(directive.errorText).toBe('new value'); expect(nativeElement.errorText).toBe('new value'); }); + + it('can be configured with attribute binding for errorVisible', () => { + expect(directive.errorVisible).toBeFalse(); + expect(nativeElement.errorVisible).toBeFalse(); + + fixture.componentInstance.errorVisible = ''; + fixture.detectChanges(); + + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); }); }); \ No newline at end of file diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/nimble-text-field.directive.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/nimble-text-field.directive.ts index b95083ae63..73e9fb4ecf 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/nimble-text-field.directive.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/nimble-text-field.directive.ts @@ -106,6 +106,16 @@ export class NimbleTextFieldDirective { this.renderer.setProperty(this.elementRef.nativeElement, 'errorText', value); } + public get errorVisible(): boolean { + return this.elementRef.nativeElement.errorVisible; + } + + // Renaming because property should have camel casing, but attribute should not + // eslint-disable-next-line @angular-eslint/no-input-rename + @Input('error-visible') public set errorVisible(value: BooleanValueOrAttribute) { + this.renderer.setProperty(this.elementRef.nativeElement, 'errorVisible', toBooleanProperty(value)); + } + public get size(): number { return this.elementRef.nativeElement.size; } diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/tests/nimble-text-field.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/tests/nimble-text-field.directive.spec.ts index 38fd0c08cb..2f8eadd119 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/tests/nimble-text-field.directive.spec.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/tests/nimble-text-field.directive.spec.ts @@ -153,6 +153,17 @@ describe('Nimble text field', () => { expect(nativeElement.errorText).toBe('new value'); }); + it('has expected defaults for errorVisible', () => { + expect(directive.errorVisible).toBeFalse(); + expect(nativeElement.errorVisible).toBeFalse(); + }); + + it('can use the directive to set errorVisible', () => { + directive.errorVisible = true; + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); + it('has expected defaults for size', () => { expect(directive.size).toBeUndefined(); expect(nativeElement.size).toBeUndefined(); @@ -189,8 +200,10 @@ describe('Nimble text field', () => { minlength="20" pattern="foo *" error-text="error text" + error-visible size="10" - spellcheck> + spellcheck + >
` }) class TestHostComponent { @@ -268,6 +281,11 @@ describe('Nimble text field', () => { expect(nativeElement.errorText).toBe('error text'); }); + it('will use template string values for errorVisible', () => { + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); + it('will use template string values for size', () => { expect(directive.size).toBe(10); expect(nativeElement.size).toBe(10); @@ -294,8 +312,10 @@ describe('Nimble text field', () => { [minlength]="minlength" [pattern]="pattern" [error-text]="errorText" + [error-visible]="errorVisible" [size]="size" - [spellcheck]="spellcheck"> + [spellcheck]="spellcheck" + > ` }) class TestHostComponent { @@ -312,6 +332,7 @@ describe('Nimble text field', () => { public minlength = 5; public pattern = 'initial'; public errorText = 'initial value'; + public errorVisible = false; public size = 2; public spellcheck = false; } @@ -452,6 +473,17 @@ describe('Nimble text field', () => { expect(nativeElement.errorText).toBe('new value'); }); + it('can be configured with property binding for errorVisible', () => { + expect(directive.errorVisible).toBeFalse(); + expect(nativeElement.errorVisible).toBeFalse(); + + fixture.componentInstance.errorVisible = true; + fixture.detectChanges(); + + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); + it('can be configured with property binding for size', () => { expect(directive.size).toBe(2); expect(nativeElement.size).toBe(2); @@ -490,8 +522,10 @@ describe('Nimble text field', () => { [attr.minlength]="minlength" [attr.pattern]="pattern" [attr.error-text]="errorText" + [attr.error-visible]="errorVisible" [attr.size]="size" - [attr.spellcheck]="spellcheck"> + [attr.spellcheck]="spellcheck" + > ` }) class TestHostComponent { @@ -508,6 +542,7 @@ describe('Nimble text field', () => { public minlength: NumberValueOrAttribute = 5; public pattern = 'initial'; public errorText = 'initial value'; + public errorVisible: BooleanValueOrAttribute = null; public size: NumberValueOrAttribute = 2; public spellcheck: BooleanValueOrAttribute = null; } @@ -648,6 +683,17 @@ describe('Nimble text field', () => { expect(nativeElement.errorText).toBe('new value'); }); + it('can be configured with attribute binding for errorVisible', () => { + expect(directive.errorVisible).toBeFalse(); + expect(nativeElement.errorVisible).toBeFalse(); + + fixture.componentInstance.errorVisible = ''; + fixture.detectChanges(); + + expect(directive.errorVisible).toBeTrue(); + expect(nativeElement.errorVisible).toBeTrue(); + }); + it('can be configured with attribute binding for size', () => { expect(directive.size).toBe(2); expect(nativeElement.size).toBe(2); From ce91ec7bfd8b724784d2f15dad3ef30f406f7794 Mon Sep 17 00:00:00 2001 From: rajsite Date: Mon, 5 Sep 2022 18:33:11 -0500 Subject: [PATCH 20/43] icons angular --- .../build/generate-icons/source/index.js | 3 +- .../icon-base/nimble-icon-base.directive.ts | 19 ++ .../tests/nimble-icon-check.directive.spec.ts | 167 ++++++++++++++++++ .../ni/nimble-angular/src/public-api.ts | 2 +- .../nimble-components/src/icon-base/index.ts | 6 +- .../nimble-components/src/icon-base/styles.ts | 8 +- .../icon-base/tests/icon-matrix.stories.ts | 16 +- .../src/icon-base/tests/icons.stories.ts | 18 +- .../src/icon-base/tests/types.spec.ts | 4 +- .../nimble-components/src/icon-base/types.ts | 4 +- 10 files changed, 217 insertions(+), 30 deletions(-) create mode 100644 angular-workspace/projects/ni/nimble-angular/src/directives/icon-base/nimble-icon-base.directive.ts create mode 100644 angular-workspace/projects/ni/nimble-angular/src/directives/icon-base/tests/nimble-icon-check.directive.spec.ts diff --git a/angular-workspace/projects/ni/nimble-angular/build/generate-icons/source/index.js b/angular-workspace/projects/ni/nimble-angular/build/generate-icons/source/index.js index 174925b48d..67c3eb83dc 100644 --- a/angular-workspace/projects/ni/nimble-angular/build/generate-icons/source/index.js +++ b/angular-workspace/projects/ni/nimble-angular/build/generate-icons/source/index.js @@ -52,6 +52,7 @@ for (const key of Object.keys(icons)) { const directiveFileContents = `${generatedFilePrefix} import { Directive } from '@angular/core'; import type { ${className} } from '@ni/nimble-components/dist/esm/icons/${directoryName}'; +import { NimbleIconBaseDirective } from '../../icon-base/nimble-icon-base.directive'; export type { ${className} }; @@ -61,7 +62,7 @@ export type { ${className} }; @Directive({ selector: '${elementName}' }) -export class ${directiveName} { +export class ${directiveName} extends NimbleIconBaseDirective { } `; const directiveFileName = `${elementName}.directive`; diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/icon-base/nimble-icon-base.directive.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/icon-base/nimble-icon-base.directive.ts new file mode 100644 index 0000000000..10ea111478 --- /dev/null +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/icon-base/nimble-icon-base.directive.ts @@ -0,0 +1,19 @@ +import { Directive, ElementRef, Input, Renderer2 } from '@angular/core'; +import type { Icon } from '@ni/nimble-components/dist/esm/icon-base'; +import type { IconSeverity } from '@ni/nimble-components/dist/esm/icon-base/types'; + +/** + * Base class for the nimble icon directives + */ +@Directive() +export class NimbleIconBaseDirective { + public get severity(): IconSeverity { + return this.elementRef.nativeElement.severity; + } + + @Input() public set severity(value: IconSeverity) { + this.renderer.setProperty(this.elementRef.nativeElement, 'severity', value); + } + + public constructor(private readonly renderer: Renderer2, private readonly elementRef: ElementRef) {} +} diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/icon-base/tests/nimble-icon-check.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/icon-base/tests/nimble-icon-check.directive.spec.ts new file mode 100644 index 0000000000..df0c06973a --- /dev/null +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/icon-base/tests/nimble-icon-check.directive.spec.ts @@ -0,0 +1,167 @@ +import { Component, ElementRef, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { IconSeverity } from '../../../public-api'; +import { IconCheck, NimbleIconCheckDirective } from '../../icons/check/nimble-icon-check.directive'; +import { NimbleIconCheckModule } from '../../icons/check/nimble-icon-check.module'; + +describe('Nimble icon check', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [NimbleIconCheckModule] + }); + }); + + it('custom element is defined', () => { + expect(customElements.get('nimble-icon-check')).not.toBeUndefined(); + }); + + describe('with no values in template', () => { + @Component({ + template: ` + + ` + }) + class TestHostComponent { + @ViewChild('icon', { read: NimbleIconCheckDirective }) public directive: NimbleIconCheckDirective; + @ViewChild('icon', { read: ElementRef }) public elementRef: ElementRef; + } + + let fixture: ComponentFixture; + let directive: NimbleIconCheckDirective; + let nativeElement: IconCheck; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleIconCheckModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('has expected defaults for severity', () => { + expect(directive.severity).toBe(IconSeverity.default); + expect(nativeElement.severity).toBe(IconSeverity.default); + }); + }); + + describe('with template string values', () => { + @Component({ + template: ` + + ` + }) + class TestHostComponent { + @ViewChild('icon', { read: NimbleIconCheckDirective }) public directive: NimbleIconCheckDirective; + @ViewChild('icon', { read: ElementRef }) public elementRef: ElementRef; + } + + let fixture: ComponentFixture; + let directive: NimbleIconCheckDirective; + let nativeElement: IconCheck; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleIconCheckModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('will use template string values for disabled', () => { + expect(directive.severity).toBe(IconSeverity.error); + expect(nativeElement.severity).toBe(IconSeverity.error); + }); + }); + + describe('with property bound values', () => { + @Component({ + template: ` + + + ` + }) + class TestHostComponent { + @ViewChild('icon', { read: NimbleIconCheckDirective }) public directive: NimbleIconCheckDirective; + @ViewChild('icon', { read: ElementRef }) public elementRef: ElementRef; + public severity: IconSeverity; + } + + let fixture: ComponentFixture; + let directive: NimbleIconCheckDirective; + let nativeElement: IconCheck; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleIconCheckModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('can be configured with property binding for severity', () => { + expect(directive.severity).toBe(IconSeverity.default); + expect(nativeElement.severity).toBe(IconSeverity.default); + + fixture.componentInstance.severity = IconSeverity.error; + fixture.detectChanges(); + + expect(directive.severity).toBe(IconSeverity.error); + expect(nativeElement.severity).toBe(IconSeverity.error); + }); + }); + + describe('with attribute bound values', () => { + @Component({ + template: ` + + + ` + }) + class TestHostComponent { + @ViewChild('icon', { read: NimbleIconCheckDirective }) public directive: NimbleIconCheckDirective; + @ViewChild('icon', { read: ElementRef }) public elementRef: ElementRef; + public severity: IconSeverity; + } + + let fixture: ComponentFixture; + let directive: NimbleIconCheckDirective; + let nativeElement: IconCheck; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleIconCheckModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('can be configured with attribute binding for disabled', () => { + expect(directive.severity).toBe(IconSeverity.default); + expect(nativeElement.severity).toBe(IconSeverity.default); + + fixture.componentInstance.severity = IconSeverity.error; + fixture.detectChanges(); + + expect(directive.severity).toBe(IconSeverity.error); + expect(nativeElement.severity).toBe(IconSeverity.error); + }); + }); +}); diff --git a/angular-workspace/projects/ni/nimble-angular/src/public-api.ts b/angular-workspace/projects/ni/nimble-angular/src/public-api.ts index 196bde65fd..ec611307d3 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/public-api.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/public-api.ts @@ -73,4 +73,4 @@ export * from './testing/async-helpers'; // Export enums that are used by multiple components here to avoid exporting them multiple times. export { ButtonAppearance } from '@ni/nimble-components/dist/esm/patterns/button/types'; export { DropdownAppearance } from '@ni/nimble-components/dist/esm/patterns/dropdown/types'; -export { IconAppearance } from '@ni/nimble-components/dist/esm/icon-base/types'; \ No newline at end of file +export { IconSeverity } from '@ni/nimble-components/dist/esm/icon-base/types'; diff --git a/packages/nimble-components/src/icon-base/index.ts b/packages/nimble-components/src/icon-base/index.ts index 5d875f7a9f..2c7a85545f 100644 --- a/packages/nimble-components/src/icon-base/index.ts +++ b/packages/nimble-components/src/icon-base/index.ts @@ -3,7 +3,7 @@ import { DesignSystem, FoundationElement } from '@microsoft/fast-foundation'; import type { NimbleIcon } from '@ni/nimble-tokens/dist/icons/js'; import { template } from './template'; import { styles } from './styles'; -import type { IconAppearance } from './types'; +import type { IconSeverity } from './types'; /** * The base class for icon components @@ -12,10 +12,10 @@ export class Icon extends FoundationElement { /** * @public * @remarks - * HTML Attribute: appearance + * HTML Attribute: severity */ @attr - public appearance: IconAppearance; + public severity: IconSeverity; public constructor(/** @internal */ public readonly icon: NimbleIcon) { super(); diff --git a/packages/nimble-components/src/icon-base/styles.ts b/packages/nimble-components/src/icon-base/styles.ts index 0a45431f5f..d580af7c25 100644 --- a/packages/nimble-components/src/icon-base/styles.ts +++ b/packages/nimble-components/src/icon-base/styles.ts @@ -24,19 +24,19 @@ export const styles = css` height: 100%; } - :host([appearance='error']) { + :host([severity='error']) { ${iconColor.cssCustomProperty}: ${failColor}; } - :host([appearance='warning']) { + :host([severity='warning']) { ${iconColor.cssCustomProperty}: ${warningColor}; } - :host([appearance='success']) { + :host([severity='success']) { ${iconColor.cssCustomProperty}: ${passColor}; } - :host([appearance='information']) { + :host([severity='information']) { ${iconColor.cssCustomProperty}: ${informationColor}; } diff --git a/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts b/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts index b3bef133e0..5f682848e3 100644 --- a/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts +++ b/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts @@ -9,7 +9,7 @@ import { createMatrixThemeStory, createStory } from '../../utilities/tests/storybook'; -import { IconAppearance } from '../types'; +import { IconSeverity } from '../types'; import { bodyFontColor } from '../../theme-provider/design-tokens'; import { hiddenWrapper } from '../../utilities/tests/hidden'; import '../../all-components'; @@ -23,24 +23,24 @@ const metadata: Meta = { export default metadata; -const appearanceStates: [string, string | undefined][] = Object.entries( - IconAppearance +const severityStates: [string, string | undefined][] = Object.entries( + IconSeverity ).map(([key, value]) => [pascalCase(key), value]); -type AppearanceState = typeof appearanceStates[number]; +type SeverityState = typeof severityStates[number]; -const component = ([stateName, state]: AppearanceState): ViewTemplate => html` +const component = ([stateName, state]: SeverityState): ViewTemplate => html` ${() => stateName} - + `; export const iconThemeMatrix: Story = createMatrixThemeStory( - createMatrix(component, [appearanceStates]) + createMatrix(component, [severityStates]) ); export const hiddenIcon: Story = createStory( hiddenWrapper( - html`` + html`` ) ); diff --git a/packages/nimble-components/src/icon-base/tests/icons.stories.ts b/packages/nimble-components/src/icon-base/tests/icons.stories.ts index d38a74c90e..183b3d13ad 100644 --- a/packages/nimble-components/src/icon-base/tests/icons.stories.ts +++ b/packages/nimble-components/src/icon-base/tests/icons.stories.ts @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/html'; import { html, repeat } from '@microsoft/fast-element'; import { DesignSystem } from '@microsoft/fast-foundation'; import * as nimbleIconComponentsMap from '../../icons/all-icons'; -import { IconAppearance } from '../types'; +import { IconSeverity } from '../types'; import { createUserSelectedThemeStory, overrideWarning @@ -16,7 +16,7 @@ import { const nimbleIconComponents = Object.values(nimbleIconComponentsMap); interface IconArgs { - appearance: keyof typeof IconAppearance; + severity: keyof typeof IconSeverity; } const metadata: Meta = { @@ -34,7 +34,7 @@ type IconClass = typeof Icon; const iconTemplate = html` ${(x, c) => html` <${DesignSystem.tagFor(x)} - appearance=${() => IconAppearance[c.parent.appearance]} + severity=${() => IconSeverity[c.parent.severity]} title=${DesignSystem.tagFor(x)} > @@ -46,8 +46,8 @@ With SCSS properties, the icon color can be overriden. For example: ${scssInternalPropertySetterMarkdown(tokenNames.iconColor, 'purple')} `; -const appearanceDescription = ` -Set appearance on the element to switch between the theme-aware color options. +const severityDescription = ` +Set severity on the element to switch between the theme-aware color options. ${overrideWarning('Color', appearanceDescriptionOverride)} `; @@ -55,13 +55,13 @@ ${overrideWarning('Color', appearanceDescriptionOverride)} // prettier-ignore export const icons: StoryObj = { args: { - appearance: 'default' + severity: 'default' }, argTypes: { - appearance: { - options: Object.keys(IconAppearance), + severity: { + options: Object.keys(IconSeverity), control: { type: 'radio' }, - description: appearanceDescription + description: severityDescription } }, render: createUserSelectedThemeStory(html` diff --git a/packages/nimble-components/src/icon-base/tests/types.spec.ts b/packages/nimble-components/src/icon-base/tests/types.spec.ts index cc8da8ab0a..4341996fe1 100644 --- a/packages/nimble-components/src/icon-base/tests/types.spec.ts +++ b/packages/nimble-components/src/icon-base/tests/types.spec.ts @@ -1,9 +1,9 @@ -import type { IconAppearance } from '../types'; +import type { IconSeverity } from '../types'; describe('Icon type', () => { it('IconStatus fails compile if assigning arbitrary string values', () => { // @ts-expect-error This expect will fail if the enum-like type is missing "as const" - const status: IconAppearance = 'hello'; + const status: IconSeverity = 'hello'; // @ts-expect-error This expect will fail if the enum-like type is missing "as const" expect(status).toEqual('hello'); }); diff --git a/packages/nimble-components/src/icon-base/types.ts b/packages/nimble-components/src/icon-base/types.ts index 9aa3424612..14bbfc07b3 100644 --- a/packages/nimble-components/src/icon-base/types.ts +++ b/packages/nimble-components/src/icon-base/types.ts @@ -2,11 +2,11 @@ * Predefined icon appearance states * @public */ -export const IconAppearance = { +export const IconSeverity = { default: undefined, error: 'error', warning: 'warning', success: 'success', information: 'information' } as const; -export type IconAppearance = typeof IconAppearance[keyof typeof IconAppearance]; +export type IconSeverity = typeof IconSeverity[keyof typeof IconSeverity]; From 5c400426a8a9b6810389d0dcf30ea47ce8088140 Mon Sep 17 00:00:00 2001 From: rajsite Date: Mon, 5 Sep 2022 18:37:31 -0500 Subject: [PATCH 21/43] lint --- .../src/icon-base/tests/icon-matrix.stories.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts b/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts index 5f682848e3..29c218f1b0 100644 --- a/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts +++ b/packages/nimble-components/src/icon-base/tests/icon-matrix.stories.ts @@ -40,7 +40,5 @@ export const iconThemeMatrix: Story = createMatrixThemeStory( ); export const hiddenIcon: Story = createStory( - hiddenWrapper( - html`` - ) + hiddenWrapper(html``) ); From 240eace1b4c0ed56ffc9882b37fba00117709ef6 Mon Sep 17 00:00:00 2001 From: rajsite Date: Mon, 5 Sep 2022 19:42:34 -0500 Subject: [PATCH 22/43] DesignSystem.tagFor consistency --- .../nimble-components/src/combobox/index.ts | 20 +- .../src/menu-button/template.ts | 21 +- .../src/number-field/index.ts | 30 +- .../nimble-components/src/text-field/index.ts | 8 +- .../nimble-components/src/tooltip/styles.ts | 4 +- .../nimble-components/src/tooltip/template.ts | 26 +- .../nimble-components/src/tree-item/styles.ts | 399 +++++++++--------- .../src/utilities/tests/storybook.ts | 15 +- 8 files changed, 258 insertions(+), 265 deletions(-) diff --git a/packages/nimble-components/src/combobox/index.ts b/packages/nimble-components/src/combobox/index.ts index 4721abca3e..cd2d467013 100644 --- a/packages/nimble-components/src/combobox/index.ts +++ b/packages/nimble-components/src/combobox/index.ts @@ -11,10 +11,10 @@ import { keyEnter, keySpace } from '@microsoft/fast-web-utilities'; -import type { ToggleButton } from '../toggle-button'; +import { ToggleButton } from '../toggle-button'; import { errorTextTemplate } from '../patterns/error/template'; -import '../icons/exclamation-mark'; -import '../icons/arrow-expander-down'; +import { IconArrowExpanderDown } from '../icons/arrow-expander-down'; +import { IconExclamationMark } from '../icons/exclamation-mark'; import { styles } from './styles'; import type { ErrorPattern } from '../patterns/error/types'; @@ -218,12 +218,12 @@ const nimbleCombobox = Combobox.compose({ }, end: html`
- + >
- ({ aria-expanded="${x => x.open}" tabindex="-1" > - - - + +
${errorTextTemplate} ` diff --git a/packages/nimble-components/src/menu-button/template.ts b/packages/nimble-components/src/menu-button/template.ts index 2069a46fc3..752e57b85a 100644 --- a/packages/nimble-components/src/menu-button/template.ts +++ b/packages/nimble-components/src/menu-button/template.ts @@ -1,23 +1,16 @@ -import { - elements, - html, - ref, - slotted, - ViewTemplate, - when -} from '@microsoft/fast-element'; -import type { FoundationElementTemplate } from '@microsoft/fast-foundation'; +import { elements, html, ref, slotted, when } from '@microsoft/fast-element'; +import { DesignSystem } from '@microsoft/fast-foundation'; import type { MenuButton } from '.'; import { ToggleButton } from '../toggle-button'; import { AnchoredRegion } from '../anchored-region'; // prettier-ignore -export const template: FoundationElementTemplate> = context => html` +export const template = html` diff --git a/packages/nimble-components/src/number-field/index.ts b/packages/nimble-components/src/number-field/index.ts index a7509b6602..020dd33ef0 100644 --- a/packages/nimble-components/src/number-field/index.ts +++ b/packages/nimble-components/src/number-field/index.ts @@ -8,10 +8,11 @@ import { import { styles } from './styles'; import { NumberFieldAppearance } from './types'; import { errorTextTemplate } from '../patterns/error/template'; -import '../icons/add'; -import '../icons/exclamation-mark'; -import '../icons/minus-wide'; import type { ErrorPattern } from '../patterns/error/types'; +import { Button } from '../button'; +import { IconMinusWide } from '../icons/minus-wide'; +import { IconAdd } from '../icons/add'; +import { IconExclamationMark } from '../icons/exclamation-mark'; declare global { interface HTMLElementTagNameMap { @@ -64,32 +65,37 @@ const nimbleNumberField = NumberField.compose({ delegatesFocus: true }, stepDownGlyph: html` - "Decrement" - - + <${DesignSystem.tagFor(IconMinusWide)} + slot="start" + > + + `, stepUpGlyph: html` - "Increment" - - + <${DesignSystem.tagFor(IconAdd)} + slot="start"> + + `, end: html` - + > ${errorTextTemplate} ` }); diff --git a/packages/nimble-components/src/text-field/index.ts b/packages/nimble-components/src/text-field/index.ts index c58c2ae22a..9415e08c95 100644 --- a/packages/nimble-components/src/text-field/index.ts +++ b/packages/nimble-components/src/text-field/index.ts @@ -5,11 +5,11 @@ import { TextFieldOptions, textFieldTemplate as template } from '@microsoft/fast-foundation'; -import '../icons/exclamation-mark'; import { styles } from './styles'; import { TextFieldAppearance } from './types'; import { errorTextTemplate } from '../patterns/error/template'; import type { ErrorPattern } from '../patterns/error/types'; +import { IconExclamationMark } from '../icons/exclamation-mark'; declare global { interface HTMLElementTagNameMap { @@ -57,10 +57,10 @@ const nimbleTextField = TextField.compose({ delegatesFocus: true }, end: html` - + > diff --git a/packages/nimble-components/src/tooltip/styles.ts b/packages/nimble-components/src/tooltip/styles.ts index ca394b25f6..77e5572976 100644 --- a/packages/nimble-components/src/tooltip/styles.ts +++ b/packages/nimble-components/src/tooltip/styles.ts @@ -54,12 +54,12 @@ export const styles = css` padding-right: 8px; } - :host([appearance='error'][icon-visible]) [appearance='error'] { + :host([appearance='error'][icon-visible]) [severity='error'] { display: flex; flex: 0 0 auto; } - :host([appearance='information'][icon-visible]) [appearance='information'] { + :host([appearance='information'][icon-visible]) [severity='information'] { display: flex; flex: 0 0 auto; } diff --git a/packages/nimble-components/src/tooltip/template.ts b/packages/nimble-components/src/tooltip/template.ts index 67b670bef7..fc0e071ed3 100644 --- a/packages/nimble-components/src/tooltip/template.ts +++ b/packages/nimble-components/src/tooltip/template.ts @@ -1,17 +1,16 @@ -import { html, ref, ViewTemplate, when } from '@microsoft/fast-element'; -import type { FoundationElementTemplate } from '@microsoft/fast-foundation'; +import { html, ref, when } from '@microsoft/fast-element'; +import { DesignSystem } from '@microsoft/fast-foundation'; import { AnchoredRegion } from '../anchored-region'; import { IconExclamationMark } from '../icons/exclamation-mark'; import { IconInfo } from '../icons/info'; import type { Tooltip } from '.'; // prettier-ignore -export const template: FoundationElementTemplate> = context => { - return html` +export const template = html` ${when( x => x.tooltipVisible, html` - <${context.tagFor(AnchoredRegion)} + <${DesignSystem.tagFor(AnchoredRegion)} class="anchored-region" fixed-placement="true" auto-update-mode="${x => x.autoUpdateMode}" @@ -29,18 +28,17 @@ export const template: FoundationElementTemplate> = contex ${ref('region')} > - + ` )} - `; -}; +`; diff --git a/packages/nimble-components/src/tree-item/styles.ts b/packages/nimble-components/src/tree-item/styles.ts index 2215e3f52a..d2baa7a9ac 100644 --- a/packages/nimble-components/src/tree-item/styles.ts +++ b/packages/nimble-components/src/tree-item/styles.ts @@ -1,10 +1,5 @@ -import { css, ElementStyles } from '@microsoft/fast-element'; -import { - display, - FoundationElementTemplate, - TreeItem, - TreeItemOptions -} from '@microsoft/fast-foundation'; +import { css } from '@microsoft/fast-element'; +import { DesignSystem, display, TreeItem } from '@microsoft/fast-foundation'; import { focusVisible } from '../utilities/style/focus'; import { bodyFontColor, @@ -21,205 +16,203 @@ import { import { groupSelectedAttribute } from '../tree-view/types'; import { DirectionalStyleSheetBehavior } from '../utilities/style/direction'; -export const styles: FoundationElementTemplate = (context, _definition) => css` - ${display('block')} - - :host { - ${ - /* don't set font-size here or else it overrides what we set on .items */ '' - } - font-family: ${bodyFontFamily}; - font-weight: ${bodyFontWeight}; - contain: content; - position: relative; - outline: none; - color: ${bodyFontColor}; - cursor: pointer; - --ni-private-tree-item-nested-width: 0; - } - - ${/* this controls the side border */ ''} - :host([${groupSelectedAttribute}])::after { - background: ${borderHoverColor}; - border-radius: 0px; - content: ''; - display: block; - position: absolute; - top: 0px; - width: calc(${borderWidth} * 2); - height: calc(${iconSize} * 2); - } - - .positioning-region { - display: flex; - position: relative; - box-sizing: border-box; - height: calc(${iconSize} * 2); - } - - .positioning-region:hover { - background: ${fillHoverColor}; - } - - :host([${groupSelectedAttribute}]) .positioning-region:hover { - background: ${fillHoverSelectedColor}; - } - - :host(${focusVisible}) .positioning-region { - box-shadow: 0px 0px 0px ${borderWidth} ${borderHoverColor} inset; - outline: ${borderWidth} solid ${borderHoverColor}; - outline-offset: -2px; - } - - :host([selected]) .positioning-region { - background: ${fillSelectedColor}; - } - - :host([selected]) .positioning-region:hover { - background: ${fillHoverSelectedColor}; - } - - .positioning-region::before { - content: ''; - display: block; - width: var(--ni-private-tree-item-nested-width); - flex-shrink: 0; - } - - .content-region { - display: inline-flex; - align-items: center; - white-space: nowrap; - width: 100%; - padding-left: 10px; - font: inherit; - font-size: ${bodyFontSize}; - user-select: none; - position: relative; - margin-inline-start: ${iconSize}; - } - - :host(${focusVisible}) .content-region { - outline: none; - } - - :host([disabled]) .content-region { - opacity: 0.5; - cursor: not-allowed; - } - - .expand-collapse-button { - background: none; - border: none; - outline: none; - width: ${iconSize}; - height: ${iconSize}; - padding: 0px; - justify-content: center; - align-items: center; - cursor: pointer; - margin-left: 10px; - position: absolute; - } - - .expand-collapse-button svg { - width: ${iconSize}; - height: ${iconSize}; - transition: transform 0.2s ease-in; - pointer-events: none; - fill: currentcolor; - } - - ${ - /* this rule keeps children without an icon text aligned with parents */ '' - } - span[part="start"] { - width: ${iconSize}; - } - - ${ - /* the start class is applied when the corresponding slots is filled */ '' - } - .start { - display: flex; - fill: currentcolor; - margin-inline-start: ${iconSize}; - margin-inline-end: ${iconSize}; - } - - slot[name='start']::slotted(*) { - width: ${iconSize}; - height: ${iconSize}; - } - - ::slotted(${context.tagFor(TreeItem)}) { - --ni-private-tree-item-nested-width: 1em; - --ni-private-expand-collapse-button-nested-width: calc( - ${iconSize} * -1 - ); - } - - ${ - /* the end class is applied when the corresponding slots is filled */ '' - } - .end { - display: flex; - fill: currentcolor; - margin-inline-start: ${iconSize}; - } - - .items { - display: none; - ${ - /* - * this controls the nested indentation (by affecting .positioning-region::before) - * it must minimally contain arithmetic with an em and a px value - * make it larger or shorter by changing the px value - */ '' - } - font-size: calc(1em + (${iconSize} * 2)); - } - - :host([expanded]) .items { - display: block; - } - ` -// prettier-ignore +export const styles = css` + ${display('block')} + + :host { + ${ + /* don't set font-size here or else it overrides what we set on .items */ '' + } + font-family: ${bodyFontFamily}; + font-weight: ${bodyFontWeight}; + contain: content; + position: relative; + outline: none; + color: ${bodyFontColor}; + cursor: pointer; + --ni-private-tree-item-nested-width: 0; + } + + ${/* this controls the side border */ ''} + :host([${groupSelectedAttribute}])::after { + background: ${borderHoverColor}; + border-radius: 0px; + content: ''; + display: block; + position: absolute; + top: 0px; + width: calc(${borderWidth} * 2); + height: calc(${iconSize} * 2); + } + + .positioning-region { + display: flex; + position: relative; + box-sizing: border-box; + height: calc(${iconSize} * 2); + } + + .positioning-region:hover { + background: ${fillHoverColor}; + } + + :host([${groupSelectedAttribute}]) .positioning-region:hover { + background: ${fillHoverSelectedColor}; + } + + :host(${focusVisible}) .positioning-region { + box-shadow: 0px 0px 0px ${borderWidth} ${borderHoverColor} inset; + outline: ${borderWidth} solid ${borderHoverColor}; + outline-offset: -2px; + } + + :host([selected]) .positioning-region { + background: ${fillSelectedColor}; + } + + :host([selected]) .positioning-region:hover { + background: ${fillHoverSelectedColor}; + } + + .positioning-region::before { + content: ''; + display: block; + width: var(--ni-private-tree-item-nested-width); + flex-shrink: 0; + } + + .content-region { + display: inline-flex; + align-items: center; + white-space: nowrap; + width: 100%; + padding-left: 10px; + font: inherit; + font-size: ${bodyFontSize}; + user-select: none; + position: relative; + margin-inline-start: ${iconSize}; + } + + :host(${focusVisible}) .content-region { + outline: none; + } + + :host([disabled]) .content-region { + opacity: 0.5; + cursor: not-allowed; + } + + .expand-collapse-button { + background: none; + border: none; + outline: none; + width: ${iconSize}; + height: ${iconSize}; + padding: 0px; + justify-content: center; + align-items: center; + cursor: pointer; + margin-left: 10px; + position: absolute; + } + + .expand-collapse-button svg { + width: ${iconSize}; + height: ${iconSize}; + transition: transform 0.2s ease-in; + pointer-events: none; + fill: currentcolor; + } + + ${ + /* this rule keeps children without an icon text aligned with parents */ '' + } + span[part="start"] { + width: ${iconSize}; + } + + ${ + /* the start class is applied when the corresponding slots is filled */ '' + } + .start { + display: flex; + fill: currentcolor; + margin-inline-start: ${iconSize}; + margin-inline-end: ${iconSize}; + } + + slot[name='start']::slotted(*) { + width: ${iconSize}; + height: ${iconSize}; + } + + ::slotted(${DesignSystem.tagFor(TreeItem)}) { + --ni-private-tree-item-nested-width: 1em; + --ni-private-expand-collapse-button-nested-width: calc( + ${iconSize} * -1 + ); + } + + ${/* the end class is applied when the corresponding slots is filled */ ''} + .end { + display: flex; + fill: currentcolor; + margin-inline-start: ${iconSize}; + } + + .items { + display: none; + ${ + /* + * this controls the nested indentation (by affecting .positioning-region::before) + * it must minimally contain arithmetic with an em and a px value + * make it larger or shorter by changing the px value + */ '' + } + font-size: calc(1em + (${iconSize} * 2)); + } + + :host([expanded]) .items { + display: block; + } +` + // prettier-ignore .withBehaviors( new DirectionalStyleSheetBehavior( css` - ${/* ltr styles */ ''} - .expand-collapse-button { - left: var( - --ni-private-expand-collapse-button-nested-width, - calc(${iconSize} * -1) - ); - } - - .expand-collapse-button svg { - transform: rotate(90deg); - } - - :host([expanded]) .expand-collapse-button svg { - transform: rotate(180deg); - } - `, + ${/* ltr styles */ ''} + .expand-collapse-button { + left: var( + --ni-private-expand-collapse-button-nested-width, + calc(${iconSize} * -1) + ); + } + + .expand-collapse-button svg { + transform: rotate(90deg); + } + + :host([expanded]) .expand-collapse-button svg { + transform: rotate(180deg); + } + `, css` - ${/* rtl styles */ ''} - .expand-collapse-button { - right: var( - --ni-private-expand-collapse-button-nested-width, - calc(${iconSize} * -1) - ); - } - - .expand-collapse-button svg { - transform: rotate(180deg); - } - - :host([expanded]) .expand-collapse-button svg { - transform: rotate(135deg); - } - ` + ${/* rtl styles */ ''} + .expand-collapse-button { + right: var( + --ni-private-expand-collapse-button-nested-width, + calc(${iconSize} * -1) + ); + } + + .expand-collapse-button svg { + transform: rotate(180deg); + } + + :host([expanded]) .expand-collapse-button svg { + transform: rotate(135deg); + } + ` ) ); diff --git a/packages/nimble-components/src/utilities/tests/storybook.ts b/packages/nimble-components/src/utilities/tests/storybook.ts index 585a84c263..1389454cd0 100644 --- a/packages/nimble-components/src/utilities/tests/storybook.ts +++ b/packages/nimble-components/src/utilities/tests/storybook.ts @@ -1,5 +1,7 @@ import { html, ViewTemplate } from '@microsoft/fast-element'; +import { DesignSystem } from '@microsoft/fast-foundation'; import type { Story } from '@storybook/html'; +import { ThemeProvider } from '../../theme-provider'; import type { Theme } from '../../theme-provider/types'; import { createMatrix } from './matrix'; import { @@ -57,12 +59,12 @@ export const createUserSelectedThemeStory = ( ): Story => { return (source: TSource, context: unknown): Element => { const wrappedViewTemplate = html` - ${viewTemplate} - + `; const fragment = renderViewTemplate(wrappedViewTemplate, source); const content = fragment.firstElementChild!; @@ -81,7 +83,7 @@ export const createFixedThemeStory = ( ): Story => { return (source: TSource, _context: unknown): Element => { const wrappedViewTemplate = html` - @@ -97,7 +99,7 @@ export const createFixedThemeStory = ( > ${viewTemplate}
- + `; const fragment = renderViewTemplate(wrappedViewTemplate, source); const content = fragment.firstElementChild!; @@ -114,11 +116,12 @@ export const createMatrixThemeStory = ( return (source: TSource, _context: unknown): Element => { const matrixTemplate = createMatrix( ({ theme, value }: BackgroundState) => html` - + <${DesignSystem.tagFor(ThemeProvider)} + theme="${theme}">
${viewTemplate}
-
+ `, [backgroundStates] ); From 81b34c3604671734b4cd97ebb4a6810903c76c42 Mon Sep 17 00:00:00 2001 From: rajsite Date: Tue, 6 Sep 2022 11:22:38 -0500 Subject: [PATCH 23/43] breadcrumb angular --- .../breadcrumb/nimble-breadcrumb.directive.ts | 13 +- .../tests/nimble-breadcrumb.directive.spec.ts | 166 ++++++++++++++++++ .../combobox/nimble-combobox.module.ts | 1 + .../list-option/nimble-list-option.module.ts | 3 +- .../nimble-number-field.module.ts | 1 + .../text-area/nimble-text-area.module.ts | 1 + .../text-field/nimble-text-field.module.ts | 1 + .../ni/nimble-angular/src/public-api.ts | 4 +- 8 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/tests/nimble-breadcrumb.directive.spec.ts diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/nimble-breadcrumb.directive.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/nimble-breadcrumb.directive.ts index 8110f8b8f7..c51d339daa 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/nimble-breadcrumb.directive.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/nimble-breadcrumb.directive.ts @@ -1,7 +1,9 @@ -import { Directive } from '@angular/core'; +import { Directive, ElementRef, Input, Renderer2 } from '@angular/core'; import type { Breadcrumb } from '@ni/nimble-components/dist/esm/breadcrumb'; +import { BreadcrumbAppearance } from '@ni/nimble-components/dist/esm/breadcrumb/types'; export type { Breadcrumb }; +export { BreadcrumbAppearance }; /** * Directive to provide Angular integration for the breadcrumb. @@ -10,4 +12,13 @@ export type { Breadcrumb }; selector: 'nimble-breadcrumb' }) export class NimbleBreadcrumbDirective { + public get appearance(): BreadcrumbAppearance { + return this.elementRef.nativeElement.appearance; + } + + @Input() public set appearance(value: BreadcrumbAppearance) { + this.renderer.setProperty(this.elementRef.nativeElement, 'appearance', value); + } + + public constructor(private readonly renderer: Renderer2, private readonly elementRef: ElementRef) {} } diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/tests/nimble-breadcrumb.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/tests/nimble-breadcrumb.directive.spec.ts new file mode 100644 index 0000000000..6d8a176310 --- /dev/null +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/breadcrumb/tests/nimble-breadcrumb.directive.spec.ts @@ -0,0 +1,166 @@ +import { Component, ElementRef, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Breadcrumb, BreadcrumbAppearance, NimbleBreadcrumbDirective } from '../nimble-breadcrumb.directive'; +import { NimbleBreadcrumbModule } from '../nimble-breadcrumb.module'; + +describe('Nimble breadcrumb', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [NimbleBreadcrumbModule] + }); + }); + + it('custom element is defined', () => { + expect(customElements.get('nimble-breadcrumb')).not.toBeUndefined(); + }); + + describe('with no values in template', () => { + @Component({ + template: ` + + ` + }) + class TestHostComponent { + @ViewChild('target', { read: NimbleBreadcrumbDirective }) public directive: NimbleBreadcrumbDirective; + @ViewChild('target', { read: ElementRef }) public elementRef: ElementRef; + } + + let fixture: ComponentFixture; + let directive: NimbleBreadcrumbDirective; + let nativeElement: Breadcrumb; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleBreadcrumbModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('has expected defaults for appearance', () => { + expect(directive.appearance).toBe(BreadcrumbAppearance.default); + expect(nativeElement.appearance).toBe(BreadcrumbAppearance.default); + }); + }); + + describe('with template string values', () => { + @Component({ + template: ` + + ` + }) + class TestHostComponent { + @ViewChild('target', { read: NimbleBreadcrumbDirective }) public directive: NimbleBreadcrumbDirective; + @ViewChild('target', { read: ElementRef }) public elementRef: ElementRef; + } + + let fixture: ComponentFixture; + let directive: NimbleBreadcrumbDirective; + let nativeElement: Breadcrumb; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleBreadcrumbModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('will use template string values for appearance', () => { + expect(directive.appearance).toBe(BreadcrumbAppearance.prominent); + expect(nativeElement.appearance).toBe(BreadcrumbAppearance.prominent); + }); + }); + + describe('with property bound values', () => { + @Component({ + template: ` + + + ` + }) + class TestHostComponent { + @ViewChild('target', { read: NimbleBreadcrumbDirective }) public directive: NimbleBreadcrumbDirective; + @ViewChild('target', { read: ElementRef }) public elementRef: ElementRef; + public appearance: BreadcrumbAppearance; + } + + let fixture: ComponentFixture; + let directive: NimbleBreadcrumbDirective; + let nativeElement: Breadcrumb; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleBreadcrumbModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('can be configured with property binding for appearance', () => { + expect(directive.appearance).toBe(BreadcrumbAppearance.default); + expect(nativeElement.appearance).toBe(BreadcrumbAppearance.default); + + fixture.componentInstance.appearance = BreadcrumbAppearance.prominent; + fixture.detectChanges(); + + expect(directive.appearance).toBe(BreadcrumbAppearance.prominent); + expect(nativeElement.appearance).toBe(BreadcrumbAppearance.prominent); + }); + }); + + describe('with attribute bound values', () => { + @Component({ + template: ` + + + ` + }) + class TestHostComponent { + @ViewChild('target', { read: NimbleBreadcrumbDirective }) public directive: NimbleBreadcrumbDirective; + @ViewChild('target', { read: ElementRef }) public elementRef: ElementRef; + public appearance: BreadcrumbAppearance; + } + + let fixture: ComponentFixture; + let directive: NimbleBreadcrumbDirective; + let nativeElement: Breadcrumb; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TestHostComponent], + imports: [NimbleBreadcrumbModule] + }); + fixture = TestBed.createComponent(TestHostComponent); + fixture.detectChanges(); + directive = fixture.componentInstance.directive; + nativeElement = fixture.componentInstance.elementRef.nativeElement; + }); + + it('can be configured with attribute binding for disabled', () => { + expect(directive.appearance).toBe(BreadcrumbAppearance.default); + expect(nativeElement.appearance).toBe(BreadcrumbAppearance.default); + + fixture.componentInstance.appearance = BreadcrumbAppearance.prominent; + fixture.detectChanges(); + + expect(directive.appearance).toBe(BreadcrumbAppearance.prominent); + expect(nativeElement.appearance).toBe(BreadcrumbAppearance.prominent); + }); + }); +}); diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.module.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.module.ts index e6b80f6e04..0bfb38dd5d 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.module.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/combobox/nimble-combobox.module.ts @@ -2,6 +2,7 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { NimbleComboboxDirective } from './nimble-combobox.directive'; import { NimbleComboboxControlValueAccessorDirective } from './nimble-combobox-control-value-accessor.directive'; + import '@ni/nimble-components/dist/esm/combobox'; @NgModule({ diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/list-option/nimble-list-option.module.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/list-option/nimble-list-option.module.ts index 4629303ee7..82583ee90f 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/list-option/nimble-list-option.module.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/list-option/nimble-list-option.module.ts @@ -1,10 +1,9 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { ListOption } from '@ni/nimble-components/dist/esm/list-option'; import { NimbleSelectListOptionDirective } from './nimble-select-list-option.directive'; import { NimbleComboboxListOptionDirective } from './nimble-combobox-list-option.directive'; -export type { ListOption }; +import '@ni/nimble-components/dist/esm/list-option'; @NgModule({ declarations: [NimbleSelectListOptionDirective, NimbleComboboxListOptionDirective], diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/nimble-number-field.module.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/nimble-number-field.module.ts index 5f9b1be319..233c35d0cd 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/nimble-number-field.module.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/number-field/nimble-number-field.module.ts @@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { NimbleNumberFieldDirective } from './nimble-number-field.directive'; import { NimbleNumberFieldControlValueAccessorDirective } from './nimble-number-field-control-value-accessor.directive'; + import '@ni/nimble-components/dist/esm/number-field'; @NgModule({ diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/text-area/nimble-text-area.module.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/text-area/nimble-text-area.module.ts index e355ef469d..e5ca6c2b03 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/text-area/nimble-text-area.module.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/text-area/nimble-text-area.module.ts @@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { NimbleTextAreaDirective } from './nimble-text-area.directive'; import { NimbleTextAreaControlValueAccessorDirective } from './nimble-text-area-control-value-accessor.directive'; + import '@ni/nimble-components/dist/esm/text-area'; @NgModule({ diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/nimble-text-field.module.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/nimble-text-field.module.ts index 2f7ff0a059..544b74db99 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/nimble-text-field.module.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/text-field/nimble-text-field.module.ts @@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { NimbleTextFieldDirective } from './nimble-text-field.directive'; import { NimbleTextFieldControlValueAccessorDirective } from './nimble-text-field-control-value-accessor.directive'; + import '@ni/nimble-components/dist/esm/text-field'; @NgModule({ diff --git a/angular-workspace/projects/ni/nimble-angular/src/public-api.ts b/angular-workspace/projects/ni/nimble-angular/src/public-api.ts index ec611307d3..3171ad320c 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/public-api.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/public-api.ts @@ -70,7 +70,9 @@ export * from './directives/tooltip/nimble-tooltip.directive'; export * from './directives/tooltip/nimble-tooltip.module'; export * from './testing/async-helpers'; -// Export enums that are used by multiple components here to avoid exporting them multiple times. +// Export items that would otherwise be exported by multiple components just from here to avoid exporting them multiple times. +// Can be cleaned up when switching to multiple entry points, see: https://github.com/ni/nimble/issues/172 export { ButtonAppearance } from '@ni/nimble-components/dist/esm/patterns/button/types'; export { DropdownAppearance } from '@ni/nimble-components/dist/esm/patterns/dropdown/types'; export { IconSeverity } from '@ni/nimble-components/dist/esm/icon-base/types'; +export type { ListOption } from '@ni/nimble-components/dist/esm/list-option'; From 32383c48e0e3fc79fd5b9615de4536720263fcf9 Mon Sep 17 00:00:00 2001 From: rajsite Date: Tue, 6 Sep 2022 12:20:08 -0500 Subject: [PATCH 24/43] button appearance-variant angular --- .../button/nimble-button.directive.ts | 16 +++++++- .../tests/nimble-button.directive.spec.ts | 41 ++++++++++++++++++- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/button/nimble-button.directive.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/button/nimble-button.directive.ts index 6c30121b0c..6170792abc 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/button/nimble-button.directive.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/button/nimble-button.directive.ts @@ -1,9 +1,11 @@ import { Directive, ElementRef, Input, Renderer2 } from '@angular/core'; import type { Button } from '@ni/nimble-components/dist/esm/button'; -import type { ButtonAppearance, ButtonType } from '@ni/nimble-components/dist/esm/button/types'; +import type { ButtonAppearance } from '@ni/nimble-components/dist/esm/button/types'; +import { ButtonType, ButtonAppearanceVariant } from '@ni/nimble-components/dist/esm/button/types'; import { BooleanValueOrAttribute, toBooleanProperty } from '../utilities/template-value-helpers'; -export type { Button, ButtonType }; +export type { Button }; +export { ButtonType, ButtonAppearanceVariant }; /** * Directive to provide Angular integration for the button. @@ -20,6 +22,16 @@ export class NimbleButtonDirective { this.renderer.setProperty(this.elementRef.nativeElement, 'appearance', value); } + public get appearanceVariant(): ButtonAppearanceVariant { + return this.elementRef.nativeElement.appearanceVariant; + } + + // appearanceVariant property intentionally maps to the appearance-variant attribute + // eslint-disable-next-line @angular-eslint/no-input-rename + @Input('appearance-variant') public set appearanceVariant(value: ButtonAppearanceVariant) { + this.renderer.setProperty(this.elementRef.nativeElement, 'appearanceVariant', value); + } + public get disabled(): boolean { return this.elementRef.nativeElement.disabled; } diff --git a/angular-workspace/projects/ni/nimble-angular/src/directives/button/tests/nimble-button.directive.spec.ts b/angular-workspace/projects/ni/nimble-angular/src/directives/button/tests/nimble-button.directive.spec.ts index b3490b0651..b9fb4bd51e 100644 --- a/angular-workspace/projects/ni/nimble-angular/src/directives/button/tests/nimble-button.directive.spec.ts +++ b/angular-workspace/projects/ni/nimble-angular/src/directives/button/tests/nimble-button.directive.spec.ts @@ -2,7 +2,7 @@ import { Component, ElementRef, ViewChild } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ButtonAppearance } from '../../../public-api'; import type { BooleanValueOrAttribute } from '../../utilities/template-value-helpers'; -import { Button, NimbleButtonDirective } from '../nimble-button.directive'; +import { Button, NimbleButtonDirective, ButtonAppearanceVariant } from '../nimble-button.directive'; import { NimbleButtonModule } from '../nimble-button.module'; describe('Nimble button', () => { @@ -54,6 +54,11 @@ describe('Nimble button', () => { expect(nativeElement.appearance).toBe(ButtonAppearance.outline); }); + it('has expected defaults for appearanceVariant', () => { + expect(directive.appearanceVariant).toBe(ButtonAppearanceVariant.default); + expect(nativeElement.appearanceVariant).toBe(ButtonAppearanceVariant.default); + }); + it('has expected defaults for contentHidden', () => { expect(directive.contentHidden).toBeFalse(); expect(nativeElement.contentHidden).toBeFalse(); @@ -65,7 +70,8 @@ describe('Nimble button', () => { template: ` ` }) @@ -99,6 +105,11 @@ describe('Nimble button', () => { expect(nativeElement.appearance).toBe(ButtonAppearance.ghost); }); + it('will use template string values for appearanceVariant', () => { + expect(directive.appearanceVariant).toBe(ButtonAppearanceVariant.primary); + expect(nativeElement.appearanceVariant).toBe(ButtonAppearanceVariant.primary); + }); + it('will use template string values for contentHidden', () => { expect(directive.contentHidden).toBeTrue(); expect(nativeElement.contentHidden).toBeTrue(); @@ -111,6 +122,7 @@ describe('Nimble button', () => { ` @@ -120,6 +132,7 @@ describe('Nimble button', () => { @ViewChild('button', { read: ElementRef }) public elementRef: ElementRef