@motion-proto/live-tokens 0.96.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 +309 -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/bin/set-colors.mjs +1 -0
- package/bin/setup-claude.mjs +2 -2
- 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.cjs +7 -1
- package/dist-plugin/setColors/index.d.cts +9 -4
- package/dist-plugin/setColors/index.d.ts +9 -4
- package/dist-plugin/setColors/index.js +8 -2
- package/dist-plugin/setGeometry/index.d.cts +1 -1
- package/dist-plugin/setGeometry/index.d.ts +1 -1
- package/dist-plugin/setType/index.d.cts +1 -1
- package/dist-plugin/setType/index.d.ts +1 -1
- package/dist-plugin/{themeTypes-B8_Idrp4.d.cts → themeTypes-BaTQUyac.d.cts} +10 -1
- package/dist-plugin/{themeTypes-B8_Idrp4.d.ts → themeTypes-BaTQUyac.d.ts} +10 -1
- package/package.json +49 -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 -10
- 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/editorPersistence.ts +9 -1
- package/src/editor/core/store/editorRenderer.ts +2 -0
- package/src/editor/core/store/editorStore.ts +29 -0
- package/src/editor/core/store/editorTypes.ts +9 -0
- package/src/editor/core/store/editorViewStore.ts +2 -2
- package/src/editor/core/store/unsavedEdits.ts +10 -0
- package/src/editor/core/themes/buildColors.ts +16 -5
- package/src/editor/core/themes/liveStateStream.ts +7 -1
- package/src/editor/core/themes/parsers/gradient.ts +5 -2
- package/src/editor/core/themes/slices/customColors.ts +226 -0
- package/src/editor/core/themes/themeTypes.ts +10 -0
- 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 +56 -1
- package/src/editor/docs/content.generated.ts +2 -1
- package/src/editor/pages/ComponentEditorPage.svelte +10 -1
- package/src/editor/pages/EditorShell.svelte +97 -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/CustomColorReplaceStep.svelte +118 -0
- 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 +347 -15
- package/src/editor/ui/UITokenSelector.svelte +33 -14
- package/src/editor/ui/VariablesTab.svelte +3 -0
- 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/anchorToTrigger.ts +63 -0
- package/src/editor/ui/contrastReadout.ts +45 -0
- package/src/editor/ui/sections/CustomColorsSection.svelte +254 -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 +26 -26
- 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 +163 -18
- 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/editor/ui/keepInViewport.ts +0 -84
- 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 { buildSiblings } from './scaffolding/siblings';
|
|
3
3
|
import type { Token, IntrinsicSpec } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'iconbutton';
|
|
6
7
|
|
|
@@ -104,6 +105,32 @@
|
|
|
104
105
|
default: { default: 'var(--color-transparent)' },
|
|
105
106
|
},
|
|
106
107
|
];
|
|
108
|
+
|
|
109
|
+
function variantContrastPairs(v: Variant): ContrastPair[] {
|
|
110
|
+
const icon = (s: StateName) => `${statePrefix(v, s)}-icon`;
|
|
111
|
+
const surface = (s: StateName) => `${statePrefix(v, s)}-surface`;
|
|
112
|
+
const hoverStack = ['--iconbutton-hover-tint-enabled', surface('hover')];
|
|
113
|
+
const disabled: ContrastPair = { foreground: icon('disabled'), backdrop: [surface('disabled')], role: 'non-text', inactive: true };
|
|
114
|
+
if (v !== 'outline') {
|
|
115
|
+
return [
|
|
116
|
+
{ foreground: icon('default'), backdrop: [surface('default')], role: 'non-text' },
|
|
117
|
+
{ foreground: icon('hover'), backdrop: hoverStack, role: 'non-text' },
|
|
118
|
+
disabled,
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
// `:active` repaints the surface without the tint. A pointer press keeps the
|
|
122
|
+
// hover icon color, and a key press keeps the default one.
|
|
123
|
+
const active = ['--iconbutton-outline-active-surface'];
|
|
124
|
+
return [
|
|
125
|
+
{ foreground: icon('default'), backdrop: [surface('default')], role: 'non-text', context: 'default' },
|
|
126
|
+
{ foreground: icon('default'), backdrop: active, role: 'non-text', context: 'active' },
|
|
127
|
+
{ foreground: icon('hover'), backdrop: hoverStack, role: 'non-text', context: 'hover' },
|
|
128
|
+
{ foreground: icon('hover'), backdrop: active, role: 'non-text', context: 'active' },
|
|
129
|
+
disabled,
|
|
130
|
+
];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const contrastPairs: ContrastPair[] = variants.flatMap(variantContrastPairs);
|
|
107
134
|
</script>
|
|
108
135
|
|
|
109
136
|
<script lang="ts">
|
|
@@ -113,6 +140,7 @@
|
|
|
113
140
|
import { editorState, setComponentAlias, clearComponentAlias } from '../core/store/editorStore';
|
|
114
141
|
import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
|
|
115
142
|
import Toggle from '../ui/Toggle.svelte';
|
|
143
|
+
import A11yPropertyMark from '../ui/a11y/A11yPropertyMark.svelte';
|
|
116
144
|
import UIPaletteSelector from '../ui/UIPaletteSelector.svelte';
|
|
117
145
|
|
|
118
146
|
// One switch. Turning the tint on also stands each hover surface down to its
|
|
@@ -193,7 +221,7 @@
|
|
|
193
221
|
{#snippet extraPropertyRows(stateName)}
|
|
194
222
|
{#if stateName === 'hover'}
|
|
195
223
|
<div class="property-row" data-token-variables="--iconbutton-hover-tint-enabled">
|
|
196
|
-
<span class="property-label">tint layer
|
|
224
|
+
<span class="property-label">tint layer<A11yPropertyMark variables={['--iconbutton-hover-tint-enabled']} /></span>
|
|
197
225
|
<Toggle checked={tintOn} onchange={setTintOn} />
|
|
198
226
|
</div>
|
|
199
227
|
{#if tintOn}
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
import VariantGroup from './scaffolding/VariantGroup.svelte';
|
|
51
51
|
import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
|
|
52
52
|
import { buildSiblings } from './scaffolding/siblings';
|
|
53
|
+
import A11yPropertyMark from '../ui/a11y/A11yPropertyMark.svelte';
|
|
53
54
|
import demoImageUrl from '../../system/assets/newspaper.webp';
|
|
54
55
|
import { editorState, setComponentAlias } from '../core/store/editorStore';
|
|
55
56
|
|
|
@@ -77,17 +78,23 @@
|
|
|
77
78
|
<ComponentEditorBase {component} title="Image" description="Picture in the page flow. Default frames it with rounded corners, a border, and a shadow. Bare shows the picture alone." tokens={allTokens} variants={variantOptions}>
|
|
78
79
|
<VariantGroup name="default" title="Default" states={variantStates('default')} {component} siblings={buildSiblings(variants, 'default', variantStates)}>
|
|
79
80
|
{#snippet stateActions()}
|
|
80
|
-
<
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
<span class="zoom-control" data-token-variables="--image-zoom-enabled">
|
|
82
|
+
<label class="zoom-enable">
|
|
83
|
+
<input type="checkbox" checked={useZoom} onchange={(e) => setUseZoom(e.currentTarget.checked)} />
|
|
84
|
+
<span>Use zoom on hover</span>
|
|
85
|
+
</label>
|
|
86
|
+
<A11yPropertyMark variables={['--image-zoom-enabled']} />
|
|
87
|
+
</span>
|
|
88
|
+
<span class="zoom-control" data-token-variables="--image-grow-enabled">
|
|
89
|
+
<label class="zoom-enable" class:disabled={!useZoom}>
|
|
90
|
+
<input type="checkbox" checked={overflowScaling} disabled={!useZoom} onchange={(e) => setOverflowScaling(e.currentTarget.checked)} />
|
|
91
|
+
<span>Overflow scaling (mask zoom to frame)</span>
|
|
92
|
+
</label>
|
|
93
|
+
<A11yPropertyMark variables={['--image-grow-enabled']} />
|
|
94
|
+
</span>
|
|
88
95
|
{/snippet}
|
|
89
96
|
<Image src={demoImageUrl} alt="Demo" size="banner" zoom={useZoom ? undefined : false} {overflowScaling} forceHover={useZoom} />
|
|
90
|
-
<p class="zoom-help">
|
|
97
|
+
<p class="zoom-help" data-preview-demo>
|
|
91
98
|
Use zoom on hover: every image scales on hover (a page can still force it per image with the
|
|
92
99
|
<code>zoom</code> prop). Overflow scaling on (default): the content zooms inside the fixed frame,
|
|
93
100
|
masked by overflow. Off: the whole framed image grows past its box. Override per image with
|
|
@@ -100,6 +107,10 @@
|
|
|
100
107
|
</ComponentEditorBase>
|
|
101
108
|
|
|
102
109
|
<style>
|
|
110
|
+
.zoom-control {
|
|
111
|
+
display: inline-flex;
|
|
112
|
+
align-items: center;
|
|
113
|
+
}
|
|
103
114
|
.zoom-enable {
|
|
104
115
|
display: inline-flex;
|
|
105
116
|
align-items: center;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import type { Token, IntrinsicSpec } from './scaffolding/types';
|
|
3
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
3
4
|
|
|
4
5
|
export const component = 'imagelightbox';
|
|
5
6
|
|
|
@@ -39,13 +40,26 @@
|
|
|
39
40
|
default: { default: 'contain' },
|
|
40
41
|
},
|
|
41
42
|
];
|
|
43
|
+
|
|
44
|
+
// One color paints the chrome's icons and its extra-small counter text. The
|
|
45
|
+
// chrome floats on the scrim.
|
|
46
|
+
const scrim = '--imagelightbox-scrim-surface';
|
|
47
|
+
export const contrastPairs: ContrastPair[] = [
|
|
48
|
+
{ foreground: '--imagelightbox-chrome-icon', backdrop: ['--imagelightbox-chrome-surface', scrim], role: 'non-text', context: 'icons' },
|
|
49
|
+
{ foreground: '--imagelightbox-chrome-icon', backdrop: ['--imagelightbox-chrome-hover-surface', scrim], role: 'non-text', context: 'hovered icons' },
|
|
50
|
+
{ foreground: '--imagelightbox-chrome-icon', backdrop: ['--imagelightbox-chrome-surface', scrim], role: 'text', fontSize: '--font-size-xs', context: 'counter' },
|
|
51
|
+
];
|
|
42
52
|
</script>
|
|
43
53
|
|
|
44
54
|
<script lang="ts">
|
|
45
55
|
import ImageLightbox from '../../system/components/ImageLightbox.svelte';
|
|
46
56
|
import VariantGroup from './scaffolding/VariantGroup.svelte';
|
|
47
57
|
import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
|
|
58
|
+
import UISegmentedControl from '../ui/UISegmentedControl.svelte';
|
|
59
|
+
import A11yPropertyMark from '../ui/a11y/A11yPropertyMark.svelte';
|
|
48
60
|
import newspaperUrl from '../../system/assets/newspaper.webp';
|
|
61
|
+
import { editorState, setComponentAlias } from '../core/store/editorStore';
|
|
62
|
+
import type { CssVarRef } from '../core/store/editorTypes';
|
|
49
63
|
|
|
50
64
|
const demoImages = [
|
|
51
65
|
// The first entry carries explicit dimensions (the no-reflow path); the second
|
|
@@ -56,6 +70,18 @@
|
|
|
56
70
|
|
|
57
71
|
let multiple = $state(true);
|
|
58
72
|
let shadow = $state<'box' | 'content' | 'none'>('box');
|
|
73
|
+
|
|
74
|
+
type TileFit = 'contain' | 'cover';
|
|
75
|
+
const TILE_FIT = intrinsics[0].variable('default');
|
|
76
|
+
const fitOptions: { value: TileFit; label: string; title: string }[] = [
|
|
77
|
+
{ value: 'contain', label: 'Contain', title: 'Show the whole image inside the tile' },
|
|
78
|
+
{ value: 'cover', label: 'Cover', title: 'Crop the image to fill the tile' },
|
|
79
|
+
];
|
|
80
|
+
let tileFit = $derived.by((): TileFit => {
|
|
81
|
+
const ref = ($editorState.components[component]?.aliases as Record<string, CssVarRef> | undefined)?.[TILE_FIT];
|
|
82
|
+
const value = ref?.kind === 'literal' ? ref.value : intrinsics[0].default.default;
|
|
83
|
+
return value === 'cover' ? 'cover' : 'contain';
|
|
84
|
+
});
|
|
59
85
|
</script>
|
|
60
86
|
|
|
61
87
|
<ComponentEditorBase
|
|
@@ -79,6 +105,21 @@
|
|
|
79
105
|
</select>
|
|
80
106
|
</label>
|
|
81
107
|
{/snippet}
|
|
108
|
+
{#snippet extraPropertyRowsTop(stateName)}
|
|
109
|
+
{#if stateName === 'tile'}
|
|
110
|
+
<div class="property-row" data-token-variables={TILE_FIT}>
|
|
111
|
+
<span class="property-label">tile fit<A11yPropertyMark variables={[TILE_FIT]} /></span>
|
|
112
|
+
<div class="tile-fit-control">
|
|
113
|
+
<UISegmentedControl
|
|
114
|
+
value={tileFit}
|
|
115
|
+
options={fitOptions}
|
|
116
|
+
ariaLabel="Tile fit"
|
|
117
|
+
onchange={(value) => setComponentAlias(component, TILE_FIT, { kind: 'literal', value })}
|
|
118
|
+
/>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
{/if}
|
|
122
|
+
{/snippet}
|
|
82
123
|
<div class="preview-frame">
|
|
83
124
|
<ImageLightbox images={multiple ? demoImages : [demoImages[0]]} {shadow} extended />
|
|
84
125
|
</div>
|
|
@@ -91,6 +132,9 @@
|
|
|
91
132
|
max-width: 28rem;
|
|
92
133
|
margin: 0 auto;
|
|
93
134
|
}
|
|
135
|
+
.tile-fit-control {
|
|
136
|
+
display: flex;
|
|
137
|
+
}
|
|
94
138
|
.preview-toggle {
|
|
95
139
|
display: inline-flex;
|
|
96
140
|
align-items: center;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { buildSiblings } from './scaffolding/siblings';
|
|
3
3
|
import type { Token } from './scaffolding/types';
|
|
4
|
+
import type { ContrastPair } from '../core/palettes/contrastPairs';
|
|
4
5
|
|
|
5
6
|
export const component = 'inlineeditactions';
|
|
6
7
|
|
|
@@ -38,6 +39,17 @@
|
|
|
38
39
|
[`--inlineeditactions-${btn}-default-padding`, btn] as const,
|
|
39
40
|
[`--inlineeditactions-${btn}-default-icon-size`, btn] as const,
|
|
40
41
|
]));
|
|
42
|
+
|
|
43
|
+
// Each button holds a glyph and no text, so its color is a non-text pair.
|
|
44
|
+
function buttonContrastPairs(btn: Button): ContrastPair[] {
|
|
45
|
+
return (['default', 'hover'] as const).map((state) => ({
|
|
46
|
+
foreground: `--inlineeditactions-${btn}-${state}-text`,
|
|
47
|
+
backdrop: [`--inlineeditactions-${btn}-${state}-surface`],
|
|
48
|
+
role: 'non-text',
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const contrastPairs: ContrastPair[] = buttons.flatMap(buttonContrastPairs);
|
|
41
53
|
</script>
|
|
42
54
|
|
|
43
55
|
<script lang="ts">
|
|
@@ -66,7 +78,7 @@
|
|
|
66
78
|
{#snippet children({ activeState })}
|
|
67
79
|
{@const forceClass = activeState === 'hover' ? 'force-hover' : ''}
|
|
68
80
|
<div class="inline-edit-demo-row">
|
|
69
|
-
<span style="color: var(--text-secondary);">Editing value...</span>
|
|
81
|
+
<span style="color: var(--text-secondary);" data-preview-demo>Editing value...</span>
|
|
70
82
|
<InlineEditActions
|
|
71
83
|
onsave={() => {}}
|
|
72
84
|
oncancel={() => {}}
|
|
@@ -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}
|