asma-ui-core 3.78.4 → 3.78.6
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/dist/src/a11y/contrast/contrastPairs.d.ts +110 -0
- package/dist/src/a11y/contrast/themeContrast.test.d.ts +1 -0
- package/dist/src/a11y/contrast/themeTokens.d.ts +36 -0
- package/dist/src/a11y/contrast/themeTokens.test.d.ts +1 -0
- package/dist/src/a11y/contrast/wcagContrast.d.ts +32 -0
- package/dist/src/a11y/contrast/wcagContrast.test.d.ts +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The colour pairs this library actually puts on screen, as a data table.
|
|
3
|
+
*
|
|
4
|
+
* Every row cites the component file that pairs the two tokens, so a reviewer can check the claim
|
|
5
|
+
* without trusting the table. Tokens are cited by NAME, never by line number — `src/styles/**` is
|
|
6
|
+
* ASMA-8133's area and its line numbers move.
|
|
7
|
+
*
|
|
8
|
+
* Rows with a `finding` are measured failures against master. They are quarantined, not fixed:
|
|
9
|
+
* changing a token value is a visual (potentially breaking) change to a brand theme and needs
|
|
10
|
+
* design sign-off, so each one is written up in `docs/a11y-contrast.md` and escalated instead.
|
|
11
|
+
*
|
|
12
|
+
* @see docs/a11y-contrast.md — findings register, exemption rationale, measured ratios
|
|
13
|
+
* @see docs/a11y-allowlist.md — the axe (SC 1.4.3 only) story baseline this cross-references
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The surface the library composites onto when a token is `transparent`, and the surface an
|
|
17
|
+
* unparented control is assumed to sit on. The library ships no page-background token; every
|
|
18
|
+
* component that sets its own opaque surface (input, tooltip, chip) uses white or a delta tint.
|
|
19
|
+
*/
|
|
20
|
+
export declare const APP_SURFACE = "#ffffff";
|
|
21
|
+
export declare const REQUIREMENT_RATIO: {
|
|
22
|
+
/** SC 1.4.3, body text below 18.66px bold / 24px regular. */
|
|
23
|
+
readonly text: 4.5;
|
|
24
|
+
/** SC 1.4.3, large text at or above that size. */
|
|
25
|
+
readonly largeText: 3;
|
|
26
|
+
/** SC 1.4.11, UI component boundaries, state indicators and focus rings. */
|
|
27
|
+
readonly nonText: 3;
|
|
28
|
+
};
|
|
29
|
+
export type ContrastRequirement = keyof typeof REQUIREMENT_RATIO;
|
|
30
|
+
export interface ContrastPair {
|
|
31
|
+
/** Stable id. Quarantined rows use it to join to `docs/a11y-contrast.md`. */
|
|
32
|
+
readonly id: string;
|
|
33
|
+
/** Custom-property name, or a literal colour for a hard-coded component value. */
|
|
34
|
+
readonly foreground: string;
|
|
35
|
+
readonly background: string;
|
|
36
|
+
readonly requirement: ContrastRequirement;
|
|
37
|
+
/** Repo-relative path of the component that pairs these two. */
|
|
38
|
+
readonly usedBy: string;
|
|
39
|
+
/** Findings id in docs/a11y-contrast.md. Present means "measured failing, quarantined". */
|
|
40
|
+
readonly finding?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Hand-curated pairs. The button token family is generated instead — see `buildButtonPairs`.
|
|
44
|
+
*/
|
|
45
|
+
export declare const COMPONENT_PAIRS: readonly ContrastPair[];
|
|
46
|
+
/**
|
|
47
|
+
* `StyledButton.module.scss` builds every button from a single mixin over
|
|
48
|
+
* `--colors-button-{type}-{color}-{state}-{text|bg|border}-color`, so the button pairs are
|
|
49
|
+
* generated from the token names rather than transcribed. A new variant or state added to the
|
|
50
|
+
* token files is contrast-checked the moment it lands, with no edit here.
|
|
51
|
+
*/
|
|
52
|
+
export declare const BUTTON_TYPES: readonly ["contained", "outlined", "text", "textGray", "textWhite"];
|
|
53
|
+
export declare const BUTTON_COLORS: readonly ["common", "error"];
|
|
54
|
+
/**
|
|
55
|
+
* `disabled` is deliberately absent. SC 1.4.3 exempts "text ... that is part of an inactive user
|
|
56
|
+
* interface component", and 1.4.11 exempts inactive components in the same words. See the
|
|
57
|
+
* exemptions section of docs/a11y-contrast.md.
|
|
58
|
+
*/
|
|
59
|
+
export declare const BUTTON_STATES: readonly ["base", "hover", "active", "focused"];
|
|
60
|
+
export type ButtonType = (typeof BUTTON_TYPES)[number];
|
|
61
|
+
export type ButtonState = (typeof BUTTON_STATES)[number];
|
|
62
|
+
export interface ButtonTokenNames {
|
|
63
|
+
readonly text: string;
|
|
64
|
+
readonly background: string;
|
|
65
|
+
readonly border: string;
|
|
66
|
+
}
|
|
67
|
+
export declare const buttonTokenNames: (type: ButtonType, color: (typeof BUTTON_COLORS)[number], state: ButtonState) => ButtonTokenNames;
|
|
68
|
+
/**
|
|
69
|
+
* Types whose boundary is a designed, always-present edge. `text` / `textGray` are borderless by
|
|
70
|
+
* design — the label carries the affordance and is held to 4.5:1, which is what SC 1.4.11's
|
|
71
|
+
* "visual information required to identify user interface components" asks for. `textWhite` is
|
|
72
|
+
* excluded from contrast assertions entirely: it is white-on-transparent, meant to be placed on a
|
|
73
|
+
* consumer-supplied dark surface this package never sees. Documented in docs/a11y-contrast.md.
|
|
74
|
+
*/
|
|
75
|
+
export declare const BUTTON_TYPES_WITH_BOUNDARY: readonly ButtonType[];
|
|
76
|
+
export declare const BUTTON_TYPES_WITHOUT_KNOWN_SURFACE: readonly ButtonType[];
|
|
77
|
+
/**
|
|
78
|
+
* Button pairs that fail against master, keyed `{type}/{color}/{state}/{aspect}`.
|
|
79
|
+
*
|
|
80
|
+
* `text-on-tinted-hover` (F-12): outlined/text/textGray put gama-500 on a gama-50 or gama-100 tint
|
|
81
|
+
* at hover and active, which drops the label under 4.5:1 in every theme.
|
|
82
|
+
* `boundary-focus` (F-07): the focus border is gama-400 everywhere, which is under 3:1 on white in
|
|
83
|
+
* default and fretex.
|
|
84
|
+
* `boundary-outlined-hover` (F-13): outlined's hover/active border is gama-300, under 3:1 in all
|
|
85
|
+
* three themes.
|
|
86
|
+
* `outlined/error/focused/text` (F-16): white label on a beta-100 tint, 1.27:1 in every theme.
|
|
87
|
+
* The error/focused boundary rows (F-15): the border points at `--colors-beta-400`, which no theme
|
|
88
|
+
* defines, so `default` and `greenish` render no focus border at all; `fretex` overrides it to
|
|
89
|
+
* gama-400 and lands at 2.24:1, which is F-07's root cause again.
|
|
90
|
+
*/
|
|
91
|
+
export declare const BUTTON_FINDINGS: Readonly<Record<string, string>>;
|
|
92
|
+
/**
|
|
93
|
+
* Regression floors for the quarantined pairs: the ratio each one measures on master, per theme.
|
|
94
|
+
*
|
|
95
|
+
* A quarantined pair is asserted against its floor rather than against the WCAG threshold, so the
|
|
96
|
+
* suite still detects *decay* on an already-failing pair while staying green if ASMA-8133 or a
|
|
97
|
+
* design fix legitimately *improves* the number. This is a characterization test — the floor is a
|
|
98
|
+
* record of the status quo, not a standard. The real target stays in docs/a11y-contrast.md against
|
|
99
|
+
* the finding id, and lifting a quarantine means deleting the pair's `finding` key so the live SC
|
|
100
|
+
* assertion takes over.
|
|
101
|
+
*
|
|
102
|
+
* `null` means the pair has no computed value at all — see F-15, where the `var()` chain is
|
|
103
|
+
* dangling so the browser drops the declaration outright. A floor is meaningless there, so those
|
|
104
|
+
* stay skipped.
|
|
105
|
+
*
|
|
106
|
+
* Values are produced by `contrastRatio`, which already truncates to two decimals, so the floor and
|
|
107
|
+
* the measurement are byte-identical and the comparison needs no epsilon. Regenerate after
|
|
108
|
+
* ASMA-8133 lands.
|
|
109
|
+
*/
|
|
110
|
+
export declare const REGRESSION_FLOORS: Readonly<Record<string, Readonly<Record<string, number | null>>>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** The theme every other theme layers on top of; selected by `:root`, not by a `data-theme` value. */
|
|
2
|
+
export declare const DEFAULT_THEME = "default";
|
|
3
|
+
export type ThemeName = string;
|
|
4
|
+
/**
|
|
5
|
+
* Every theme the stylesheets define, discovered rather than listed, so adding a fourth theme file
|
|
6
|
+
* automatically brings it into the contrast matrix instead of silently going unchecked.
|
|
7
|
+
*/
|
|
8
|
+
export declare const discoverThemeNames: () => ThemeName[];
|
|
9
|
+
export declare class TokenResolutionError extends Error {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Follows a `var()` chain to a literal. `var(--a, fallback)` uses the fallback only when `--a` is
|
|
13
|
+
* undefined, matching CSS. A cycle or a missing terminal value throws rather than resolving to
|
|
14
|
+
* something plausible — a contrast suite that silently treats an unresolvable token as black would
|
|
15
|
+
* report passes it has not earned.
|
|
16
|
+
*/
|
|
17
|
+
export declare const resolveDeclaration: (declarations: ReadonlyMap<string, string>, value: string, seen?: ReadonlySet<string>) => string;
|
|
18
|
+
export interface UnresolvableToken {
|
|
19
|
+
readonly property: string;
|
|
20
|
+
readonly reason: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ThemeResolution {
|
|
23
|
+
readonly resolved: Map<string, string>;
|
|
24
|
+
/**
|
|
25
|
+
* Properties whose `var()` chain never reaches a literal. At runtime the browser treats these
|
|
26
|
+
* as invalid at computed-value time, so the declaration is dropped entirely and the element
|
|
27
|
+
* falls back to the inherited or initial value — i.e. the styling the token file *says* it
|
|
28
|
+
* applies is silently not applied. Worth a test of its own.
|
|
29
|
+
*/
|
|
30
|
+
readonly unresolvable: UnresolvableToken[];
|
|
31
|
+
}
|
|
32
|
+
export declare const resolveTheme: (theme: ThemeName) => ThemeResolution;
|
|
33
|
+
/** Every custom property that applies to `theme`, resolved to a literal value. */
|
|
34
|
+
export declare const resolveThemeTokens: (theme: ThemeName) => Map<string, string>;
|
|
35
|
+
/** `resolveThemeTokens` for every discovered theme, keyed by theme name. */
|
|
36
|
+
export declare const resolveAllThemes: () => Map<ThemeName, Map<string, string>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WCAG 2.2 contrast maths, kept dependency-free and side-effect-free so it can be exercised from a
|
|
3
|
+
* plain node-environment vitest run (the `unit` project in vite.config.ts) with no DOM.
|
|
4
|
+
*
|
|
5
|
+
* Only the colour notations the theme CSS actually uses are supported — `#rgb` / `#rgba` /
|
|
6
|
+
* `#rrggbb` / `#rrggbbaa`, `rgb()` / `rgba()` (comma or space separated), and the `white` / `black`
|
|
7
|
+
* / `transparent` keywords. Anything else returns `null` rather than guessing, so an unparsed value
|
|
8
|
+
* surfaces as a loud failure instead of a silently-skipped assertion.
|
|
9
|
+
*
|
|
10
|
+
* @see https://www.w3.org/TR/WCAG22/#dfn-relative-luminance
|
|
11
|
+
* @see https://www.w3.org/TR/WCAG22/#dfn-contrast-ratio
|
|
12
|
+
*/
|
|
13
|
+
export interface Rgba {
|
|
14
|
+
readonly r: number;
|
|
15
|
+
readonly g: number;
|
|
16
|
+
readonly b: number;
|
|
17
|
+
/** 0–1. */
|
|
18
|
+
readonly a: number;
|
|
19
|
+
}
|
|
20
|
+
export declare const parseCssColor: (value: string) => Rgba | null;
|
|
21
|
+
/** Source-over compositing. `backdrop` must be opaque; the result always is. */
|
|
22
|
+
export declare const compositeOver: (source: Rgba, backdrop: Rgba) => Rgba;
|
|
23
|
+
export declare const relativeLuminance: ({ r, g, b }: Rgba) => number;
|
|
24
|
+
/**
|
|
25
|
+
* Contrast ratio of two opaque colours, truncated to two decimals.
|
|
26
|
+
*
|
|
27
|
+
* Truncated rather than rounded, for two reasons. It is conservative at the threshold — rounding
|
|
28
|
+
* would report a true 4.4951:1 as "4.5" and let a failing pair through — and it is what axe-core
|
|
29
|
+
* reports, so a ratio quoted in docs/a11y-contrast.md is digit-for-digit the same number as the
|
|
30
|
+
* one in the axe baseline in docs/a11y-allowlist.md.
|
|
31
|
+
*/
|
|
32
|
+
export declare const contrastRatio: (first: Rgba, second: Rgba) => number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "3.78.
|
|
6
|
+
"version": "3.78.6",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"**/*.css",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"vrt:accept": "bash scripts/vrt.sh accept",
|
|
67
67
|
"vrt:report": "playwright show-report",
|
|
68
68
|
"test-storybook": "npx vitest --project=storybook",
|
|
69
|
+
"test:interaction": "vitest --project=interaction --run",
|
|
69
70
|
"changeset:pre-beta": "changeset pre enter beta",
|
|
70
71
|
"changeset:pre-exit": "changeset pre exit",
|
|
71
72
|
"changeset:version": "changeset version",
|