@motion-proto/live-tokens 0.97.0 → 0.98.2
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/.claude/skills/live-tokens-check-compliance/SKILL.md +5 -0
- package/.claude/skills/live-tokens-create-component/SKILL.md +4 -3
- package/.claude/skills/live-tokens-create-component/references/contract-tests.md +71 -11
- package/CHANGELOG.md +272 -0
- package/README.md +2 -2
- package/bin/check-component.mjs +8 -0
- package/bin/check-page.mjs +6 -0
- package/bin/cli.mjs +36 -6
- package/bin/contractRunner.mjs +142 -17
- package/bin/lib/findings.mjs +20 -4
- package/bin/rules/a11y.mjs +53 -0
- package/dist-plugin/{chunk-A4TBP4MM.js → chunk-SLICH4IH.js} +2 -2
- package/dist-plugin/index.cjs +148 -3
- package/dist-plugin/index.js +250 -105
- package/dist-plugin/setColors/index.js +1 -1
- package/package.json +47 -2
- package/src/demo/LabeledSelect.svelte +1 -1
- package/src/editor/bootstrap.ts +3 -1
- package/src/editor/component-editor/BadgeEditor.svelte +13 -0
- package/src/editor/component-editor/ButtonEditor.svelte +33 -2
- package/src/editor/component-editor/CalloutEditor.svelte +13 -0
- package/src/editor/component-editor/CardEditor.svelte +12 -2
- package/src/editor/component-editor/CodeSnippetEditor.svelte +11 -1
- package/src/editor/component-editor/CollapsibleSectionEditor.svelte +18 -1
- package/src/editor/component-editor/CornerBadgeEditor.svelte +13 -0
- package/src/editor/component-editor/DialogEditor.svelte +15 -0
- package/src/editor/component-editor/IconButtonEditor.svelte +29 -1
- package/src/editor/component-editor/ImageEditor.svelte +20 -9
- package/src/editor/component-editor/ImageLightboxEditor.svelte +44 -0
- package/src/editor/component-editor/InlineEditActionsEditor.svelte +13 -1
- package/src/editor/component-editor/InputEditor.svelte +23 -0
- package/src/editor/component-editor/MenuSelectEditor.svelte +27 -1
- package/src/editor/component-editor/NotificationEditor.svelte +15 -0
- package/src/editor/component-editor/PanelEditor.svelte +1 -1
- package/src/editor/component-editor/ProgressBarEditor.svelte +13 -0
- package/src/editor/component-editor/RadioButtonEditor.svelte +20 -1
- package/src/editor/component-editor/SectionDividerEditor.svelte +41 -13
- package/src/editor/component-editor/SegmentedControlEditor.svelte +29 -1
- package/src/editor/component-editor/SideNavigationEditor.svelte +40 -1
- package/src/editor/component-editor/SlidePagerEditor.svelte +20 -0
- package/src/editor/component-editor/SliderEditor.svelte +33 -0
- package/src/editor/component-editor/TabBarEditor.svelte +23 -2
- package/src/editor/component-editor/TableEditor.svelte +14 -0
- package/src/editor/component-editor/ToggleEditor.svelte +17 -0
- package/src/editor/component-editor/TooltipEditor.svelte +11 -2
- package/src/editor/component-editor/VideoFrameEditor.svelte +8 -0
- package/src/editor/component-editor/VideoLightboxEditor.svelte +10 -0
- package/src/editor/component-editor/registration.ts +2 -1
- package/src/editor/component-editor/registry.ts +69 -27
- package/src/editor/component-editor/scaffolding/DemoHeader.svelte +2 -0
- package/src/editor/component-editor/scaffolding/StateBlock.svelte +19 -8
- package/src/editor/component-editor/scaffolding/TokenLayout.svelte +3 -0
- package/src/editor/component-editor/scaffolding/VariantGroup.svelte +70 -3
- package/src/editor/component-editor/scaffolding/editorContext.ts +7 -0
- package/src/editor/core/a11y/a11yReport.ts +101 -0
- package/src/editor/core/a11y/a11yReportTypes.ts +69 -0
- package/src/editor/core/a11y/contrastFailures.ts +22 -0
- package/src/editor/core/components/contrastPairRegistry.ts +18 -0
- package/src/editor/core/palettes/contrast.ts +44 -0
- package/src/editor/core/palettes/contrastPairs.ts +79 -0
- package/src/editor/core/palettes/resolveColor.ts +77 -0
- package/src/editor/core/store/editorStore.ts +4 -0
- package/src/editor/core/store/editorViewStore.ts +2 -2
- package/src/editor/core/store/unsavedEdits.ts +10 -0
- package/src/editor/core/themes/liveStateStream.ts +7 -1
- package/src/editor/core/themes/parsers/gradient.ts +5 -2
- package/src/editor/docs/chapters.ts +1 -0
- package/src/editor/docs/content/accessibility.md +362 -0
- package/src/editor/docs/content/editing-tokens.md +28 -1
- package/src/editor/docs/content.generated.ts +2 -1
- package/src/editor/pages/ComponentEditorPage.svelte +10 -1
- package/src/editor/pages/EditorShell.svelte +96 -10
- package/src/editor/skill-atlas/skillSources.generated.ts +3 -3
- package/src/editor/skill-atlas/trees/check-compliance.ts +3 -3
- package/src/editor/skill-atlas/trees/create-component.ts +12 -12
- package/src/editor/ui/EditorViewSwitcher.svelte +15 -2
- package/src/editor/ui/GradientEditor.svelte +9 -1
- package/src/editor/ui/ThemePanel.svelte +4 -4
- package/src/editor/ui/UIContrastReadout.svelte +186 -0
- package/src/editor/ui/UIInfoPopover.svelte +16 -2
- package/src/editor/ui/UIPaletteSelector.svelte +9 -0
- package/src/editor/ui/UITokenSelector.svelte +26 -2
- package/src/editor/ui/a11y/A11yComponentIssues.svelte +103 -0
- package/src/editor/ui/a11y/A11yFindingRow.svelte +57 -0
- package/src/editor/ui/a11y/A11yIssueRow.svelte +121 -0
- package/src/editor/ui/a11y/A11yOverview.svelte +242 -0
- package/src/editor/ui/a11y/A11yPanel.svelte +128 -0
- package/src/editor/ui/a11y/A11yPropertyMark.svelte +84 -0
- package/src/editor/ui/a11y/A11yRailMark.svelte +34 -0
- package/src/editor/ui/a11y/AccessibilityTab.svelte +334 -0
- package/src/editor/ui/a11y/a11yView.ts +218 -0
- package/src/editor/ui/contrastReadout.ts +45 -0
- package/src/live-tokens/data/themes/autumn.json +20 -20
- package/src/live-tokens/data/themes/halloween.json +20 -20
- package/src/live-tokens/data/themes/midnight-study.json +20 -20
- package/src/live-tokens/data/themes/ocean.json +20 -20
- package/src/live-tokens/data/themes/royal-velvet.json +20 -20
- package/src/live-tokens/data/themes/sketchy.json +20 -20
- package/src/live-tokens/data/themes/spring-meadow.json +20 -20
- package/src/live-tokens/data/themes/sunset.json +20 -20
- package/src/system/components/Badge.svelte +3 -3
- package/src/system/components/Button.svelte +9 -3
- package/src/system/components/CodeSnippet.svelte +8 -1
- package/src/system/components/CornerBadge.svelte +3 -3
- package/src/system/components/Dialog.svelte +43 -14
- package/src/system/components/IconButton.svelte +1 -1
- package/src/system/components/Image.svelte +7 -0
- package/src/system/components/ImageLightbox.svelte +18 -25
- package/src/system/components/Input.svelte +8 -1
- package/src/system/components/MenuSelect.svelte +30 -2
- package/src/system/components/Notification.svelte +1 -1
- package/src/system/components/ProgressBar.svelte +6 -0
- package/src/system/components/RadioButton.svelte +36 -3
- package/src/system/components/SegmentedControl.svelte +36 -2
- package/src/system/components/SlidePager.svelte +2 -2
- package/src/system/components/Slider.svelte +13 -9
- package/src/system/components/TabBar.svelte +33 -3
- package/src/system/components/Toggle.svelte +2 -2
- package/src/system/components/VideoFrame.svelte +1 -1
- package/src/system/components/VideoLightbox.svelte +2 -2
- package/src/system/internal/focusTrap.ts +35 -0
- package/src/testing-js/__aria__/badge.yml +40 -0
- package/src/testing-js/__aria__/button.yml +88 -0
- package/src/testing-js/__aria__/callout.yml +12 -0
- package/src/testing-js/__aria__/card.yml +8 -0
- package/src/testing-js/__aria__/codesnippet.yml +21 -0
- package/src/testing-js/__aria__/collapsiblesection.yml +23 -0
- package/src/testing-js/__aria__/cornerbadge.yml +24 -0
- package/src/testing-js/__aria__/dialog.yml +42 -0
- package/src/testing-js/__aria__/iconbutton.yml +57 -0
- package/src/testing-js/__aria__/image.yml +10 -0
- package/src/testing-js/__aria__/imagelightbox.yml +50 -0
- package/src/testing-js/__aria__/inlineeditactions.yml +16 -0
- package/src/testing-js/__aria__/input.yml +61 -0
- package/src/testing-js/__aria__/menuselect.yml +30 -0
- package/src/testing-js/__aria__/notification.yml +30 -0
- package/src/testing-js/__aria__/panel.yml +2 -0
- package/src/testing-js/__aria__/progressbar.yml +2 -0
- package/src/testing-js/__aria__/radiobutton.yml +20 -0
- package/src/testing-js/__aria__/sectiondivider.yml +9 -0
- package/src/testing-js/__aria__/segmentedcontrol.yml +35 -0
- package/src/testing-js/__aria__/sidenavigation.yml +304 -0
- package/src/testing-js/__aria__/slidepager.yml +72 -0
- package/src/testing-js/__aria__/slider.yml +28 -0
- package/src/testing-js/__aria__/tabbar.yml +35 -0
- package/src/testing-js/__aria__/table.yml +144 -0
- package/src/testing-js/__aria__/toggle.yml +12 -0
- package/src/testing-js/__aria__/tooltip.yml +2 -0
- package/src/testing-js/__aria__/videoframe.yml +6 -0
- package/src/testing-js/__aria__/videolightbox.yml +12 -0
- package/src/testing-js/{chunk-WIZ6W7UT.js → chunk-3WCLMOM7.js} +2 -2
- package/src/testing-js/{chunk-SHBYZUPD.js → chunk-5HNZHIHG.js} +211 -14
- package/src/testing-js/chunk-5HNZHIHG.js.map +1 -0
- package/src/testing-js/{chunk-NB3NZRBM.js → chunk-7CM5D7PF.js} +5 -1
- package/src/testing-js/chunk-7CM5D7PF.js.map +1 -0
- package/src/testing-js/chunk-EWSGE27V.js +168 -0
- package/src/testing-js/chunk-EWSGE27V.js.map +1 -0
- package/src/testing-js/{chunk-GKO27NGN.js → chunk-R54I7YL6.js} +2 -2
- package/src/testing-js/{chunk-X6KHEVIG.js → chunk-RWH46IU5.js} +97 -29
- package/src/testing-js/chunk-RWH46IU5.js.map +1 -0
- package/src/testing-js/chunk-SHLPDNAQ.js +658 -0
- package/src/testing-js/chunk-SHLPDNAQ.js.map +1 -0
- package/src/testing-js/{chunk-3UKGXCDL.js → chunk-YVVR3GJZ.js} +1 -1
- package/src/testing-js/chunk-YVVR3GJZ.js.map +1 -0
- package/src/testing-js/component-a11y.contract.js +283 -0
- package/src/testing-js/component-a11y.contract.js.map +1 -0
- package/src/testing-js/component-alias.contract.js +2 -2
- package/src/testing-js/component-behavior.contract.js +2 -2
- package/src/testing-js/component-editor.contract.js +6 -5
- package/src/testing-js/component-editor.contract.js.map +1 -1
- package/src/testing-js/component-render.contract.js +10 -6
- package/src/testing-js/component-render.contract.js.map +1 -1
- package/src/testing-js/index.d.ts +44 -16
- package/src/testing-js/index.js +9 -9
- package/src/testing-js/page-compliance.contract.js +132 -13
- package/src/testing-js/page-compliance.contract.js.map +1 -1
- package/src/testing-js/vitest.js +3 -3
- package/template/package.json +9 -0
- package/src/testing-js/chunk-3UKGXCDL.js.map +0 -1
- package/src/testing-js/chunk-NB3NZRBM.js.map +0 -1
- package/src/testing-js/chunk-SHBYZUPD.js.map +0 -1
- package/src/testing-js/chunk-X6KHEVIG.js.map +0 -1
- /package/src/testing-js/{chunk-WIZ6W7UT.js.map → chunk-3WCLMOM7.js.map} +0 -0
- /package/src/testing-js/{chunk-GKO27NGN.js.map → chunk-R54I7YL6.js.map} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildTypeGroupTokens, buildTypeGroupShareableContexts } from './scaffolding/buildTypeGroupTokens';
|
|
3
3
|
import type { Token, TypeGroupConfig } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'input';
|
|
6
7
|
|
|
@@ -146,6 +147,28 @@
|
|
|
146
147
|
// Silence unused-import lint without changing behavior; buildTypeGroupTokens stays available
|
|
147
148
|
// for editors that want auto-derived color rows, but we keep ours hand-built for slot-prefixed groupKeys.
|
|
148
149
|
void buildTypeGroupTokens;
|
|
150
|
+
|
|
151
|
+
function textPair(foreground: string, state: string, backdrop: string[]): ContrastPair {
|
|
152
|
+
const g = typeGroups[state][0];
|
|
153
|
+
return { foreground, backdrop, role: 'text', fontSize: g.sizeVariable, fontWeight: g.weightVariable };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// The placeholder paints on each state's surface at that state's text size.
|
|
157
|
+
// The icon button takes the focused icon color on hover and focus while the
|
|
158
|
+
// field itself stays unfocused. Label, hint and error sit on no surface.
|
|
159
|
+
export const contrastPairs: ContrastPair[] = [
|
|
160
|
+
textPair('--input-default-text', 'default', ['--input-default-surface']),
|
|
161
|
+
textPair('--input-focused-text', 'focused', ['--input-focused-surface']),
|
|
162
|
+
{ ...textPair('--input-disabled-text', 'disabled', ['--input-disabled-surface']), inactive: true },
|
|
163
|
+
{ ...textPair('--input-default-placeholder', 'default', ['--input-default-surface']), context: 'default' },
|
|
164
|
+
{ ...textPair('--input-default-placeholder', 'focused', ['--input-focused-surface']), context: 'focused' },
|
|
165
|
+
{ ...textPair('--input-default-placeholder', 'disabled', ['--input-disabled-surface']), context: 'disabled', inactive: true },
|
|
166
|
+
{ foreground: '--input-default-icon', backdrop: ['--input-default-surface'], role: 'non-text' },
|
|
167
|
+
{ foreground: '--input-focused-icon', backdrop: ['--input-focused-surface'], role: 'non-text', context: 'focused' },
|
|
168
|
+
{ foreground: '--input-focused-icon', backdrop: ['--input-default-surface'], role: 'non-text', context: 'icon button' },
|
|
169
|
+
{ foreground: '--input-disabled-icon', backdrop: ['--input-disabled-surface'], role: 'non-text', inactive: true },
|
|
170
|
+
...(['label', 'hint', 'error'] as const).map((slot) => textPair(`--input-${slot}`, slot, [])),
|
|
171
|
+
];
|
|
149
172
|
</script>
|
|
150
173
|
|
|
151
174
|
<script lang="ts">
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildTypeGroupTokens, buildTypeGroupShareableContexts } from './scaffolding/buildTypeGroupTokens';
|
|
3
3
|
import type { Token, TypeGroupConfig, IntrinsicSpec } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'menuselect';
|
|
6
7
|
|
|
@@ -106,6 +107,29 @@
|
|
|
106
107
|
default: { default: 'var(--color-transparent)' },
|
|
107
108
|
},
|
|
108
109
|
];
|
|
110
|
+
|
|
111
|
+
// Every item sits on the menu surface. The check mark paints on the selected item alone.
|
|
112
|
+
const menu = '--menuselect-menu-surface';
|
|
113
|
+
function itemContrastPairs(s: 'default' | 'hover' | 'selected' | 'disabled'): ContrastPair[] {
|
|
114
|
+
const backdrop = s === 'hover'
|
|
115
|
+
? ['--menuselect-hover-tint-enabled', '--menuselect-hover-surface', menu]
|
|
116
|
+
: [`--menuselect-${s}-surface`, menu];
|
|
117
|
+
const inactive = s === 'disabled' ? { inactive: true } : {};
|
|
118
|
+
const marks = s === 'selected' ? ['--menuselect-selected-icon', '--menuselect-selected-indicator'] : [`--menuselect-${s}-icon`];
|
|
119
|
+
return [
|
|
120
|
+
...typeGroups[`${s} item`].map((g): ContrastPair => ({
|
|
121
|
+
foreground: g.colorVariable,
|
|
122
|
+
backdrop,
|
|
123
|
+
role: 'text',
|
|
124
|
+
fontSize: g.sizeVariable,
|
|
125
|
+
fontWeight: g.weightVariable,
|
|
126
|
+
...inactive,
|
|
127
|
+
})),
|
|
128
|
+
...marks.map((foreground): ContrastPair => ({ foreground, backdrop, role: 'non-text', ...inactive })),
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export const contrastPairs: ContrastPair[] = (['default', 'hover', 'selected', 'disabled'] as const).flatMap(itemContrastPairs);
|
|
109
133
|
</script>
|
|
110
134
|
|
|
111
135
|
<script lang="ts">
|
|
@@ -115,6 +139,7 @@
|
|
|
115
139
|
import { editorState, setComponentAlias, clearComponentAlias } from '../core/store/editorStore';
|
|
116
140
|
import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
|
|
117
141
|
import Toggle from '../ui/Toggle.svelte';
|
|
142
|
+
import A11yPropertyMark from '../ui/a11y/A11yPropertyMark.svelte';
|
|
118
143
|
import UIPaletteSelector from '../ui/UIPaletteSelector.svelte';
|
|
119
144
|
|
|
120
145
|
// One switch. Turning the tint on also stands each hover surface down to its
|
|
@@ -178,7 +203,7 @@
|
|
|
178
203
|
{#snippet extraPropertyRows(stateName)}
|
|
179
204
|
{#if stateName === 'hover item'}
|
|
180
205
|
<div class="property-row" data-token-variables="--menuselect-hover-tint-enabled">
|
|
181
|
-
<span class="property-label">tint layer
|
|
206
|
+
<span class="property-label">tint layer<A11yPropertyMark variables={['--menuselect-hover-tint-enabled']} /></span>
|
|
182
207
|
<Toggle checked={tintOn} onchange={setTintOn} />
|
|
183
208
|
</div>
|
|
184
209
|
{#if tintOn}
|
|
@@ -203,6 +228,7 @@
|
|
|
203
228
|
items={previewItems}
|
|
204
229
|
value={previewValue}
|
|
205
230
|
forceHoverValue={previewForceHover}
|
|
231
|
+
ariaLabel="Options"
|
|
206
232
|
/>
|
|
207
233
|
{/snippet}
|
|
208
234
|
</VariantGroup>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import type { Token } from './scaffolding/types';
|
|
3
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
3
4
|
|
|
4
5
|
export const component = 'notification';
|
|
5
6
|
const variants = ['info', 'success', 'warning', 'danger'] as const;
|
|
@@ -67,6 +68,20 @@
|
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
const variantOptions = variants.map((v) => ({ value: v, label: v.charAt(0).toUpperCase() + v.slice(1) }));
|
|
71
|
+
|
|
72
|
+
// The body color also paints the dismiss button on the header. The body has
|
|
73
|
+
// no surface, and size="small" sets its description in --font-size-sm.
|
|
74
|
+
function variantContrastPairs(v: Variant): ContrastPair[] {
|
|
75
|
+
const header = [`--notification-${v}-surface`];
|
|
76
|
+
return [
|
|
77
|
+
{ foreground: `--notification-${v}-title`, backdrop: header, role: 'text', fontSize: `--notification-${v}-title-font-size`, fontWeight: `--notification-${v}-title-font-weight` },
|
|
78
|
+
{ foreground: `--notification-${v}-icon`, backdrop: header, role: 'non-text' },
|
|
79
|
+
{ foreground: `--notification-${v}-text`, backdrop: header, role: 'non-text', context: 'dismiss button' },
|
|
80
|
+
{ foreground: `--notification-${v}-text`, backdrop: [], role: 'text', fontSize: '--font-size-sm', fontWeight: `--notification-${v}-text-font-weight`, context: 'body' },
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const contrastPairs: ContrastPair[] = variants.flatMap(variantContrastPairs);
|
|
70
85
|
</script>
|
|
71
86
|
|
|
72
87
|
<script lang="ts">
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildTypeGroupColorTokens } from './scaffolding/buildTypeGroupTokens';
|
|
3
3
|
import type { Token, TypeGroupConfig } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'progressbar';
|
|
6
7
|
|
|
@@ -71,6 +72,18 @@
|
|
|
71
72
|
...buildTypeGroupColorTokens(typeGroups, { component }),
|
|
72
73
|
...typeGroupTokens,
|
|
73
74
|
];
|
|
75
|
+
|
|
76
|
+
// The label and value sit on no surface. The fill paints on the track.
|
|
77
|
+
export const contrastPairs: ContrastPair[] = [
|
|
78
|
+
...typeGroups.default.map((g): ContrastPair => ({
|
|
79
|
+
foreground: g.colorVariable,
|
|
80
|
+
backdrop: [],
|
|
81
|
+
role: 'text',
|
|
82
|
+
fontSize: g.sizeVariable,
|
|
83
|
+
fontWeight: g.weightVariable,
|
|
84
|
+
})),
|
|
85
|
+
{ foreground: '--progressbar-fill', backdrop: ['--progressbar-track-surface'], role: 'non-text' },
|
|
86
|
+
];
|
|
74
87
|
</script>
|
|
75
88
|
|
|
76
89
|
<script lang="ts">
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildTypeGroupColorTokens } from './scaffolding/buildTypeGroupTokens';
|
|
3
3
|
import type { Token, TypeGroupConfig } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'radiobutton';
|
|
6
7
|
|
|
@@ -79,6 +80,24 @@
|
|
|
79
80
|
...buildTypeGroupColorTokens(typeGroups, { component, variants: Object.keys(states) }),
|
|
80
81
|
...typeGroupTokens,
|
|
81
82
|
];
|
|
83
|
+
|
|
84
|
+
// The button paints no surface without the `color` prop, and the default dot
|
|
85
|
+
// stays hidden.
|
|
86
|
+
function stateContrastPairs(s: 'default' | 'hover' | 'selected'): ContrastPair[] {
|
|
87
|
+
const marks = s === 'default' ? ['--radiobutton-default-dot-border-color'] : [`--radiobutton-${s}-dot-border-color`, `--radiobutton-${s}-dot-fill`];
|
|
88
|
+
return [
|
|
89
|
+
...typeGroups[s].map((g): ContrastPair => ({
|
|
90
|
+
foreground: g.colorVariable,
|
|
91
|
+
backdrop: [],
|
|
92
|
+
role: 'text',
|
|
93
|
+
fontSize: g.sizeVariable,
|
|
94
|
+
fontWeight: g.weightVariable,
|
|
95
|
+
})),
|
|
96
|
+
...marks.map((foreground): ContrastPair => ({ foreground, backdrop: [], role: 'non-text' })),
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export const contrastPairs: ContrastPair[] = (['default', 'hover', 'selected'] as const).flatMap(stateContrastPairs);
|
|
82
101
|
</script>
|
|
83
102
|
|
|
84
103
|
<script lang="ts">
|
|
@@ -109,7 +128,7 @@
|
|
|
109
128
|
{#snippet children({ activeState })}
|
|
110
129
|
{@const forceClass = activeState === 'hover' ? 'force-hover' : ''}
|
|
111
130
|
{@const forceSelected = activeState === 'selected'}
|
|
112
|
-
<div class="radio-demo-row">
|
|
131
|
+
<div class="radio-demo-row" role="radiogroup" aria-label="Priority">
|
|
113
132
|
<RadioButton
|
|
114
133
|
label="Defense"
|
|
115
134
|
selected={forceSelected || selectedRadio === 'option-a'}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildSiblings } from './scaffolding/siblings';
|
|
3
3
|
import type { Token, TypeGroupConfig, IntrinsicSpec } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'sectiondivider';
|
|
6
7
|
|
|
@@ -193,6 +194,22 @@
|
|
|
193
194
|
},
|
|
194
195
|
];
|
|
195
196
|
const INTRINSIC_BY_KEY = new Map(intrinsics.map((i) => [i.key, i]));
|
|
197
|
+
|
|
198
|
+
function variantContrastPairs(v: Variant): ContrastPair[] {
|
|
199
|
+
const backdrop = [`--sectiondivider-${v}-surface`];
|
|
200
|
+
return [
|
|
201
|
+
...variantTypeGroups(v).map((g): ContrastPair => ({
|
|
202
|
+
foreground: g.colorVariable,
|
|
203
|
+
backdrop,
|
|
204
|
+
role: 'text',
|
|
205
|
+
fontSize: g.sizeVariable,
|
|
206
|
+
fontWeight: g.weightVariable,
|
|
207
|
+
})),
|
|
208
|
+
{ foreground: `--sectiondivider-${v}-hairline-color`, backdrop, role: 'non-text' },
|
|
209
|
+
];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export const contrastPairs: ContrastPair[] = variants.flatMap((v) => variantContrastPairs(v.key));
|
|
196
213
|
</script>
|
|
197
214
|
|
|
198
215
|
<script lang="ts">
|
|
@@ -200,6 +217,7 @@
|
|
|
200
217
|
import VariantGroup from './scaffolding/VariantGroup.svelte';
|
|
201
218
|
import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
|
|
202
219
|
import GradientEditor from '../ui/GradientEditor.svelte';
|
|
220
|
+
import A11yPropertyMark from '../ui/a11y/A11yPropertyMark.svelte';
|
|
203
221
|
import { editorState, mutate, setComponentAlias, setComponentConfig } from '../core/store/editorStore';
|
|
204
222
|
import { componentGradientSource } from '../core/store/gradientSource';
|
|
205
223
|
import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
|
|
@@ -376,16 +394,19 @@
|
|
|
376
394
|
description: {
|
|
377
395
|
checked: getShowDescription(v),
|
|
378
396
|
label: 'Show description',
|
|
397
|
+
variables: [`--sectiondivider-${v}-description-display`],
|
|
379
398
|
onchange: (c: boolean) => setIntrinsic(v, 'description-display', c ? 'flex' : 'none'),
|
|
380
399
|
},
|
|
381
400
|
eyebrow: {
|
|
382
401
|
checked: getShowEyebrow(v),
|
|
383
402
|
label: 'Show eyebrow',
|
|
403
|
+
variables: [`--sectiondivider-${v}-eyebrow-display`],
|
|
384
404
|
onchange: (c: boolean) => setIntrinsic(v, 'eyebrow-display', c ? 'block' : 'none'),
|
|
385
405
|
},
|
|
386
406
|
hairline: {
|
|
387
407
|
checked: getShowHairline(v),
|
|
388
408
|
label: 'Show',
|
|
409
|
+
variables: [`--sectiondivider-${v}-hairline`],
|
|
389
410
|
onchange: (c: boolean) => setIntrinsic(v, 'hairline', c ? getHairlinePosition(v) : 'none'),
|
|
390
411
|
},
|
|
391
412
|
};
|
|
@@ -431,8 +452,8 @@
|
|
|
431
452
|
</div>
|
|
432
453
|
{/snippet}
|
|
433
454
|
{#snippet extraPropertyRowsTop(_stateName)}
|
|
434
|
-
<div class="property-row sd-intrinsic-row">
|
|
435
|
-
<span class="property-label">alignment
|
|
455
|
+
<div class="property-row sd-intrinsic-row" data-token-variables={`--sectiondivider-${v.key}-align`}>
|
|
456
|
+
<span class="property-label">alignment<A11yPropertyMark variables={[`--sectiondivider-${v.key}-align`]} /></span>
|
|
436
457
|
<select
|
|
437
458
|
class="sd-intrinsic-select"
|
|
438
459
|
value={getAlign(v.key)}
|
|
@@ -462,18 +483,21 @@
|
|
|
462
483
|
{/snippet}
|
|
463
484
|
{#snippet elementExtras(elementName)}
|
|
464
485
|
{#if elementName === 'eyebrow'}
|
|
465
|
-
<
|
|
466
|
-
<
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
486
|
+
<span class="sd-element-check-host" data-token-variables={`--sectiondivider-${v.key}-eyebrow-text-transform`}>
|
|
487
|
+
<label class="sd-element-check">
|
|
488
|
+
<input
|
|
489
|
+
type="checkbox"
|
|
490
|
+
checked={getEyebrowUppercase(v.key)}
|
|
491
|
+
onchange={(e) => setIntrinsic(v.key, 'eyebrow-text-transform', (e.currentTarget as HTMLInputElement).checked ? 'uppercase' : 'none')}
|
|
492
|
+
/>
|
|
493
|
+
<span>All caps</span>
|
|
494
|
+
</label>
|
|
495
|
+
<A11yPropertyMark variables={[`--sectiondivider-${v.key}-eyebrow-text-transform`]} />
|
|
496
|
+
</span>
|
|
473
497
|
{/if}
|
|
474
498
|
{#if elementName === 'hairline'}
|
|
475
|
-
<div class="property-row sd-intrinsic-row sd-hairline-position-row">
|
|
476
|
-
<span class="property-label">position
|
|
499
|
+
<div class="property-row sd-intrinsic-row sd-hairline-position-row" data-token-variables={`--sectiondivider-${v.key}-hairline`}>
|
|
500
|
+
<span class="property-label">position<A11yPropertyMark variables={[`--sectiondivider-${v.key}-hairline`]} /></span>
|
|
477
501
|
<select
|
|
478
502
|
class="sd-intrinsic-select"
|
|
479
503
|
value={getHairlinePosition(v.key)}
|
|
@@ -551,6 +575,11 @@
|
|
|
551
575
|
/* Inline boolean control inside an element-section (e.g. "All caps" under
|
|
552
576
|
the eyebrow heading). Sits flush-left so it reads as a section property
|
|
553
577
|
rather than aligning with the token grid below. */
|
|
578
|
+
:global(.sd-element-check-host) {
|
|
579
|
+
display: inline-flex;
|
|
580
|
+
align-items: center;
|
|
581
|
+
margin-bottom: var(--ui-space-4);
|
|
582
|
+
}
|
|
554
583
|
:global(.sd-element-check) {
|
|
555
584
|
display: inline-flex;
|
|
556
585
|
align-items: center;
|
|
@@ -559,7 +588,6 @@
|
|
|
559
588
|
color: var(--ui-text-secondary);
|
|
560
589
|
cursor: pointer;
|
|
561
590
|
user-select: none;
|
|
562
|
-
margin-bottom: var(--ui-space-4);
|
|
563
591
|
}
|
|
564
592
|
:global(.sd-element-check:hover) { color: var(--ui-text-primary); }
|
|
565
593
|
:global(.sd-element-check input) { margin: 0; cursor: pointer; }
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildTypeGroupTokens, buildTypeGroupShareableContexts } from './scaffolding/buildTypeGroupTokens';
|
|
3
3
|
import type { Token, TypeGroupConfig, IntrinsicSpec } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'segmentedcontrol';
|
|
6
7
|
|
|
@@ -140,6 +141,32 @@
|
|
|
140
141
|
default: { default: 'var(--color-transparent)' },
|
|
141
142
|
},
|
|
142
143
|
];
|
|
144
|
+
|
|
145
|
+
// Every option sits on the bar, and the default option paints no surface of
|
|
146
|
+
// its own. The small size sets every option's text in
|
|
147
|
+
// --segmentedcontrol-option-small-text-font-size, the smaller of its two sizes.
|
|
148
|
+
function optionContrastPairs(state: string, icon: string, backdrop: string[]): ContrastPair[] {
|
|
149
|
+
const inactive = state === 'disabled option' ? { inactive: true } : {};
|
|
150
|
+
return [
|
|
151
|
+
...typeGroups[state].map((g): ContrastPair => ({
|
|
152
|
+
foreground: g.colorVariable,
|
|
153
|
+
backdrop,
|
|
154
|
+
role: 'text',
|
|
155
|
+
fontSize: '--segmentedcontrol-option-small-text-font-size',
|
|
156
|
+
fontWeight: g.weightVariable,
|
|
157
|
+
...inactive,
|
|
158
|
+
})),
|
|
159
|
+
{ foreground: icon, backdrop, role: 'non-text', ...inactive },
|
|
160
|
+
];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const bar = '--segmentedcontrol-bar-surface';
|
|
164
|
+
export const contrastPairs: ContrastPair[] = [
|
|
165
|
+
...optionContrastPairs('default option', '--segmentedcontrol-option-icon', [bar]),
|
|
166
|
+
...optionContrastPairs('hover option', '--segmentedcontrol-option-hover-icon', ['--segmentedcontrol-hover-tint-enabled', '--segmentedcontrol-option-hover-surface', bar]),
|
|
167
|
+
...optionContrastPairs('selected option', '--segmentedcontrol-selected-icon', ['--segmentedcontrol-selected-surface', bar]),
|
|
168
|
+
...optionContrastPairs('disabled option', '--segmentedcontrol-disabled-icon', ['--segmentedcontrol-disabled-surface', bar]),
|
|
169
|
+
];
|
|
143
170
|
</script>
|
|
144
171
|
|
|
145
172
|
<script lang="ts">
|
|
@@ -149,6 +176,7 @@
|
|
|
149
176
|
import { editorState, setComponentAlias, clearComponentAlias } from '../core/store/editorStore';
|
|
150
177
|
import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
|
|
151
178
|
import Toggle from '../ui/Toggle.svelte';
|
|
179
|
+
import A11yPropertyMark from '../ui/a11y/A11yPropertyMark.svelte';
|
|
152
180
|
import UIPaletteSelector from '../ui/UIPaletteSelector.svelte';
|
|
153
181
|
|
|
154
182
|
// One switch. Turning the tint on also stands each hover surface down to its
|
|
@@ -214,7 +242,7 @@
|
|
|
214
242
|
{#snippet extraPropertyRows(stateName)}
|
|
215
243
|
{#if stateName === 'hover option'}
|
|
216
244
|
<div class="property-row" data-token-variables="--segmentedcontrol-hover-tint-enabled">
|
|
217
|
-
<span class="property-label">tint layer
|
|
245
|
+
<span class="property-label">tint layer<A11yPropertyMark variables={['--segmentedcontrol-hover-tint-enabled']} /></span>
|
|
218
246
|
<Toggle checked={tintOn} onchange={setTintOn} />
|
|
219
247
|
</div>
|
|
220
248
|
{#if tintOn}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildTypeGroupColorTokens } from './scaffolding/buildTypeGroupTokens';
|
|
3
3
|
import type { Token, TypeGroupConfig, IntrinsicSpec } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'sidenavigation';
|
|
6
7
|
|
|
@@ -271,6 +272,43 @@
|
|
|
271
272
|
default: { default: 'var(--color-transparent)' },
|
|
272
273
|
},
|
|
273
274
|
];
|
|
275
|
+
|
|
276
|
+
// Every part sits on the panel, and a hover rule lays the tint over its
|
|
277
|
+
// surface. The section header's own CollapsibleSection surface belongs to
|
|
278
|
+
// that component and stays out of the stack.
|
|
279
|
+
const panel = '--sidenavigation-panel-surface';
|
|
280
|
+
const tint = '--sidenavigation-hover-tint-enabled';
|
|
281
|
+
const partStack = (part: string, s: string): string[] =>
|
|
282
|
+
s === 'hover' ? [tint, `--sidenavigation-${part}-hover-surface`] : [`--sidenavigation-${part}-${s}-surface`];
|
|
283
|
+
const textPairs = (groups: TypeGroupConfig[], backdrop: string[]): ContrastPair[] =>
|
|
284
|
+
groups.map((g) => ({ foreground: g.colorVariable, backdrop, role: 'text', fontSize: g.sizeVariable, fontWeight: g.weightVariable }));
|
|
285
|
+
|
|
286
|
+
// The toggle sits on the title, which a pointer on the toggle also hovers.
|
|
287
|
+
const toggleContrastPairs: ContrastPair[] = [
|
|
288
|
+
...STATEFUL_STATES.map((title): ContrastPair => ({
|
|
289
|
+
foreground: '--sidenavigation-toggle-default-icon',
|
|
290
|
+
backdrop: ['--sidenavigation-toggle-default-surface', ...partStack('title', title), panel],
|
|
291
|
+
role: 'non-text',
|
|
292
|
+
context: `title ${title}`,
|
|
293
|
+
})),
|
|
294
|
+
...(['hover', 'selected'] as const).map((title): ContrastPair => ({
|
|
295
|
+
foreground: '--sidenavigation-toggle-hover-icon',
|
|
296
|
+
backdrop: [...partStack('toggle', 'hover'), ...partStack('title', title), panel],
|
|
297
|
+
role: 'non-text',
|
|
298
|
+
context: `title ${title}`,
|
|
299
|
+
})),
|
|
300
|
+
];
|
|
301
|
+
|
|
302
|
+
export const contrastPairs: ContrastPair[] = [
|
|
303
|
+
...STATEFUL_STATES.flatMap((s): ContrastPair[] => [
|
|
304
|
+
...textPairs(titleStateTypeGroups(s), ['--sidenavigation-title-label-surface', ...partStack('title', s), panel]),
|
|
305
|
+
...textPairs(sectionStateTypeGroups(s), [...partStack('section', s), panel]),
|
|
306
|
+
...textPairs(itemStateTypeGroups(s), [...partStack('item', s), panel]),
|
|
307
|
+
...textPairs(footerStateTypeGroups(s), [...partStack('footer', s), panel]),
|
|
308
|
+
{ foreground: `--sidenavigation-footer-${s}-icon`, backdrop: [...partStack('footer', s), panel], role: 'non-text' },
|
|
309
|
+
]),
|
|
310
|
+
...toggleContrastPairs,
|
|
311
|
+
];
|
|
274
312
|
</script>
|
|
275
313
|
|
|
276
314
|
<script lang="ts">
|
|
@@ -280,6 +318,7 @@
|
|
|
280
318
|
import { editorState, setComponentAlias, clearComponentAlias } from '../core/store/editorStore';
|
|
281
319
|
import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
|
|
282
320
|
import Toggle from '../ui/Toggle.svelte';
|
|
321
|
+
import A11yPropertyMark from '../ui/a11y/A11yPropertyMark.svelte';
|
|
283
322
|
import UIPaletteSelector from '../ui/UIPaletteSelector.svelte';
|
|
284
323
|
|
|
285
324
|
// One switch. Turning the tint on also stands each hover surface down to its
|
|
@@ -384,7 +423,7 @@
|
|
|
384
423
|
{#snippet extraPropertyRows(stateName)}
|
|
385
424
|
{#if stateName.endsWith(' / Hover')}
|
|
386
425
|
<div class="property-row" data-token-variables="--sidenavigation-hover-tint-enabled">
|
|
387
|
-
<span class="property-label">tint layer
|
|
426
|
+
<span class="property-label">tint layer<A11yPropertyMark variables={['--sidenavigation-hover-tint-enabled']} /></span>
|
|
388
427
|
<Toggle checked={tintOn} onchange={setTintOn} />
|
|
389
428
|
</div>
|
|
390
429
|
{#if tintOn}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import type { Token } from './scaffolding/types';
|
|
3
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
3
4
|
|
|
4
5
|
export const component = 'slidepager';
|
|
5
6
|
|
|
@@ -46,6 +47,25 @@
|
|
|
46
47
|
};
|
|
47
48
|
|
|
48
49
|
export const allTokens: Token[] = Object.values(states).flat();
|
|
50
|
+
|
|
51
|
+
// The bar sits on the page inline and on the scrim when zoomed.
|
|
52
|
+
const scrim = '--slidepager-scrim-surface';
|
|
53
|
+
function controlContrastPairs(foreground: string, surface: string, inactive: boolean): ContrastPair[] {
|
|
54
|
+
const flag = inactive ? { inactive } : {};
|
|
55
|
+
return [
|
|
56
|
+
{ foreground, backdrop: [surface], role: 'non-text', context: 'inline', ...flag },
|
|
57
|
+
{ foreground, backdrop: [surface, scrim], role: 'non-text', context: 'zoomed', ...flag },
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
const counter = { foreground: '--slidepager-counter-text', role: 'text', fontSize: '--slidepager-counter-font-size', fontWeight: '--slidepager-counter-font-weight' } as const;
|
|
61
|
+
|
|
62
|
+
export const contrastPairs: ContrastPair[] = [
|
|
63
|
+
...controlContrastPairs('--slidepager-control-icon', '--slidepager-control-surface', false),
|
|
64
|
+
...controlContrastPairs('--slidepager-control-hover-icon', '--slidepager-control-hover-surface', false),
|
|
65
|
+
...controlContrastPairs('--slidepager-control-disabled-icon', '--slidepager-control-disabled-surface', true),
|
|
66
|
+
{ ...counter, backdrop: [], context: 'inline' },
|
|
67
|
+
{ ...counter, backdrop: [scrim], context: 'zoomed' },
|
|
68
|
+
];
|
|
49
69
|
</script>
|
|
50
70
|
|
|
51
71
|
<script lang="ts">
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildTypeGroupColorTokens } from './scaffolding/buildTypeGroupTokens';
|
|
3
3
|
import type { Token, TypeGroupConfig } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
import { sliderVariants } from '../../system/components/Slider.svelte';
|
|
5
6
|
|
|
6
7
|
export const component = 'slider';
|
|
@@ -109,6 +110,38 @@
|
|
|
109
110
|
]);
|
|
110
111
|
|
|
111
112
|
const variantOptions = variants.map((v) => ({ value: v, label: v.charAt(0).toUpperCase() + v.slice(1) }));
|
|
113
|
+
|
|
114
|
+
// The fill paints on the track, and the thumb straddles the fill and the track.
|
|
115
|
+
function variantContrastPairs(v: Variant): ContrastPair[] {
|
|
116
|
+
const thumbPairs = (thumb: string, fill: string, track: string, inactive: boolean): ContrastPair[] => {
|
|
117
|
+
const flag = inactive ? { inactive } : {};
|
|
118
|
+
return [
|
|
119
|
+
{ foreground: thumb, backdrop: [fill, track], role: 'non-text', context: 'fill', ...flag },
|
|
120
|
+
{ foreground: thumb, backdrop: [track], role: 'non-text', context: 'track', ...flag },
|
|
121
|
+
];
|
|
122
|
+
};
|
|
123
|
+
const track = `--slider-${v}-track-surface`;
|
|
124
|
+
const disabledTrack = `--slider-${v}-disabled-track-surface`;
|
|
125
|
+
return [
|
|
126
|
+
{ foreground: `--slider-${v}-fill`, backdrop: [track], role: 'non-text' },
|
|
127
|
+
...thumbPairs(`--slider-${v}-thumb-surface`, `--slider-${v}-fill`, track, false),
|
|
128
|
+
...thumbPairs(`--slider-${v}-hover-thumb-surface`, `--slider-${v}-fill`, track, false),
|
|
129
|
+
{ foreground: `--slider-${v}-disabled-fill`, backdrop: [disabledTrack], role: 'non-text', inactive: true },
|
|
130
|
+
...thumbPairs(`--slider-${v}-disabled-thumb-surface`, `--slider-${v}-disabled-fill`, disabledTrack, true),
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Both variants share the label and value, which sit on no surface.
|
|
135
|
+
export const contrastPairs: ContrastPair[] = [
|
|
136
|
+
...typeGroups.default.map((g): ContrastPair => ({
|
|
137
|
+
foreground: g.colorVariable,
|
|
138
|
+
backdrop: [],
|
|
139
|
+
role: 'text',
|
|
140
|
+
fontSize: g.sizeVariable,
|
|
141
|
+
fontWeight: g.weightVariable,
|
|
142
|
+
})),
|
|
143
|
+
...variants.flatMap(variantContrastPairs),
|
|
144
|
+
];
|
|
112
145
|
</script>
|
|
113
146
|
|
|
114
147
|
<script lang="ts">
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildTypeGroupColorTokens } from './scaffolding/buildTypeGroupTokens';
|
|
3
3
|
import type { Token, TypeGroupConfig, IntrinsicSpec } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'tabbar';
|
|
6
7
|
|
|
@@ -93,6 +94,25 @@
|
|
|
93
94
|
default: { default: 'var(--color-transparent)' },
|
|
94
95
|
},
|
|
95
96
|
];
|
|
97
|
+
|
|
98
|
+
// The bottom indicator paints over its own tab's surface.
|
|
99
|
+
function tabContrastPairs(s: TabState): ContrastPair[] {
|
|
100
|
+
const backdrop = s === 'hover' ? ['--tabbar-hover-tint-enabled', '--tabbar-hover-surface'] : [`--tabbar-${s}-surface`];
|
|
101
|
+
const inactive = s === 'disabled' ? { inactive: true } : {};
|
|
102
|
+
return [
|
|
103
|
+
...tabStateTypeGroups(s).map((g): ContrastPair => ({
|
|
104
|
+
foreground: g.colorVariable,
|
|
105
|
+
backdrop,
|
|
106
|
+
role: 'text',
|
|
107
|
+
fontSize: g.sizeVariable,
|
|
108
|
+
fontWeight: g.weightVariable,
|
|
109
|
+
...inactive,
|
|
110
|
+
})),
|
|
111
|
+
{ foreground: `--tabbar-${s}-border`, backdrop, role: 'non-text', ...inactive },
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export const contrastPairs: ContrastPair[] = tabStateNames.flatMap(tabContrastPairs);
|
|
96
116
|
</script>
|
|
97
117
|
|
|
98
118
|
<script lang="ts">
|
|
@@ -102,6 +122,7 @@
|
|
|
102
122
|
import { editorState, setComponentAlias, clearComponentAlias } from '../core/store/editorStore';
|
|
103
123
|
import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
|
|
104
124
|
import Toggle from '../ui/Toggle.svelte';
|
|
125
|
+
import A11yPropertyMark from '../ui/a11y/A11yPropertyMark.svelte';
|
|
105
126
|
import UIPaletteSelector from '../ui/UIPaletteSelector.svelte';
|
|
106
127
|
|
|
107
128
|
// One switch. Turning the tint on also stands each hover surface down to its
|
|
@@ -163,7 +184,7 @@
|
|
|
163
184
|
{#snippet extraPropertyRows(stateName)}
|
|
164
185
|
{#if stateName === 'hover tab'}
|
|
165
186
|
<div class="property-row" data-token-variables="--tabbar-hover-tint-enabled">
|
|
166
|
-
<span class="property-label">tint layer
|
|
187
|
+
<span class="property-label">tint layer<A11yPropertyMark variables={['--tabbar-hover-tint-enabled']} /></span>
|
|
167
188
|
<Toggle checked={tintOn} onchange={setTintOn} />
|
|
168
189
|
</div>
|
|
169
190
|
{#if tintOn}
|
|
@@ -177,7 +198,7 @@
|
|
|
177
198
|
{#snippet children({ activeState })}
|
|
178
199
|
{@const forceClass = activeState === 'hover tab' ? 'force-hover' : ''}
|
|
179
200
|
<TabBar tabs={demoTabs} value={selectedDemoTab} class={forceClass} onchange={(id) => (selectedDemoTab = id)} />
|
|
180
|
-
<div class="tab-content-demo">
|
|
201
|
+
<div class="tab-content-demo" data-preview-demo>
|
|
181
202
|
<p style="margin: 0;">placeholder tab content</p>
|
|
182
203
|
</div>
|
|
183
204
|
{/snippet}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildTypeGroupColorTokens, buildTypeGroupFontTokens } from './scaffolding/buildTypeGroupTokens';
|
|
3
3
|
import type { Token, TypeGroupConfig } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'table';
|
|
6
7
|
|
|
@@ -72,6 +73,19 @@
|
|
|
72
73
|
...buildTypeGroupColorTokens(typeGroups, derivation),
|
|
73
74
|
...buildTypeGroupFontTokens(typeGroups, derivation),
|
|
74
75
|
];
|
|
76
|
+
|
|
77
|
+
// Every cell sits on the wrapper. Even rows lay the stripe over the row surface.
|
|
78
|
+
const wrapper = '--table-default-surface';
|
|
79
|
+
const textPair = (state: string, backdrop: string[]): ContrastPair => {
|
|
80
|
+
const g = typeGroups[state][0];
|
|
81
|
+
return { foreground: g.colorVariable, backdrop, role: 'text', fontSize: g.sizeVariable, fontWeight: g.weightVariable };
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const contrastPairs: ContrastPair[] = [
|
|
85
|
+
textPair('header', ['--table-default-header-surface', wrapper]),
|
|
86
|
+
{ ...textPair('cell', ['--table-default-row-surface', wrapper]), context: 'odd rows' },
|
|
87
|
+
{ ...textPair('cell', ['--table-default-row-stripe-surface', '--table-default-row-surface', wrapper]), context: 'even rows' },
|
|
88
|
+
];
|
|
75
89
|
</script>
|
|
76
90
|
|
|
77
91
|
<script lang="ts">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import type { Token } from './scaffolding/types';
|
|
3
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
3
4
|
|
|
4
5
|
export const component = 'toggle';
|
|
5
6
|
|
|
@@ -44,6 +45,22 @@
|
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
export const allTokens: Token[] = Object.values(states).flat();
|
|
48
|
+
|
|
49
|
+
const label = { role: 'text', fontSize: '--toggle-label-font-size', fontWeight: '--toggle-label-font-weight' } as const;
|
|
50
|
+
// Each state's thumb paints on its own state's track.
|
|
51
|
+
const thumbOnTrack: [thumb: string, track: string][] = [
|
|
52
|
+
['--toggle-thumb-surface', '--toggle-track-surface'],
|
|
53
|
+
['--toggle-hover-thumb-surface', '--toggle-hover-track-surface'],
|
|
54
|
+
['--toggle-on-thumb-surface', '--toggle-on-track-surface'],
|
|
55
|
+
['--toggle-on-hover-thumb-surface', '--toggle-on-hover-track-surface'],
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
export const contrastPairs: ContrastPair[] = [
|
|
59
|
+
{ foreground: '--toggle-label', backdrop: [], ...label },
|
|
60
|
+
{ foreground: '--toggle-disabled-label', backdrop: [], ...label, inactive: true },
|
|
61
|
+
...thumbOnTrack.map(([thumb, track]): ContrastPair => ({ foreground: thumb, backdrop: [track], role: 'non-text' })),
|
|
62
|
+
{ foreground: '--toggle-disabled-thumb-surface', backdrop: ['--toggle-disabled-track-surface'], role: 'non-text', inactive: true },
|
|
63
|
+
];
|
|
47
64
|
</script>
|
|
48
65
|
|
|
49
66
|
<script lang="ts">
|