From a686d09dab4cf40548448ccdc7e050d6322afb24 Mon Sep 17 00:00:00 2001 From: Melanie Boeckmann Date: Thu, 14 Mar 2024 10:11:37 -0700 Subject: [PATCH] feat: set allowed values for grid tag property to limit misuse (#470) --- packages/web/src/components.d.ts | 20 +++++++++- .../src/components/gcds-grid/gcds-grid.tsx | 37 ++++++++++++++++++- .../gcds-grid/stories/gcds-grid.stories.tsx | 27 +++++++++++++- .../components/gcds-grid/stories/overview.mdx | 6 +++ .../gcds-grid/test/gcds-grid.spec.ts | 18 +++++++++ 5 files changed, 103 insertions(+), 5 deletions(-) diff --git a/packages/web/src/components.d.ts b/packages/web/src/components.d.ts index 8d45a0832..67db172a0 100644 --- a/packages/web/src/components.d.ts +++ b/packages/web/src/components.d.ts @@ -483,7 +483,15 @@ export namespace Components { /** * Set tag for grid container */ - "tag"?: string; + "tag"?: | 'article' + | 'aside' + | 'div' + | 'dl' + | 'main' + | 'nav' + | 'ol' + | 'section' + | 'ul'; } interface GcdsGridCol { /** @@ -2287,7 +2295,15 @@ declare namespace LocalJSX { /** * Set tag for grid container */ - "tag"?: string; + "tag"?: | 'article' + | 'aside' + | 'div' + | 'dl' + | 'main' + | 'nav' + | 'ol' + | 'section' + | 'ul'; } interface GcdsGridCol { /** diff --git a/packages/web/src/components/gcds-grid/gcds-grid.tsx b/packages/web/src/components/gcds-grid/gcds-grid.tsx index b1fd235f9..76bb8c2e5 100644 --- a/packages/web/src/components/gcds-grid/gcds-grid.tsx +++ b/packages/web/src/components/gcds-grid/gcds-grid.tsx @@ -1,4 +1,4 @@ -import { Component, Element, Host, Prop, h } from '@stencil/core'; +import { Component, Element, Host, Watch, Prop, h } from '@stencil/core'; export type ContentValues = | 'center' @@ -53,7 +53,35 @@ export class GcdsGrid { /** * Set tag for grid container */ - @Prop() tag?: string = 'div'; + @Prop({ mutable: true }) tag?: + | 'article' + | 'aside' + | 'div' + | 'dl' + | 'main' + | 'nav' + | 'ol' + | 'section' + | 'ul' = 'div'; + + @Watch('tag') + validateTag(newValue: string) { + const values = [ + 'article', + 'aside', + 'div', + 'dl', + 'main', + 'nav', + 'ol', + 'section', + 'ul', + ]; + + if (!values.includes(newValue)) { + this.tag = 'div'; + } + } /** * If total grid size is less than the size of its grid container, @@ -87,6 +115,11 @@ export class GcdsGrid { */ @Prop() placeItems?: 'center' | 'end' | 'start' | 'stretch'; + componentWillLoad() { + // Validate attributes and set defaults + this.validateTag(this.tag); + } + render() { const { alignContent, diff --git a/packages/web/src/components/gcds-grid/stories/gcds-grid.stories.tsx b/packages/web/src/components/gcds-grid/stories/gcds-grid.stories.tsx index e3d61c3d5..ee23fac74 100644 --- a/packages/web/src/components/gcds-grid/stories/gcds-grid.stories.tsx +++ b/packages/web/src/components/gcds-grid/stories/gcds-grid.stories.tsx @@ -52,7 +52,18 @@ export default { }, }, tag: { - control: 'text', + control: { type: 'select' }, + options: [ + 'article', + 'aside', + 'div', + 'dl', + 'main', + 'nav', + 'ol', + 'section', + 'ul', + ], table: { type: { summary: 'string' }, defaultValue: { summary: 'div' }, @@ -323,6 +334,20 @@ Individual.args = { default: 'This is some example content to display the grid component.', }; +// ------ Grid tag ------ + +export const Tag = Template.bind({}); +Tag.args = { + columns: 'repeat(auto-fit, minmax(100px, 250px))', + columnsDesktop: '', + columnsTablet: '', + container: 'full', + tag: 'article', + default: `

This is some example content to display the grid component.

+

This is some example content to display the grid component.

+

This is some example content to display the grid component.

`, +}; + // ------ Grid events & props ------ export const Props = Template.bind({}); diff --git a/packages/web/src/components/gcds-grid/stories/overview.mdx b/packages/web/src/components/gcds-grid/stories/overview.mdx index 58847cd36..8bb0fcc5b 100644 --- a/packages/web/src/components/gcds-grid/stories/overview.mdx +++ b/packages/web/src/components/gcds-grid/stories/overview.mdx @@ -61,6 +61,12 @@ Use the `columns-desktop` property to define your layout for larger screens **(6 +### Tag + +Always use the tag in a standard way to maintain accessibility. + + + ## Resources {/* prettier-ignore */} diff --git a/packages/web/src/components/gcds-grid/test/gcds-grid.spec.ts b/packages/web/src/components/gcds-grid/test/gcds-grid.spec.ts index 3ef3f047b..8974f13c1 100644 --- a/packages/web/src/components/gcds-grid/test/gcds-grid.spec.ts +++ b/packages/web/src/components/gcds-grid/test/gcds-grid.spec.ts @@ -55,4 +55,22 @@ describe('gcds-grid', () => { `); }); + + it('renders - div when passed an invalid tag value', async () => { + const { root } = await newSpecPage({ + components: [GcdsGrid], + html: ` + + `, + }); + expect(root).toEqualHtml(` + + +
+ +
+
+
+ `); + }); });