@ogds/elements 1.0.0-alpha.6 → 1.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/.storybook/{UswdsTheme.js → OgdsTheme.js} +1 -1
  2. package/.storybook/manager.js +2 -2
  3. package/.storybook/preview.js +2 -2
  4. package/.storybook/worker.js +5 -0
  5. package/README.md +39 -136
  6. package/dist/components/frameworks/react/{UsaLink.d.ts → OGDSAlert.d.ts} +15 -14
  7. package/dist/components/frameworks/react/OGDSAlert.js +23 -0
  8. package/dist/components/frameworks/react/OgdsAccordionToggle.d.ts +4 -6
  9. package/dist/components/frameworks/react/OgdsAccordionToggle.js +1 -3
  10. package/dist/components/frameworks/react/{UsaBanner.d.ts → OgdsBanner.d.ts} +9 -9
  11. package/dist/components/frameworks/react/{UsaBanner.js → OgdsBanner.js} +3 -3
  12. package/dist/components/frameworks/react/OgdsTaskList.d.ts +48 -0
  13. package/dist/components/frameworks/react/{UsaLink.js → OgdsTaskList.js} +4 -7
  14. package/dist/components/frameworks/react/index.d.ts +3 -2
  15. package/dist/components/frameworks/react/index.js +3 -2
  16. package/dist/components/index.cjs +15 -1
  17. package/dist/components/index.cjs.map +1 -1
  18. package/dist/components/index.d.ts +4 -3
  19. package/dist/components/index.js +162 -4
  20. package/dist/components/index.js.map +1 -1
  21. package/dist/components/ogds-accordion/index.d.ts +36 -0
  22. package/dist/components/ogds-accordion/ogds-accordion.spec.d.ts +1 -0
  23. package/dist/components/ogds-accordion-toggle/index.d.ts +25 -0
  24. package/dist/components/ogds-accordion-toggle/ogds-accordion-toggle.spec.d.ts +1 -0
  25. package/dist/components/ogds-alert/index.d.ts +21 -0
  26. package/dist/components/{usa-banner → ogds-banner}/index.d.ts +7 -7
  27. package/dist/components/ogds-banner.cjs +1 -0
  28. package/dist/components/ogds-banner.cjs.map +1 -0
  29. package/dist/components/ogds-banner.js +7 -0
  30. package/dist/components/ogds-banner.js.map +1 -0
  31. package/dist/components/task-list/index.d.ts +21 -0
  32. package/dist/core/token-styles.d.ts +1 -0
  33. package/dist/index-CC1QRihN.cjs +95 -0
  34. package/dist/index-CC1QRihN.cjs.map +1 -0
  35. package/dist/{components/usa-banner.js → index-DDf2o6Dk.js} +34 -28
  36. package/dist/index-DDf2o6Dk.js.map +1 -0
  37. package/dist/types/custom-element-jsx.d.ts +32 -22
  38. package/dist/types/custom-element-solidjs.d.ts +39 -27
  39. package/dist/types/custom-element-svelte.d.ts +32 -22
  40. package/dist/types/custom-element-vuejs.d.ts +32 -22
  41. package/package.json +44 -29
  42. package/src/Globals.d.ts +3 -0
  43. package/src/components/index.ts +3 -3
  44. package/src/components/ogds-accordion/docs.mdx +31 -20
  45. package/src/components/ogds-accordion/ogds-accordion.stories.ts +12 -0
  46. package/src/components/ogds-accordion-toggle/docs.mdx +54 -0
  47. package/src/components/ogds-accordion-toggle/index.ts +38 -11
  48. package/src/components/ogds-accordion-toggle/ogds-accordion-toggle.css +31 -0
  49. package/src/components/ogds-accordion-toggle/ogds-accordion-toggle.spec.ts +227 -0
  50. package/src/components/ogds-accordion-toggle/ogds-accordion-toggle.stories.ts +95 -0
  51. package/src/components/ogds-alert/base-variables.css +496 -0
  52. package/src/components/ogds-alert/index.ts +78 -0
  53. package/src/components/ogds-alert/ogds-alert.css +119 -0
  54. package/src/components/ogds-alert/ogds-alert.stories.ts +75 -0
  55. package/src/components/{usa-banner → ogds-banner}/docs.mdx +1 -10
  56. package/src/components/{usa-banner → ogds-banner}/index.ts +17 -15
  57. package/src/components/{usa-banner/usa-banner.spec.ts → ogds-banner/ogds-banner.spec.ts} +5 -5
  58. package/src/components/{usa-banner/usa-banner.stories.ts → ogds-banner/ogds-banner.stories.ts} +2 -2
  59. package/src/components/task-list/docs.mdx +23 -0
  60. package/src/components/task-list/index.ts +65 -0
  61. package/src/components/task-list/ogds-task-list.css +34 -0
  62. package/src/components/task-list/ogds-task-list.stories.ts +46 -0
  63. package/src/core/token-styles.ts +2 -0
  64. package/src/declaration.d.ts +5 -0
  65. package/storybook/contributing.mdx +1 -110
  66. package/storybook/framework-guidance.mdx +5 -5
  67. package/storybook/readme.mdx +1 -1
  68. package/dist/components/usa-banner/usa-banner.stories.d.ts +0 -95
  69. package/dist/components/usa-banner.cjs +0 -95
  70. package/dist/components/usa-banner.cjs.map +0 -1
  71. package/dist/components/usa-banner.js.map +0 -1
  72. package/dist/components/usa-header/index.d.ts +0 -6
  73. package/dist/components/usa-link/index.d.ts +0 -30
  74. package/dist/components/usa-link/usa-link.spec.d.ts +0 -0
  75. package/dist/components/usa-link.cjs +0 -5
  76. package/dist/components/usa-link.cjs.map +0 -1
  77. package/dist/components/usa-link.js +0 -32
  78. package/dist/components/usa-link.js.map +0 -1
  79. package/dist/core/OgdsElement.d.ts +0 -3
  80. package/dist/index-7kIMQwBw.cjs +0 -1
  81. package/dist/index-7kIMQwBw.cjs.map +0 -1
  82. package/dist/index-BrHk1-6T.js +0 -10
  83. package/dist/index-BrHk1-6T.js.map +0 -1
  84. package/src/components/ogds-accordion/.claude/settings.local.json +0 -7
  85. package/src/components/usa-header/index.ts +0 -50
  86. package/src/components/usa-header/usa-header.css +0 -1
  87. package/src/components/usa-link/index.ts +0 -66
  88. package/src/components/usa-link/usa-link.css +0 -24
  89. package/src/components/usa-link/usa-link.spec.ts +0 -50
  90. /package/dist/components/{usa-banner/usa-banner.spec.d.ts → ogds-banner/ogds-banner.spec.d.ts} +0 -0
  91. /package/src/components/{usa-banner/usa-banner.css → ogds-banner/ogds-banner.css} +0 -0
@@ -51,13 +51,20 @@ type OgdsAccordionProps = {
51
51
  type OgdsAccordionToggleProps = {
52
52
  /** The `id` of the `<ogds-accordion>` to control. Required. */
53
53
  controls?: string;
54
- /** Button label when all panels are collapsed. Defaults to "Expand All". */
55
- "expand-label"?: string;
56
- /** Button label when one or more panels are open. Defaults to "Collapse All". */
57
- "collapse-label"?: string;
58
54
  };
59
55
 
60
- type UsaBannerProps = {
56
+ type OGDSAlertProps = {
57
+ /** The type of alert (info, warning, etc) */
58
+ type?: string;
59
+ /** Use this attribute to hide the icon */
60
+ noIcon?: string;
61
+ /** */
62
+ "no-icon"?: boolean;
63
+ /** */
64
+ "bind:_headingNodes"?: Node[];
65
+ };
66
+
67
+ type OgdsBannerProps = {
61
68
  /** The element's language. */
62
69
  lang?: "en" | "es";
63
70
  /** The custom aria label users can override. */
@@ -70,10 +77,7 @@ type UsaBannerProps = {
70
77
  isOpen?: boolean;
71
78
  };
72
79
 
73
- type UsaLinkProps = {
74
- /** The url for the link */
75
- href?: string | undefined;
76
- };
80
+ type OgdsTaskListProps = {};
77
81
 
78
82
  export type CustomElements = {
79
83
  /**
@@ -103,13 +107,28 @@ export type CustomElements = {
103
107
  * ---
104
108
  *
105
109
  *
110
+ * ### **Slots:**
111
+ * - **expand-label** - Button label when all panels are collapsed. Defaults to "Expand All".
112
+ * - **collapse-label** - Button label when one or more panels are open. Defaults to "Collapse All".
113
+ *
106
114
  * ### **CSS Parts:**
107
115
  * - **button** - The toggle button.
108
116
  */
109
117
  "ogds-accordion-toggle": Partial<OgdsAccordionToggleProps & BaseProps & BaseEvents>;
110
118
 
111
119
  /**
112
- * The usa-banner component.
120
+ * The ogds-alert component.
121
+ * ---
122
+ *
123
+ *
124
+ * ### **Slots:**
125
+ * - **heading** - Text for the heading. Make sure to specify the correct heading level (h2, h3, etc)
126
+ * - **body** - Body content for the alert. Can contain HTML (links, etc).
127
+ */
128
+ "ogds-alert": Partial<OGDSAlertProps & BaseProps & BaseEvents>;
129
+
130
+ /**
131
+ * The ogds-banner component.
113
132
  * ---
114
133
  *
115
134
  *
@@ -132,23 +151,14 @@ export type CustomElements = {
132
151
  * - **--ogds-banner-link-hover-color** - Sets the default link color. _(default: undefined)_
133
152
  * - **--ogds-banner-text-color** - Sets the default text color. _(default: undefined)_
134
153
  */
135
- "usa-banner": Partial<UsaBannerProps & BaseProps & BaseEvents>;
154
+ "ogds-banner": Partial<OgdsBannerProps & BaseProps & BaseEvents>;
136
155
 
137
156
  /**
138
- * The usa-link component.
139
- * ---
140
157
  *
158
+ * ---
141
159
  *
142
- * ### **Slots:**
143
- * - _default_ - This element has a slot
144
- *
145
- * ### **CSS Properties:**
146
- * - **--theme-link-color** - Sets the link color _(default: undefined)_
147
- * - **--theme-link-visited-color** - Sets the color for visited links _(default: undefined)_
148
- * - **--theme-link-hover-color** - Sets the hover state link color _(default: undefined)_
149
- * - **--theme-link-active-color** - Sets the active state link color _(default: undefined)_
150
160
  */
151
- "usa-link": Partial<UsaLinkProps & BaseProps & BaseEvents>;
161
+ "ogds-task-list": Partial<OgdsTaskListProps & BaseProps & BaseEvents>;
152
162
  };
153
163
 
154
164
  declare namespace svelteHTML {
@@ -14,13 +14,20 @@ type OgdsAccordionProps = {
14
14
  type OgdsAccordionToggleProps = {
15
15
  /** The `id` of the `<ogds-accordion>` to control. Required. */
16
16
  controls?: string;
17
- /** Button label when all panels are collapsed. Defaults to "Expand All". */
18
- "expand-label"?: string;
19
- /** Button label when one or more panels are open. Defaults to "Collapse All". */
20
- "collapse-label"?: string;
21
17
  };
22
18
 
23
- type UsaBannerProps = {
19
+ type OGDSAlertProps = {
20
+ /** The type of alert (info, warning, etc) */
21
+ type?: string;
22
+ /** Use this attribute to hide the icon */
23
+ noIcon?: string;
24
+ /** */
25
+ "no-icon"?: boolean;
26
+ /** */
27
+ _headingNodes?: Node[];
28
+ };
29
+
30
+ type OgdsBannerProps = {
24
31
  /** The element's language. */
25
32
  lang?: "en" | "es";
26
33
  /** The custom aria label users can override. */
@@ -33,10 +40,7 @@ type UsaBannerProps = {
33
40
  isOpen?: boolean;
34
41
  };
35
42
 
36
- type UsaLinkProps = {
37
- /** The url for the link */
38
- href?: string | undefined;
39
- };
43
+ type OgdsTaskListProps = {};
40
44
 
41
45
  export type CustomElements = {
42
46
  /**
@@ -66,13 +70,28 @@ export type CustomElements = {
66
70
  * ---
67
71
  *
68
72
  *
73
+ * ### **Slots:**
74
+ * - **expand-label** - Button label when all panels are collapsed. Defaults to "Expand All".
75
+ * - **collapse-label** - Button label when one or more panels are open. Defaults to "Collapse All".
76
+ *
69
77
  * ### **CSS Parts:**
70
78
  * - **button** - The toggle button.
71
79
  */
72
80
  "ogds-accordion-toggle": DefineComponent<OgdsAccordionToggleProps>;
73
81
 
74
82
  /**
75
- * The usa-banner component.
83
+ * The ogds-alert component.
84
+ * ---
85
+ *
86
+ *
87
+ * ### **Slots:**
88
+ * - **heading** - Text for the heading. Make sure to specify the correct heading level (h2, h3, etc)
89
+ * - **body** - Body content for the alert. Can contain HTML (links, etc).
90
+ */
91
+ "ogds-alert": DefineComponent<OGDSAlertProps>;
92
+
93
+ /**
94
+ * The ogds-banner component.
76
95
  * ---
77
96
  *
78
97
  *
@@ -95,23 +114,14 @@ export type CustomElements = {
95
114
  * - **--ogds-banner-link-hover-color** - Sets the default link color. _(default: undefined)_
96
115
  * - **--ogds-banner-text-color** - Sets the default text color. _(default: undefined)_
97
116
  */
98
- "usa-banner": DefineComponent<UsaBannerProps>;
117
+ "ogds-banner": DefineComponent<OgdsBannerProps>;
99
118
 
100
119
  /**
101
- * The usa-link component.
102
- * ---
103
120
  *
121
+ * ---
104
122
  *
105
- * ### **Slots:**
106
- * - _default_ - This element has a slot
107
- *
108
- * ### **CSS Properties:**
109
- * - **--theme-link-color** - Sets the link color _(default: undefined)_
110
- * - **--theme-link-visited-color** - Sets the color for visited links _(default: undefined)_
111
- * - **--theme-link-hover-color** - Sets the hover state link color _(default: undefined)_
112
- * - **--theme-link-active-color** - Sets the active state link color _(default: undefined)_
113
123
  */
114
- "usa-link": DefineComponent<UsaLinkProps>;
124
+ "ogds-task-list": DefineComponent<OgdsTaskListProps>;
115
125
  };
116
126
 
117
127
  declare module "vue" {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ogds/elements",
3
- "version": "1.0.0-alpha.6",
3
+ "version": "1.0.0-alpha.8",
4
4
  "type": "module",
5
5
  "customElements": "custom-elements.json",
6
6
  "types": "./dist/index.d.ts",
@@ -37,11 +37,16 @@
37
37
  "dev": "vite --config ./config/vite.config.ts",
38
38
  "fix-permissions": "sudo chown -R $(id -u):$(id -g) .",
39
39
  "pages": "npm run storybook:build && cp -r storybook-static _site",
40
+ "playwright:install": "playwright install --with-deps",
41
+ "playwright:test": "playwright test --config=./config/playwright.config.ts",
42
+ "playwright:update-screenshots": "playwright test --config=./config/playwright.config.ts --update-snapshots",
40
43
  "prepare": "husky",
41
- "prettier:js": "npx prettier --check '**/*.{cjs,css,js,json,jsx,mjs,ts,tsx}' --config ./config/.prettierrc",
42
- "prettier:js:fix": "npx prettier --write '**/*.{cjs,css,js,json,jsx,mjs,ts,tsx}' --config ./config/.prettierrc",
43
- "prettier:md": "npx prettier --check '**/*.{md,mdx}' --config ./config/.prettierrc",
44
- "prettier:md:fix": "npx prettier --write '**/*.{md,mdx}' --config ./config/.prettierrc",
44
+ "prettier:js": "prettier --check '**/*.{cjs,css,js,json,jsx,mjs,ts,tsx}' --config ./config/.prettierrc",
45
+ "prettier:js:fix": "prettier --write '**/*.{cjs,css,js,json,jsx,mjs,ts,tsx}' --config ./config/.prettierrc",
46
+ "prettier:md": "prettier --check '**/*.{md,mdx}' --config ./config/.prettierrc",
47
+ "prettier:md:fix": "prettier --write '**/*.{md,mdx}' --config ./config/.prettierrc",
48
+ "prettier:github": "prettier --check '.github' --config ./config/.prettierrc",
49
+ "prettier:github:fix": "prettier --write '.github' --config ./config/.prettierrc",
45
50
  "start": "npm run storybook & npm run manifest:watch",
46
51
  "storybook:build": "storybook build",
47
52
  "storybook": "storybook dev -p 8008",
@@ -49,8 +54,8 @@
49
54
  "storybook:serve": "node ./internals/scripts/serve-storybook.js",
50
55
  "stylelint": "stylelint './src/components/**/*.{css,css.js,css.ts}' --config=./config/stylelint.config.mjs",
51
56
  "stylelint:fix": "stylelint './src/components/**/*.{css,css.js,css.ts}' --fix --config=./config/stylelint.config.mjs",
52
- "manifest:build": "npx cem analyze --config ./config/custom-elements-manifest.config.js",
53
- "manifest:watch": "npx cem analyze --config ./config/custom-elements-manifest.config.js --watch --dev",
57
+ "manifest:build": "cem analyze --config ./config/custom-elements-manifest.config.js",
58
+ "manifest:watch": "cem analyze --config ./config/custom-elements-manifest.config.js --watch --dev",
54
59
  "release": "npm run build && changeset publish",
55
60
  "test": "vitest --config ./config/vitest.config.js",
56
61
  "test:ci": "vitest run --config ./config/vitest.config.js",
@@ -66,54 +71,64 @@
66
71
  "devDependencies": {
67
72
  "@changesets/cli": "^2.29.8",
68
73
  "@custom-elements-manifest/analyzer": "^0.11.0",
69
- "@eslint/css": "^1.1.0",
74
+ "@eslint/css": "^1.2.0",
70
75
  "@eslint/js": "^10.0.1",
71
- "@playwright/test": "^1.58.2",
72
- "@storybook/addon-a11y": "^10.2.10",
73
- "@storybook/addon-docs": "^10.2.10",
74
- "@storybook/addon-links": "^10.2.10",
75
- "@storybook/test-runner": "^0.24.2",
76
- "@storybook/web-components-vite": "^10.2.10",
76
+ "@playwright/test": "^1.60.0",
77
+ "@storybook/addon-a11y": "^10.3.6",
78
+ "@storybook/addon-docs": "^10.3.6",
79
+ "@storybook/addon-links": "^10.3.6",
80
+ "@storybook/test-runner": "^0.24.3",
81
+ "@storybook/web-components-vite": "^10.3.6",
77
82
  "@types/express": "^5.0.6",
78
- "@types/node": "^25.3.3",
83
+ "@types/node": "^25.6.0",
79
84
  "@types/serve-static": "^2.2.0",
80
- "@vitest/eslint-plugin": "^1.6.10",
81
- "@vitest/ui": "^4.0.18",
82
- "@wc-toolkit/storybook-helpers": "^10.2.0",
85
+ "@vitest/eslint-plugin": "^1.6.16",
86
+ "@vitest/ui": "^4.1.8",
87
+ "@wc-toolkit/storybook-helpers": "^10.3.0",
83
88
  "axe-playwright": "^2.2.2",
84
89
  "browserslist": "^4.28.1",
85
- "concurrently": "^9.2.1",
90
+ "concurrently": "^10.0.3",
86
91
  "custom-element-jsx-integration": "^1.6.0",
87
92
  "custom-element-react-wrappers": "^1.7.3",
88
93
  "custom-element-solidjs-integration": "^1.9.0",
89
94
  "custom-element-svelte-integration": "^1.2.0",
90
95
  "custom-element-vuejs-integration": "^1.4.0",
91
96
  "custom-elements-manifest": "^2.1.0",
92
- "eslint": "^10.0.3",
97
+ "eslint": "^10.3.0",
93
98
  "eslint-config-prettier": "^10.1.8",
94
- "eslint-plugin-storybook": "10.2.10",
99
+ "eslint-plugin-storybook": "10.3.6",
95
100
  "express": "^5.2.1",
96
101
  "husky": "^9.1.7",
97
- "jsdom": "^28.1.0",
102
+ "jsdom": "^29.1.1",
98
103
  "lightningcss": "^1.31.1",
99
- "prettier": "^3.8.1",
104
+ "prettier": "^3.8.3",
100
105
  "serve-static": "^2.2.1",
101
106
  "shadow-dom-testing-library": "^1.13.1",
102
107
  "storybook": "^10.0.7",
103
- "storybook-addon-tag-badges": "^3.0.6",
104
- "stylelint": "^17.4.0",
108
+ "storybook-addon-tag-badges": "^3.1.0",
109
+ "stylelint": "^17.10.0",
105
110
  "stylelint-config-standard": "^40.0.0",
106
- "stylelint-order": "^8.0.0",
107
- "typescript": "^5.9.3",
111
+ "stylelint-order": "^8.1.1",
112
+ "typescript": "^6.0.3",
108
113
  "vite": "^7.3.1",
109
114
  "vite-plugin-bundlesize": "^0.3.0",
110
115
  "vite-plugin-dts": "^4.5.4",
111
116
  "vite-plugin-lit-css": "^2.2.2",
112
117
  "vitest": "^4.0.8",
113
- "wait-on": "^9.0.4",
114
- "web-vitals": "^5.1.0"
118
+ "wait-on": "^9.0.10",
119
+ "web-vitals": "^5.3.0"
115
120
  },
116
121
  "optionalDependencies": {
117
122
  "@rollup/rollup-linux-x64-gnu": "^4.59.0"
123
+ },
124
+ "allowScripts": {
125
+ "esbuild@0.25.9": true,
126
+ "esbuild@0.27.3": true,
127
+ "@parcel/watcher@2.5.1": true,
128
+ "@swc/core@1.13.5": true,
129
+ "fsevents@2.3.3": true,
130
+ "fsevents@2.3.2": true,
131
+ "unrs-resolver@1.11.1": true,
132
+ "rs-module-lexer@2.6.0": true
118
133
  }
119
134
  }
@@ -0,0 +1,3 @@
1
+ declare module "*.css";
2
+ declare module "*.png";
3
+ declare module "*.svg";
@@ -1,5 +1,5 @@
1
- import { UsaLink } from "./usa-link";
2
- import { UsaBanner } from "./usa-banner";
1
+ import { OgdsBanner } from "./ogds-banner";
3
2
  import { OgdsAccordion } from "./ogds-accordion";
3
+ import { OgdsAccordionToggle } from "./ogds-accordion-toggle";
4
4
 
5
- export { UsaLink, UsaBanner, OgdsAccordion };
5
+ export { OgdsBanner, OgdsAccordion, OgdsAccordionToggle };
@@ -4,41 +4,41 @@ import { Meta, Title, Primary, Stories } from "@storybook/addon-docs/blocks";
4
4
 
5
5
  <Title />
6
6
 
7
- Accordions show and hide sections of related content on a page.
7
+ See also: [USWDS Accessibility Checklist for Accordion](https://designsystem.digital.gov/components/accordion/accessibility-tests/).
8
8
 
9
- ---
10
-
11
- ## Default
9
+ Accordions show and hide sections of related content on a page. This component can be used without JavaScript (see [Fallbacks Without JavaScript](#fallbacks-without-javascript)).
12
10
 
13
- <Primary />
11
+ ## Differences between the OGDS Accordion and USWDS Accordion
14
12
 
15
- ---
13
+ - The OGDS implementation uses [the browser-native `<details>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/details), which works even when JavaScript is not available.
14
+ - The OGDS implementation allows for the icon to be on the left or the right.
15
+ - The OGDS implementation allows for the icon itself to be customized.
16
16
 
17
- ## Variations
17
+ ## Example Accordion
18
18
 
19
- <Stories />
19
+ <Primary />
20
20
 
21
21
  ## Guidance
22
22
 
23
23
  ### When to use the accordion component
24
24
 
25
- _To organize related content._ Accordions can help reduce page length when there are multiple sections of content that users may not need to read in full.
25
+ **To organize related content.** Accordions can help reduce page length when there are multiple sections of content that users may not need to read in full.
26
26
 
27
- _To let users get to relevant content faster._ Accordions keep a page focused by allowing users to choose what they read rather than having to scroll past large amounts of content.
27
+ **To let users get to relevant content faster.** Accordions keep a page focused by allowing users to choose what they read rather than having to scroll past large amounts of content.
28
28
 
29
29
  ### When to consider something else
30
30
 
31
- _If users need most or all of the content._ If users are likely to need most of the content on a page, showing it all at once may be more helpful than hiding it behind an accordion.
31
+ **If users need most or all of the content.** If users are likely to need most of the content on a page, showing it all at once may be more helpful than hiding it behind an accordion.
32
32
 
33
- _For critical information._ Avoid using accordions to hide important content that all users should see, as users may miss it.
33
+ **For critical information.** Avoid using accordions to hide important content that all users should see, as users may miss it.
34
34
 
35
35
  ### Usability guidance
36
36
 
37
- _Use clear, descriptive labels._ The summary text should clearly describe the content within. Users should be able to decide whether to expand a section based on the label alone.
37
+ **Use clear, descriptive labels.** The summary text should clearly describe the content within. Users should be able to decide whether to expand a section based on the label alone.
38
38
 
39
- _Use icons to reinforce state._ Add the `with-icon` class to provide a visual indicator of open and closed state. Use `with-icon right` to align the icon to the trailing edge of the summary, or `with-icon plus` to use plus/minus icons instead of chevrons.
39
+ **Use icons to reinforce state.** Add the `with-icon` class to provide a visual indicator of open and closed state. Use `with-icon right` to align the icon to the trailing edge of the summary, or `with-icon plus` to use plus/minus icons instead of chevrons.
40
40
 
41
- _Use `bordered` for visual separation._ Add the `bordered` class when the accordion needs stronger visual separation from surrounding content.
41
+ **Use `bordered` for visual separation.** Add the `bordered` class when the accordion needs stronger visual separation from surrounding content.
42
42
 
43
43
  #### Built-in `<details>` element functionality
44
44
 
@@ -71,13 +71,20 @@ Depending on the kind of content in the accordion, you may want to add some ARIA
71
71
  1. **Heading semantics.** The USWDS accordion uses heading elements inside the buttons that toggle the sections. If you want to follow this pattern, you can add a `heading-level=<Number>` attribute to the opening `<ogds-accordion>` tag, and it will automatically set the correct ARIA attributes on each of the child `<summary>` tags to set the heading at the level you tell it. As always, it is important to use the right heading level to preserve the document outline. Even if you are not using the web component version of the component, you can achieve this same effect by including a heading element inside the summary tag, though this may require a little extra CSS to keep the visual appearance consistent.
72
72
  2. **List semantics.** If the content in the accordion makes more sense as a list, adding a `use-list-semantics` attribute to the `<ogds-accordion>` tag will add the correct ARIA.
73
73
 
74
- ### Web component usage
74
+ ## Custom Element vs CSS-Only Versions
75
75
 
76
- The stories above show how to use the accordion web component. This component uses all light DOM (no shadow DOM). That means that it's up to you to add the required markup inside the `<ogds-accordion>` tag. As shown, it only needs at least one `details` element.
76
+ ### Custom Element Behavior
77
77
 
78
- ### CSS-only usage
78
+ The examples on this page use the cusom element `<ogds-accordion></ogds-accordion>`. This custom element uses all light DOM (no [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM)). This custom element is used for styling, and it makes it easy to access the icon variations. [Custom elements](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements) have been [widely supported since 2020](https://caniuse.com/wf-autonomous-custom-elements), but do require JavaScript for some of their functionality.
79
79
 
80
- The accordion component can be used without JavaScript by applying the styles in `ogds-accordion.css` directly to your page. If using the icon variants, you must set the following custom properties to point to your own icon assets:
80
+ ### Fallbacks without JavaScript
81
+
82
+ If a user does not have JavaScript for any reason, this component will still generally work.
83
+
84
+ 1. **Native details component.** This approach uses the browser-native `<details>` component, these can be opened in closed without JavaScript in all browsers that support this feature ([widely available since January 2020](https://caniuse.com/details)). In an even older browser, the accordions would all be open by default, so content would not be hidden.
85
+ 2. **Styles.** As long as you have the accordion styles pulled into your application's styles, the visual styling will still work without JavaScript.
86
+ 3. **Class-based equivalent.** You can optionally substitute `<div class="ogds-accordion">` in place of `<ogds-accordion>`. These are equivalent, and will not affect styling or behavior for this component.
87
+ 4. **Icons.** If you are using non-default icons and you also want those to work witohut JavaScript, then you can update your project's CSS styles to point to the svg files:
81
88
 
82
89
  ```css
83
90
  ogds-accordion,
@@ -87,4 +94,8 @@ ogds-accordion,
87
94
  }
88
95
  ```
89
96
 
90
- Even if you are not using the web component JavaScript, the CSS will work on a `<ogds-accordion>` tag. However, if you'd prefer to stick with built-in elements, all of the above will also work on a `<div class="ogds-accordion">`.
97
+ ---
98
+
99
+ ## More Examples
100
+
101
+ <Stories />
@@ -75,3 +75,15 @@ export const WithPlusIconsBordered = {
75
75
  >${items}</ogds-accordion
76
76
  >`,
77
77
  };
78
+
79
+ export const WithPlusIconsRight = {
80
+ render: () =>
81
+ html`<ogds-accordion class="with-icon plus right"
82
+ >${items}</ogds-accordion
83
+ >`,
84
+ };
85
+
86
+ export const WithPlusIconsRightWithoutCustomElement = {
87
+ render: () =>
88
+ html`<div class="ogds-accordion with-icon plus right">${items}</div>`,
89
+ };
@@ -0,0 +1,54 @@
1
+ import { Meta, Title, Primary, Stories } from "@storybook/addon-docs/blocks";
2
+
3
+ <Meta isTemplate />
4
+
5
+ <Title />
6
+
7
+ The accordion toggle provides a single button to expand or collapse all panels in an associated `<ogds-accordion>`.
8
+
9
+ ---
10
+
11
+ ## Default
12
+
13
+ <Primary />
14
+
15
+ ---
16
+
17
+ ## Variations
18
+
19
+ <Stories />
20
+
21
+ ## Guidance
22
+
23
+ ### When to use the accordion toggle
24
+
25
+ _When accordions have many items._ The toggle is most useful when an accordion has more than two or three items, where expanding each individually would be tedious and users may want to scan all of the content at once.
26
+
27
+ _For cross-browser in-page search._ `Cmd-/Ctrl-F` will find content in collapsed accordion sections and open the relevant sections in Chrome and Chromium-based browsers. However, as of now this behavior is limited to only those browsers (see ["Auto-opens when matched via page search"](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/details#browser_compatibility)). Adding the toggle button will allow users to search all of the accordion content in any browser.
28
+
29
+ _To support users looking to print the page content._ Let users display all of the page's content so it can be printed.
30
+
31
+ ### Usage
32
+
33
+ Connect the toggle to an accordion using the `controls` attribute, which must match the `id` of the target `<ogds-accordion>`:
34
+
35
+ ```html
36
+ <ogds-accordion-toggle controls="my-accordion"></ogds-accordion-toggle>
37
+ <ogds-accordion id="my-accordion">
38
+ <details>
39
+ <summary>Item One</summary>
40
+ <p>Content</p>
41
+ </details>
42
+ </ogds-accordion>
43
+ ```
44
+
45
+ ### Customizing labels
46
+
47
+ By default, the button reads "Expand All" when all panels are collapsed and "Collapse All" when any panel is open. Override these with the `expand-label` and `collapse-label` named slots:
48
+
49
+ ```html
50
+ <ogds-accordion-toggle controls="my-accordion">
51
+ <span slot="expand-label">Show All</span>
52
+ <span slot="collapse-label">Hide All</span>
53
+ </ogds-accordion-toggle>
54
+ ```
@@ -3,34 +3,43 @@ import { adoptTokenStyles } from "../../core/token-styles";
3
3
  import { defineCustomElement } from "../../utils";
4
4
 
5
5
  import { property, state } from "lit/decorators.js";
6
+ import styles from "./ogds-accordion-toggle.css";
6
7
 
7
8
  /**
8
9
  * @summary A button that expands or collapses all panels in an associated `<ogds-accordion>`.
9
10
  *
10
11
  * @attribute {string} controls - The `id` of the `<ogds-accordion>` to control. Required.
11
- * @attribute {string} expand-label - Button label when all panels are collapsed. Defaults to "Expand All".
12
- * @attribute {string} collapse-label - Button label when one or more panels are open. Defaults to "Collapse All".
12
+ *
13
+ * @slot expand-label - Button label when all panels are collapsed. Defaults to "Expand All".
14
+ * @slot collapse-label - Button label when one or more panels are open. Defaults to "Collapse All".
13
15
  *
14
16
  * @csspart button - The toggle button.
15
17
  *
16
18
  * @element ogds-accordion-toggle
17
19
  */
18
20
  export class OgdsAccordionToggle extends LitElement {
21
+ /** @ignore */
22
+ private static _sheet: CSSStyleSheet | null = null;
23
+
19
24
  @property({ type: String, attribute: "controls" })
20
25
  controls = "";
21
26
 
22
- @property({ type: String, attribute: "expand-label" })
23
- expandLabel = "Expand All";
24
-
25
- @property({ type: String, attribute: "collapse-label" })
26
- collapseLabel = "Collapse All";
27
-
28
27
  @state()
29
28
  private _anyOpen = false;
30
29
 
30
+ private _observer: MutationObserver | null = null;
31
+
31
32
  override connectedCallback() {
32
33
  super.connectedCallback();
33
-
34
+ adoptTokenStyles();
35
+ if (!OgdsAccordionToggle._sheet) {
36
+ OgdsAccordionToggle._sheet = new CSSStyleSheet();
37
+ OgdsAccordionToggle._sheet.replaceSync(styles.cssText);
38
+ document.adoptedStyleSheets = [
39
+ ...document.adoptedStyleSheets,
40
+ OgdsAccordionToggle._sheet,
41
+ ];
42
+ }
34
43
  if (this.controls == "") {
35
44
  console.error(
36
45
  "<ogds-accordion-toggle>: Component must have a controls attribute with the ID" +
@@ -39,7 +48,22 @@ export class OgdsAccordionToggle extends LitElement {
39
48
  return;
40
49
  }
41
50
  this._anyOpen = this.checkOpen();
42
- adoptTokenStyles();
51
+ this._observer = new MutationObserver(() => {
52
+ this._anyOpen = this.checkOpen();
53
+ });
54
+ const accordionEl = document.getElementById(this.controls);
55
+ if (accordionEl) {
56
+ this._observer.observe(accordionEl, {
57
+ subtree: true,
58
+ attributeFilter: ["open"],
59
+ });
60
+ }
61
+ }
62
+
63
+ override disconnectedCallback() {
64
+ super.disconnectedCallback();
65
+ this._observer?.disconnect();
66
+ this._observer = null;
43
67
  }
44
68
 
45
69
  checkOpen() {
@@ -71,7 +95,10 @@ export class OgdsAccordionToggle extends LitElement {
71
95
  protected override render(): unknown {
72
96
  return html`
73
97
  <button @click="${this.toggleAll}" part="button">
74
- ${this._anyOpen ? this.collapseLabel : this.expandLabel}
98
+ <slot name="expand-label" ?hidden="${this._anyOpen}">Expand All</slot>
99
+ <slot name="collapse-label" ?hidden="${!this._anyOpen}"
100
+ >Collapse All</slot
101
+ >
75
102
  </button>
76
103
  `;
77
104
  }
@@ -0,0 +1,31 @@
1
+ @layer ogds.components;
2
+
3
+ @layer ogds.components {
4
+ ogds-accordion-toggle::part(button) {
5
+ appearance: none;
6
+ background-color: var(--ogds-theme-button-fill-color);
7
+ border-color: transparent;
8
+ border-radius: var(--ogds-theme-button-border-radius);
9
+ border-width: var(--ogds-theme-button-stroke-width);
10
+ color: var(--ogds-theme-button-text-color);
11
+ cursor: pointer;
12
+ font-family: var(--ogds-theme-button-font-family);
13
+ font-size: var(--ogds-theme-type-scale-md);
14
+ font-weight: 700;
15
+ padding: var(--ogds-spacing-105) var(--ogds-spacing-205);
16
+
17
+ &:hover {
18
+ background-color: color-mix(
19
+ in srgb,
20
+ var(--ogds-theme-button-fill-color),
21
+ black 20%
22
+ );
23
+ }
24
+
25
+ &:focus {
26
+ /* :not([disabled]) doesn't seem to be supported on shadow parts */
27
+ outline: rgb(36 145 255) solid 0.25rem;
28
+ outline-offset: 0.25rem;
29
+ }
30
+ }
31
+ }