-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## π€¨ Rationale Part of #1013 ## π©βπ» Implementation Created new `nimble-table-column-icon` component plus the supporting elements `nimble-mapping-icon` and `nimble-mapping-spinner`. Angular and Blazor support will be implemented in follow-on PRs. ## π§ͺ Testing Unit tests written for all new components. Tested in Storybook. ## β Checklist - [x] I have updated the project documentation to reflect my changes or determined no changes are needed. --------- Co-authored-by: Jonathan Meyer <[email protected]>
- Loading branch information
1 parent
04c76db
commit 4f0f474
Showing
37 changed files
with
1,574 additions
and
22 deletions.
There are no files selected for viewing
7 changes: 7 additions & 0 deletions
7
change/@ni-nimble-components-6bfc2c11-64d5-45f8-85b7-85d6afbf3d5f.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"type": "patch", | ||
"comment": "Icon table column", | ||
"packageName": "@ni/nimble-components", | ||
"email": "[email protected]", | ||
"dependentChangeType": "patch" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { attr, observable } from '@microsoft/fast-element'; | ||
import { DesignSystem } from '@microsoft/fast-foundation'; | ||
import { Mapping } from '../base'; | ||
import { template } from '../base/template'; | ||
import type { IconSeverity } from '../../icon-base/types'; | ||
import { Icon } from '../../icon-base'; | ||
|
||
declare global { | ||
interface HTMLElementTagNameMap { | ||
'nimble-mapping-icon': MappingIcon; | ||
} | ||
} | ||
|
||
function isIconClass(elementClass: CustomElementConstructor): boolean { | ||
return elementClass.prototype instanceof Icon; | ||
} | ||
|
||
/** | ||
* Maps a data value to an icon. | ||
* One or more may be added as children of a nimble-table-column-icon element to define | ||
* how specific data values should be displayed as icons in that column's cells. | ||
*/ | ||
export class MappingIcon extends Mapping { | ||
@attr() | ||
public icon?: string; | ||
|
||
@attr() | ||
public severity: IconSeverity; | ||
|
||
/** | ||
* @internal | ||
* Calculated asynchronously by the icon mapping based on the configured icon value. | ||
* When assigned, it corresponds to an element name that is resolved to type of Nimble Icon. | ||
*/ | ||
@observable | ||
public resolvedIcon?: string; | ||
|
||
// Allow icons to be defined asynchronously from when the property is configured | ||
private async resolveIconAsync(icon: string): Promise<void> { | ||
try { | ||
// Clear the current resolution while waiting for async resolution | ||
this.resolvedIcon = undefined; | ||
await customElements.whenDefined(icon); | ||
} catch (ex) { | ||
// If any error (i.e. invalid custom element name) don't continue | ||
// Don't update the resolvedIcon as it was already set to undefined before async resolution | ||
// (in case other async resolutions were started) | ||
return; | ||
} | ||
|
||
if (icon !== this.icon) { | ||
// Possible the icon has changed while waiting for async resolution | ||
// Don't update the resolvedIcon as it was already set to undefined before async resolution | ||
// (in case other async resolutions were started) | ||
return; | ||
} | ||
|
||
const elementClass = customElements.get(icon)!; | ||
this.resolvedIcon = isIconClass(elementClass) ? icon : undefined; | ||
} | ||
|
||
private iconChanged(): void { | ||
const icon = this.icon; | ||
if (!icon) { | ||
this.resolvedIcon = undefined; | ||
return; | ||
} | ||
const elementClass = customElements.get(icon); | ||
if (elementClass) { | ||
this.resolvedIcon = isIconClass(elementClass) ? icon : undefined; | ||
return; | ||
} | ||
void this.resolveIconAsync(icon); | ||
} | ||
} | ||
|
||
const iconMapping = MappingIcon.compose({ | ||
baseName: 'mapping-icon', | ||
template | ||
}); | ||
DesignSystem.getOrCreate().withPrefix('nimble').register(iconMapping()); | ||
export const mappingIconTag = DesignSystem.tagFor(MappingIcon); |
53 changes: 53 additions & 0 deletions
53
packages/nimble-components/src/mapping/icon/tests/mapping-icon.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { html } from '@microsoft/fast-element'; | ||
import { MappingIcon, mappingIconTag } from '..'; | ||
import { | ||
fixture, | ||
uniqueElementName, | ||
type Fixture | ||
} from '../../../utilities/tests/fixture'; | ||
import { waitForUpdatesAsync } from '../../../testing/async-helpers'; | ||
import { Icon, registerIcon } from '../../../icon-base'; | ||
|
||
describe('Icon Mapping', () => { | ||
const testIconElementName = uniqueElementName(); | ||
class TestIcon extends Icon {} | ||
|
||
let element: MappingIcon; | ||
let connect: () => Promise<void>; | ||
let disconnect: () => Promise<void>; | ||
|
||
// prettier-ignore | ||
async function setup(): Promise<Fixture<MappingIcon>> { | ||
return fixture<MappingIcon>(html` | ||
<${mappingIconTag} | ||
key="foo" | ||
text="foo" | ||
icon="nimble-${testIconElementName}"> | ||
</${mappingIconTag}>`); | ||
} | ||
|
||
it('should export its tag', () => { | ||
expect(mappingIconTag).toBe('nimble-mapping-icon'); | ||
}); | ||
|
||
it('can construct an element instance', () => { | ||
expect(document.createElement('nimble-mapping-icon')).toBeInstanceOf( | ||
MappingIcon | ||
); | ||
}); | ||
|
||
it('resolves icon after it is defined', async () => { | ||
({ element, connect, disconnect } = await setup()); | ||
await connect(); | ||
await waitForUpdatesAsync(); | ||
|
||
expect(element.resolvedIcon).toBeUndefined(); | ||
|
||
registerIcon(testIconElementName, TestIcon); | ||
await waitForUpdatesAsync(); | ||
|
||
expect(element.resolvedIcon).toBeDefined(); | ||
|
||
await disconnect(); | ||
}); | ||
}); |
43 changes: 43 additions & 0 deletions
43
packages/nimble-components/src/mapping/icon/tests/mapping-icon.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { html } from '@microsoft/fast-element'; | ||
import type { Meta, StoryObj } from '@storybook/html'; | ||
import { createUserSelectedThemeStory } from '../../../utilities/tests/storybook'; | ||
import { hiddenWrapper } from '../../../utilities/tests/hidden'; | ||
import { mappingKeyDescription } from '../../base/tests/story-helpers'; | ||
|
||
const metadata: Meta = { | ||
title: 'Internal/Mappings', | ||
parameters: { | ||
docs: { | ||
description: { | ||
component: | ||
'The `nimble-mapping-icon` element defines a mapping from a data value to an icon representation to use for that value. It is meant to be used as content of the `nimble-table-column-icon` element.' | ||
} | ||
} | ||
} | ||
}; | ||
|
||
export default metadata; | ||
|
||
export const iconMapping: StoryObj = { | ||
render: createUserSelectedThemeStory(hiddenWrapper(html`<style></style>`)), | ||
argTypes: { | ||
key: { | ||
description: mappingKeyDescription('the mapped icon'), | ||
control: { type: 'none' } | ||
}, | ||
icon: { | ||
control: { type: 'none' }, | ||
description: | ||
'The tag name of the Nimble icon to render, e.g. `nimble-icon-check`.' | ||
}, | ||
severity: { | ||
description: | ||
'Must be one of the values in the `IconSeverity` enum. Controls the color of the icon.' | ||
}, | ||
text: { | ||
description: | ||
'A textual description of the value which will be used as the tooltip and accessible name of the icon. The text is also displayed next to the icon in a group header. This attribute is required.' | ||
} | ||
}, | ||
args: {} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { DesignSystem } from '@microsoft/fast-foundation'; | ||
import { Mapping } from '../base'; | ||
import { template } from '../base/template'; | ||
|
||
declare global { | ||
interface HTMLElementTagNameMap { | ||
'nimble-mapping-spinner': MappingSpinner; | ||
} | ||
} | ||
|
||
/** | ||
* Maps data values to a spinner. | ||
* One or more may be added as children of a nimble-table-column-icon element to define | ||
* which specific data values should be displayed as spinners in that column's cells. | ||
*/ | ||
export class MappingSpinner extends Mapping {} | ||
|
||
const spinnerMapping = MappingSpinner.compose({ | ||
baseName: 'mapping-spinner', | ||
template | ||
}); | ||
DesignSystem.getOrCreate().withPrefix('nimble').register(spinnerMapping()); | ||
export const mappingSpinnerTag = DesignSystem.tagFor(MappingSpinner); |
13 changes: 13 additions & 0 deletions
13
packages/nimble-components/src/mapping/spinner/tests/mapping-spinner.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { MappingSpinner, mappingSpinnerTag } from '..'; | ||
|
||
describe('Spinner Mapping', () => { | ||
it('should export its tag', () => { | ||
expect(mappingSpinnerTag).toBe('nimble-mapping-spinner'); | ||
}); | ||
|
||
it('can construct an element instance', () => { | ||
expect(document.createElement('nimble-mapping-spinner')).toBeInstanceOf( | ||
MappingSpinner | ||
); | ||
}); | ||
}); |
34 changes: 34 additions & 0 deletions
34
packages/nimble-components/src/mapping/spinner/tests/mapping-spinner.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { html } from '@microsoft/fast-element'; | ||
import type { Meta, StoryObj } from '@storybook/html'; | ||
import { createUserSelectedThemeStory } from '../../../utilities/tests/storybook'; | ||
import { hiddenWrapper } from '../../../utilities/tests/hidden'; | ||
import { mappingKeyDescription } from '../../base/tests/story-helpers'; | ||
|
||
const metadata: Meta = { | ||
title: 'Internal/Mappings', | ||
parameters: { | ||
docs: { | ||
description: { | ||
component: | ||
'The `nimble-mapping-spinner` element defines a mapping from a data value to the Nimble spinner. It is meant to be used as content of the `nimble-table-column-icon` element.' | ||
} | ||
} | ||
} | ||
}; | ||
|
||
export default metadata; | ||
|
||
export const spinnerMapping: StoryObj = { | ||
render: createUserSelectedThemeStory(hiddenWrapper(html`<style></style>`)), | ||
argTypes: { | ||
key: { | ||
description: mappingKeyDescription('a spinner'), | ||
control: { type: 'none' } | ||
}, | ||
text: { | ||
description: | ||
'A textual description of the value which will be used as the tooltip and accessible name of the spinner. The text is also displayed next to the spinner in a group header. This attribute is required.' | ||
} | ||
}, | ||
args: {} | ||
}; |
13 changes: 13 additions & 0 deletions
13
packages/nimble-components/src/mapping/text/tests/mapping-text.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { MappingText, mappingTextTag } from '..'; | ||
|
||
describe('Text Mapping', () => { | ||
it('should export its tag', () => { | ||
expect(mappingTextTag).toBe('nimble-mapping-text'); | ||
}); | ||
|
||
it('can construct an element instance', () => { | ||
expect(document.createElement('nimble-mapping-text')).toBeInstanceOf( | ||
MappingText | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
packages/nimble-components/src/table-column/enum-base/models/mapping-icon-config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { html, type ViewTemplate } from '@microsoft/fast-element'; | ||
import type { IconSeverity } from '../../../icon-base/types'; | ||
import { MappingConfig } from './mapping-config'; | ||
|
||
export interface IconView { | ||
severity: IconSeverity; | ||
text?: string; | ||
} | ||
const createIconTemplate = (icon: string): ViewTemplate<IconView> => html` | ||
<${icon} | ||
title="${x => x.text}" | ||
aria-label="${x => x.text}" | ||
severity="${x => x.severity}" | ||
class="no-shrink" | ||
> | ||
</${icon}>`; | ||
|
||
/** | ||
* Mapping configuration corresponding to a icon mapping | ||
*/ | ||
export class MappingIconConfig extends MappingConfig { | ||
public readonly iconTemplate: ViewTemplate<IconView>; | ||
public constructor( | ||
resolvedIcon: string, | ||
public readonly severity: IconSeverity, | ||
text: string | undefined | ||
) { | ||
super(text); | ||
this.iconTemplate = createIconTemplate(resolvedIcon); | ||
} | ||
} |
Oops, something went wrong.