@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.
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/chiralkit-ds/chiralkit-ds.css +1 -0
- package/dist/chiralkit-ds/chiralkit-ds.esm.js +1 -0
- package/dist/chiralkit-ds/index.esm.js +1 -0
- package/dist/chiralkit-ds/p-038fa008.entry.js +1 -0
- package/dist/chiralkit-ds/p-2fdc1012.entry.js +1 -0
- package/dist/chiralkit-ds/p-306ec33b.entry.js +1 -0
- package/dist/chiralkit-ds/p-3f704698.entry.js +1 -0
- package/dist/chiralkit-ds/p-41081d22.entry.js +1 -0
- package/dist/chiralkit-ds/p-7d7e5aac.entry.js +1 -0
- package/dist/chiralkit-ds/p-84b801f8.entry.js +1 -0
- package/dist/chiralkit-ds/p-a28c71b4.entry.js +1 -0
- package/dist/chiralkit-ds/p-be84312f.entry.js +1 -0
- package/dist/chiralkit-ds/p-c8015fe6.entry.js +1 -0
- package/dist/chiralkit-ds/p-d36a6bea.entry.js +1 -0
- package/dist/chiralkit-ds/p-e-glNjK6.js +2 -0
- package/dist/chiralkit-ds/p-f0f9ff61.entry.js +1 -0
- package/dist/cjs/chiralkit-ds.cjs.js +24 -0
- package/dist/cjs/ds-badge.cjs.entry.js +18 -0
- package/dist/cjs/ds-button.cjs.entry.js +26 -0
- package/dist/cjs/ds-card.cjs.entry.js +17 -0
- package/dist/cjs/ds-checkbox.cjs.entry.js +67 -0
- package/dist/cjs/ds-code-block.cjs.entry.js +39 -0
- package/dist/cjs/ds-dialog.cjs.entry.js +67 -0
- package/dist/cjs/ds-input.cjs.entry.js +50 -0
- package/dist/cjs/ds-loader.cjs.entry.js +26 -0
- package/dist/cjs/ds-select.cjs.entry.js +85 -0
- package/dist/cjs/ds-tabs.cjs.entry.js +138 -0
- package/dist/cjs/ds-textarea.cjs.entry.js +50 -0
- package/dist/cjs/ds-tooltip.cjs.entry.js +233 -0
- package/dist/cjs/index-mMvyq7U_.js +2018 -0
- package/dist/cjs/index.cjs.js +10 -0
- package/dist/cjs/loader.cjs.js +12 -0
- package/dist/collection/collection-manifest.json +24 -0
- package/dist/collection/components/ds-badge/ds-badge.css +36 -0
- package/dist/collection/components/ds-badge/ds-badge.js +93 -0
- package/dist/collection/components/ds-button/ds-button.css +66 -0
- package/dist/collection/components/ds-button/ds-button.js +197 -0
- package/dist/collection/components/ds-card/ds-card.css +12 -0
- package/dist/collection/components/ds-card/ds-card.js +68 -0
- package/dist/collection/components/ds-checkbox/ds-checkbox.css +22 -0
- package/dist/collection/components/ds-checkbox/ds-checkbox.js +339 -0
- package/dist/collection/components/ds-code-block/ds-code-block.css +65 -0
- package/dist/collection/components/ds-code-block/ds-code-block.js +162 -0
- package/dist/collection/components/ds-dialog/ds-dialog.css +30 -0
- package/dist/collection/components/ds-dialog/ds-dialog.js +313 -0
- package/dist/collection/components/ds-input/ds-input.css +38 -0
- package/dist/collection/components/ds-input/ds-input.js +353 -0
- package/dist/collection/components/ds-loader/ds-loader.css +94 -0
- package/dist/collection/components/ds-loader/ds-loader.js +149 -0
- package/dist/collection/components/ds-select/ds-select.css +69 -0
- package/dist/collection/components/ds-select/ds-select.js +235 -0
- package/dist/collection/components/ds-tabs/ds-tabs.css +59 -0
- package/dist/collection/components/ds-tabs/ds-tabs.js +248 -0
- package/dist/collection/components/ds-textarea/ds-textarea.css +41 -0
- package/dist/collection/components/ds-textarea/ds-textarea.js +342 -0
- package/dist/collection/components/ds-tooltip/ds-tooltip.css +31 -0
- package/dist/collection/components/ds-tooltip/ds-tooltip.js +318 -0
- package/dist/collection/components.js +2 -0
- package/dist/collection/index.js +1 -0
- package/dist/components/ds-badge.d.ts +11 -0
- package/dist/components/ds-badge.js +1 -0
- package/dist/components/ds-button.d.ts +11 -0
- package/dist/components/ds-button.js +1 -0
- package/dist/components/ds-card.d.ts +11 -0
- package/dist/components/ds-card.js +1 -0
- package/dist/components/ds-checkbox.d.ts +11 -0
- package/dist/components/ds-checkbox.js +1 -0
- package/dist/components/ds-code-block.d.ts +11 -0
- package/dist/components/ds-code-block.js +1 -0
- package/dist/components/ds-dialog.d.ts +11 -0
- package/dist/components/ds-dialog.js +1 -0
- package/dist/components/ds-input.d.ts +11 -0
- package/dist/components/ds-input.js +1 -0
- package/dist/components/ds-loader.d.ts +11 -0
- package/dist/components/ds-loader.js +1 -0
- package/dist/components/ds-select.d.ts +11 -0
- package/dist/components/ds-select.js +1 -0
- package/dist/components/ds-tabs.d.ts +11 -0
- package/dist/components/ds-tabs.js +1 -0
- package/dist/components/ds-textarea.d.ts +11 -0
- package/dist/components/ds-textarea.js +1 -0
- package/dist/components/ds-tooltip.d.ts +11 -0
- package/dist/components/ds-tooltip.js +1 -0
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +1 -0
- package/dist/components/p-DDUZow8F.js +1 -0
- package/dist/components/p-ZsYP0VBq.js +1 -0
- package/dist/components/p-k0ywxWpC.js +1 -0
- package/dist/esm/chiralkit-ds.js +20 -0
- package/dist/esm/ds-badge.entry.js +16 -0
- package/dist/esm/ds-button.entry.js +24 -0
- package/dist/esm/ds-card.entry.js +15 -0
- package/dist/esm/ds-checkbox.entry.js +65 -0
- package/dist/esm/ds-code-block.entry.js +37 -0
- package/dist/esm/ds-dialog.entry.js +65 -0
- package/dist/esm/ds-input.entry.js +48 -0
- package/dist/esm/ds-loader.entry.js +24 -0
- package/dist/esm/ds-select.entry.js +83 -0
- package/dist/esm/ds-tabs.entry.js +136 -0
- package/dist/esm/ds-textarea.entry.js +48 -0
- package/dist/esm/ds-tooltip.entry.js +231 -0
- package/dist/esm/index-e-glNjK6.js +2008 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/loader.js +10 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/layouts/app-shell.css +84 -0
- package/dist/tests/a11y.js +55 -0
- package/dist/types/Users/alex/projects/MyGitHub/chiralkit/packages/design-system/.stencil/tests/a11y.d.ts +17 -0
- package/dist/types/components/ds-badge/ds-badge.d.ts +54 -0
- package/dist/types/components/ds-button/ds-button.d.ts +75 -0
- package/dist/types/components/ds-card/ds-card.d.ts +53 -0
- package/dist/types/components/ds-checkbox/ds-checkbox.d.ts +94 -0
- package/dist/types/components/ds-code-block/ds-code-block.d.ts +83 -0
- package/dist/types/components/ds-dialog/ds-dialog.d.ts +148 -0
- package/dist/types/components/ds-input/ds-input.d.ts +104 -0
- package/dist/types/components/ds-loader/ds-loader.d.ts +64 -0
- package/dist/types/components/ds-select/ds-select.d.ts +123 -0
- package/dist/types/components/ds-tabs/ds-tabs.d.ts +155 -0
- package/dist/types/components/ds-textarea/ds-textarea.d.ts +93 -0
- package/dist/types/components/ds-tooltip/ds-tooltip.d.ts +26 -0
- package/dist/types/components.d.ts +3068 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/stencil-public-runtime.d.ts +1861 -0
- package/docs.json +2112 -0
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +78 -0
- package/react/components/ds-badge.tsx +25 -0
- package/react/components/ds-button.tsx +25 -0
- package/react/components/ds-card.tsx +25 -0
- package/react/components/ds-checkbox.tsx +25 -0
- package/react/components/ds-code-block.tsx +25 -0
- package/react/components/ds-dialog.tsx +31 -0
- package/react/components/ds-input.tsx +25 -0
- package/react/components/ds-loader.tsx +25 -0
- package/react/components/ds-select.tsx +25 -0
- package/react/components/ds-tabs.tsx +25 -0
- package/react/components/ds-textarea.tsx +25 -0
- package/react/components/ds-tooltip.tsx +25 -0
- package/react/components.ts +162 -0
|
@@ -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
|
+
}
|