@brad-frost-web/eddie-web-components 0.18.0 → 0.19.0

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 (145) hide show
  1. package/.storybook/components/system-docs/system-docs.stories.ts +3 -3
  2. package/.storybook/components/tier-2-tokens/colors.ts +43 -0
  3. package/.storybook/components/tier-2-tokens/tier-2-tokens.scss +47 -0
  4. package/.storybook/main.ts +1 -1
  5. package/.storybook/pages/homepage/homepage.ts +6 -6
  6. package/README.md +37 -25
  7. package/cdn/eddie-autoloader.ts +197 -0
  8. package/cdn/eddie.ts +100 -0
  9. package/components/accordion/accordion.stories.ts +14 -0
  10. package/components/accordion/accordion.ts +16 -2
  11. package/components/accordion-panel/accordion-panel.ts +14 -1
  12. package/components/alert/alert.stories.ts +23 -0
  13. package/components/alert/alert.ts +20 -4
  14. package/components/badge/badge.stories.ts +23 -0
  15. package/components/badge/badge.ts +13 -10
  16. package/components/band/band.stories.ts +22 -0
  17. package/components/band/band.ts +16 -8
  18. package/components/box/box.stories.ts +12 -0
  19. package/components/box/box.ts +9 -1
  20. package/components/breadcrumbs/breadcrumbs.stories.ts +14 -0
  21. package/components/breadcrumbs/breadcrumbs.ts +25 -1
  22. package/components/breadcrumbs-item/breadcrumbs-item.ts +17 -1
  23. package/components/button/button.stories.ts +71 -0
  24. package/components/button/button.ts +16 -5
  25. package/components/button-group/button-group.stories.ts +18 -0
  26. package/components/button-group/button-group.ts +21 -3
  27. package/components/card/card.stories.ts +14 -0
  28. package/components/card/card.ts +21 -3
  29. package/components/checkbox-field/checkbox-field.stories.ts +24 -0
  30. package/components/checkbox-field/checkbox-field.ts +17 -1
  31. package/components/counter/counter.ts +2 -6
  32. package/components/drawer/drawer.stories.ts +25 -0
  33. package/components/drawer/drawer.ts +24 -3
  34. package/components/file-upload/file-upload.stories.ts +23 -0
  35. package/components/file-upload/file-upload.ts +31 -1
  36. package/components/footer/footer.stories.ts +16 -0
  37. package/components/footer/footer.ts +22 -3
  38. package/components/grid/grid.stories.ts +66 -0
  39. package/components/grid/grid.ts +37 -29
  40. package/components/grid-item/grid-item.ts +9 -1
  41. package/components/header/header.stories.ts +95 -0
  42. package/components/header/header.ts +10 -1
  43. package/components/heading/heading.stories.ts +88 -2
  44. package/components/heading/heading.ts +16 -36
  45. package/components/hr/hr.stories.ts +18 -0
  46. package/components/hr/hr.ts +17 -7
  47. package/components/icon/icon.stories.ts +18 -0
  48. package/components/icon/icon.ts +23 -14
  49. package/components/key-value-table/key-value-table.stories.ts +22 -0
  50. package/components/key-value-table/key-value-table.ts +19 -1
  51. package/components/key-value-table-row/key-value-table-row.ts +11 -0
  52. package/components/layout/layout.stories.ts +73 -0
  53. package/components/layout/layout.ts +34 -28
  54. package/components/layout-container/layout-container.stories.ts +19 -0
  55. package/components/layout-container/layout-container.ts +13 -5
  56. package/components/layout-section/layout-section.ts +22 -9
  57. package/components/link-list/link-list.stories.ts +41 -0
  58. package/components/link-list/link-list.ts +29 -1
  59. package/components/link-list-item/link-list-item.ts +18 -1
  60. package/components/list/list.stories.ts +17 -0
  61. package/components/list/list.ts +14 -14
  62. package/components/list-item/list-item.ts +18 -1
  63. package/components/loading-indicator/loading-indicator.stories.ts +24 -0
  64. package/components/loading-indicator/loading-indicator.ts +17 -1
  65. package/components/logo/logo.stories.ts +20 -0
  66. package/components/logo/logo.ts +17 -2
  67. package/components/main/main.stories.ts +13 -0
  68. package/components/main/main.ts +17 -1
  69. package/components/modal/modal.stories.ts +14 -0
  70. package/components/modal/modal.ts +23 -3
  71. package/components/nav-container/nav-container.stories.ts +12 -0
  72. package/components/nav-container/nav-container.ts +25 -1
  73. package/components/page-header/page-header.stories.ts +14 -0
  74. package/components/page-header/page-header.ts +19 -1
  75. package/components/pagination/pagination.stories.ts +28 -0
  76. package/components/pagination/pagination.ts +36 -1
  77. package/components/pagination-item/pagination-item.ts +25 -1
  78. package/components/primary-nav/primary-nav.stories.ts +19 -0
  79. package/components/primary-nav/primary-nav.ts +20 -1
  80. package/components/primary-nav-item/primary-nav-item.ts +19 -1
  81. package/components/radio-field/radio-field.stories.ts +24 -0
  82. package/components/radio-field/radio-field.ts +17 -1
  83. package/components/search-form/search-form.stories.ts +14 -0
  84. package/components/search-form/search-form.ts +19 -1
  85. package/components/section/section.stories.ts +20 -0
  86. package/components/section/section.ts +9 -2
  87. package/components/select-field/select-field.stories.ts +23 -0
  88. package/components/select-field/select-field.ts +21 -1
  89. package/components/show-hide/show-hide.stories.ts +10 -0
  90. package/components/show-hide/show-hide.ts +19 -5
  91. package/components/show-more/show-more.stories.ts +9 -0
  92. package/components/show-more/show-more.ts +19 -1
  93. package/components/skeleton/skeleton.ts +5 -5
  94. package/components/tab/tab.ts +12 -1
  95. package/components/table/table.stories.ts +42 -0
  96. package/components/table/table.ts +17 -2
  97. package/components/table-body/table-body.ts +4 -1
  98. package/components/table-cell/table-cell.ts +10 -6
  99. package/components/table-header/table-header.ts +4 -1
  100. package/components/table-header-cell/table-header-cell.ts +7 -2
  101. package/components/table-row/table-row.ts +4 -1
  102. package/components/tabs/tabs.stories.ts +21 -0
  103. package/components/tabs/tabs.ts +24 -1
  104. package/components/tag/tag.stories.ts +38 -0
  105. package/components/tag/tag.ts +23 -4
  106. package/components/tag-list/tag-list.stories.ts +13 -0
  107. package/components/tag-list/tag-list.ts +18 -1
  108. package/components/text-field/text-field.stories.ts +22 -0
  109. package/components/text-field/text-field.ts +24 -6
  110. package/components/text-link/text-link.stories.ts +18 -0
  111. package/components/text-link/text-link.ts +28 -17
  112. package/components/text-passage/text-passage.stories.ts +37 -0
  113. package/components/text-passage/text-passage.ts +26 -12
  114. package/components/textarea-field/textarea-field.stories.ts +35 -0
  115. package/components/textarea-field/textarea-field.ts +15 -1
  116. package/components/toast/toast.stories.ts +30 -0
  117. package/components/toast/toast.ts +20 -4
  118. package/components/toggle/toggle.stories.ts +43 -0
  119. package/components/toggle/toggle.ts +18 -2
  120. package/components/toolbar/toolbar.stories.ts +19 -0
  121. package/components/toolbar/toolbar.ts +20 -2
  122. package/components/tooltip/tooltip.stories.ts +19 -0
  123. package/components/tooltip/tooltip.ts +14 -1
  124. package/custom-elements.json +341 -203
  125. package/package.json +3 -3
  126. package/plopfile.cjs +2 -27
  127. package/vite.config.cdn.ts +93 -0
  128. package/.storybook/recipes/example-form/example-form.scss +0 -12
  129. package/.storybook/recipes/example-form/example-form.stories.ts +0 -10
  130. package/.storybook/recipes/example-form/example-form.ts +0 -152
  131. package/.storybook/recipes/promo-block/promo-block.scss +0 -24
  132. package/.storybook/recipes/promo-block/promo-block.stories.ts +0 -10
  133. package/.storybook/recipes/promo-block/promo-block.ts +0 -49
  134. package/.storybook/recipes/site-footer/site-footer.scss +0 -49
  135. package/.storybook/recipes/site-footer/site-footer.stories.ts +0 -9
  136. package/.storybook/recipes/site-footer/site-footer.ts +0 -57
  137. package/.storybook/recipes/site-header/site-header.scss +0 -58
  138. package/.storybook/recipes/site-header/site-header.stories.ts +0 -9
  139. package/.storybook/recipes/site-header/site-header.ts +0 -196
  140. package/docs/CODE_GUIDELINES.md +0 -492
  141. package/docs/THEMING.md +0 -5
  142. package/docs/TOKENS.md +0 -54
  143. package/plop-templates/recipe/recipe.scss.hbs +0 -12
  144. package/plop-templates/recipe/recipe.stories.ts.hbs +0 -10
  145. package/plop-templates/recipe/recipe.ts.hbs +0 -41
@@ -1,8 +1,8 @@
1
1
  import '@brad-frost-web/eddie-web-components/components/layout-container/layout-container';
2
2
  import MarkdownIt from 'markdown-it';
3
- import Code from '../../../docs/CODE_GUIDELINES.md?raw';
4
- import ThemingDocus from '../../../docs/THEMING.md?raw';
5
- import TokenDocs from '../../../docs/TOKENS.md?raw';
3
+ import Code from '../../../../../docs/CODE_GUIDELINES.md?raw';
4
+ import ThemingDocus from '../../../../../docs/THEMING.md?raw';
5
+ import TokenDocs from '../../../../../docs/TOKENS.md?raw';
6
6
  import './system-docs';
7
7
 
8
8
  export default {
@@ -66,6 +66,10 @@ export class Tier2Colors extends LitElement {
66
66
  return filtered;
67
67
  }
68
68
 
69
+ getAccentNumbers() {
70
+ return [1, 2, 3, 4, 5, 6, 7, 8];
71
+ }
72
+
69
73
  render() {
70
74
  return html`<ed-section>
71
75
  <ed-heading slot="header" tagName="h2" variant="headline-lg">Background Colors</ed-heading>
@@ -145,6 +149,45 @@ export class Tier2Colors extends LitElement {
145
149
  </ed-grid>
146
150
  </ed-grid-item>
147
151
  </ed-grid>
152
+ </ed-section>
153
+
154
+ <ed-section>
155
+ <ed-heading slot="header" tagName="h2" variant="headline-lg">On-Accent Token Demos</ed-heading>
156
+ <ed-text-passage slot="header">
157
+ <p>Each accent background is paired with its <code>on-accent</code> content and border tokens to ensure proper contrast. The background uses <code>--ed-theme-color-background-accent-N</code>, the text uses <code>--ed-theme-color-content-on-accent-N</code>, and the inner border uses <code>--ed-theme-color-border-on-accent-N</code>.</p>
158
+ </ed-text-passage>
159
+ <ed-grid>
160
+ <ed-grid-item>
161
+ <ed-grid variant="1-3up">
162
+ ${this.getAccentNumbers().map((n) => {
163
+ const bgToken = `--ed-theme-color-background-accent-${n}`;
164
+ const contentToken = `--ed-theme-color-content-on-accent-${n}`;
165
+ const borderToken = `--ed-theme-color-border-on-accent-${n}`;
166
+ return html`
167
+ <ed-grid-item>
168
+ <div class="on-accent-demo">
169
+ <div class="on-accent-demo__swatch" style="background-color: var(${bgToken}); padding: 1.5rem;">
170
+ <div class="on-accent-demo__inner" style="border: 3px solid var(${borderToken}); padding: 1rem; border-radius: 4px;">
171
+ <p class="on-accent-demo__text" style="color: var(${contentToken}); margin: 0; font-weight: 700;">
172
+ On Accent ${n}
173
+ </p>
174
+ <p class="on-accent-demo__subtext" style="color: var(${contentToken}); margin: 0.25rem 0 0; font-size: 0.875rem; opacity: 0.85;">
175
+ Content and border contrast
176
+ </p>
177
+ </div>
178
+ </div>
179
+ <div class="on-accent-demo__info">
180
+ <code class="on-accent-demo__token">bg: ${bgToken}</code>
181
+ <code class="on-accent-demo__token">content: ${contentToken}</code>
182
+ <code class="on-accent-demo__token">border: ${borderToken}</code>
183
+ </div>
184
+ </div>
185
+ </ed-grid-item>
186
+ `;
187
+ })}
188
+ </ed-grid>
189
+ </ed-grid-item>
190
+ </ed-grid>
148
191
  </ed-section>`;
149
192
  }
150
193
  }
@@ -13,3 +13,50 @@ ul {
13
13
  li {
14
14
  margin-block-end: 1rem;
15
15
  }
16
+
17
+ /**
18
+ * On-accent demo styles
19
+ */
20
+ .on-accent-demo {
21
+ border: 1px solid var(--ed-theme-color-border-subtle);
22
+ overflow: hidden;
23
+ }
24
+
25
+ .on-accent-demo__swatch {
26
+ min-height: 6rem;
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: center;
30
+ }
31
+
32
+ .on-accent-demo__inner {
33
+ width: 100%;
34
+ }
35
+
36
+ .on-accent-demo__text {
37
+ font-family: var(--ed-theme-typography-label-default-font-family, sans-serif);
38
+ font-size: 1.125rem;
39
+ }
40
+
41
+ .on-accent-demo__subtext {
42
+ font-family: var(--ed-theme-typography-body-sm-font-family, sans-serif);
43
+ }
44
+
45
+ .on-accent-demo__info {
46
+ padding: 0.75rem;
47
+ display: flex;
48
+ flex-direction: column;
49
+ gap: 0.25rem;
50
+ }
51
+
52
+ .on-accent-demo__token {
53
+ display: block;
54
+ font-size: 0.75rem;
55
+ background: rgb(242, 242, 242);
56
+ color: rgb(235, 87, 87);
57
+ padding: 0.15rem 0.3rem;
58
+ border-radius: 3px;
59
+ white-space: nowrap;
60
+ overflow: hidden;
61
+ text-overflow: ellipsis;
62
+ }
@@ -4,8 +4,8 @@ const config: StorybookConfig = {
4
4
  stories: [
5
5
  './components/**/*.stories.@(js|jsx|ts|tsx|mdx)',
6
6
  '../components/**/*.stories.@(js|jsx|mjs|ts|tsx)',
7
- './recipes/**/*.stories.@(js|jsx|mjs|ts|tsx)',
8
7
  './pages/**/*.stories.@(js|jsx|mjs|ts|tsx)',
8
+ '../../eddie-recipes/recipes/**/*.stories.@(js|jsx|mjs|ts|tsx)',
9
9
  ],
10
10
  addons: ['@chromatic-com/storybook', '@storybook/addon-docs', '@storybook/addon-themes', '@storybook/addon-a11y', '@storybook/addon-vitest'],
11
11
  framework: {
@@ -9,9 +9,9 @@ import '../../../components/layout-container/layout-container';
9
9
  import '../../../components/main/main';
10
10
  import '../../../components/page-header/page-header';
11
11
  import '../../../components/text-passage/text-passage';
12
- import '../../recipes/promo-block/promo-block';
13
- import '../../recipes/site-footer/site-footer';
14
- import '../../recipes/site-header/site-header';
12
+ import '@brad-frost-web/eddie-recipes/recipes/common/promo-block/promo-block';
13
+ import '@brad-frost-web/eddie-recipes/recipes/common/site-footer/site-footer';
14
+ import '@brad-frost-web/eddie-recipes/recipes/common/site-header/site-header';
15
15
 
16
16
  export class Homepage extends LitElement {
17
17
  handleCloseBlackFridayDrawer(event: CustomEvent) {
@@ -20,13 +20,13 @@ export class Homepage extends LitElement {
20
20
  render() {
21
21
  return html`
22
22
  <div style="display: flex; flex-direction: column; min-height: 100vh;">
23
- <site-header></site-header>
23
+ <ed-r-site-header></ed-r-site-header>
24
24
  <ed-main class="ed-u-display-block ed-u-margin-bottom-xl">
25
25
  <ed-hero imgSrc="images/1200x650.svg" imgAlt="Hero Alt Text">
26
26
  <ed-heading tagName="h2">Hero title</ed-heading>
27
27
  <ed-text-passage>This is the hero description</ed-text-passage>
28
28
  </ed-hero>
29
- <promo-block class="ed-u-display-block ed-u-margin-bottom-xl"></promo-block>
29
+ <ed-r-promo-block class="ed-u-display-block ed-u-margin-bottom-xl"></ed-r-promo-block>
30
30
  <ed-layout-container>
31
31
  <ed-grid variant="1-3up">
32
32
  <ed-grid-item>
@@ -56,7 +56,7 @@ export class Homepage extends LitElement {
56
56
  </ed-grid>
57
57
  </ed-layout-container>
58
58
  </ed-main>
59
- <site-footer></site-footer>
59
+ <ed-r-site-footer></ed-r-site-footer>
60
60
  </div>
61
61
  `;
62
62
  }
package/README.md CHANGED
@@ -1,45 +1,57 @@
1
- # Eddie Design System
1
+ # Eddie Web Components
2
2
 
3
- Eddie Design System provides presentational UI components to be consumed by [COMPANY NAME] web applications.
3
+ `@brad-frost-web/eddie-web-components` the core Lit web component library for Eddie Design System.
4
4
 
5
- ## Developing Locally
5
+ This package provides presentational UI components (buttons, cards, forms, navigation, layout, etc.) organized by [atomic design](https://atomicdesign.bradfrost.com/chapter-2/#the-atomic-design-methodology): Atoms, Molecules, and Organisms.
6
6
 
7
- First, clone the repository and install the project dependencies:
7
+ ## Usage
8
8
 
9
9
  ```bash
10
- npm install --legacy-peer-deps
10
+ npm install @brad-frost-web/eddie-web-components
11
11
  ```
12
12
 
13
- Note, because of a peer dependency issue with `reach/router` it is necessary to install with `--legacy-peer-deps` for the
14
- time being. This will no longer be necessary once Storybook updates to 6.4, tracked here:
15
- https://github.com/storybookjs/storybook/issues/14619.
13
+ ```js
14
+ import '@brad-frost-web/eddie-web-components/components/button/button';
15
+ ```
16
+
17
+ ```html
18
+ <ed-button text="Click me" variant="primary"></ed-button>
19
+ ```
20
+
21
+ ## Development
22
+
23
+ See the [root README](../../README.md) for monorepo setup instructions and the [code guidelines](../../docs/CODE_GUIDELINES.md) for conventions.
16
24
 
17
- Then, run the project with the following command
25
+ ### Scaffold a new component
18
26
 
19
27
  ```bash
20
- npm start
28
+ npm run eddie-web-components:plop
21
29
  ```
22
30
 
23
- This will build the project and open Storybook at http://localhost:6006 in your browser.
31
+ ### Run tests
24
32
 
25
- ## Working with the library
33
+ ```bash
34
+ npx vitest
35
+ ```
26
36
 
27
- Please read the [code guidelines documentation](docs/CODE_GUIDELINES.md) in order to successfully develop with and contribute to the library.
37
+ ## Component structure
28
38
 
29
- If you use VS Code, we highly recommend the [lit-plugin extension](https://marketplace.visualstudio.com/items?itemName=runem.lit-plugin), which enables some extremely useful features for lit-html templates:
39
+ Each component lives in `components/<name>/`:
30
40
 
31
- - Syntax highlighting
32
- - Type-checking
33
- - Code completion
34
- - Hover-over docs
35
- - Jump to definition
36
- - Linting
37
- - Quick Fixes
41
+ ```
42
+ components/button/
43
+ ├── button.ts # Component class extending EdElement
44
+ ├── button.scss # Scoped BEM styles
45
+ ├── button.stories.ts # Storybook stories
46
+ └── test/
47
+ └── button.test.ts # Unit tests
48
+ ```
38
49
 
39
- ## Build
50
+ ## Base classes
40
51
 
41
- TODO
52
+ - **`EdElement`** — Root base class extending `LitElement`. Provides `componentClassNames()`, `slotEmpty()`, and `dispatch()`.
53
+ - **`EdFormElement`** — Extends `EdElement` for form-associated components with `ElementInternals` support.
42
54
 
43
- ## Support
55
+ ## Editor support
44
56
 
45
- TODO
57
+ The [lit-plugin extension](https://marketplace.visualstudio.com/items?itemName=runem.lit-plugin) for VS Code / Cursor provides syntax highlighting, type-checking, code completion, hover docs, and linting for Lit templates.
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Eddie Autoloader
3
+ *
4
+ * Watches the DOM for any `ed-*` custom elements and automatically
5
+ * lazy-loads their component definitions on demand. This means you
6
+ * only pay for the components you actually use in your HTML.
7
+ *
8
+ * Usage (CDN):
9
+ * <script type="module" src="https://cdn.jsdelivr.net/npm/@brad-frost-web/eddie-web-components@VERSION/cdn/eddie-autoloader.js"></script>
10
+ *
11
+ * Usage (local):
12
+ * <script type="module" src="./node_modules/@brad-frost-web/eddie-web-components/cdn/eddie-autoloader.js"></script>
13
+ */
14
+
15
+ // Tag → module path mapping. The autoloader resolves paths relative to itself.
16
+ const COMPONENT_MAP: Record<string, string> = {
17
+ 'ed-accordion': './components/accordion/accordion.js',
18
+ 'ed-accordion-panel': './components/accordion-panel/accordion-panel.js',
19
+ 'ed-alert': './components/alert/alert.js',
20
+ 'ed-badge': './components/badge/badge.js',
21
+ 'ed-band': './components/band/band.js',
22
+ 'ed-black-friday-banner': './components/black-friday-banner/black-friday-banner.js',
23
+ 'ed-black-friday-modal': './components/black-friday-modal/black-friday-modal.js',
24
+ 'ed-box': './components/box/box.js',
25
+ 'ed-breadcrumbs': './components/breadcrumbs/breadcrumbs.js',
26
+ 'ed-breadcrumbs-item': './components/breadcrumbs-item/breadcrumbs-item.js',
27
+ 'ed-button': './components/button/button.js',
28
+ 'ed-button-group': './components/button-group/button-group.js',
29
+ 'ed-card': './components/card/card.js',
30
+ 'ed-checkbox-field': './components/checkbox-field/checkbox-field.js',
31
+ 'ed-checkbox-field-item': './components/checkbox-field-item/checkbox-field-item.js',
32
+ 'ed-counter': './components/counter/counter.js',
33
+ 'ed-drawer': './components/drawer/drawer.js',
34
+ 'ed-feature': './components/feature/feature.js',
35
+ 'ed-field-note': './components/field-note/field-note.js',
36
+ 'ed-file-upload': './components/file-upload/file-upload.js',
37
+ 'ed-footer': './components/footer/footer.js',
38
+ 'ed-global-nav': './components/global-nav/global-nav.js',
39
+ 'ed-global-nav-item': './components/global-nav-item/global-nav-item.js',
40
+ 'ed-grid': './components/grid/grid.js',
41
+ 'ed-grid-item': './components/grid-item/grid-item.js',
42
+ 'ed-header': './components/header/header.js',
43
+ 'ed-heading': './components/heading/heading.js',
44
+ 'ed-hero': './components/hero/hero.js',
45
+ 'ed-hr': './components/hr/hr.js',
46
+ 'ed-icon': './components/icon/icon.js',
47
+ 'ed-icon-link-list': './components/icon-link-list/icon-link-list.js',
48
+ 'ed-icon-link-list-item': './components/icon-link-list-item/icon-link-list-item.js',
49
+ 'ed-inline-checkbox': './components/inline-checkbox/inline-checkbox.js',
50
+ 'ed-key-value-table': './components/key-value-table/key-value-table.js',
51
+ 'ed-key-value-table-row': './components/key-value-table-row/key-value-table-row.js',
52
+ 'ed-layout': './components/layout/layout.js',
53
+ 'ed-layout-container': './components/layout-container/layout-container.js',
54
+ 'ed-layout-section': './components/layout-section/layout-section.js',
55
+ 'ed-linelength-container': './components/linelength-container/linelength-container.js',
56
+ 'ed-link-list': './components/link-list/link-list.js',
57
+ 'ed-link-list-item': './components/link-list-item/link-list-item.js',
58
+ 'ed-list': './components/list/list.js',
59
+ 'ed-list-item': './components/list-item/list-item.js',
60
+ 'ed-loading-indicator': './components/loading-indicator/loading-indicator.js',
61
+ 'ed-logo': './components/logo/logo.js',
62
+ 'ed-main': './components/main/main.js',
63
+ 'ed-media-block': './components/media-block/media-block.js',
64
+ 'ed-modal': './components/modal/modal.js',
65
+ 'ed-nav-container': './components/nav-container/nav-container.js',
66
+ 'ed-page-header': './components/page-header/page-header.js',
67
+ 'ed-pagination': './components/pagination/pagination.js',
68
+ 'ed-pagination-item': './components/pagination-item/pagination-item.js',
69
+ 'ed-primary-nav': './components/primary-nav/primary-nav.js',
70
+ 'ed-primary-nav-item': './components/primary-nav-item/primary-nav-item.js',
71
+ 'ed-radio-field': './components/radio-field/radio-field.js',
72
+ 'ed-radio-field-item': './components/radio-field-item/radio-field-item.js',
73
+ 'ed-search-form': './components/search-form/search-form.js',
74
+ 'ed-section': './components/section/section.js',
75
+ 'ed-select-field': './components/select-field/select-field.js',
76
+ 'ed-show-hide': './components/show-hide/show-hide.js',
77
+ 'ed-show-more': './components/show-more/show-more.js',
78
+ 'ed-skeleton': './components/skeleton/skeleton.js',
79
+ 'ed-tab': './components/tab/tab.js',
80
+ 'ed-table': './components/table/table.js',
81
+ 'ed-table-body': './components/table-body/table-body.js',
82
+ 'ed-table-cell': './components/table-cell/table-cell.js',
83
+ 'ed-table-header': './components/table-header/table-header.js',
84
+ 'ed-table-header-cell': './components/table-header-cell/table-header-cell.js',
85
+ 'ed-table-object': './components/table-object/table-object.js',
86
+ 'ed-table-row': './components/table-row/table-row.js',
87
+ 'ed-tabs': './components/tabs/tabs.js',
88
+ 'ed-tag': './components/tag/tag.js',
89
+ 'ed-tag-list': './components/tag-list/tag-list.js',
90
+ 'ed-text-field': './components/text-field/text-field.js',
91
+ 'ed-text-link': './components/text-link/text-link.js',
92
+ 'ed-text-passage': './components/text-passage/text-passage.js',
93
+ 'ed-textarea-field': './components/textarea-field/textarea-field.js',
94
+ 'ed-toast': './components/toast/toast.js',
95
+ 'ed-toggle': './components/toggle/toggle.js',
96
+ 'ed-toolbar': './components/toolbar/toolbar.js',
97
+ 'ed-tooltip': './components/tooltip/tooltip.js',
98
+ 'ed-tooltip-trigger': './components/tooltip-trigger/tooltip-trigger.js',
99
+ 'ed-utility-nav': './components/utility-nav/utility-nav.js',
100
+ 'ed-utility-nav-item': './components/utility-nav-item/utility-nav-item.js'
101
+ };
102
+
103
+ // Detect the base path from this script's location
104
+ let basePath: string;
105
+
106
+ function getBasePath(): string {
107
+ if (basePath !== undefined) return basePath;
108
+
109
+ // Try to detect from the current script's src attribute
110
+ const scripts = document.querySelectorAll('script[src]');
111
+ for (const script of scripts) {
112
+ const src = script.getAttribute('src') || '';
113
+ if (src.includes('eddie-autoloader')) {
114
+ basePath = src.substring(0, src.lastIndexOf('/') + 1);
115
+ return basePath;
116
+ }
117
+ }
118
+
119
+ // Fallback: try import.meta.url
120
+ if (import.meta.url) {
121
+ basePath = import.meta.url.substring(0, import.meta.url.lastIndexOf('/') + 1);
122
+ return basePath;
123
+ }
124
+
125
+ // Last resort
126
+ basePath = '';
127
+ return basePath;
128
+ }
129
+
130
+ /**
131
+ * Override the base path for component resolution.
132
+ * Useful when self-hosting Eddie assets at a custom location.
133
+ */
134
+ export function setBasePath(path: string): void {
135
+ basePath = path.endsWith('/') ? path : path + '/';
136
+ }
137
+
138
+ // Track which components are currently being loaded
139
+ const loading = new Set<string>();
140
+
141
+ async function loadComponent(tagName: string): Promise<void> {
142
+ if (loading.has(tagName)) return;
143
+ if (customElements.get(tagName)) return;
144
+
145
+ const modulePath = COMPONENT_MAP[tagName];
146
+ if (!modulePath) return;
147
+
148
+ loading.add(tagName);
149
+
150
+ try {
151
+ const resolvedPath = getBasePath() + modulePath;
152
+ await import(resolvedPath);
153
+ } catch (err) {
154
+ console.error(`[Eddie] Failed to load component: ${tagName}`, err);
155
+ }
156
+ }
157
+
158
+ // Scan existing DOM for undefined ed-* elements
159
+ function scanDOM(root: ParentNode = document.body): void {
160
+ const undefinedElements = root.querySelectorAll(':not(:defined)');
161
+ for (const el of undefinedElements) {
162
+ const tagName = el.tagName.toLowerCase();
163
+ if (tagName.startsWith('ed-') && COMPONENT_MAP[tagName]) {
164
+ loadComponent(tagName);
165
+ }
166
+ }
167
+ }
168
+
169
+ // Watch for new ed-* elements added to the DOM
170
+ const observer = new MutationObserver((mutations) => {
171
+ for (const mutation of mutations) {
172
+ for (const node of mutation.addedNodes) {
173
+ if (node instanceof HTMLElement) {
174
+ const tagName = node.tagName.toLowerCase();
175
+ if (tagName.startsWith('ed-') && COMPONENT_MAP[tagName]) {
176
+ loadComponent(tagName);
177
+ }
178
+ // Also scan children of the added node
179
+ scanDOM(node);
180
+ }
181
+ }
182
+ }
183
+ });
184
+
185
+ // Start observing once DOM is ready
186
+ if (document.readyState === 'loading') {
187
+ document.addEventListener('DOMContentLoaded', () => {
188
+ scanDOM();
189
+ observer.observe(document.body, { subtree: true, childList: true });
190
+ });
191
+ } else {
192
+ scanDOM();
193
+ observer.observe(document.body, { subtree: true, childList: true });
194
+ }
195
+
196
+ // Export version info
197
+ export const EDDIE_VERSION = '__EDDIE_VERSION__';
package/cdn/eddie.ts ADDED
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Eddie — Full Bundle
3
+ *
4
+ * Imports and registers ALL Eddie web components at once.
5
+ * Use this when you want everything available immediately
6
+ * without waiting for lazy loading.
7
+ *
8
+ * Usage:
9
+ * <script type="module" src="https://cdn.jsdelivr.net/npm/@brad-frost-web/eddie-web-components@VERSION/cdn/eddie.js"></script>
10
+ *
11
+ * For lazy loading (better performance), use eddie-autoloader.js instead.
12
+ */
13
+
14
+ // All components — auto-register on import
15
+ import '../components/accordion/accordion';
16
+ import '../components/accordion-panel/accordion-panel';
17
+ import '../components/alert/alert';
18
+ import '../components/badge/badge';
19
+ import '../components/band/band';
20
+ import '../components/black-friday-banner/black-friday-banner';
21
+ import '../components/black-friday-modal/black-friday-modal';
22
+ import '../components/box/box';
23
+ import '../components/breadcrumbs/breadcrumbs';
24
+ import '../components/breadcrumbs-item/breadcrumbs-item';
25
+ import '../components/button/button';
26
+ import '../components/button-group/button-group';
27
+ import '../components/card/card';
28
+ import '../components/checkbox-field/checkbox-field';
29
+ import '../components/checkbox-field-item/checkbox-field-item';
30
+ import '../components/counter/counter';
31
+ import '../components/drawer/drawer';
32
+ import '../components/feature/feature';
33
+ import '../components/field-note/field-note';
34
+ import '../components/file-upload/file-upload';
35
+ import '../components/footer/footer';
36
+ import '../components/global-nav/global-nav';
37
+ import '../components/global-nav-item/global-nav-item';
38
+ import '../components/grid/grid';
39
+ import '../components/grid-item/grid-item';
40
+ import '../components/header/header';
41
+ import '../components/heading/heading';
42
+ import '../components/hero/hero';
43
+ import '../components/hr/hr';
44
+ import '../components/icon/icon';
45
+ import '../components/icon-link-list/icon-link-list';
46
+ import '../components/icon-link-list-item/icon-link-list-item';
47
+ import '../components/inline-checkbox/inline-checkbox';
48
+ import '../components/key-value-table/key-value-table';
49
+ import '../components/key-value-table-row/key-value-table-row';
50
+ import '../components/layout/layout';
51
+ import '../components/layout-container/layout-container';
52
+ import '../components/layout-section/layout-section';
53
+ import '../components/linelength-container/linelength-container';
54
+ import '../components/link-list/link-list';
55
+ import '../components/link-list-item/link-list-item';
56
+ import '../components/list/list';
57
+ import '../components/list-item/list-item';
58
+ import '../components/loading-indicator/loading-indicator';
59
+ import '../components/logo/logo';
60
+ import '../components/main/main';
61
+ import '../components/media-block/media-block';
62
+ import '../components/modal/modal';
63
+ import '../components/nav-container/nav-container';
64
+ import '../components/page-header/page-header';
65
+ import '../components/pagination/pagination';
66
+ import '../components/pagination-item/pagination-item';
67
+ import '../components/primary-nav/primary-nav';
68
+ import '../components/primary-nav-item/primary-nav-item';
69
+ import '../components/radio-field/radio-field';
70
+ import '../components/radio-field-item/radio-field-item';
71
+ import '../components/search-form/search-form';
72
+ import '../components/section/section';
73
+ import '../components/select-field/select-field';
74
+ import '../components/show-hide/show-hide';
75
+ import '../components/show-more/show-more';
76
+ import '../components/skeleton/skeleton';
77
+ import '../components/tab/tab';
78
+ import '../components/table/table';
79
+ import '../components/table-body/table-body';
80
+ import '../components/table-cell/table-cell';
81
+ import '../components/table-header/table-header';
82
+ import '../components/table-header-cell/table-header-cell';
83
+ import '../components/table-object/table-object';
84
+ import '../components/table-row/table-row';
85
+ import '../components/tabs/tabs';
86
+ import '../components/tag/tag';
87
+ import '../components/tag-list/tag-list';
88
+ import '../components/text-field/text-field';
89
+ import '../components/text-link/text-link';
90
+ import '../components/text-passage/text-passage';
91
+ import '../components/textarea-field/textarea-field';
92
+ import '../components/toast/toast';
93
+ import '../components/toggle/toggle';
94
+ import '../components/toolbar/toolbar';
95
+ import '../components/tooltip/tooltip';
96
+ import '../components/tooltip-trigger/tooltip-trigger';
97
+ import '../components/utility-nav/utility-nav';
98
+ import '../components/utility-nav-item/utility-nav-item';
99
+
100
+ export const EDDIE_VERSION = '__EDDIE_VERSION__';
@@ -3,11 +3,21 @@ import {spread} from '../../directives/spread';
3
3
  import '../accordion-panel/accordion-panel';
4
4
  import './accordion';
5
5
 
6
+ /**
7
+ * Accordion component for organizing collapsible content panels.
8
+ *
9
+ * Accordions group content into expandable/collapsible sections. One panel can be open at a time,
10
+ * with smooth height animations when toggling. Compose with `ed-accordion-panel` children, using the `header` slot for titles and the default slot for content.
11
+ */
6
12
  export default {
7
13
  title: 'Organisms/Interactive/Accordion',
8
14
  component: 'ed-accordion',
9
15
  };
10
16
 
17
+ /**
18
+ * Default accordion with multiple panels. First panel is expanded by default.
19
+ * Demonstrates the standard accordion composition and smooth open/close interactions.
20
+ */
11
21
  export const Default = (args) =>
12
22
  html`<ed-accordion ${spread(args)}>
13
23
  <ed-accordion-panel ?isActive=${true}>
@@ -29,6 +39,10 @@ export const Default = (args) =>
29
39
  </ed-accordion-panel>
30
40
  </ed-accordion>`;
31
41
 
42
+ /**
43
+ * Accordion with inverted colors for dark backgrounds.
44
+ * Use on dark surfaces where the default colors would not have sufficient contrast.
45
+ */
32
46
  export const Inverted = () =>
33
47
  html` <div style="background: #000; padding: 1rem;">
34
48
  <ed-accordion ?inverted=${true}>
@@ -4,9 +4,23 @@ import { EdElement } from '@brad-frost-web/eddie-web-components/components/EdEle
4
4
  import styles from './accordion.scss?inline';
5
5
 
6
6
  /**
7
- * @slot - The component content
7
+ * An accordion container that groups collapsible panels for progressive content disclosure.
8
+ * Renders as semantic `<dl>` element with accordion-panel children.
9
+ * Panels can be independently toggled open/closed with smooth height animations.
10
+ * Only the active panel is expanded; clicking another panel closes the previously active one.
11
+ *
12
+ * Use accordions to:
13
+ * - Organize large content sections (FAQs, product features, documentation)
14
+ * - Show/hide detailed information progressively
15
+ * - Create expandable content lists with clear interactions
16
+ * - Group related information hierarchically
17
+ *
18
+ * Each accordion-panel contains:
19
+ * - A header slot with the panel title (rendered in a button trigger)
20
+ * - Default slot content that expands/collapses
21
+ *
22
+ * @slot - Accordion panels (ed-accordion-panel elements)
8
23
  */
9
-
10
24
  export class EdAccordion extends EdElement {
11
25
  static get styles() {
12
26
  return unsafeCSS(styles.toString());
@@ -6,7 +6,20 @@ import styles from './accordion-panel.scss?inline';
6
6
  import '../icon/icon';
7
7
 
8
8
  /**
9
- * @slot - The component content
9
+ * An accordion panel for use within ed-accordion containers.
10
+ * Each panel has a collapsible header section and expandable content body with smooth height animation.
11
+ * Panels render as semantic `<dl>` > `<dt>` (header) + `<dd>` (content) elements.
12
+ *
13
+ * Use slots:
14
+ * - `header`: The panel title/heading (rendered in a clickable button)
15
+ * - default: The panel content body (expands/collapses with animation)
16
+ *
17
+ * Properties:
18
+ * - `isActive`: Set to true to expand the panel (expands on init and toggle)
19
+ * - `fullyOpen`: Internal state for animation completion (do not set directly)
20
+ *
21
+ * @slot header - Panel title/heading
22
+ * @slot - Panel content body (expands/collapses)
10
23
  */
11
24
  export class EdAccordionPanel extends EdElement {
12
25
  static get styles() {