@chiralkit/design-system 0.1.0-alpha.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 (146) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/dist/chiralkit-ds/chiralkit-ds.css +1 -0
  4. package/dist/chiralkit-ds/chiralkit-ds.esm.js +1 -0
  5. package/dist/chiralkit-ds/index.esm.js +1 -0
  6. package/dist/chiralkit-ds/p-038fa008.entry.js +1 -0
  7. package/dist/chiralkit-ds/p-2fdc1012.entry.js +1 -0
  8. package/dist/chiralkit-ds/p-306ec33b.entry.js +1 -0
  9. package/dist/chiralkit-ds/p-3f704698.entry.js +1 -0
  10. package/dist/chiralkit-ds/p-41081d22.entry.js +1 -0
  11. package/dist/chiralkit-ds/p-7d7e5aac.entry.js +1 -0
  12. package/dist/chiralkit-ds/p-84b801f8.entry.js +1 -0
  13. package/dist/chiralkit-ds/p-a28c71b4.entry.js +1 -0
  14. package/dist/chiralkit-ds/p-be84312f.entry.js +1 -0
  15. package/dist/chiralkit-ds/p-c8015fe6.entry.js +1 -0
  16. package/dist/chiralkit-ds/p-d36a6bea.entry.js +1 -0
  17. package/dist/chiralkit-ds/p-e-glNjK6.js +2 -0
  18. package/dist/chiralkit-ds/p-f0f9ff61.entry.js +1 -0
  19. package/dist/cjs/chiralkit-ds.cjs.js +24 -0
  20. package/dist/cjs/ds-badge.cjs.entry.js +18 -0
  21. package/dist/cjs/ds-button.cjs.entry.js +26 -0
  22. package/dist/cjs/ds-card.cjs.entry.js +17 -0
  23. package/dist/cjs/ds-checkbox.cjs.entry.js +67 -0
  24. package/dist/cjs/ds-code-block.cjs.entry.js +39 -0
  25. package/dist/cjs/ds-dialog.cjs.entry.js +67 -0
  26. package/dist/cjs/ds-input.cjs.entry.js +50 -0
  27. package/dist/cjs/ds-loader.cjs.entry.js +26 -0
  28. package/dist/cjs/ds-select.cjs.entry.js +85 -0
  29. package/dist/cjs/ds-tabs.cjs.entry.js +138 -0
  30. package/dist/cjs/ds-textarea.cjs.entry.js +50 -0
  31. package/dist/cjs/ds-tooltip.cjs.entry.js +233 -0
  32. package/dist/cjs/index-mMvyq7U_.js +2018 -0
  33. package/dist/cjs/index.cjs.js +10 -0
  34. package/dist/cjs/loader.cjs.js +12 -0
  35. package/dist/collection/collection-manifest.json +24 -0
  36. package/dist/collection/components/ds-badge/ds-badge.css +36 -0
  37. package/dist/collection/components/ds-badge/ds-badge.js +93 -0
  38. package/dist/collection/components/ds-button/ds-button.css +66 -0
  39. package/dist/collection/components/ds-button/ds-button.js +197 -0
  40. package/dist/collection/components/ds-card/ds-card.css +12 -0
  41. package/dist/collection/components/ds-card/ds-card.js +68 -0
  42. package/dist/collection/components/ds-checkbox/ds-checkbox.css +22 -0
  43. package/dist/collection/components/ds-checkbox/ds-checkbox.js +339 -0
  44. package/dist/collection/components/ds-code-block/ds-code-block.css +65 -0
  45. package/dist/collection/components/ds-code-block/ds-code-block.js +162 -0
  46. package/dist/collection/components/ds-dialog/ds-dialog.css +30 -0
  47. package/dist/collection/components/ds-dialog/ds-dialog.js +313 -0
  48. package/dist/collection/components/ds-input/ds-input.css +38 -0
  49. package/dist/collection/components/ds-input/ds-input.js +353 -0
  50. package/dist/collection/components/ds-loader/ds-loader.css +94 -0
  51. package/dist/collection/components/ds-loader/ds-loader.js +149 -0
  52. package/dist/collection/components/ds-select/ds-select.css +69 -0
  53. package/dist/collection/components/ds-select/ds-select.js +235 -0
  54. package/dist/collection/components/ds-tabs/ds-tabs.css +59 -0
  55. package/dist/collection/components/ds-tabs/ds-tabs.js +248 -0
  56. package/dist/collection/components/ds-textarea/ds-textarea.css +41 -0
  57. package/dist/collection/components/ds-textarea/ds-textarea.js +342 -0
  58. package/dist/collection/components/ds-tooltip/ds-tooltip.css +31 -0
  59. package/dist/collection/components/ds-tooltip/ds-tooltip.js +318 -0
  60. package/dist/collection/components.js +2 -0
  61. package/dist/collection/index.js +1 -0
  62. package/dist/components/ds-badge.d.ts +11 -0
  63. package/dist/components/ds-badge.js +1 -0
  64. package/dist/components/ds-button.d.ts +11 -0
  65. package/dist/components/ds-button.js +1 -0
  66. package/dist/components/ds-card.d.ts +11 -0
  67. package/dist/components/ds-card.js +1 -0
  68. package/dist/components/ds-checkbox.d.ts +11 -0
  69. package/dist/components/ds-checkbox.js +1 -0
  70. package/dist/components/ds-code-block.d.ts +11 -0
  71. package/dist/components/ds-code-block.js +1 -0
  72. package/dist/components/ds-dialog.d.ts +11 -0
  73. package/dist/components/ds-dialog.js +1 -0
  74. package/dist/components/ds-input.d.ts +11 -0
  75. package/dist/components/ds-input.js +1 -0
  76. package/dist/components/ds-loader.d.ts +11 -0
  77. package/dist/components/ds-loader.js +1 -0
  78. package/dist/components/ds-select.d.ts +11 -0
  79. package/dist/components/ds-select.js +1 -0
  80. package/dist/components/ds-tabs.d.ts +11 -0
  81. package/dist/components/ds-tabs.js +1 -0
  82. package/dist/components/ds-textarea.d.ts +11 -0
  83. package/dist/components/ds-textarea.js +1 -0
  84. package/dist/components/ds-tooltip.d.ts +11 -0
  85. package/dist/components/ds-tooltip.js +1 -0
  86. package/dist/components/index.d.ts +35 -0
  87. package/dist/components/index.js +1 -0
  88. package/dist/components/p-DDUZow8F.js +1 -0
  89. package/dist/components/p-ZsYP0VBq.js +1 -0
  90. package/dist/components/p-k0ywxWpC.js +1 -0
  91. package/dist/esm/chiralkit-ds.js +20 -0
  92. package/dist/esm/ds-badge.entry.js +16 -0
  93. package/dist/esm/ds-button.entry.js +24 -0
  94. package/dist/esm/ds-card.entry.js +15 -0
  95. package/dist/esm/ds-checkbox.entry.js +65 -0
  96. package/dist/esm/ds-code-block.entry.js +37 -0
  97. package/dist/esm/ds-dialog.entry.js +65 -0
  98. package/dist/esm/ds-input.entry.js +48 -0
  99. package/dist/esm/ds-loader.entry.js +24 -0
  100. package/dist/esm/ds-select.entry.js +83 -0
  101. package/dist/esm/ds-tabs.entry.js +136 -0
  102. package/dist/esm/ds-textarea.entry.js +48 -0
  103. package/dist/esm/ds-tooltip.entry.js +231 -0
  104. package/dist/esm/index-e-glNjK6.js +2008 -0
  105. package/dist/esm/index.js +3 -0
  106. package/dist/esm/loader.js +10 -0
  107. package/dist/index.cjs.js +1 -0
  108. package/dist/index.js +1 -0
  109. package/dist/layouts/app-shell.css +84 -0
  110. package/dist/tests/a11y.js +55 -0
  111. package/dist/types/Users/alex/projects/MyGitHub/chiralkit/packages/design-system/.stencil/tests/a11y.d.ts +17 -0
  112. package/dist/types/components/ds-badge/ds-badge.d.ts +54 -0
  113. package/dist/types/components/ds-button/ds-button.d.ts +75 -0
  114. package/dist/types/components/ds-card/ds-card.d.ts +53 -0
  115. package/dist/types/components/ds-checkbox/ds-checkbox.d.ts +94 -0
  116. package/dist/types/components/ds-code-block/ds-code-block.d.ts +83 -0
  117. package/dist/types/components/ds-dialog/ds-dialog.d.ts +148 -0
  118. package/dist/types/components/ds-input/ds-input.d.ts +104 -0
  119. package/dist/types/components/ds-loader/ds-loader.d.ts +64 -0
  120. package/dist/types/components/ds-select/ds-select.d.ts +123 -0
  121. package/dist/types/components/ds-tabs/ds-tabs.d.ts +155 -0
  122. package/dist/types/components/ds-textarea/ds-textarea.d.ts +93 -0
  123. package/dist/types/components/ds-tooltip/ds-tooltip.d.ts +26 -0
  124. package/dist/types/components.d.ts +3068 -0
  125. package/dist/types/index.d.ts +1 -0
  126. package/dist/types/stencil-public-runtime.d.ts +1861 -0
  127. package/docs.json +2112 -0
  128. package/loader/cdn.js +1 -0
  129. package/loader/index.cjs.js +1 -0
  130. package/loader/index.d.ts +24 -0
  131. package/loader/index.es2017.js +1 -0
  132. package/loader/index.js +2 -0
  133. package/package.json +78 -0
  134. package/react/components/ds-badge.tsx +25 -0
  135. package/react/components/ds-button.tsx +25 -0
  136. package/react/components/ds-card.tsx +25 -0
  137. package/react/components/ds-checkbox.tsx +25 -0
  138. package/react/components/ds-code-block.tsx +25 -0
  139. package/react/components/ds-dialog.tsx +31 -0
  140. package/react/components/ds-input.tsx +25 -0
  141. package/react/components/ds-loader.tsx +25 -0
  142. package/react/components/ds-select.tsx +25 -0
  143. package/react/components/ds-tabs.tsx +25 -0
  144. package/react/components/ds-textarea.tsx +25 -0
  145. package/react/components/ds-tooltip.tsx +25 -0
  146. package/react/components.ts +162 -0
@@ -0,0 +1,3 @@
1
+ export { ds_button as DsButton } from './ds-button.entry.js';
2
+ export { ds_select as DsSelect } from './ds-select.entry.js';
3
+ import './index-e-glNjK6.js';
@@ -0,0 +1,10 @@
1
+ import { g as globalScripts, b as bootstrapLazy } from './index-e-glNjK6.js';
2
+ export { s as setNonce } from './index-e-glNjK6.js';
3
+
4
+ const defineCustomElements = async (win, options) => {
5
+ if (typeof window === 'undefined') return undefined;
6
+ await globalScripts();
7
+ return bootstrapLazy([["ds-badge",[[769,"ds-badge",{"variant":[1]}]]],["ds-button",[[769,"ds-button",{"variant":[1],"size":[1],"disabled":[4],"type":[1],"href":[1]}]]],["ds-card",[[257,"ds-card"]]],["ds-checkbox",[[513,"ds-checkbox",{"checked":[4],"indeterminate":[4],"name":[1],"value":[1],"disabled":[4],"required":[4],"invalid":[4],"describedBy":[1,"described-by"],"label":[1]},null,{"checked":[{"watchChecked":0}],"indeterminate":[{"watchIndeterminate":0}]}]]],["ds-code-block",[[513,"ds-code-block",{"code":[1],"language":[1],"copied":[32]}]]],["ds-dialog",[[769,"ds-dialog",{"open":[4],"label":[1],"labelledBy":[1,"labelled-by"],"describedBy":[1,"described-by"]},null,{"open":[{"watchOpen":0}]}]]],["ds-input",[[513,"ds-input",{"value":[1],"name":[1],"type":[1],"placeholder":[1],"disabled":[4],"required":[4],"invalid":[4],"describedBy":[1,"described-by"],"label":[1],"size":[1]},null,{"value":[{"watchValue":0}]}]]],["ds-loader",[[513,"ds-loader",{"size":[1],"label":[1],"speed":[1]}]]],["ds-select",[[513,"ds-select",{"value":[1],"name":[1],"disabled":[4],"size":[1],"label":[1],"options":[1]},null,{"value":[{"watchValue":0}],"options":[{"watchOptions":0}]}]]],["ds-tabs",[[512,"ds-tabs",{"items":[1],"active":[1025],"orientation":[1],"label":[1]},null,{"items":[{"watchItems":0}]}]]],["ds-textarea",[[513,"ds-textarea",{"value":[1],"name":[1],"placeholder":[1],"disabled":[4],"required":[4],"invalid":[4],"describedBy":[1,"described-by"],"label":[1],"rows":[2],"size":[1]},null,{"value":[{"watchValue":0}]}]]],["ds-tooltip",[[772,"ds-tooltip",{"label":[1],"openDelay":[2,"open-delay"],"closeDelay":[2,"close-delay"],"placement":[1]},null,{"label":[{"watchLabel":0}]}]]]], options);
8
+ };
9
+
10
+ export { defineCustomElements };
@@ -0,0 +1 @@
1
+ module.exports = require('./cjs/index.cjs.js');
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from './esm/index.js';
@@ -0,0 +1,84 @@
1
+ .ds-app-shell {
2
+ --ds-app-shell-header-size: calc(var(--ds-spacing-xl, 1.5rem) * 2);
3
+ --ds-app-shell-primary-size: 16rem;
4
+ --ds-app-shell-secondary-size: 20rem;
5
+ --ds-app-shell-content-max: 80rem;
6
+ --ds-app-shell-gutter: var(--ds-spacing-lg, 1rem);
7
+
8
+ box-sizing: border-box;
9
+ display: grid;
10
+ grid-template-columns: minmax(0, 1fr);
11
+ gap: var(--ds-app-shell-gutter);
12
+ padding: var(--ds-app-shell-gutter);
13
+ }
14
+
15
+ .ds-app-shell > .ds-app-shell__header,
16
+ .ds-app-shell > .ds-app-shell__primary,
17
+ .ds-app-shell > .ds-app-shell__main,
18
+ .ds-app-shell > .ds-app-shell__secondary,
19
+ .ds-app-shell > .ds-app-shell__footer {
20
+ box-sizing: border-box;
21
+ grid-column: 1;
22
+ min-inline-size: 0;
23
+ }
24
+
25
+ .ds-app-shell > .ds-app-shell__header {
26
+ min-block-size: var(--ds-app-shell-header-size);
27
+ }
28
+
29
+ .ds-app-shell > .ds-app-shell__main {
30
+ min-width: 0;
31
+ }
32
+
33
+ @media (min-width: 64rem) {
34
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):not(:has(> .ds-app-shell__primary)):not(:has(> .ds-app-shell__secondary)) {
35
+ grid-template-columns: minmax(0, min(var(--ds-app-shell-content-max), 100%));
36
+ justify-content: center;
37
+ }
38
+
39
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):has(> .ds-app-shell__primary):not(:has(> .ds-app-shell__secondary)) {
40
+ grid-template-columns: minmax(0, var(--ds-app-shell-primary-size)) minmax(0, 1fr);
41
+ }
42
+
43
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):not(:has(> .ds-app-shell__primary)):has(> .ds-app-shell__secondary) {
44
+ grid-template-columns: minmax(0, 1fr) minmax(0, var(--ds-app-shell-secondary-size));
45
+ }
46
+
47
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):has(> .ds-app-shell__primary):has(> .ds-app-shell__secondary) {
48
+ grid-template-columns: minmax(0, var(--ds-app-shell-primary-size)) minmax(0, 1fr) minmax(0, var(--ds-app-shell-secondary-size));
49
+ }
50
+
51
+ .ds-app-shell[data-layout="fixed-rails"] > .ds-app-shell__header,
52
+ .ds-app-shell[data-layout="fixed-rails"] > .ds-app-shell__footer {
53
+ grid-column: 1 / -1;
54
+ }
55
+
56
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):has(> .ds-app-shell__primary):not(:has(> .ds-app-shell__secondary)) > .ds-app-shell__primary,
57
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):has(> .ds-app-shell__primary):has(> .ds-app-shell__secondary) > .ds-app-shell__primary {
58
+ grid-column: 1;
59
+ }
60
+
61
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):has(> .ds-app-shell__primary):not(:has(> .ds-app-shell__secondary)) > .ds-app-shell__main,
62
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):has(> .ds-app-shell__primary):has(> .ds-app-shell__secondary) > .ds-app-shell__main {
63
+ grid-column: 2;
64
+ }
65
+
66
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):not(:has(> .ds-app-shell__primary)):has(> .ds-app-shell__secondary) > .ds-app-shell__main {
67
+ grid-column: 1;
68
+ }
69
+
70
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):not(:has(> .ds-app-shell__primary)):has(> .ds-app-shell__secondary) > .ds-app-shell__secondary {
71
+ grid-column: 2;
72
+ }
73
+
74
+ .ds-app-shell[data-layout="fixed-rails"]:has(> .ds-app-shell__main):has(> .ds-app-shell__primary):has(> .ds-app-shell__secondary) > .ds-app-shell__secondary {
75
+ grid-column: 3;
76
+ }
77
+
78
+ .ds-app-shell[data-layout="fixed-rails"] > .ds-app-shell__primary,
79
+ .ds-app-shell[data-layout="fixed-rails"] > .ds-app-shell__secondary {
80
+ align-self: start;
81
+ max-block-size: calc(100dvb - var(--ds-app-shell-header-size) - (var(--ds-app-shell-gutter) * 2));
82
+ overflow: auto;
83
+ }
84
+ }
@@ -0,0 +1,55 @@
1
+ import { AxePuppeteer } from "@axe-core/puppeteer";
2
+ /**
3
+ * Run axe-core against the given e2e page and fail loudly on any
4
+ * WCAG 2.1 A or AA violation. Best-practice rules are surfaced as
5
+ * warnings but do not fail the test — they belong to code review.
6
+ *
7
+ * Every ui-component test file MUST call this at least once per
8
+ * meaningful rendered state (default, disabled, error, open, …).
9
+ *
10
+ * @example
11
+ * const page = await newE2EPage({ html: `<ds-button>Click</ds-button>` });
12
+ * await expectA11y(page);
13
+ */
14
+ export async function expectA11y(page, opts) {
15
+ // Stencil's newE2EPage() test fixture renders the given HTML fragment
16
+ // into a bare document that never gets a `lang` attribute on <html> —
17
+ // that's an artifact of the test harness, not something any DS
18
+ // component controls (a real consuming app always sets its own
19
+ // document lang). Without this, every component test would fail axe's
20
+ // `html-has-lang` (wcag2a) rule regardless of the component under
21
+ // test, masking real component-level violations in the noise. Set it
22
+ // here so the analysis reflects the component's own a11y, matching
23
+ // how it is actually consumed.
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ // Same reasoning for `document-title` (wcag2a): the bare test fixture
26
+ // has no <title>, which a real consuming page always provides.
27
+ await page.evaluate(() => {
28
+ if (!document.documentElement.lang) {
29
+ document.documentElement.lang = 'en';
30
+ }
31
+ if (!document.title) {
32
+ document.title = 'a11y test fixture';
33
+ }
34
+ });
35
+ // Stencil's E2EPage wraps a puppeteer Page; the AxePuppeteer
36
+ // constructor accepts the underlying page instance.
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ const results = await new AxePuppeteer(page)
39
+ .withTags(['wcag2a', 'wcag2aa'])
40
+ .disableRules(opts?.skip ?? [])
41
+ .analyze();
42
+ if (results.violations.length > 0) {
43
+ const summary = results.violations
44
+ .map((v) => `- [${v.impact ?? '?'}] ${v.id}: ${v.help} (${v.nodes.length} node(s))`)
45
+ .join('\n');
46
+ const label = opts?.label ? ` [${opts.label}]` : '';
47
+ throw new Error(`axe found ${results.violations.length} violation(s)${label}:\n${summary}\n\nFull results: ${JSON.stringify(results.violations, null, 2)}`);
48
+ }
49
+ // Surface best-practice warnings without failing.
50
+ const bp = results.incomplete?.filter((r) => r.tags?.includes('best-practice')) ?? [];
51
+ if (bp.length > 0) {
52
+ // eslint-disable-next-line no-console
53
+ console.warn(`axe best-practice notes${opts?.label ? ` [${opts.label}]` : ''}: ${bp.map((r) => r.id).join(', ')}`);
54
+ }
55
+ }
@@ -0,0 +1,17 @@
1
+ import type { E2EPage } from '@stencil/core/testing';
2
+ /**
3
+ * Run axe-core against the given e2e page and fail loudly on any
4
+ * WCAG 2.1 A or AA violation. Best-practice rules are surfaced as
5
+ * warnings but do not fail the test — they belong to code review.
6
+ *
7
+ * Every ui-component test file MUST call this at least once per
8
+ * meaningful rendered state (default, disabled, error, open, …).
9
+ *
10
+ * @example
11
+ * const page = await newE2EPage({ html: `<ds-button>Click</ds-button>` });
12
+ * await expectA11y(page);
13
+ */
14
+ export declare function expectA11y(page: E2EPage, opts?: {
15
+ skip?: string[];
16
+ label?: string;
17
+ }): Promise<void>;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * ## Accessibility
3
+ *
4
+ * **Category:** static-display
5
+ * **APG pattern:** N/A — non-interactive text label.
6
+ *
7
+ * **Keyboard interactions:**
8
+ * - Tab: N/A — the badge is not focusable and does not appear in tab order.
9
+ * - Enter: N/A.
10
+ * - Escape: N/A.
11
+ * - Arrow keys: N/A.
12
+ * - Printable characters: N/A.
13
+ *
14
+ * **ARIA:**
15
+ * - Roles used: none — renders a plain `<span>` around a `<slot />`. The
16
+ * `variant` prop is a purely visual axis and MUST NOT be the sole carrier
17
+ * of information (color/style alone fails WCAG 1.4.1 Use of Color); the
18
+ * textual content inside the slot must convey the same meaning.
19
+ * - State attributes: none.
20
+ * - Labeling strategy: visible text via `<slot />`. Consumers place the
21
+ * readable label directly inside the tag.
22
+ *
23
+ * **Focus:**
24
+ * - On mount: nothing auto-focuses.
25
+ * - On activate/open: N/A — non-interactive.
26
+ * - On close/deactivate: N/A.
27
+ * - Focus indicator: N/A — the host is not focusable. If a consumer wraps
28
+ * `ds-badge` in an interactive element (e.g. `<button>`, `<a>`), that
29
+ * wrapper owns the focus indicator via the DS `--ds-color-focus` token
30
+ * and its own `:focus-visible` rule.
31
+ *
32
+ * **Motion:**
33
+ * - Animations: none.
34
+ * - Reduced-motion behavior: N/A.
35
+ *
36
+ * **Contrast:**
37
+ * - Text: inherits `color: inherit` / `currentColor` from the host page and
38
+ * the variant-specific style; not verified in isolation here. Consumers
39
+ * are responsible for confirming ≥ 4.5:1 (WCAG 1.4.3) against the surface
40
+ * the badge is placed on.
41
+ * - Non-text: no state-conveying icons or borders that need the 3:1
42
+ * non-text contrast threshold.
43
+ *
44
+ * **Screen reader announcement:**
45
+ * - Rendered state: announces the slot text as inline content within its
46
+ * surrounding context (no role means AT reads it as plain text). The
47
+ * `variant` value is not announced — that is intentional; the label text
48
+ * is the source of truth for meaning.
49
+ * - State change: N/A — no dynamic state owned by this component.
50
+ */
51
+ export declare class DsBadge {
52
+ variant: "neutral" | "ui-component" | "recipe" | "agent" | "config";
53
+ render(): any;
54
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * ## Accessibility
3
+ *
4
+ * **Category:** interactive-display
5
+ * **APG pattern:** Button — https://www.w3.org/WAI/ARIA/apg/patterns/button/
6
+ * (satisfied natively by the underlying `<button>` element). When `href` is
7
+ * set, the component renders `<a href>` instead — a link, not a button — and
8
+ * that surface follows native `<a>` semantics rather than the Button pattern.
9
+ *
10
+ * **Keyboard interactions:**
11
+ * - Tab: moves focus to the internal `<button>` or `<a>` (shadow DOM does not
12
+ * interrupt tab order).
13
+ * - Enter: activates (fires click on `<button>`, navigates on `<a>`).
14
+ * - Space: activates the `<button>` variant only (native behavior); on the
15
+ * `<a>` variant Space scrolls the page as usual.
16
+ * - Escape: N/A — no dismissible state owned by this component.
17
+ * - Arrow keys: N/A.
18
+ * - Printable characters: N/A.
19
+ *
20
+ * **ARIA:**
21
+ * - Roles used: none explicit — the native `<button>` / `<a href>` supplies
22
+ * the implicit `button` / `link` role.
23
+ * - State attributes: `disabled` (native attribute on `<button>`, not
24
+ * `aria-disabled`). The `<a>` variant does not accept `disabled` — a
25
+ * disabled navigation is a spec smell (see spec §"Button vs Link"); if a
26
+ * link needs a disabled state, model it as a `<button>` action instead.
27
+ * - Labeling strategy: visible text via `<slot />`. Consumers MUST place
28
+ * readable text (or a labeled icon) inside the tag. An empty slot leaves
29
+ * the button/link without an accessible name and fails
30
+ * `button-name` / `link-name` axe rules. Icon-only usage is out of contract
31
+ * for `ds-button`; use a future `ds-icon-button` with a required
32
+ * `aria-label` prop when that lands.
33
+ *
34
+ * **Focus:**
35
+ * - On mount: nothing auto-focuses.
36
+ * - On activate: focus stays on the element (native click behavior; the
37
+ * component does not move focus on its own).
38
+ * - On close/deactivate: N/A.
39
+ * - Focus indicator: 2px `outline` in `var(--ds-color-focus)` with 2px
40
+ * `outline-offset`, applied via `:focus-visible` — replaces the browser
41
+ * default so both `<button>` and `<a>` variants use the same DS ring
42
+ * (spec universal rule 3, WCAG 1.4.11 non-text contrast ≥ 3:1).
43
+ *
44
+ * **Motion:**
45
+ * - Animations: 150ms `background-color` ease-in-out transition on
46
+ * `primary`/`secondary` variants (hover).
47
+ * - Reduced-motion behavior: N/A — 150ms is below the spec's 200ms threshold
48
+ * for `prefers-reduced-motion` handling, and the transition animates color
49
+ * only (no motion of position, scale, or opacity).
50
+ *
51
+ * **Contrast:**
52
+ * - Text: `primary` and `secondary` variants pair `--ds-color-{primary,secondary}`
53
+ * with `--ds-color-text-on-{primary,secondary}` — the token pairs are
54
+ * authored to meet WCAG 2.1 AA (≥ 4.5:1). The `ghost` variant inherits
55
+ * `color: inherit` and pins `opacity: 0.85`, so its effective contrast
56
+ * depends on the consumer's surface — verify per site.
57
+ * - Non-text (border on `ghost`): 1px `currentColor`; contrast tracks the
58
+ * text color 1:1, subject to the same host-page caveat.
59
+ *
60
+ * **Screen reader announcement:**
61
+ * - Rendered state: announces the slot text followed by "button" (or "link"
62
+ * for the `href` variant), plus "dimmed" / "unavailable" when `disabled`
63
+ * is set (browser/AT dependent wording).
64
+ * - State change: N/A — this component does not own toggle state. A pressed
65
+ * toggle needs `aria-pressed`, which is out of scope here; model that as
66
+ * a distinct component or extend the API deliberately per the spec.
67
+ */
68
+ export declare class DsButton {
69
+ variant: "primary" | "secondary" | "ghost";
70
+ size: "md" | "lg";
71
+ disabled: boolean;
72
+ type: "button" | "submit" | "reset";
73
+ href?: string;
74
+ render(): any;
75
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * ## Accessibility
3
+ *
4
+ * **Category:** static-display
5
+ * **APG pattern:** N/A — a container surface with no interactive
6
+ * behavior of its own. If a consumer nests interactive elements
7
+ * inside (button, link, form field), those elements satisfy their
8
+ * own a11y bucket independently.
9
+ *
10
+ * **Keyboard interactions:**
11
+ * - Tab / Shift+Tab: N/A — the card itself is not focusable. Any
12
+ * interactive descendant carries its own tab semantics.
13
+ * - Enter / Space / Arrow / Escape / Printable: N/A.
14
+ *
15
+ * **ARIA:**
16
+ * - Roles used: none. `<ds-card>` is a purely visual grouping and
17
+ * deliberately does not carry `role="region"` — that would demand
18
+ * a labelledby target, which would only be correct in a subset of
19
+ * uses. Consumers that need a labeled landmark should render a
20
+ * `<section aria-labelledby>` around the card.
21
+ * - State attributes: none.
22
+ * - Labeling strategy: none applied by the component; consumer's
23
+ * heading structure inside the slot supplies the accessible name
24
+ * when needed.
25
+ *
26
+ * **Focus:**
27
+ * - On mount: nothing auto-focuses.
28
+ * - Focus indicator: N/A — the card itself is not focusable.
29
+ *
30
+ * **Motion:**
31
+ * - Animations: none.
32
+ * - Reduced-motion behavior: N/A.
33
+ *
34
+ * **Contrast:**
35
+ * - Text: inherits `color: inherit` / `currentColor`; the card does
36
+ * not impose a text color, so contrast is the consumer theme's
37
+ * responsibility.
38
+ * - Non-text (border, subtle background tint): both derived from
39
+ * `color-mix(in oklch, currentColor N%, transparent)`, matching
40
+ * the pattern used by `ds-input` and `ds-select`. WCAG 1.4.11
41
+ * (3:1 non-text contrast) is met in themes where the surface has
42
+ * enough delta against the page background; the component does
43
+ * not override the consumer's palette to force it.
44
+ *
45
+ * **Screen reader announcement:**
46
+ * - Rendered state: no announcement of the card itself. AT
47
+ * navigates to the slotted content directly, using whatever
48
+ * heading and landmark structure the consumer places inside.
49
+ * - State change: N/A.
50
+ */
51
+ export declare class DsCard {
52
+ render(): any;
53
+ }
@@ -0,0 +1,94 @@
1
+ import { EventEmitter } from "../../stencil-public-runtime";
2
+ /**
3
+ * ## Accessibility
4
+ *
5
+ * **Category:** form-field
6
+ * **APG pattern:** N/A — native element. This wraps a native
7
+ * `<input type="checkbox">`; the browser already implements the
8
+ * checkbox role and its state semantics. Reference:
9
+ * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox
10
+ *
11
+ * Note: `ds-checkbox` intentionally does NOT reach for the WAI-ARIA
12
+ * APG "tri-state checkbox" pattern (indeterminate + on + off) as a
13
+ * scratch-built ARIA widget. The native input already exposes the
14
+ * `indeterminate` DOM property and browsers report it to AT
15
+ * correctly; the `indeterminate` prop here forwards to that DOM
16
+ * property so the native mechanism carries the semantics.
17
+ *
18
+ * **Keyboard interactions:**
19
+ * - Tab: moves focus to the native `<input type="checkbox">`.
20
+ * - Space: toggles the checked state (native behavior).
21
+ * - Enter: no native effect on a checkbox (unlike button). Form
22
+ * submission triggered by Enter comes from the enclosing form's
23
+ * default submit button, not from the checkbox itself.
24
+ *
25
+ * **ARIA:**
26
+ * - Roles used: none explicit — the native checkbox supplies the
27
+ * implicit `checkbox` role.
28
+ * - State attributes: `checked` (DOM property, kept in sync via
29
+ * componentDidRender because Stencil does not JSX-forward the
30
+ * attribute cleanly for controlled use), `disabled` (native
31
+ * attribute, not `aria-disabled`), `aria-invalid` (from the
32
+ * `invalid` prop), `aria-required` (from the `required` prop),
33
+ * `aria-describedby` (from the `describedBy` prop).
34
+ * - Labeling strategy: `aria-label` set from the `label` prop onto
35
+ * the internal checkbox. This is the **canonical, recommended**
36
+ * mode. Wrapping the host in a light-DOM `<label>` also produces
37
+ * an accessible name in Chromium via flattened-tree resolution —
38
+ * same secondary mode documented on `ds-input`.
39
+ *
40
+ * **Focus:**
41
+ * - On mount: nothing auto-focuses.
42
+ * - On toggle: focus remains on the native checkbox.
43
+ * - Focus indicator: browser default `:focus-visible` ring, kept on
44
+ * purpose until the DS ships a themed focus utility using
45
+ * `--ds-color-focus`. Not overridden by `ds-checkbox.css`.
46
+ *
47
+ * **Motion:**
48
+ * - Animations: none.
49
+ * - Reduced-motion behavior: N/A.
50
+ *
51
+ * **Contrast:**
52
+ * - Text: N/A — the checkbox itself renders no text (labels are
53
+ * supplied by the consumer via `label` prop or wrapping <label>).
54
+ * - Non-text (the box and its check glyph): browser default rendering
55
+ * is kept on purpose (no `appearance: none` override); this
56
+ * preserves the OS/browser accessibility rendering that AT and
57
+ * forced-color modes rely on. A themed override is a future
58
+ * decision once the DS commits to a checkbox visual language that
59
+ * still passes 3:1 non-text contrast in every theme.
60
+ *
61
+ * **Screen reader announcement:**
62
+ * - Rendered state: announces the `label` prop text as the
63
+ * accessible name, followed by "checkbox", followed by "checked"
64
+ * / "not checked" / "mixed" per the current DOM state.
65
+ * - State change: on toggle, AT announces the new state (native
66
+ * behavior); no `aria-live` added.
67
+ *
68
+ * **Consumer contract:**
69
+ * - `checked` is the source of truth for controlled use. Reading
70
+ * `event.detail` from `dsChange` gives the new state; the internal
71
+ * input is kept in sync via a Watch + a re-sync in componentDidRender.
72
+ * - `indeterminate` is a visual/AT state, not a value — it is NOT
73
+ * submitted with a form and clears on the next user toggle.
74
+ */
75
+ export declare class DsCheckbox {
76
+ private inputEl?;
77
+ checked: boolean;
78
+ indeterminate: boolean;
79
+ name?: string;
80
+ value?: string;
81
+ disabled: boolean;
82
+ required: boolean;
83
+ invalid: boolean;
84
+ describedBy?: string;
85
+ label?: string;
86
+ dsChange: EventEmitter<boolean>;
87
+ watchChecked(newValue: boolean): void;
88
+ watchIndeterminate(newValue: boolean): void;
89
+ componentDidLoad(): void;
90
+ componentDidUpdate(): void;
91
+ private syncNativeState;
92
+ private onChange;
93
+ render(): any;
94
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * ## Accessibility
3
+ *
4
+ * **Category:** interactive-display
5
+ * **APG pattern:** Button — https://www.w3.org/WAI/ARIA/apg/patterns/button/
6
+ * (for the internal copy control; the code readout itself is static text).
7
+ *
8
+ * **Keyboard interactions:**
9
+ * - Tab: moves focus into the internal copy `<button>`; the code readout
10
+ * (`<pre><code>`) is not focusable itself, but its container is
11
+ * horizontally scrollable and remains reachable via the browser's caret
12
+ * browsing / find-in-page path.
13
+ * - Enter: activates the copy button (writes `code` to the clipboard).
14
+ * - Space: activates the copy button (native `<button>` behavior).
15
+ * - Escape: N/A — the "Copied" state auto-clears after 1.4s; no dismissible
16
+ * modal state.
17
+ * - Arrow keys: N/A.
18
+ * - Printable characters: N/A.
19
+ *
20
+ * **ARIA:**
21
+ * - Roles used: none explicit — the native `<button>` supplies the implicit
22
+ * `button` role; `<pre>` and `<code>` supply their semantic roles.
23
+ * - State attributes: none. The `copied` flag lives only in the button's
24
+ * accessible name (see below); it is intentionally not surfaced via
25
+ * `aria-pressed` because it is not a toggle — it is a transient
26
+ * post-action confirmation.
27
+ * - Labeling strategy: `aria-label` on the copy button — "Copy code" in the
28
+ * resting state, "Copied" while the confirmation is visible. This is
29
+ * authoritative because the button carries both an icon and the words
30
+ * "Copy" / "Copied", and mixed icon+text needs an explicit accessible
31
+ * name to avoid AT reading the SVG as a separate node.
32
+ *
33
+ * **Focus:**
34
+ * - On mount: nothing auto-focuses.
35
+ * - On activate: focus stays on the copy button (clipboard write is
36
+ * synchronous from the user's perspective; no focus is moved).
37
+ * - On close/deactivate: N/A — no popup or overlay to close.
38
+ * - Focus indicator: 2px `outline` in `var(--ds-color-focus)` with 2px
39
+ * `outline-offset`, applied to `.ds-code-block__copy:focus-visible`. The
40
+ * readout itself is not focusable and has no focus indicator by design.
41
+ *
42
+ * **Motion:**
43
+ * - Animations: 120ms `color` / `border-color` ease transition on the copy
44
+ * button (hover/focus).
45
+ * - Reduced-motion behavior: N/A — 120ms is below the spec's 200ms
46
+ * threshold, and the transition animates color only.
47
+ *
48
+ * **Contrast:**
49
+ * - Text (code readout): inherits `color: currentColor`; contrast depends
50
+ * on the host page's text color vs. the block's tinted background
51
+ * (`color-mix(currentColor 4%, transparent)`). Verify per site.
52
+ * - Text (copy button): `color-mix(in oklch, currentColor 70%, transparent)`
53
+ * at rest, `currentColor` on hover. The 70%-mixed resting color can drop
54
+ * below 4.5:1 on low-contrast surfaces — audit per usage site, and lean
55
+ * on the hover/focus states (both restore full `currentColor`) as the
56
+ * accessible fallback.
57
+ * - Non-text (button border, language tag border-bottom): both use
58
+ * `color-mix(currentColor <15|12>%, transparent)` — decorative separators,
59
+ * they do not convey state, so the 3:1 non-text contrast rule does not
60
+ * apply. Focus and hover borders shift up to 30% for clearer edges.
61
+ *
62
+ * **Screen reader announcement:**
63
+ * - Rendered state: announces "Copy code, button" (the `aria-label`), then
64
+ * the code content when the user navigates into the `<pre><code>` block
65
+ * (usually announced as a code block on VoiceOver).
66
+ * - State change: after clicking Copy, the button's `aria-label` flips to
67
+ * "Copied"; AT will announce this on the next focus or re-read of the
68
+ * button, but NOT proactively — there is no `aria-live` region. This is
69
+ * deliberate per spec §"What we explicitly do NOT do" (avoid live-region
70
+ * overuse), and the trade-off is that a screen-reader-only user does not
71
+ * get an unsolicited confirmation. If a future review decides that
72
+ * confirmation must be audible, add a visually-hidden
73
+ * `aria-live="polite"` element whose text toggles on `copied`.
74
+ */
75
+ export declare class DsCodeBlock {
76
+ code: string;
77
+ language: string;
78
+ copied: boolean;
79
+ private timer?;
80
+ disconnectedCallback(): void;
81
+ private onCopy;
82
+ render(): any;
83
+ }