@epa-wg/custom-element-dist 0.0.33 → 0.0.35
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/settings.local.json +18 -0
- package/.gitattributes +4 -0
- package/.github/workflows/deploy.yml +59 -0
- package/.idea/copilot.data.migration.agent.xml +6 -0
- package/.idea/copilot.data.migration.ask.xml +6 -0
- package/.idea/copilot.data.migration.ask2agent.xml +6 -0
- package/.idea/copilot.data.migration.edit.xml +6 -0
- package/.idea/custom-element-dist.iml +2 -0
- package/.storybook/main.ts +20 -17
- package/.storybook/preview.ts +23 -23
- package/.yarn/install-state.gz +0 -0
- package/.yarnrc.yml +1 -0
- package/README.md +6 -4
- package/coverage/block-navigation.js +1 -1
- package/coverage/coverage-final.json +4 -3
- package/coverage/index.html +34 -19
- package/coverage/sorter.js +21 -7
- package/coverage/src/custom-element/coverage.svg +1 -1
- package/coverage/src/custom-element/custom-element.js/coverage.svg +1 -1
- package/coverage/src/custom-element/custom-element.js.html +448 -391
- package/coverage/src/custom-element/http-request.js/coverage.svg +1 -1
- package/coverage/src/custom-element/http-request.js.html +38 -17
- package/coverage/src/custom-element/index.html +26 -26
- package/coverage/src/custom-element/local-storage.js.html +1 -1
- package/coverage/src/custom-element/location-element.js.html +1 -1
- package/coverage/src/custom-element/module-url.js.html +1 -1
- package/coverage/src/index.html +1 -1
- package/coverage/src/material/theme/colors.js/coverage.svg +10 -0
- package/coverage/src/material/theme/colors.js.html +217 -0
- package/coverage/src/material/theme/coverage.svg +10 -0
- package/coverage/src/material/theme/index.html +116 -0
- package/coverage/src/mocks/handlers.ts.html +1 -1
- package/coverage/src/mocks/index.html +1 -1
- package/coverage/src/stories/frame.canvas.ts.html +1 -1
- package/coverage/src/stories/http-request.stories.ts.html +1 -1
- package/coverage/src/stories/index.html +1 -1
- package/coverage/src/stories/testStoryBook.ts.html +12 -12
- package/coverage/src/sum.ts.html +1 -1
- package/dist/custom-element-Bssk9jRy.cjs +97 -0
- package/dist/{custom-element-WnOqmEOe.js → custom-element-BzDjIYMe.js} +193 -183
- package/dist/custom-element-bundle.cjs +1 -1
- package/dist/custom-element-bundle.js +3 -3
- package/dist/demo/a.html +10 -3
- package/dist/demo/a.svg +26 -26
- package/dist/demo/html-template.html +4 -3
- package/dist/demo/s.xml +1 -75
- package/dist/demo/s.xslt +351 -72
- package/dist/demo/s1.xml +3706 -0
- package/dist/http-request-DSaowcG1.cjs +1 -0
- package/dist/{http-request-BOvP4KTl.js → http-request-DTCzZ1gc.js} +15 -9
- package/dist/mockServiceWorker.js +105 -63
- package/package.json +5 -4
- package/public/demo/a.html +10 -3
- package/public/demo/a.svg +26 -26
- package/public/demo/html-template.html +4 -3
- package/public/demo/s.xml +1 -75
- package/public/demo/s.xslt +351 -72
- package/public/demo/s1.xml +3706 -0
- package/public/mockServiceWorker.js +105 -63
- package/src/custom-element/custom-element.js +28 -9
- package/src/custom-element/demo/a.html +10 -3
- package/src/custom-element/demo/a.svg +26 -26
- package/src/custom-element/demo/html-template.html +4 -3
- package/src/custom-element/demo/s.xml +1 -75
- package/src/custom-element/demo/s.xslt +351 -72
- package/src/custom-element/demo/s1.xml +3706 -0
- package/src/custom-element/http-request.js +7 -0
- package/src/custom-element/ide/customData-dce.json +123 -0
- package/src/custom-element/ide/web-types-dce.json +128 -1
- package/src/custom-element/ide/web-types-xsl.json +1 -1
- package/src/material/angular.css +987 -987
- package/src/material/components/action.html +262 -0
- package/src/material/components/autocomplete.html +167 -239
- package/src/material/components/badge.html +238 -239
- package/src/material/components/dropdown.html +0 -1
- package/src/material/components/icon-link.html +160 -161
- package/src/material/components/icon.html +251 -252
- package/src/material/components/input.html +569 -570
- package/src/material/components/menu.html +235 -236
- package/src/material/components.html +157 -158
- package/src/material/demo.css +36 -36
- package/src/material/index.html +109 -110
- package/src/material/material.css +356 -356
- package/src/material/theme/Base-Principles.md +339 -0
- package/src/material/theme/README.md +298 -18
- package/src/material/theme/UI Domain Model in web applications.svg +1 -0
- package/src/material/theme/User Semantic Theme tokens.svg +1 -0
- package/src/material/theme/action-pending-poc.html +62 -0
- package/src/material/theme/actions-color.html +141 -0
- package/src/material/theme/colors-light.html +631 -0
- package/src/material/theme/colors-native.html +51 -0
- package/src/material/theme/colors-poc.html +66 -0
- package/src/material/theme/colors.html +297 -0
- package/src/material/theme/colors.js +44 -0
- package/src/material/theme/consumer-theme.css +745 -0
- package/src/material/theme/semantic.css +132 -132
- package/src/material/theme/style-bug.html +123 -0
- package/src/material/theme/theme-data.css +43 -0
- package/src/material/theme/theme-data.xhtml +2926 -0
- package/src/material/theme/todo.md +274 -0
- package/src/material/theme/tokens/action-colors.png +0 -0
- package/src/material/theme/tokens/cem-article-illustration-4x1-letterbox-2000x500.png +0 -0
- package/src/material/theme/tokens/cem-breakpoints.md +519 -0
- package/src/material/theme/tokens/cem-colors.md +715 -0
- package/src/material/theme/tokens/cem-consumerflow-typography-matrix.svg +198 -0
- package/src/material/theme/tokens/cem-coupling.md +372 -0
- package/src/material/theme/tokens/cem-data-vs-reading-numerals.svg +164 -0
- package/src/material/theme/tokens/cem-dimension.md +625 -0
- package/src/material/theme/tokens/cem-layering.md +562 -0
- package/src/material/theme/tokens/cem-m3-parity.md +343 -0
- package/src/material/theme/tokens/cem-responsive.md +238 -0
- package/src/material/theme/tokens/cem-shape.md +691 -0
- package/src/material/theme/tokens/cem-stroke-density-illustration-4to1-v3.svg +102 -0
- package/src/material/theme/tokens/cem-stroke.md +480 -0
- package/src/material/theme/tokens/cem-timing.md +198 -0
- package/src/material/theme/tokens/cem-typography-model-stack.svg +64 -0
- package/src/material/theme/tokens/cem-voice-fonts-typography.md +718 -0
- package/src/material/theme/tokens/cem-voice-ladder.svg +91 -0
- package/src/material/theme/tokens/chips.png +0 -0
- package/src/material/theme/tokens/columns-page.png +0 -0
- package/src/material/theme/tokens/initials.png +0 -0
- package/src/material/theme/tokens/nav-buttons.png +0 -0
- package/src/material/theme/tokens/script.png +0 -0
- package/src/material/theme/tokens/sufler.png +0 -0
- package/src/material/theme/tokens/typography-icons.png +0 -0
- package/src/mocks/versions.mock.ts +1 -1
- package/src/stories/__screenshots__/dom-merge.test.stories.ts/dom-merge-dom-merge-OrderPreservingOn2ndTransform-1.png +0 -0
- package/src/stories/__screenshots__/xslt-conditionals.test.stories.ts/xslt-conditionals-xslt-conditionals-MultipleIfOrderingWorkaround-1.png +0 -0
- package/src/stories/dom-merge.test.stories.ts +25 -1
- package/src/stories/xslt-conditionals.test.stories.ts +492 -0
- package/src/stories/xslt-for-each.test.stories.ts +336 -0
- package/src/stories/xslt-if.test.stories.ts +89 -0
- package/storybook-static/assets/{Color-F6OSRLHC-Cbp293x2.js → Color-F6OSRLHC-DeDlDLjU.js} +1 -1
- package/storybook-static/assets/{Configure-BrFr4SLE.js → Configure-CH_tIP5N.js} +1 -1
- package/storybook-static/assets/{DocsRenderer-CFRXHY34-DhHzJiIO.js → DocsRenderer-CFRXHY34-Bc9EPsUI.js} +2 -2
- package/storybook-static/assets/{attributes.test.stories-Gg9LQTEK.js → attributes.test.stories-BtamFQkF.js} +1 -1
- package/storybook-static/assets/{css.test.stories-B_3ltOrx.js → css.test.stories-BfNxLgwr.js} +1 -1
- package/storybook-static/assets/{custom-element-CPnvJnn8.js → custom-element-CnmjNo0g.js} +6 -6
- package/storybook-static/assets/{dom-merge.test.stories-nQxcgLoM.js → dom-merge.test.stories-DxnitrLK.js} +47 -6
- package/storybook-static/assets/entry-preview-BNCt9WBs.js +26 -0
- package/storybook-static/assets/{entry-preview-docs-Dwczwtsc.js → entry-preview-docs-CbF8-81D.js} +2 -2
- package/storybook-static/assets/{external-template.test.stories-DZ-rjnfd.js → external-template.test.stories-BTsww7B0.js} +1 -1
- package/storybook-static/assets/{form.test.stories-DQhPYtMj.js → form.test.stories-DNJFtPJb.js} +1 -1
- package/storybook-static/assets/{frame.canvas-ClTqYyMN.js → frame.canvas-E5n9h6j1.js} +1 -1
- package/storybook-static/assets/{handlers-CLkps6Nz.js → handlers-Dvg8CAeR.js} +1 -1
- package/storybook-static/assets/http-request-BWeEEBkP.js +1 -0
- package/storybook-static/assets/{http-request.stories-jo0f73nw.js → http-request.stories-DgrBNle8.js} +1 -1
- package/storybook-static/assets/{iframe-CZwRpnn9.js → iframe-DiVWehoI.js} +11 -11
- package/storybook-static/assets/{index-Dr4PwNfd.js → index-CGuyH0k-.js} +87 -87
- package/storybook-static/assets/{index-CJQtnF9V.js → index-CdEbhcV9.js} +1 -1
- package/storybook-static/assets/index-DO1nmyvI.js +11 -0
- package/storybook-static/assets/{index-B68YUdzy.js → index-w6iX3YlR.js} +3 -3
- package/storybook-static/assets/{local-storage.test.stories-uA5EKRPf.js → local-storage.test.stories-Hwq80yUr.js} +1 -1
- package/storybook-static/assets/{location-element.test.stories-Cu-6Elcg.js → location-element.test.stories-mEhZzm7x.js} +1 -1
- package/storybook-static/assets/{module-url.test.stories-CD_wusXQ.js → module-url.test.stories-Bj46iT0V.js} +1 -1
- package/storybook-static/assets/{preview-CuCH40jj.js → preview-BjbXcJci.js} +2 -2
- package/storybook-static/assets/{preview-BFlNN3Wj.js → preview-Bn8igYMp.js} +1 -1
- package/storybook-static/assets/{preview-Cm4PPhHS.js → preview-CfuT8gak.js} +1 -1
- package/storybook-static/assets/{set-url.test.stories-CY7B9BVZ.js → set-url.test.stories-hzxLcqmm.js} +1 -1
- package/storybook-static/assets/{slice-events.test.stories-BVnPXm6e.js → slice-events.test.stories-DVyXFRU1.js} +1 -1
- package/storybook-static/assets/{slots.test.stories-Dxsa9KdA.js → slots.test.stories-CS544nS4.js} +1 -1
- package/storybook-static/assets/{version-select.test.stories-Buga1PAa.js → version-select.test.stories-D36nfYBq.js} +1 -1
- package/storybook-static/assets/xslt-conditionals.test.stories-BS1PTIHe.js +633 -0
- package/storybook-static/assets/xslt-for-each.test.stories-CtPS20RK.js +329 -0
- package/storybook-static/assets/xslt-if.test.stories-DcHrAMSY.js +71 -0
- package/storybook-static/demo/a.html +10 -3
- package/storybook-static/demo/a.svg +26 -26
- package/storybook-static/demo/html-template.html +4 -3
- package/storybook-static/demo/s.xml +1 -75
- package/storybook-static/demo/s.xslt +351 -72
- package/storybook-static/demo/s1.xml +3706 -0
- package/storybook-static/iframe.html +2 -2
- package/storybook-static/index.json +1 -1
- package/storybook-static/mockServiceWorker.js +105 -63
- package/storybook-static/project.json +1 -1
- package/storybook-static/sb-addons/essentials-controls-1/manager-bundle.js +69 -66
- package/storybook-static/sb-addons/essentials-docs-3/manager-bundle.js +62 -59
- package/dist/custom-element-6slVaFEs.cjs +0 -97
- package/dist/http-request-DPrY7mGh.cjs +0 -1
- package/storybook-static/assets/attributes.test.stories-CzWkKw0e.js +0 -1
- package/storybook-static/assets/entry-preview-DHVXbf3x.js +0 -26
- package/storybook-static/assets/external-template.test.stories-BivZqBTp.js +0 -1
- package/storybook-static/assets/http-request-DNq59pnj.js +0 -1
- package/storybook-static/assets/index-BwkS7JH_.js +0 -8
- package/storybook-static/assets/module-url.test.stories-CTjUAk3J.js +0 -1
|
@@ -0,0 +1,2926 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8"/>
|
|
5
|
+
<meta name="viewport" content="width=device-width"/>
|
|
6
|
+
<title>Consumer Semantic Theme tokens</title>
|
|
7
|
+
<link rel="stylesheet" href="consumer-theme.css"/>
|
|
8
|
+
<style>
|
|
9
|
+
@import url(./consumer-theme.css);
|
|
10
|
+
@import url(./theme-data.css);
|
|
11
|
+
</style>
|
|
12
|
+
</head>
|
|
13
|
+
<body>
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
<h1>Consumer Semantic Theme tokens</h1>
|
|
17
|
+
<p>
|
|
18
|
+
The content of this file is used for supplementary documentation and generation of <a href="./consumer-theme.css" >consumer-theme.css</a>.
|
|
19
|
+
</p>
|
|
20
|
+
<figure>
|
|
21
|
+
<figcaption>Color Themes</figcaption>
|
|
22
|
+
<fieldset >
|
|
23
|
+
<legend>Theme names</legend>
|
|
24
|
+
<datalist id="theme">
|
|
25
|
+
<option value="native" >System driven colors </option>
|
|
26
|
+
<option value="light" >Light </option>
|
|
27
|
+
<option value="dark" >Dark </option>
|
|
28
|
+
<option value="contrast-light" >Hight-Contrast Light </option>
|
|
29
|
+
<option value="contrast-dark" >High-Contrast Dark </option>
|
|
30
|
+
</datalist>
|
|
31
|
+
|
|
32
|
+
</fieldset>
|
|
33
|
+
<fieldset>
|
|
34
|
+
<legend>Emotional tokens</legend>
|
|
35
|
+
<datalist id="cem-emotional-tokens">
|
|
36
|
+
<option value="comfort" warms="cool" sample="white" system="Canvas" > light scene color, the scene is full of object. Purity, innocence, cleanliness, peace, coldness or emptiness </option>
|
|
37
|
+
<option value="calm" warms="cool" sample="black" system="CanvasText" > dark scene color, few objects around. Mystery, elegance, power, evil, mourning, formality, security </option>
|
|
38
|
+
<option value="trust" warms="cool" sample="blue" system="Highlight w/ HighlightText" > primary action background, text color for `focus-invert` </option>
|
|
39
|
+
<option value="danger" warms="warm" sample="red" system="N/A , red" > Passion, excitement, love, anger, energy, danger </option>
|
|
40
|
+
<option value="creativity" warms="cool" sample="cyan,purple" system="ButtonFace w/ ButtonText" > Luxury, creativity, royalty, mystery, but also grief or melancholy </option>
|
|
41
|
+
<option value="enthusiasm" warms="warm" sample="orange,yellow,pink" system="Mark w/ MarkText" > Warmth, enthusiasm, happiness, optimism, energy </option>
|
|
42
|
+
<option value="conservative" warms="neutral" sample="brown,tan,beige,grey" system="GrayText" > Natural, earthy, conservative, but also bland or boring </option>
|
|
43
|
+
</datalist>
|
|
44
|
+
</fieldset>
|
|
45
|
+
</figure>
|
|
46
|
+
<figure class="with-color">
|
|
47
|
+
<figcaption>Branded Palette Colors</figcaption>
|
|
48
|
+
<p>The branded palette establishes base colors with brightness variations, ensuring accessibility and adherence to ADA guidelines. Each color family includes up to 4 variants: xl (extra light), l (light), d (dark), xd (extra dark).</p>
|
|
49
|
+
|
|
50
|
+
<fieldset>
|
|
51
|
+
<legend>Brightness Levels</legend>
|
|
52
|
+
<dl>
|
|
53
|
+
<dt><code>xl</code> (extra light)</dt>
|
|
54
|
+
<dd>
|
|
55
|
+
Lightest variant, typically used in light themes for backgrounds and surfaces. High brightness, low saturation.
|
|
56
|
+
<br/>
|
|
57
|
+
<strong>Text color pairing:</strong> Uses <code>xd</code> (extra dark) for maximum contrast.
|
|
58
|
+
<br/>
|
|
59
|
+
<span style="background-color: var(--cem-color-blue-xl); color: var(--cem-color-blue-xd); padding: 0.5em; display: inline-block; margin-top: 0.5em;">
|
|
60
|
+
Example: xl background with xd text
|
|
61
|
+
</span>
|
|
62
|
+
</dd>
|
|
63
|
+
|
|
64
|
+
<dt><code>l</code> (light)</dt>
|
|
65
|
+
<dd>
|
|
66
|
+
Light variant, primary color for light themes. Base emotional color in light mode.
|
|
67
|
+
<br/>
|
|
68
|
+
<strong>Text color pairing:</strong> Uses <code>d</code> (dark) or <code>xd</code> (extra dark) for contrast.
|
|
69
|
+
<br/>
|
|
70
|
+
<span style="background-color: var(--cem-color-blue-l); color: var(--cem-color-blue-d); padding: 0.5em; display: inline-block; margin-top: 0.5em;">
|
|
71
|
+
Example: l background with d text
|
|
72
|
+
</span>
|
|
73
|
+
</dd>
|
|
74
|
+
|
|
75
|
+
<dt><code>d</code> (dark)</dt>
|
|
76
|
+
<dd>
|
|
77
|
+
Dark variant, primary color for dark themes. Base emotional color in dark mode.
|
|
78
|
+
<br/>
|
|
79
|
+
<strong>Text color pairing:</strong> Uses <code>l</code> (light) or <code>xl</code> (extra light) for contrast.
|
|
80
|
+
<br/>
|
|
81
|
+
<span style="background-color: var(--cem-color-blue-d); color: var(--cem-color-blue-l); padding: 0.5em; display: inline-block; margin-top: 0.5em;">
|
|
82
|
+
Example: d background with l text
|
|
83
|
+
</span>
|
|
84
|
+
</dd>
|
|
85
|
+
|
|
86
|
+
<dt><code>xd</code> (extra dark)</dt>
|
|
87
|
+
<dd>
|
|
88
|
+
Darkest variant, typically used in dark themes for backgrounds and surfaces. Low brightness, higher saturation.
|
|
89
|
+
<br/>
|
|
90
|
+
<strong>Text color pairing:</strong> Uses <code>xl</code> (extra light) for maximum contrast.
|
|
91
|
+
<br/>
|
|
92
|
+
<span style="background-color: var(--cem-color-blue-xd); color: var(--cem-color-blue-xl); padding: 0.5em; display: inline-block; margin-top: 0.5em;">
|
|
93
|
+
Example: xd background with xl text
|
|
94
|
+
</span>
|
|
95
|
+
</dd>
|
|
96
|
+
</dl>
|
|
97
|
+
|
|
98
|
+
<p><strong>Contrast Principle:</strong> Brightness levels are paired with their opposite extremes to ensure WCAG-compliant contrast ratios:</p>
|
|
99
|
+
<ul>
|
|
100
|
+
<li><code>xl</code> ↔ <code>xd</code> (maximum contrast pairing)</li>
|
|
101
|
+
<li><code>l</code> ↔ <code>d</code> or <code>xd</code> (high contrast pairing)</li>
|
|
102
|
+
<li>All pairings maintain ≥4.5:1 contrast ratio for text</li>
|
|
103
|
+
</ul>
|
|
104
|
+
<p><strong>color ranges:</strong> <code>l</code> is used as base color for light mode;
|
|
105
|
+
<code>d</code> as its opposite variation. The brightness variations in between are generated by css formula.
|
|
106
|
+
</p>
|
|
107
|
+
<p><strong>darl/light:</strong> <code>l</code> is used as base color for light mode;
|
|
108
|
+
<code>d</code> in dark. See the css <code>light-dark</code> use bellow as a switch.
|
|
109
|
+
</p>
|
|
110
|
+
<p><strong>text colors:</strong> uses primary page text (comfort) with
|
|
111
|
+
<code>xd</code>↔<code>xl</code> in light/dark mode.
|
|
112
|
+
Only in special cases when contrast is not sufficient it is overridden (danger).
|
|
113
|
+
</p>
|
|
114
|
+
|
|
115
|
+
<pre>
|
|
116
|
+
--cem-palette-comfort-text : light-dark(var( --cem-color-cyan-xd ), var( --cem-color-cyan-xl ));
|
|
117
|
+
--cem-palette-comfort-text-x : light-dark(var( --cem-color-cyan-xl ), var( --cem-color-cyan-xd ));
|
|
118
|
+
|
|
119
|
+
--cem-palette-danger : light-dark(var( --cem-color-red-l ), var( --cem-color-red-d ));
|
|
120
|
+
--cem-palette-danger-text : light-dark(var( --cem-palette-comfort-text-x ), var( --cem-palette-comfort-text ));
|
|
121
|
+
--cem-palette-danger-x : light-dark(var( --cem-color-red-d ), var( --cem-color-red-l ));
|
|
122
|
+
--cem-palette-danger-text-x : light-dark(var( --cem-color-orange-xl ), var( --cem-color-orange-xl ));
|
|
123
|
+
|
|
124
|
+
--cem-action-destructive-hover-background: color-mix(in srgb, var(--cem-palette-danger ) 60%, var(--cem-palette-danger-x ));
|
|
125
|
+
--cem-action-destructive-hover-text: var(--cem-palette-danger-text );
|
|
126
|
+
</pre>
|
|
127
|
+
</fieldset>
|
|
128
|
+
|
|
129
|
+
<fieldset>
|
|
130
|
+
<legend>Usage in Color System</legend>
|
|
131
|
+
<p>These branded colors form the foundation of the theme system:</p>
|
|
132
|
+
<ol>
|
|
133
|
+
<li><strong>Emotional Palette</strong>: Branded colors map to emotional tokens via <code>light-dark()</code> function</li>
|
|
134
|
+
<li><strong>State Variations</strong>: Colors are mixed using <code>color-mix()</code> to create state progressions</li>
|
|
135
|
+
<li><strong>Accessibility</strong>: All color pairs maintain WCAG contrast ratios (≥4.5:1 for text, ≥3:1 for UI elements)</li>
|
|
136
|
+
<li><strong>Material Design Compatibility</strong>: Tokens align with Angular Material and Material Design 3 color systems</li>
|
|
137
|
+
</ol>
|
|
138
|
+
</fieldset>
|
|
139
|
+
|
|
140
|
+
<fieldset>
|
|
141
|
+
<legend>Cyan Family</legend>
|
|
142
|
+
<datalist id="cem-color-cyan">
|
|
143
|
+
<option value="--cem-color-cyan-xl" style="background-color: var(--cem-color-cyan-xl); ">
|
|
144
|
+
#f1fefe | Extra light cyan | Used for comfort palette (light scenes) | Maps to --ng-cyan-99
|
|
145
|
+
</option>
|
|
146
|
+
<option value="--cem-color-cyan-l" style="background-color: var(--cem-color-cyan-l); ">
|
|
147
|
+
#00fbfb | Light cyan | Calm palette, creativity accent | Maps to --ng-cyan-90
|
|
148
|
+
</option>
|
|
149
|
+
<option value="--cem-color-cyan-d" style="background-color: var(--cem-color-cyan-d); ">
|
|
150
|
+
#006a6a | Dark cyan | Calm palette (dark theme) | Maps to --ng-cyan-40
|
|
151
|
+
</option>
|
|
152
|
+
<option value="--cem-color-cyan-xd" style="background-color: var(--cem-color-cyan-xd); ">
|
|
153
|
+
#001010 | Extra dark cyan | Used for comfort palette (dark scenes) | Maps to --ng-cyan-5
|
|
154
|
+
</option>
|
|
155
|
+
</datalist>
|
|
156
|
+
</fieldset>
|
|
157
|
+
|
|
158
|
+
<fieldset>
|
|
159
|
+
<legend>Blue Family</legend>
|
|
160
|
+
<datalist id="cem-color-blue">
|
|
161
|
+
<option value="--cem-color-blue-xl" style="background-color: var(--cem-color-blue-xl);">
|
|
162
|
+
#faf9fd | Lightest blue | Comfort/trust emotion (light scene) | Maps to --ng-azure-neutral-98, --mat-sys-surface
|
|
163
|
+
</option>
|
|
164
|
+
<option value="--cem-color-blue-l" style="background-color: var(--cem-color-blue-l); ">
|
|
165
|
+
#d7e3ff | Light blue | Trust palette, attention semantic | Maps to --ng-azure-90, --mat-sys-primary-container
|
|
166
|
+
</option>
|
|
167
|
+
<option value="--cem-color-blue-d" style="background-color: var(--cem-color-blue-d); ">
|
|
168
|
+
#002f65 | Dark blue | Trust palette (dark theme) | Maps to --ng-azure-20
|
|
169
|
+
</option>
|
|
170
|
+
<option value="--cem-color-blue-xd" style="background-color: var(--cem-color-blue-xd); ">
|
|
171
|
+
#1a1b1f | Darkest blue | Comfort/trust emotion (dark scene) | Maps to --ng-azure-neutral-10
|
|
172
|
+
</option>
|
|
173
|
+
</datalist>
|
|
174
|
+
</fieldset>
|
|
175
|
+
|
|
176
|
+
<fieldset>
|
|
177
|
+
<legend>Red Family</legend>
|
|
178
|
+
<datalist id="cem-color-red">
|
|
179
|
+
<option value="--cem-color-red-xl" style="background-color: var(--cem-color-red-xl);">
|
|
180
|
+
#ffb4ab | Extra light red | Danger palette (light theme) | Maps to --ng-error-80
|
|
181
|
+
</option>
|
|
182
|
+
<option value="--cem-color-red-l" style="background-color: var(--cem-color-red-l);">
|
|
183
|
+
#ba1a1a | Light red | Danger emotion, alert semantic | Maps to --ng-error-60, --mat-sys-error
|
|
184
|
+
</option>
|
|
185
|
+
<option value="--cem-color-red-d" style="background-color: var(--cem-color-red-d);" >
|
|
186
|
+
#690005 | Dark red | Danger palette (dark theme) | Maps to --ng-error-20
|
|
187
|
+
</option>
|
|
188
|
+
<option value="--cem-color-red-xd" style="background-color: var(--cem-color-red-xd);" >
|
|
189
|
+
#410002 | Extra dark red | Danger palette (dark theme, extreme) | Maps to --ng-error-10
|
|
190
|
+
</option>
|
|
191
|
+
</datalist>
|
|
192
|
+
</fieldset>
|
|
193
|
+
|
|
194
|
+
<fieldset>
|
|
195
|
+
<legend>Purple Family</legend>
|
|
196
|
+
<datalist id="cem-color-purple">
|
|
197
|
+
<option value="--cem-color-purple-xl" style="background-color: var(--cem-color-purple-xl);">
|
|
198
|
+
#f3e5f5 | Extra light purple | Creativity palette (light theme) | Maps to --mat-purple-50
|
|
199
|
+
</option>
|
|
200
|
+
<option value="--cem-color-purple-l" style="background-color: var(--cem-color-purple-l); ">
|
|
201
|
+
#e1bee7 | Light purple | Creativity emotion, brand-1 | Maps to --mat-purple-100
|
|
202
|
+
</option>
|
|
203
|
+
<option value="--cem-color-purple-d" style="background-color: var(--cem-color-purple-d); ">
|
|
204
|
+
#6a1b9a | Dark purple | Creativity palette (dark theme) | Maps to --mat-purple-800
|
|
205
|
+
</option>
|
|
206
|
+
<option value="--cem-color-purple-xd" style="background-color: var(--cem-color-purple-xd); ">
|
|
207
|
+
#4a148c | Extra dark purple | Creativity palette (dark theme, extreme) | Maps to --mat-purple-900
|
|
208
|
+
</option>
|
|
209
|
+
</datalist>
|
|
210
|
+
</fieldset>
|
|
211
|
+
|
|
212
|
+
<fieldset>
|
|
213
|
+
<legend>Orange/Yellow Family</legend>
|
|
214
|
+
<datalist id="cem-color-orange">
|
|
215
|
+
<option value="--cem-color-orange-xl" style="background-color: var(--cem-color-orange-xl); ">
|
|
216
|
+
#f0f070 | Extra light yellow | Enthusiasm palette (light theme) | Maps to --ng-yellow-80
|
|
217
|
+
</option>
|
|
218
|
+
<option value="--cem-color-orange-l" style="background-color: var(--cem-color-orange-l); ">
|
|
219
|
+
#ffe082 | Light orange | Enthusiasm emotion, brand-2 | Maps to --mat-amber-200
|
|
220
|
+
</option>
|
|
221
|
+
<option value="--cem-color-orange-d" style="background-color: var(--cem-color-orange-d); ">
|
|
222
|
+
#723600 | Dark orange | Enthusiasm hype (dark theme) | Maps to --ng-orange-30
|
|
223
|
+
</option>
|
|
224
|
+
<option value="--cem-color-orange-xd" style="background-color: var(--cem-color-orange-xd); ">
|
|
225
|
+
#502400 | Extra dark orange | Enthusiasm palette (dark theme, extreme) | Maps to --ng-orange-20
|
|
226
|
+
</option>
|
|
227
|
+
</datalist>
|
|
228
|
+
</fieldset>
|
|
229
|
+
|
|
230
|
+
<fieldset>
|
|
231
|
+
<legend>Brown Family</legend>
|
|
232
|
+
<datalist id="cem-color-brown">
|
|
233
|
+
<option value="--cem-color-brown-xl" style="background-color: var(--cem-color-brown-xl); ">
|
|
234
|
+
#d7ccc8 | Extra light brown | Conservative palette (light theme) | Maps to --mat-brown-100
|
|
235
|
+
</option>
|
|
236
|
+
<option value="--cem-color-brown-l" style="background-color: var(--cem-color-brown-l); ">
|
|
237
|
+
#a1887f | Light brown | Conservative emotion, brand-3 | Maps to --mat-brown-300
|
|
238
|
+
</option>
|
|
239
|
+
<option value="--cem-color-brown-d" style="background-color: var(--cem-color-brown-d); ">
|
|
240
|
+
#4e342e | Dark brown | Conservative palette (dark theme) | Maps to --mat-brown-800
|
|
241
|
+
</option>
|
|
242
|
+
<option value="--cem-color-brown-xd" style="background-color: var(--cem-color-brown-xd); ">
|
|
243
|
+
#3e2723 | Extra dark brown | Conservative palette (dark theme, extreme) | Maps to --mat-brown-900
|
|
244
|
+
</option>
|
|
245
|
+
</datalist>
|
|
246
|
+
</fieldset>
|
|
247
|
+
|
|
248
|
+
<fieldset>
|
|
249
|
+
<legend>Grey Family</legend>
|
|
250
|
+
<p>extreme values for grey are white and black</p>
|
|
251
|
+
<datalist id="cem-color-grey">
|
|
252
|
+
<option value="--cem-color-grey-l" style="background-color: var(--cem-color-grey-l); ">
|
|
253
|
+
#f1f1eb | Light grey | Conservative palette, neutral backgrounds | Maps to --ng-green-neutral-80
|
|
254
|
+
</option>
|
|
255
|
+
<option value="--cem-color-grey-d" style="background-color: var(--cem-color-grey-d); ">
|
|
256
|
+
#1a1c18 | Dark grey | Conservative palette (dark theme) | Maps to --ng-green-neutral-10
|
|
257
|
+
</option>
|
|
258
|
+
</datalist>
|
|
259
|
+
<p><small>Note: Grey family has only 2 variants (l, d) as neutral colors require fewer gradations.</small></p>
|
|
260
|
+
</fieldset>
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
</figure>
|
|
264
|
+
|
|
265
|
+
<figure class="with-color">
|
|
266
|
+
<figcaption>Emotional Palette</figcaption>
|
|
267
|
+
<p> Emotional palette tokens create the bridge between branded colors and action states.
|
|
268
|
+
The emotional palette is defined by marketing strategy and expressed through branded colors using design rationale.
|
|
269
|
+
Should your app aims to be aggressively seductive, calmy relaxing, or office focused will affect the choice of emotional palette.
|
|
270
|
+
</p>
|
|
271
|
+
<p> Emotional palette tokens form the link between branded colors and action states,
|
|
272
|
+
so users consistently feel what the interface intends to communicate.
|
|
273
|
+
</p>
|
|
274
|
+
<fieldset>
|
|
275
|
+
<legend>Emotional to Action Intent Mapping</legend>
|
|
276
|
+
<p>Each action intent maps to a specific emotional palette:</p>
|
|
277
|
+
<table>
|
|
278
|
+
<thead>
|
|
279
|
+
<tr>
|
|
280
|
+
<th>Action Intent</th>
|
|
281
|
+
<th>Emotional Palette</th>
|
|
282
|
+
<th>Base Color</th>
|
|
283
|
+
<th>Purpose</th>
|
|
284
|
+
</tr>
|
|
285
|
+
</thead>
|
|
286
|
+
<tbody>
|
|
287
|
+
<tr>
|
|
288
|
+
<td><code>explicit</code></td>
|
|
289
|
+
<td><code>creativity</code></td>
|
|
290
|
+
<td style="background-color: var(--cem-palette-creativity); color: var(--cem-palette-creativity-text);">Purple</td>
|
|
291
|
+
<td>User explicitly/intentionally clicks or activates</td>
|
|
292
|
+
</tr>
|
|
293
|
+
<tr>
|
|
294
|
+
<td><code>primary</code></td>
|
|
295
|
+
<td><code>trust</code></td>
|
|
296
|
+
<td style="background-color: var(--cem-palette-trust); color: var(--cem-palette-trust-text);">Blue</td>
|
|
297
|
+
<td>Default, confirmatory, triggered by ENTER</td>
|
|
298
|
+
</tr>
|
|
299
|
+
<tr>
|
|
300
|
+
<td><code>contextual</code></td>
|
|
301
|
+
<td><code>comfort</code></td>
|
|
302
|
+
<td style="background-color: var(--cem-palette-comfort); color: var(--cem-palette-comfort-text);">Cyan/White</td>
|
|
303
|
+
<td>Integrated within specific context (toolbar/menu)</td>
|
|
304
|
+
</tr>
|
|
305
|
+
<tr>
|
|
306
|
+
<td><code>alternate</code></td>
|
|
307
|
+
<td><code>enthusiasm</code></td>
|
|
308
|
+
<td style="background-color: var(--cem-palette-enthusiasm); color: var(--cem-palette-enthusiasm-text);">Orange/Yellow</td>
|
|
309
|
+
<td>Triggering non-usual alternative flow</td>
|
|
310
|
+
</tr>
|
|
311
|
+
<tr>
|
|
312
|
+
<td><code>destructive</code></td>
|
|
313
|
+
<td><code>danger</code></td>
|
|
314
|
+
<td style="background-color: var(--cem-palette-danger); color: var(--cem-palette-danger-text);">Red</td>
|
|
315
|
+
<td>Risky, potentially harmful, requires caution</td>
|
|
316
|
+
</tr>
|
|
317
|
+
</tbody>
|
|
318
|
+
</table>
|
|
319
|
+
</fieldset>
|
|
320
|
+
<fieldset>
|
|
321
|
+
<legend>Emotional Token Variants</legend>
|
|
322
|
+
<p> Each emotional token comes in four base variants to ensure reliable text contrast and accessibility.
|
|
323
|
+
Intermediate colors are generated between these variants to represent nuances such as action state importance.
|
|
324
|
+
</p>
|
|
325
|
+
<dl>
|
|
326
|
+
<dt><b>color per light theme</b></dt>
|
|
327
|
+
<dd>Each of four emotion variations bellow have own values in each of
|
|
328
|
+
light/dark/contrast/native theme. <br/>
|
|
329
|
+
For light and dark themes the <code>light-dark()</code> CSS function switches the same variation
|
|
330
|
+
to theme specific one. </dd>
|
|
331
|
+
|
|
332
|
+
<dt><code>--cem-palette-{emotion}</code></dt>
|
|
333
|
+
<dd>Base emotional color. Used as background/base surface/ primary filler color.
|
|
334
|
+
</dd>
|
|
335
|
+
|
|
336
|
+
<dt><code>--cem-palette-{emotion}-x</code></dt>
|
|
337
|
+
<dd>Extreme variant (inverted) of the base emotional color. Used by <code>color-mix()</code> formulas for state progression in
|
|
338
|
+
<a href="https://github.com/EPA-WG/custom-element-dist/discussions/14#discussioncomment-14060329">Emotional palette gradations</a>
|
|
339
|
+
</dd>
|
|
340
|
+
|
|
341
|
+
<dt><code>--cem-palette-{emotion}-text</code></dt>
|
|
342
|
+
<dd>Ink/Text color for use on the base emotional background. Ensures WCAG-compliant contrast (≥4.5:1 for text).</dd>
|
|
343
|
+
|
|
344
|
+
<dt><code>--cem-palette-{emotion}-text-x</code></dt>
|
|
345
|
+
<dd>Ink/Text color for use on the extreme variant background. The color is triggered from
|
|
346
|
+
<code>--cem-palette-{emotion}-text</code> when background become close to
|
|
347
|
+
<code>--cem-palette-{emotion}-x</code> for contrast maintaining and to emphasize the significance of deviation.
|
|
348
|
+
As in `active/pending` states of `actions`
|
|
349
|
+
</dd>
|
|
350
|
+
</dl>
|
|
351
|
+
|
|
352
|
+
<p><strong>Usage Pattern:</strong></p>
|
|
353
|
+
<pre>
|
|
354
|
+
/* Base tokens switch between light/dark mode */
|
|
355
|
+
--cem-palette-comfort: light-dark(var(--cem-color-cyan-xl), var(--cem-color-cyan-xd));
|
|
356
|
+
--cem-palette-comfort-text: light-dark(var(--cem-color-cyan-xd), var(--cem-color-cyan-xl));
|
|
357
|
+
|
|
358
|
+
/* State variations use color-mix() to create progression */
|
|
359
|
+
--cem-action-hover-background: color-mix(in srgb, var(--cem-palette-comfort) 60%, var(--cem-palette-comfort-x));
|
|
360
|
+
</pre>
|
|
361
|
+
</fieldset>
|
|
362
|
+
|
|
363
|
+
<fieldset>
|
|
364
|
+
<legend>Comfort Palette</legend>
|
|
365
|
+
<p><strong>Purpose:</strong> Light scene color for reading backgrounds. Represents purity, innocence, cleanliness, peace.</p>
|
|
366
|
+
<p><strong>System Mapping:</strong> Canvas (system color)</p>
|
|
367
|
+
<p><strong>Warmth:</strong> Cool</p>
|
|
368
|
+
<datalist id="cem-palette-comfort">
|
|
369
|
+
<option value="--cem-palette-comfort" style="background-color: var(--cem-palette-comfort); color: var(--cem-palette-comfort-text);">
|
|
370
|
+
Base comfort color | light-dark(cyan-xl, cyan-xd) | Main canvas/background
|
|
371
|
+
</option>
|
|
372
|
+
<option value="--cem-palette-comfort-text" style="background-color: var(--cem-palette-comfort); color: var(--cem-palette-comfort-text);">
|
|
373
|
+
Comfort text color | light-dark(cyan-xd, cyan-xl) | Primary text on comfort backgrounds
|
|
374
|
+
</option>
|
|
375
|
+
<option value="--cem-palette-comfort-x" style="background-color: var(--cem-palette-comfort-x); color: var(--cem-palette-comfort-text-x);">
|
|
376
|
+
Comfort extreme variant | light-dark(cyan-xd, cyan-xl) | Used in color-mix for state variations
|
|
377
|
+
</option>
|
|
378
|
+
<option value="--cem-palette-comfort-text-x" style="background-color: var(--cem-palette-comfort-x); color: var(--cem-palette-comfort-text-x);">
|
|
379
|
+
Comfort extreme text | light-dark(cyan-xl, cyan-xd) | Text on extreme variant backgrounds
|
|
380
|
+
</option>
|
|
381
|
+
</datalist>
|
|
382
|
+
<p><small><strong>CSS Definition:</strong></small></p>
|
|
383
|
+
<pre>
|
|
384
|
+
--cem-palette-comfort : light-dark(var(--cem-color-cyan-xl), var(--cem-color-cyan-xd));
|
|
385
|
+
--cem-palette-comfort-text : light-dark(var(--cem-color-cyan-xd), var(--cem-color-cyan-xl));
|
|
386
|
+
--cem-palette-comfort-x : light-dark(var(--cem-color-cyan-xd), var(--cem-color-cyan-xl));
|
|
387
|
+
--cem-palette-comfort-text-x: light-dark(var(--cem-color-cyan-xl), var(--cem-color-cyan-xd));
|
|
388
|
+
</pre>
|
|
389
|
+
</fieldset>
|
|
390
|
+
|
|
391
|
+
<fieldset>
|
|
392
|
+
<legend>Calm Palette</legend>
|
|
393
|
+
<p><strong>Purpose:</strong> Dark scene color for minimal object environments. Represents mystery, elegance, power.</p>
|
|
394
|
+
<p><strong>System Mapping:</strong> CanvasText (system color)</p>
|
|
395
|
+
<p><strong>Warmth:</strong> Cool</p>
|
|
396
|
+
<datalist id="cem-palette-calm">
|
|
397
|
+
<option value="--cem-palette-calm" style="background-color: var(--cem-palette-calm); color: var(--cem-palette-calm-text);">
|
|
398
|
+
Base calm color | light-dark(cyan-l, cyan-d) | Foreground elements
|
|
399
|
+
</option>
|
|
400
|
+
<option value="--cem-palette-calm-text" style="background-color: var(--cem-palette-calm); color: var(--cem-palette-calm-text);">
|
|
401
|
+
Calm text color | Uses comfort-text | Text on calm backgrounds
|
|
402
|
+
</option>
|
|
403
|
+
<option value="--cem-palette-calm-x" style="background-color: var(--cem-palette-calm-x); color: var(--cem-palette-calm-text-x);">
|
|
404
|
+
Calm extreme variant | light-dark(cyan-d, cyan-l) | Inverted calm color
|
|
405
|
+
</option>
|
|
406
|
+
<option value="--cem-palette-calm-text-x" style="background-color: var(--cem-palette-calm-x); color: var(--cem-palette-calm-text-x);">
|
|
407
|
+
Calm extreme text | Uses comfort-text-x | Text on extreme calm backgrounds
|
|
408
|
+
</option>
|
|
409
|
+
</datalist>
|
|
410
|
+
<p><small><strong>CSS Definition:</strong></small></p>
|
|
411
|
+
<pre>
|
|
412
|
+
--cem-palette-calm : light-dark(var(--cem-color-cyan-l), var(--cem-color-cyan-d));
|
|
413
|
+
--cem-palette-calm-text : var(--cem-palette-comfort-text);
|
|
414
|
+
--cem-palette-calm-x : light-dark(var(--cem-color-cyan-d), var(--cem-color-cyan-l));
|
|
415
|
+
--cem-palette-calm-text-x: var(--cem-palette-comfort-text-x);
|
|
416
|
+
</pre>
|
|
417
|
+
</fieldset>
|
|
418
|
+
|
|
419
|
+
<fieldset>
|
|
420
|
+
<legend>Trust Palette</legend>
|
|
421
|
+
<p><strong>Purpose:</strong> Primary action backgrounds, attention-grabbing elements. Represents reliability, confidence.</p>
|
|
422
|
+
<p><strong>System Mapping:</strong> Highlight with HighlightText (system colors)</p>
|
|
423
|
+
<p><strong>Warmth:</strong> Cool</p>
|
|
424
|
+
<datalist id="cem-palette-trust">
|
|
425
|
+
<option value="--cem-palette-trust" style="background-color: var(--cem-palette-trust); color: var(--cem-palette-trust-text);">
|
|
426
|
+
Base trust color | light-dark(blue-l, blue-d) | Primary actions, highlights
|
|
427
|
+
</option>
|
|
428
|
+
<option value="--cem-palette-trust-text" style="background-color: var(--cem-palette-trust); color: var(--cem-palette-trust-text);">
|
|
429
|
+
Trust text color | light-dark(comfort-text, white) | Text on trust backgrounds
|
|
430
|
+
</option>
|
|
431
|
+
<option value="--cem-palette-trust-x" style="background-color: var(--cem-palette-trust-x); color: var(--cem-palette-trust-text-x);">
|
|
432
|
+
Trust extreme variant | light-dark(blue-d, blue-l) | Darker/lighter trust variation
|
|
433
|
+
</option>
|
|
434
|
+
<option value="--cem-palette-trust-text-x" style="background-color: var(--cem-palette-trust-x); color: var(--cem-palette-trust-text-x);">
|
|
435
|
+
Trust extreme text | Uses comfort-text-x | Text on extreme trust backgrounds
|
|
436
|
+
</option>
|
|
437
|
+
</datalist>
|
|
438
|
+
<p><small><strong>CSS Definition:</strong></small></p>
|
|
439
|
+
<pre>
|
|
440
|
+
--cem-palette-trust : light-dark(var(--cem-color-blue-l), var(--cem-color-blue-d));
|
|
441
|
+
--cem-palette-trust-text : light-dark(var(--cem-palette-comfort-text), white);
|
|
442
|
+
--cem-palette-trust-x : light-dark(var(--cem-color-blue-d), var(--cem-color-blue-l));
|
|
443
|
+
--cem-palette-trust-text-x: var(--cem-palette-comfort-text-x);
|
|
444
|
+
</pre>
|
|
445
|
+
</fieldset>
|
|
446
|
+
|
|
447
|
+
<fieldset>
|
|
448
|
+
<legend>Danger Palette</legend>
|
|
449
|
+
<p><strong>Purpose:</strong> Alert messages, destructive actions, error states. Represents urgency, caution, passion.</p>
|
|
450
|
+
<p><strong>System Mapping:</strong> N/A (uses red)</p>
|
|
451
|
+
<p><strong>Warmth:</strong> Warm</p>
|
|
452
|
+
<datalist id="cem-palette-danger">
|
|
453
|
+
<option value="--cem-palette-danger" style="background-color: var(--cem-palette-danger); color: var(--cem-palette-danger-text);">
|
|
454
|
+
Base danger color | light-dark(red-l, red-d) | Error messages, destructive actions
|
|
455
|
+
</option>
|
|
456
|
+
<option value="--cem-palette-danger-text" style="background-color: var(--cem-palette-danger); color: var(--cem-palette-danger-text);">
|
|
457
|
+
Danger text color | light-dark(comfort-text-x, comfort-text) | Text on danger backgrounds
|
|
458
|
+
</option>
|
|
459
|
+
<option value="--cem-palette-danger-x" style="background-color: var(--cem-palette-danger-x); color: var(--cem-palette-danger-text-x);">
|
|
460
|
+
Danger extreme variant | light-dark(red-d, red-l) | Darker/lighter danger variation
|
|
461
|
+
</option>
|
|
462
|
+
<option value="--cem-palette-danger-text-x" style="background-color: var(--cem-palette-danger-x); color: var(--cem-palette-danger-text-x);">
|
|
463
|
+
Danger extreme text | Uses orange-xl | High contrast text on extreme danger backgrounds
|
|
464
|
+
</option>
|
|
465
|
+
</datalist>
|
|
466
|
+
<p><small><strong>CSS Definition:</strong></small></p>
|
|
467
|
+
<pre>
|
|
468
|
+
--cem-palette-danger : light-dark(var(--cem-color-red-l), var(--cem-color-red-d));
|
|
469
|
+
--cem-palette-danger-text : light-dark(var(--cem-palette-comfort-text-x), var(--cem-palette-comfort-text));
|
|
470
|
+
--cem-palette-danger-x : light-dark(var(--cem-color-red-d), var(--cem-color-red-l));
|
|
471
|
+
--cem-palette-danger-text-x: light-dark(var(--cem-color-orange-xl), var(--cem-color-orange-xl));
|
|
472
|
+
</pre>
|
|
473
|
+
</fieldset>
|
|
474
|
+
|
|
475
|
+
<fieldset>
|
|
476
|
+
<legend>Creativity Palette</legend>
|
|
477
|
+
<p><strong>Purpose:</strong> Brand identity (brand-1), creative elements, explicit actions. Represents luxury, innovation, royalty.</p>
|
|
478
|
+
<p><strong>System Mapping:</strong> ButtonFace with ButtonText (system colors)</p>
|
|
479
|
+
<p><strong>Warmth:</strong> Cool</p>
|
|
480
|
+
<datalist id="cem-palette-creativity">
|
|
481
|
+
<option value="--cem-palette-creativity" style="background-color: var(--cem-palette-creativity); color: var(--cem-palette-creativity-text);">
|
|
482
|
+
Base creativity color | light-dark(purple-l, purple-d) | Brand-1, explicit actions
|
|
483
|
+
</option>
|
|
484
|
+
<option value="--cem-palette-creativity-text" style="background-color: var(--cem-palette-creativity); color: var(--cem-palette-creativity-text);">
|
|
485
|
+
Creativity text color | Uses comfort-text | Text on creativity backgrounds
|
|
486
|
+
</option>
|
|
487
|
+
<option value="--cem-palette-creativity-x" style="background-color: var(--cem-palette-creativity-x); color: var(--cem-palette-creativity-text-x);">
|
|
488
|
+
Creativity extreme variant | light-dark(purple-d, purple-l) | Darker/lighter creativity variation
|
|
489
|
+
</option>
|
|
490
|
+
<option value="--cem-palette-creativity-text-x" style="background-color: var(--cem-palette-creativity-x); color: var(--cem-palette-creativity-text-x);">
|
|
491
|
+
Creativity extreme text | Uses comfort-text-x | Text on extreme creativity backgrounds
|
|
492
|
+
</option>
|
|
493
|
+
</datalist>
|
|
494
|
+
<p><small><strong>CSS Definition:</strong></small></p>
|
|
495
|
+
<pre>
|
|
496
|
+
--cem-palette-creativity : light-dark(var(--cem-color-purple-l), var(--cem-color-purple-d));
|
|
497
|
+
--cem-palette-creativity-text : var(--cem-palette-comfort-text);
|
|
498
|
+
--cem-palette-creativity-x : light-dark(var(--cem-color-purple-d), var(--cem-color-purple-l));
|
|
499
|
+
--cem-palette-creativity-text-x: var(--cem-palette-comfort-text-x);
|
|
500
|
+
</pre>
|
|
501
|
+
</fieldset>
|
|
502
|
+
|
|
503
|
+
<fieldset>
|
|
504
|
+
<legend>Enthusiasm Palette</legend>
|
|
505
|
+
<p><strong>Purpose:</strong> Brand identity (brand-2), alternate flow actions, positive feedback. Represents warmth, optimism, energy.</p>
|
|
506
|
+
<p><strong>System Mapping:</strong> Mark with MarkText (system colors)</p>
|
|
507
|
+
<p><strong>Warmth:</strong> Warm</p>
|
|
508
|
+
<datalist id="cem-palette-enthusiasm">
|
|
509
|
+
<option value="--cem-palette-enthusiasm" style="background-color: var(--cem-palette-enthusiasm); color: var(--cem-palette-enthusiasm-text);">
|
|
510
|
+
Base enthusiasm color | light-dark(orange-l, orange-d) | Brand-2, alternate actions
|
|
511
|
+
</option>
|
|
512
|
+
<option value="--cem-palette-enthusiasm-text" style="background-color: var(--cem-palette-enthusiasm); color: var(--cem-palette-enthusiasm-text);">
|
|
513
|
+
Enthusiasm text color | light-dark(comfort-text, white) | Text on enthusiasm backgrounds
|
|
514
|
+
</option>
|
|
515
|
+
<option value="--cem-palette-enthusiasm-x" style="background-color: var(--cem-palette-enthusiasm-x); color: var(--cem-palette-enthusiasm-text-x);">
|
|
516
|
+
Enthusiasm extreme variant | light-dark(orange-xd, orange-xl) | Darker/lighter enthusiasm variation
|
|
517
|
+
</option>
|
|
518
|
+
<option value="--cem-palette-enthusiasm-text-x" style="background-color: var(--cem-palette-enthusiasm-x); color: var(--cem-palette-enthusiasm-text-x);">
|
|
519
|
+
Enthusiasm extreme text | Uses comfort-text-x | Text on extreme enthusiasm backgrounds
|
|
520
|
+
</option>
|
|
521
|
+
</datalist>
|
|
522
|
+
<p><small><strong>CSS Definition:</strong></small></p>
|
|
523
|
+
<pre>
|
|
524
|
+
--cem-palette-enthusiasm : light-dark(var(--cem-color-orange-l), var(--cem-color-orange-d));
|
|
525
|
+
--cem-palette-enthusiasm-text : light-dark(var(--cem-palette-comfort-text), white);
|
|
526
|
+
--cem-palette-enthusiasm-x : light-dark(var(--cem-color-orange-xd), var(--cem-color-orange-xl));
|
|
527
|
+
--cem-palette-enthusiasm-text-x: var(--cem-palette-comfort-text-x);
|
|
528
|
+
</pre>
|
|
529
|
+
</fieldset>
|
|
530
|
+
|
|
531
|
+
<fieldset>
|
|
532
|
+
<legend>Conservative Palette</legend>
|
|
533
|
+
<p><strong>Purpose:</strong> Brand identity (brand-3), disabled states, neutral elements. Represents stability, earthiness, restraint.</p>
|
|
534
|
+
<p><strong>System Mapping:</strong> GrayText (system color)</p>
|
|
535
|
+
<p><strong>Warmth:</strong> Neutral</p>
|
|
536
|
+
<datalist id="cem-palette-conservative">
|
|
537
|
+
<option value="--cem-palette-conservative" style="background-color: var(--cem-palette-conservative); color: var(--cem-palette-conservative-text);">
|
|
538
|
+
Base conservative color | light-dark(grey-l, grey-d) | Brand-3, disabled states
|
|
539
|
+
</option>
|
|
540
|
+
<option value="--cem-palette-conservative-text" style="background-color: var(--cem-palette-conservative); color: var(--cem-palette-conservative-text);">
|
|
541
|
+
Conservative text color | Uses comfort-text | Text on conservative backgrounds
|
|
542
|
+
</option>
|
|
543
|
+
<option value="--cem-palette-conservative-x" style="background-color: var(--cem-palette-conservative-x); color: var(--cem-palette-conservative-text-x);">
|
|
544
|
+
Conservative extreme variant | light-dark(grey-d, grey-l) | Darker/lighter conservative variation
|
|
545
|
+
</option>
|
|
546
|
+
<option value="--cem-palette-conservative-text-x" style="background-color: var(--cem-palette-conservative-x); color: var(--cem-palette-conservative-text-x);">
|
|
547
|
+
Conservative extreme text | Uses comfort-text-x | Text on extreme conservative backgrounds
|
|
548
|
+
</option>
|
|
549
|
+
</datalist>
|
|
550
|
+
<p><small><strong>CSS Definition:</strong></small></p>
|
|
551
|
+
<pre>
|
|
552
|
+
--cem-palette-conservative : light-dark(var(--cem-color-grey-l), var(--cem-color-grey-d));
|
|
553
|
+
--cem-palette-conservative-text : var(--cem-palette-comfort-text);
|
|
554
|
+
--cem-palette-conservative-x : light-dark(var(--cem-color-grey-d), var(--cem-color-grey-l));
|
|
555
|
+
--cem-palette-conservative-text-x: var(--cem-palette-comfort-text-x);
|
|
556
|
+
</pre>
|
|
557
|
+
</fieldset>
|
|
558
|
+
|
|
559
|
+
</figure>
|
|
560
|
+
|
|
561
|
+
<figure>
|
|
562
|
+
<figcaption>Actions</figcaption>
|
|
563
|
+
<fieldset >
|
|
564
|
+
<legend>Action selectors</legend>
|
|
565
|
+
<datalist id="action-selector-variants">
|
|
566
|
+
<span class="action">.action</span>
|
|
567
|
+
<button>button</button>
|
|
568
|
+
<input type="submit" value="input[type='submit']" />
|
|
569
|
+
<input type="reset" value="input[type='reset']" />
|
|
570
|
+
<input type="button" value="input[type='button']" />
|
|
571
|
+
</datalist>
|
|
572
|
+
</fieldset>
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
<fieldset>
|
|
576
|
+
<legend>Action Intent Categories</legend>
|
|
577
|
+
<p>Action intents categorize user interactions by their purpose and consequence, guiding both visual design and user expectations. Each intent maps to a specific emotional palette to create consistent psychological associations.</p>
|
|
578
|
+
|
|
579
|
+
<datalist id="cem-action-intent">
|
|
580
|
+
<option value="explicit" base-color="white" > user explicitly/intentionally clicks or activates </option>
|
|
581
|
+
<option value="primary" base-color="black" > default, confirmatory, implicit. Triggered by ENTER </option>
|
|
582
|
+
<option value="contextual" base-color="blue" > integrated within a specific context, Toolbar/menu </option>
|
|
583
|
+
<option value="alternate" base-color="yellow" > triggering not usual alternative flow </option>
|
|
584
|
+
<option value="destructive" base-color="red" > risky, potentially harmful, requires caution </option>
|
|
585
|
+
</datalist>
|
|
586
|
+
<hr/>
|
|
587
|
+
|
|
588
|
+
<details>
|
|
589
|
+
<summary><strong>Explicit Intent</strong> — <code>.explicit</code>, <code>[flow="explicit"]</code>, <code>[explicit]</code></summary>
|
|
590
|
+
<dl>
|
|
591
|
+
<dt>Purpose</dt>
|
|
592
|
+
<dd>Actions that require deliberate, conscious user activation. The user must explicitly choose to engage with these elements.</dd>
|
|
593
|
+
|
|
594
|
+
<dt>Emotional Mapping</dt>
|
|
595
|
+
<dd><strong>Creativity</strong> (Purple/Violet) — Represents uniqueness, deliberate choice, and creative decision-making.</dd>
|
|
596
|
+
|
|
597
|
+
<dt>Use Cases</dt>
|
|
598
|
+
<dd>
|
|
599
|
+
<ul>
|
|
600
|
+
<li>Custom action buttons that initiate non-standard workflows</li>
|
|
601
|
+
<li>Feature toggles requiring conscious activation</li>
|
|
602
|
+
<li>Specialized tools or operations outside the main flow</li>
|
|
603
|
+
<li>Actions that open new contexts or modes</li>
|
|
604
|
+
</ul>
|
|
605
|
+
</dd>
|
|
606
|
+
|
|
607
|
+
<dt>Trigger Method</dt>
|
|
608
|
+
<dd>Mouse click, touch tap, or explicit keyboard activation (Space on focused element)</dd>
|
|
609
|
+
|
|
610
|
+
<dt>Visual Characteristics</dt>
|
|
611
|
+
<dd>Purple/violet background distinguishes these from standard actions, signaling intentionality</dd>
|
|
612
|
+
|
|
613
|
+
<dt>Example</dt>
|
|
614
|
+
<dd><button class="action explicit">Customize Layout</button></dd>
|
|
615
|
+
</dl>
|
|
616
|
+
</details>
|
|
617
|
+
|
|
618
|
+
<details>
|
|
619
|
+
<summary><strong>Primary Intent</strong> — <code>.primary</code>, <code>[flow="primary"]</code>, <code>[primary]</code></summary>
|
|
620
|
+
<dl>
|
|
621
|
+
<dt>Purpose</dt>
|
|
622
|
+
<dd>Default, confirmatory actions representing the expected next step in a workflow. These are the "happy path" actions.</dd>
|
|
623
|
+
|
|
624
|
+
<dt>Emotional Mapping</dt>
|
|
625
|
+
<dd><strong>Trust</strong> (Blue) — Conveys reliability, safety, and confidence in moving forward.</dd>
|
|
626
|
+
|
|
627
|
+
<dt>Use Cases</dt>
|
|
628
|
+
<dd>
|
|
629
|
+
<ul>
|
|
630
|
+
<li>Submit buttons in forms</li>
|
|
631
|
+
<li>Confirmation dialogs ("OK", "Continue", "Save")</li>
|
|
632
|
+
<li>Next step in wizards or multi-step processes</li>
|
|
633
|
+
<li>Primary call-to-action buttons</li>
|
|
634
|
+
</ul>
|
|
635
|
+
</dd>
|
|
636
|
+
|
|
637
|
+
<dt>Trigger Method</dt>
|
|
638
|
+
<dd>Triggered by ENTER key when form/dialog is focused, or explicit click/tap</dd>
|
|
639
|
+
|
|
640
|
+
<dt>Visual Characteristics</dt>
|
|
641
|
+
<dd>Blue background signals trustworthiness and forward progress</dd>
|
|
642
|
+
|
|
643
|
+
<dt>Example</dt>
|
|
644
|
+
<dd><button class="action primary">Submit Form</button></dd>
|
|
645
|
+
</dl>
|
|
646
|
+
</details>
|
|
647
|
+
|
|
648
|
+
<details>
|
|
649
|
+
<summary><strong>Contextual Intent</strong> — <code>.contextual</code>, <code>[flow="contextual"]</code>, <code>[contextual]</code></summary>
|
|
650
|
+
<dl>
|
|
651
|
+
<dt>Purpose</dt>
|
|
652
|
+
<dd>Actions integrated within a specific UI context (toolbar, menu, inline controls) that operate on or within that context.</dd>
|
|
653
|
+
|
|
654
|
+
<dt>Emotional Mapping</dt>
|
|
655
|
+
<dd><strong>Comfort</strong> (Cyan/White/Canvas) — Blends with the interface, providing calm, non-intrusive functionality.</dd>
|
|
656
|
+
|
|
657
|
+
<dt>Use Cases</dt>
|
|
658
|
+
<dd>
|
|
659
|
+
<ul>
|
|
660
|
+
<li>Toolbar buttons (bold, italic, align)</li>
|
|
661
|
+
<li>Menu items and dropdown options</li>
|
|
662
|
+
<li>Inline editing controls</li>
|
|
663
|
+
<li>Navigation elements within a panel</li>
|
|
664
|
+
<li>Filter and sort controls</li>
|
|
665
|
+
</ul>
|
|
666
|
+
</dd>
|
|
667
|
+
|
|
668
|
+
<dt>Trigger Method</dt>
|
|
669
|
+
<dd>Click, tap, or keyboard selection within context</dd>
|
|
670
|
+
|
|
671
|
+
<dt>Visual Characteristics</dt>
|
|
672
|
+
<dd>Subtle, blends with canvas/background. No default outline in some themes to reduce visual noise.</dd>
|
|
673
|
+
|
|
674
|
+
<dt>Example</dt>
|
|
675
|
+
<dd><button class="action contextual">⋮ More Options</button></dd>
|
|
676
|
+
</dl>
|
|
677
|
+
</details>
|
|
678
|
+
|
|
679
|
+
<details>
|
|
680
|
+
<summary><strong>Alternate Intent</strong> — <code>.alternate</code>, <code>[flow="alternate"]</code>, <code>[alternate]</code></summary>
|
|
681
|
+
<dl>
|
|
682
|
+
<dt>Purpose</dt>
|
|
683
|
+
<dd>Actions that trigger non-standard or alternative workflows, offering secondary paths or optional features.</dd>
|
|
684
|
+
|
|
685
|
+
<dt>Emotional Mapping</dt>
|
|
686
|
+
<dd><strong>Enthusiasm</strong> (Orange/Yellow) — Signals energy, optimism, and alternative possibilities without danger.</dd>
|
|
687
|
+
|
|
688
|
+
<dt>Use Cases</dt>
|
|
689
|
+
<dd>
|
|
690
|
+
<ul>
|
|
691
|
+
<li>Cancel or back buttons</li>
|
|
692
|
+
<li>Skip or bypass options</li>
|
|
693
|
+
<li>Alternative save options ("Save as Draft")</li>
|
|
694
|
+
<li>Secondary actions in dialogs</li>
|
|
695
|
+
<li>Feature previews or beta options</li>
|
|
696
|
+
</ul>
|
|
697
|
+
</dd>
|
|
698
|
+
|
|
699
|
+
<dt>Trigger Method</dt>
|
|
700
|
+
<dd>Explicit click/tap. Often ESC key for cancel operations.</dd>
|
|
701
|
+
|
|
702
|
+
<dt>Visual Characteristics</dt>
|
|
703
|
+
<dd>Orange/yellow background distinguishes from primary flow while remaining inviting</dd>
|
|
704
|
+
|
|
705
|
+
<dt>Example</dt>
|
|
706
|
+
<dd><button class="action alternate">Save as Draft</button></dd>
|
|
707
|
+
</dl>
|
|
708
|
+
</details>
|
|
709
|
+
|
|
710
|
+
<details>
|
|
711
|
+
<summary><strong>Destructive Intent</strong> — <code>.destructive</code>, <code>[flow="destructive"]</code>, <code>[destructive]</code></summary>
|
|
712
|
+
<dl>
|
|
713
|
+
<dt>Purpose</dt>
|
|
714
|
+
<dd>High-risk actions that are potentially harmful, irreversible, or require extreme caution. These actions may result in data loss or significant changes.</dd>
|
|
715
|
+
|
|
716
|
+
<dt>Emotional Mapping</dt>
|
|
717
|
+
<dd><strong>Danger</strong> (Red) — Universal signal for caution, urgency, and potential negative consequences.</dd>
|
|
718
|
+
|
|
719
|
+
<dt>Use Cases</dt>
|
|
720
|
+
<dd>
|
|
721
|
+
<ul>
|
|
722
|
+
<li>Delete buttons</li>
|
|
723
|
+
<li>Remove or uninstall actions</li>
|
|
724
|
+
<li>Reset or clear operations</li>
|
|
725
|
+
<li>Permanent data modifications</li>
|
|
726
|
+
<li>Account termination or logout</li>
|
|
727
|
+
</ul>
|
|
728
|
+
</dd>
|
|
729
|
+
|
|
730
|
+
<dt>Trigger Method</dt>
|
|
731
|
+
<dd>Explicit click/tap only. Should often require confirmation.</dd>
|
|
732
|
+
|
|
733
|
+
<dt>Visual Characteristics</dt>
|
|
734
|
+
<dd>Red background immediately signals danger and prompts careful consideration</dd>
|
|
735
|
+
|
|
736
|
+
<dt>Best Practice</dt>
|
|
737
|
+
<dd>⚠️ Destructive actions should typically be accompanied by confirmation dialogs or require a secondary verification step.</dd>
|
|
738
|
+
|
|
739
|
+
<dt>Example</dt>
|
|
740
|
+
<dd><button class="action destructive">Delete Account</button></dd>
|
|
741
|
+
</dl>
|
|
742
|
+
</details>
|
|
743
|
+
|
|
744
|
+
</fieldset>
|
|
745
|
+
|
|
746
|
+
<fieldset>
|
|
747
|
+
<legend>Intent ➢ Emotion ➢ Color Mapping</legend>
|
|
748
|
+
<p>This table shows the complete chain from action intent through emotional palette to branded colors:</p>
|
|
749
|
+
<table>
|
|
750
|
+
<thead>
|
|
751
|
+
<tr>
|
|
752
|
+
<th>Action Intent</th>
|
|
753
|
+
<th>Emotional Palette</th>
|
|
754
|
+
<th>Branded Color (Light Mode)</th>
|
|
755
|
+
<th>Branded Color (Dark Mode)</th>
|
|
756
|
+
<th>CSS Token</th>
|
|
757
|
+
</tr>
|
|
758
|
+
</thead>
|
|
759
|
+
<tbody>
|
|
760
|
+
<tr>
|
|
761
|
+
<td><code>explicit</code></td>
|
|
762
|
+
<td><code>creativity</code></td>
|
|
763
|
+
<td style="background-color: var(--cem-color-purple-l); color: var(--cem-color-purple-xd);">purple-l (#e1bee7)</td>
|
|
764
|
+
<td style="background-color: var(--cem-color-purple-d); color: var(--cem-color-purple-xl);">purple-d (#6a1b9a)</td>
|
|
765
|
+
<td><code>--cem-action-explicit-default-background</code></td>
|
|
766
|
+
</tr>
|
|
767
|
+
<tr>
|
|
768
|
+
<td><code>primary</code></td>
|
|
769
|
+
<td><code>trust</code></td>
|
|
770
|
+
<td style="background-color: var(--cem-color-blue-l); color: var(--cem-color-blue-xd);">blue-l (#d7e3ff)</td>
|
|
771
|
+
<td style="background-color: var(--cem-color-blue-d); color: var(--cem-color-blue-xl);">blue-d (#002f65)</td>
|
|
772
|
+
<td><code>--cem-action-primary-default-background</code></td>
|
|
773
|
+
</tr>
|
|
774
|
+
<tr>
|
|
775
|
+
<td><code>contextual</code></td>
|
|
776
|
+
<td><code>comfort</code></td>
|
|
777
|
+
<td style="background-color: var(--cem-color-cyan-xl); color: var(--cem-color-cyan-xd);">cyan-xl (#f1fefe)</td>
|
|
778
|
+
<td style="background-color: var(--cem-color-cyan-xd); color: var(--cem-color-cyan-xl);">cyan-xd (#001010)</td>
|
|
779
|
+
<td><code>--cem-action-contextual-default-background</code></td>
|
|
780
|
+
</tr>
|
|
781
|
+
<tr>
|
|
782
|
+
<td><code>alternate</code></td>
|
|
783
|
+
<td><code>enthusiasm</code></td>
|
|
784
|
+
<td style="background-color: var(--cem-color-orange-l); color: var(--cem-color-orange-xd);">orange-l (#ffe082)</td>
|
|
785
|
+
<td style="background-color: var(--cem-color-orange-d); color: var(--cem-color-orange-xl);">orange-d (#723600)</td>
|
|
786
|
+
<td><code>--cem-action-alternate-default-background</code></td>
|
|
787
|
+
</tr>
|
|
788
|
+
<tr>
|
|
789
|
+
<td><code>destructive</code></td>
|
|
790
|
+
<td><code>danger</code></td>
|
|
791
|
+
<td style="background-color: var(--cem-color-red-l); color: white;">red-l (#ba1a1a)</td>
|
|
792
|
+
<td style="background-color: var(--cem-color-red-d); color: var(--cem-color-red-xl);">red-d (#690005)</td>
|
|
793
|
+
<td><code>--cem-action-destructive-default-background</code></td>
|
|
794
|
+
</tr>
|
|
795
|
+
</tbody>
|
|
796
|
+
</table>
|
|
797
|
+
|
|
798
|
+
<p><small><strong>Note:</strong> The automatic theme switching is handled by the <code>light-dark()</code> CSS function in the emotional palette tokens, which reference these branded colors.</small></p>
|
|
799
|
+
</fieldset>
|
|
800
|
+
|
|
801
|
+
<fieldset>
|
|
802
|
+
<legend>CSS Selector Patterns</legend>
|
|
803
|
+
<p>Each intent can be applied using multiple selector patterns for maximum compatibility:</p>
|
|
804
|
+
<pre>
|
|
805
|
+
/* Class selector */
|
|
806
|
+
.action.explicit { }
|
|
807
|
+
.action.primary { }
|
|
808
|
+
|
|
809
|
+
/* Attribute with value */
|
|
810
|
+
.action[flow="explicit"] { }
|
|
811
|
+
.action[flow="primary"] { }
|
|
812
|
+
|
|
813
|
+
/* Boolean attribute */
|
|
814
|
+
.action[explicit] { }
|
|
815
|
+
.action[primary] { }
|
|
816
|
+
</pre>
|
|
817
|
+
<p><small>The triple-selector pattern ensures compatibility across different framework conventions and coding styles.
|
|
818
|
+
On application level it is sufficient to choose only one. </small></p>
|
|
819
|
+
</fieldset>
|
|
820
|
+
<fieldset>
|
|
821
|
+
<legend>Action States Overview</legend>
|
|
822
|
+
<p>Action states represent different conditions and user interactions. States can be reflected by two visual aspects:</p>
|
|
823
|
+
<ul>
|
|
824
|
+
<li><strong>Background-driven states:</strong> disabled, readonly, editable, required, default, indeterminate, hover, active, pending</li>
|
|
825
|
+
<li><strong>Outline-driven states (zebra):</strong> selected, focus, target</li>
|
|
826
|
+
</ul>
|
|
827
|
+
|
|
828
|
+
<datalist id="cem-action-state">
|
|
829
|
+
<option value="disabled" tokens="color font marker" complimentary-token="color-text" > Disabled </option>
|
|
830
|
+
<option value="readonly" tokens="color outline font marker" complimentary-token="color-text" > Readonly, underline is grayed out in Material Design </option>
|
|
831
|
+
<option value="editable" tokens="color outline font marker" complimentary-token="color-text" > Editable, underlined in Material Design </option>
|
|
832
|
+
<option value="required" tokens=" outline font marker" complimentary-token="color-text" > Required, often marked by star suffix </option>
|
|
833
|
+
<option value="default" tokens="color outline font marker" complimentary-token="color-text" > button is outlined, input fields underlined in Material Design </option>
|
|
834
|
+
<option value="indeterminate" tokens="color outline font marker" complimentary-token="color-text" > No Value available, "select all" checkbox when not all of its sub-controls are checked. </option>
|
|
835
|
+
<option value="target" tokens=" outline font marker" complimentary-token="color-text" > Marked to outline the element is pointed by URL. </option>
|
|
836
|
+
<option value="focus" tokens=" outline font marker" complimentary-token="color-text" > Outlined to reflect the input is focused. Buttons do not show the focus outline </option>
|
|
837
|
+
<option value="hover" tokens="color outline font marker" complimentary-token="color-text" > Outline to reflect the focus is make by keyboard navigation, visible even in actions/buttons </option>
|
|
838
|
+
<option value="selected" tokens="color font marker" complimentary-token="color-text" > Selected item(menu, radio), checked radio, etc. </option>
|
|
839
|
+
<option value="active" tokens="color outline font marker" complimentary-token="color-text" > Pressed action element state, darkest background with alternate text color to emphasize the action follows immediately. </option>
|
|
840
|
+
<option value="pending" tokens="color outline font marker" complimentary-token="color-text" > Element state after active when element should not be used as the result of previous action is still in progress. </option>
|
|
841
|
+
</datalist>
|
|
842
|
+
</fieldset>
|
|
843
|
+
|
|
844
|
+
<fieldset>
|
|
845
|
+
<legend>State Progression & Color-Mix Formulas</legend>
|
|
846
|
+
<p>States progress from least to most emphasized through <code>color-mix()</code> formulas that blend the base emotional color with its extreme variant:</p>
|
|
847
|
+
|
|
848
|
+
<figure style="margin: 1em 0;">
|
|
849
|
+
<figcaption><strong>Background-Driven State Progression</strong>
|
|
850
|
+
( <a href="https://github.com/EPA-WG/custom-element-dist/discussions/14#discussioncomment-14060329">discussion + diagram</a> ) </figcaption>
|
|
851
|
+
<pre style="font-size: 0.9em; line-height: 1.8;">
|
|
852
|
+
<strong>disabled</strong> → <strong>readonly</strong> → <strong>editable</strong> → <strong>default</strong> → <strong>indeterminate</strong> → <strong>hover</strong> → <strong>active</strong> → <strong>pending</strong>
|
|
853
|
+
(30% mix) (80% mix) (90% mix) (base) (90% mix) (60-70% mix) (25% mix) (5% mix)
|
|
854
|
+
|
|
855
|
+
├─────────────────────────────┼──────────────────────────────────────────────────────────────┤
|
|
856
|
+
Toward conservative color Toward extreme variant (-x)
|
|
857
|
+
(less emphasized) (more emphasized, inverted text)</pre>
|
|
858
|
+
</figure>
|
|
859
|
+
|
|
860
|
+
<dl>
|
|
861
|
+
<dt><strong>disabled</strong> (30% mix with conservative-x)</dt>
|
|
862
|
+
<dd>
|
|
863
|
+
Most desaturated state. Mixes 30% of the intent's emotional color with 70% conservative extreme color.
|
|
864
|
+
<br/><code>color-mix(in srgb, var(--cem-palette-{emotion}) 30%, var(--cem-palette-conservative-x))</code>
|
|
865
|
+
<br/>Text: Uses <code>--cem-palette-conservative-text-x</code> (grey text)
|
|
866
|
+
</dd>
|
|
867
|
+
|
|
868
|
+
<dt><strong>readonly</strong> (80% mix)</dt>
|
|
869
|
+
<dd>
|
|
870
|
+
Subtly indicates non-editable content. 80% base color, 20% extreme variant.
|
|
871
|
+
<br/><code>color-mix(in srgb, var(--cem-palette-{emotion}) 80%, var(--cem-palette-{emotion}-x))</code>
|
|
872
|
+
<br/>Text: Uses <code>--cem-palette-{emotion}-text</code>
|
|
873
|
+
</dd>
|
|
874
|
+
|
|
875
|
+
<dt><strong>editable</strong> (90% mix)</dt>
|
|
876
|
+
<dd>
|
|
877
|
+
Nearly full base color with slight intensity. 90% base color, 10% extreme variant.
|
|
878
|
+
<br/><code>color-mix(in srgb, var(--cem-palette-{emotion}) 90%, var(--cem-palette-{emotion}-x))</code>
|
|
879
|
+
<br/>Text: Uses <code>--cem-palette-{emotion}-text</code>
|
|
880
|
+
</dd>
|
|
881
|
+
|
|
882
|
+
<dt><strong>default</strong> (base, 100%)</dt>
|
|
883
|
+
<dd>
|
|
884
|
+
Pure emotional palette color without mixing. Baseline state.
|
|
885
|
+
<br/><code>var(--cem-palette-{emotion})</code>
|
|
886
|
+
<br/>Text: Uses <code>--cem-palette-{emotion}-text</code>
|
|
887
|
+
</dd>
|
|
888
|
+
|
|
889
|
+
<dt><strong>indeterminate</strong> (90% mix)</dt>
|
|
890
|
+
<dd>
|
|
891
|
+
Same formula as editable. Used for indeterminate checkboxes or undefined values.
|
|
892
|
+
<br/><code>color-mix(in srgb, var(--cem-palette-{emotion}) 90%, var(--cem-palette-{emotion}-x))</code>
|
|
893
|
+
<br/>Text: Uses <code>--cem-palette-{emotion}-text</code>
|
|
894
|
+
</dd>
|
|
895
|
+
|
|
896
|
+
<dt><strong>hover</strong> (60-70% mix)</dt>
|
|
897
|
+
<dd>
|
|
898
|
+
Noticeable darkening/intensifying on hover. Mix percentage varies by intent (explicit/alternate: 70%, others: 60%).
|
|
899
|
+
<br/><code>color-mix(in srgb, var(--cem-palette-{emotion}) 60-70%, var(--cem-palette-{emotion}-x))</code>
|
|
900
|
+
<br/>Text: Uses <code>--cem-palette-{emotion}-text</code>
|
|
901
|
+
</dd>
|
|
902
|
+
|
|
903
|
+
<dt><strong>active</strong> (25% mix)</dt>
|
|
904
|
+
<dd>
|
|
905
|
+
Pressed/clicked state. Heavily mixed toward extreme variant, triggering text color inversion.
|
|
906
|
+
<br/><code>color-mix(in srgb, var(--cem-palette-{emotion}) 25%, var(--cem-palette-{emotion}-x))</code>
|
|
907
|
+
<br/>Text: Uses <code>--cem-palette-{emotion}-text-x</code> (inverted text)
|
|
908
|
+
</dd>
|
|
909
|
+
|
|
910
|
+
<dt><strong>pending</strong> (5% mix)</dt>
|
|
911
|
+
<dd>
|
|
912
|
+
Most extreme background state during async operations. Nearly fully inverted, with animated stripes.
|
|
913
|
+
<br/><code>color-mix(in srgb, var(--cem-palette-{emotion}) 5%, var(--cem-palette-{emotion}-x))</code>
|
|
914
|
+
<br/>Text: Uses <code>--cem-palette-{emotion}-text-x</code> (inverted text)
|
|
915
|
+
<br/>Special: Animated diagonal stripes using <code>linear-gradient</code> and <code>background-position</code> animation
|
|
916
|
+
</dd>
|
|
917
|
+
</dl>
|
|
918
|
+
</fieldset>
|
|
919
|
+
|
|
920
|
+
<fieldset>
|
|
921
|
+
<legend>Complete Token Reference (Intent × State)</legend>
|
|
922
|
+
<p>All action states generate CSS custom properties in the format:</p>
|
|
923
|
+
<ul>
|
|
924
|
+
<li><code>--cem-action-{intent}-{state}-background</code></li>
|
|
925
|
+
<li><code>--cem-action-{intent}-{state}-text</code></li>
|
|
926
|
+
</ul>
|
|
927
|
+
|
|
928
|
+
<details>
|
|
929
|
+
<summary><strong>Token Matrix: Explicit Intent</strong></summary>
|
|
930
|
+
<table style="font-size: 0.85em;">
|
|
931
|
+
<thead>
|
|
932
|
+
<tr>
|
|
933
|
+
<th>State</th>
|
|
934
|
+
<th>Background Token</th>
|
|
935
|
+
<th>Text Token</th>
|
|
936
|
+
<th>Status</th>
|
|
937
|
+
</tr>
|
|
938
|
+
</thead>
|
|
939
|
+
<tbody>
|
|
940
|
+
<tr><td>disabled</td><td><code>--cem-action-explicit-disabled-background</code></td><td><code>--cem-action-explicit-disabled-text</code></td><td>✓ Defined</td></tr>
|
|
941
|
+
<tr><td>readonly</td><td><code>--cem-action-explicit-readonly-background</code></td><td><code>--cem-action-explicit-readonly-text</code></td><td>✓ Defined</td></tr>
|
|
942
|
+
<tr><td>editable</td><td><code>--cem-action-explicit-editable-background</code></td><td><code>--cem-action-explicit-editable-text</code></td><td>✓ Defined</td></tr>
|
|
943
|
+
<tr><td>required</td><td><code>--cem-action-explicit-required-background</code></td><td><code>--cem-action-explicit-required-text</code></td><td>✓ Defined</td></tr>
|
|
944
|
+
<tr><td>default</td><td><code>--cem-action-explicit-default-background</code></td><td><code>--cem-action-explicit-default-text</code></td><td>✓ Defined</td></tr>
|
|
945
|
+
<tr><td>indeterminate</td><td><code>--cem-action-explicit-indeterminate-background</code></td><td><code>--cem-action-explicit-indeterminate-text</code></td><td>✓ Defined</td></tr>
|
|
946
|
+
<tr><td>target</td><td><code>--cem-action-explicit-target-background</code></td><td><code>--cem-action-explicit-target-text</code></td><td>✗ Undefined (zebra only)</td></tr>
|
|
947
|
+
<tr><td>focus</td><td><code>--cem-action-explicit-focus-background</code></td><td><code>--cem-action-explicit-focus-text</code></td><td>✗ Undefined (zebra only)</td></tr>
|
|
948
|
+
<tr><td>hover</td><td><code>--cem-action-explicit-hover-background</code></td><td><code>--cem-action-explicit-hover-text</code></td><td>✓ Defined</td></tr>
|
|
949
|
+
<tr><td>selected</td><td><code>--cem-action-explicit-selected-background</code></td><td><code>--cem-action-explicit-selected-text</code></td><td>✗ Undefined (zebra only)</td></tr>
|
|
950
|
+
<tr><td>active</td><td><code>--cem-action-explicit-active-background</code></td><td><code>--cem-action-explicit-active-text</code></td><td>✓ Defined</td></tr>
|
|
951
|
+
<tr><td>pending</td><td><code>--cem-action-explicit-pending-background</code></td><td><code>--cem-action-explicit-pending-text</code></td><td>✓ Defined</td></tr>
|
|
952
|
+
</tbody>
|
|
953
|
+
</table>
|
|
954
|
+
</details>
|
|
955
|
+
|
|
956
|
+
<p><small><strong>Note:</strong> The same token pattern applies to all intents: <code>primary</code>, <code>contextual</code>, <code>alternate</code>, and <code>destructive</code>. States marked "Undefined" rely on zebra outlines rather than background colors.</small></p>
|
|
957
|
+
</fieldset>
|
|
958
|
+
|
|
959
|
+
<fieldset>
|
|
960
|
+
<legend>Zebra Outline System</legend>
|
|
961
|
+
<p>Three states use <strong>zebra striped outlines</strong> instead of background color changes: <code>selected</code>, <code>focus</code>, and <code>target</code>. This approach separates selection/navigation from action state.</p>
|
|
962
|
+
|
|
963
|
+
<h4>Zebra Color Tokens</h4>
|
|
964
|
+
<dl>
|
|
965
|
+
<dt><code>--cem-zebra-color-0</code></dt>
|
|
966
|
+
<dd>Innermost stripe (base surface). Default: <code>Canvas</code></dd>
|
|
967
|
+
|
|
968
|
+
<dt><code>--cem-zebra-color-1</code></dt>
|
|
969
|
+
<dd>Second stripe (focus indicator). Changes to <code>CanvasText</code> when focused.</dd>
|
|
970
|
+
|
|
971
|
+
<dt><code>--cem-zebra-color-2</code></dt>
|
|
972
|
+
<dd>Third stripe (selection indicator). Changes to <code>SelectedItem</code> when selected (native theme).</dd>
|
|
973
|
+
|
|
974
|
+
<dt><code>--cem-zebra-color-3</code></dt>
|
|
975
|
+
<dd>Outermost stripe (target indicator). Changes to <code>SelectedItem</code> when targeted by URL hash (native theme).</dd>
|
|
976
|
+
</dl>
|
|
977
|
+
|
|
978
|
+
<h4>Zebra Implementation</h4>
|
|
979
|
+
<p>Zebra outlines are implemented using <code>box-shadow</code> with multiple layers:</p>
|
|
980
|
+
<pre>
|
|
981
|
+
--cem-action-box-shadow:
|
|
982
|
+
0 0 0 2px var(--cem-zebra-color-1), /* 2px wide stripe */
|
|
983
|
+
0 0 0 4px var(--cem-zebra-color-2), /* 2px wide stripe (4px - 2px) */
|
|
984
|
+
0 0 0 6px var(--cem-zebra-color-3); /* 2px wide stripe (6px - 4px) */
|
|
985
|
+
</pre>
|
|
986
|
+
|
|
987
|
+
<h4>State-Specific Zebra Behavior</h4>
|
|
988
|
+
<dl>
|
|
989
|
+
<dt><strong>Focus</strong> (<code>:focus</code>, <code>:focus-visible</code>, <code>:focus-within</code>)</dt>
|
|
990
|
+
<dd>
|
|
991
|
+
Sets <code>--cem-zebra-color-1</code> to visible contrast color (typically <code>CanvasText</code>).
|
|
992
|
+
<br/>Creates innermost colored stripe to indicate keyboard focus.
|
|
993
|
+
<br/>Selectors: <code>&[focus], &:focus, &:focus-visible, &:focus-within, &.focus</code>
|
|
994
|
+
</dd>
|
|
995
|
+
|
|
996
|
+
<dt><strong>Selected</strong> (<code>[selected]</code>, <code>.selected</code>)</dt>
|
|
997
|
+
<dd>
|
|
998
|
+
Sets <code>--cem-zebra-color-2</code> to selection color (typically <code>SelectedItem</code> or trust palette).
|
|
999
|
+
<br/>Creates middle stripe to indicate item selection (checkboxes, radio buttons, menu items).
|
|
1000
|
+
<br/>Selectors: <code>&[selected], &.selected</code>
|
|
1001
|
+
</dd>
|
|
1002
|
+
|
|
1003
|
+
<dt><strong>Target</strong> (<code>:target</code>, <code>[target]</code>)</dt>
|
|
1004
|
+
<dd>
|
|
1005
|
+
Sets <code>--cem-zebra-color-3</code> to target color (typically <code>SelectedItem</code> or enthusiasm palette).
|
|
1006
|
+
<br/>Creates outermost stripe when element is URL hash target (e.g., <code>#element-id</code>).
|
|
1007
|
+
<br/>Selectors: <code>&[target], &:target, &.target</code>
|
|
1008
|
+
</dd>
|
|
1009
|
+
</dl>
|
|
1010
|
+
|
|
1011
|
+
<h4>Visual Example</h4>
|
|
1012
|
+
<div style="display: flex; gap: 1em; flex-wrap: wrap; margin: 1em 0;">
|
|
1013
|
+
<button class="action primary" style="position: relative;">Default (no zebra)</button>
|
|
1014
|
+
<button class="action primary" style="box-shadow: 0 0 0 2px Canvas, 0 0 0 4px currentColor, 0 0 0 6px Canvas;">Focus (zebra-1 active)</button>
|
|
1015
|
+
<button class="action primary" style="box-shadow: 0 0 0 2px Canvas, 0 0 0 4px var(--cem-palette-trust), 0 0 0 6px Canvas;">Selected (zebra-2 active)</button>
|
|
1016
|
+
<button class="action primary" style="box-shadow: 0 0 0 2px Canvas, 0 0 0 4px Canvas, 0 0 0 6px var(--cem-palette-enthusiasm);">Target (zebra-3 active)</button>
|
|
1017
|
+
</div>
|
|
1018
|
+
|
|
1019
|
+
<h4>Contrast Theme Behavior</h4>
|
|
1020
|
+
<p>In high-contrast themes (<code>contrast-light</code>, <code>contrast-dark</code>):</p>
|
|
1021
|
+
<ul>
|
|
1022
|
+
<li>Backgrounds are <strong>neutralized</strong> to base surface color</li>
|
|
1023
|
+
<li>Zebra stripes become <strong>primary state indicator</strong> for ALL states</li>
|
|
1024
|
+
<li>Zebra thickness increases (4 stripes instead of 3)</li>
|
|
1025
|
+
<li>State color shifts to zebra stripe colors rather than backgrounds</li>
|
|
1026
|
+
</ul>
|
|
1027
|
+
</fieldset>
|
|
1028
|
+
|
|
1029
|
+
</figure>
|
|
1030
|
+
|
|
1031
|
+
<figure>
|
|
1032
|
+
<figcaption>Theme Variants</figcaption>
|
|
1033
|
+
<p>The theme system supports multiple visual themes that adapt to different user preferences, accessibility needs, and system settings. Each theme maintains consistent token structure while adjusting color values and visual emphasis techniques.</p>
|
|
1034
|
+
|
|
1035
|
+
<fieldset>
|
|
1036
|
+
<legend>Native Theme</legend>
|
|
1037
|
+
<p><strong>Purpose:</strong> The Native theme honors operating system and browser color preferences, using system-provided colors to ensure seamless integration with the user's environment. This theme automatically respects OS-level settings like dark mode, high contrast, and forced colors.</p>
|
|
1038
|
+
|
|
1039
|
+
<h4>System Color Mappings</h4>
|
|
1040
|
+
<p>The Native theme maps emotional palette tokens to
|
|
1041
|
+
<a href="./colors-native.html" >CSS system colors</a>, allowing the interface to adapt automatically
|
|
1042
|
+
to user preferences in OS/browser settings:</p>
|
|
1043
|
+
|
|
1044
|
+
<table style="font-size: 0.9em;" id="system-color-mapping-table">
|
|
1045
|
+
<thead>
|
|
1046
|
+
<tr>
|
|
1047
|
+
<th>👁️</th>
|
|
1048
|
+
<th>Emotional Token</th>
|
|
1049
|
+
<th>System Color (Background)</th>
|
|
1050
|
+
<th>System Color (Text)</th>
|
|
1051
|
+
<th>Purpose</th>
|
|
1052
|
+
</tr>
|
|
1053
|
+
</thead>
|
|
1054
|
+
<tbody>
|
|
1055
|
+
<tr>
|
|
1056
|
+
<td style="background: Canvas; color: CanvasText; ">⬤</td>
|
|
1057
|
+
<td><code>comfort</code></td>
|
|
1058
|
+
<td><code>Canvas</code></td>
|
|
1059
|
+
<td><code>CanvasText</code></td>
|
|
1060
|
+
<td>Main reading surface and body text</td>
|
|
1061
|
+
</tr>
|
|
1062
|
+
<tr>
|
|
1063
|
+
<td style="background: CanvasText; color: Canvas; ">⬤</td>
|
|
1064
|
+
<td><code>calm</code></td>
|
|
1065
|
+
<td><code>CanvasText</code></td>
|
|
1066
|
+
<td><code>Canvas</code></td>
|
|
1067
|
+
<td>Inverted surface (dark elements on light themes)</td>
|
|
1068
|
+
</tr>
|
|
1069
|
+
<tr>
|
|
1070
|
+
<td style="background: Highlight; color: HighlightText; ">⬤</td>
|
|
1071
|
+
<td><code>trust</code></td>
|
|
1072
|
+
<td><code>Highlight</code></td>
|
|
1073
|
+
<td><code>HighlightText</code></td>
|
|
1074
|
+
<td>Primary action buttons, selected text background</td>
|
|
1075
|
+
</tr>
|
|
1076
|
+
<tr>
|
|
1077
|
+
<td style="background: ButtonFace; color: ButtonText; ">⬤</td>
|
|
1078
|
+
<td><code>creativity</code></td>
|
|
1079
|
+
<td><code>ButtonFace</code></td>
|
|
1080
|
+
<td><code>ButtonText</code></td>
|
|
1081
|
+
<td>Standard button backgrounds</td>
|
|
1082
|
+
</tr>
|
|
1083
|
+
<tr>
|
|
1084
|
+
<td style="background: Mark; color: MarkText; ">⬤</td>
|
|
1085
|
+
<td><code>enthusiasm</code></td>
|
|
1086
|
+
<td><code>Mark</code></td>
|
|
1087
|
+
<td><code>MarkText</code></td>
|
|
1088
|
+
<td>Marked/highlighted content (HTML <code><mark></code>)</td>
|
|
1089
|
+
</tr>
|
|
1090
|
+
<tr>
|
|
1091
|
+
<td style="background: Canvas; color: GrayText; ">⬤</td>
|
|
1092
|
+
<td><code>conservative</code></td>
|
|
1093
|
+
<td><code>GrayText</code></td>
|
|
1094
|
+
<td><code>Canvas</code></td>
|
|
1095
|
+
<td>Disabled states, secondary text</td>
|
|
1096
|
+
</tr>
|
|
1097
|
+
<tr>
|
|
1098
|
+
<td style="background: var(--cem-palette-danger); color: var(--cem-palette-danger-text); ">⬤</td>
|
|
1099
|
+
<td><code>danger</code></td>
|
|
1100
|
+
<td>N/A (uses red)</td>
|
|
1101
|
+
<td><code>CanvasText</code></td>
|
|
1102
|
+
<td>Errors, destructive actions (no system equivalent)</td>
|
|
1103
|
+
</tr>
|
|
1104
|
+
</tbody>
|
|
1105
|
+
</table>
|
|
1106
|
+
|
|
1107
|
+
<h4>Zebra Outline System Colors</h4>
|
|
1108
|
+
<p>The zebra outline system for focus, selected, and target states also uses system colors:</p>
|
|
1109
|
+
<dl>
|
|
1110
|
+
<dt><strong>Focused</strong> — <code>--cem-zebra-color-1</code></dt>
|
|
1111
|
+
<dd>
|
|
1112
|
+
<strong>Focused:</strong> <code>CanvasText</code> (visible focus indicator)
|
|
1113
|
+
<br/><strong>Unfocused:</strong> <code>Canvas</code> (invisible, blends with background)
|
|
1114
|
+
</dd>
|
|
1115
|
+
|
|
1116
|
+
<dt><strong>Selected</strong> — <code>--cem-zebra-color-2</code></dt>
|
|
1117
|
+
<dd>
|
|
1118
|
+
<strong>Selected:</strong> <code>SelectedItem</code> (system selection color)
|
|
1119
|
+
<br/><strong>Unselected:</strong> <code>Canvas</code> (invisible)
|
|
1120
|
+
</dd>
|
|
1121
|
+
|
|
1122
|
+
<dt><strong>Target</strong> — <code>--cem-zebra-color-3</code></dt>
|
|
1123
|
+
<dd>
|
|
1124
|
+
<strong>Targeted:</strong> <code>SelectedItem</code> (marks URL hash target)
|
|
1125
|
+
<br/><strong>Not targeted:</strong> <code>Canvas</code> (invisible)
|
|
1126
|
+
</dd>
|
|
1127
|
+
</dl>
|
|
1128
|
+
|
|
1129
|
+
<h4>Fallback Behavior</h4>
|
|
1130
|
+
<p>When system colors are unavailable or not supported by the browser, the Native theme falls back to branded color tokens:</p>
|
|
1131
|
+
<pre style="font-size: 0.85em;">
|
|
1132
|
+
/* System color with fallback */
|
|
1133
|
+
--cem-palette-comfort: Canvas;
|
|
1134
|
+
/* If Canvas unavailable, fallback chain: */
|
|
1135
|
+
--cem-palette-comfort: var(--cem-surface, var(--cem-color-cyan-xl));
|
|
1136
|
+
|
|
1137
|
+
/* Selection color fallback */
|
|
1138
|
+
--cem-zebra-color-2: SelectedItem;
|
|
1139
|
+
/* If SelectedItem unavailable: */
|
|
1140
|
+
--cem-zebra-color-2: var(--cem-accent-600, var(--cem-palette-trust));
|
|
1141
|
+
</pre>
|
|
1142
|
+
|
|
1143
|
+
<table style="font-size: 0.85em; margin-top: 1em;">
|
|
1144
|
+
<thead>
|
|
1145
|
+
<tr>
|
|
1146
|
+
<th>System Color</th>
|
|
1147
|
+
<th>Fallback Token</th>
|
|
1148
|
+
<th>Final Fallback</th>
|
|
1149
|
+
</tr>
|
|
1150
|
+
</thead>
|
|
1151
|
+
<tbody>
|
|
1152
|
+
<tr><td><code>Canvas</code></td><td><code>--cem-surface</code></td><td><code>--cem-color-cyan-xl</code> (light) / <code>--cem-color-cyan-xd</code> (dark)</td></tr>
|
|
1153
|
+
<tr><td><code>CanvasText</code></td><td><code>--cem-ink-strong</code></td><td><code>--cem-color-cyan-xd</code> (light) / <code>--cem-color-cyan-xl</code> (dark)</td></tr>
|
|
1154
|
+
<tr><td><code>SelectedItem</code></td><td><code>--cem-accent-600</code></td><td><code>--cem-palette-trust</code></td></tr>
|
|
1155
|
+
<tr><td><code>SelectedItemText</code></td><td><code>--cem-ink-on-accent</code></td><td><code>--cem-palette-trust-text</code></td></tr>
|
|
1156
|
+
<tr><td><code>Highlight</code></td><td><code>--cem-palette-trust</code></td><td><code>--cem-color-blue-l</code> (light) / <code>--cem-color-blue-d</code> (dark)</td></tr>
|
|
1157
|
+
<tr><td><code>HighlightText</code></td><td><code>--cem-palette-trust-text</code></td><td><code>white</code> / <code>--cem-color-blue-xl</code></td></tr>
|
|
1158
|
+
<tr><td><code>GrayText</code></td><td><code>--cem-palette-conservative</code></td><td><code>--cem-color-grey-l</code> (light) / <code>--cem-color-grey-d</code> (dark)</td></tr>
|
|
1159
|
+
</tbody>
|
|
1160
|
+
</table>
|
|
1161
|
+
|
|
1162
|
+
<h4>Forced-Colors Mode Support</h4>
|
|
1163
|
+
<p>The Native theme provides full support for Windows High Contrast Mode and other forced-colors environments through the <code>@media (forced-colors: active)</code> media query:</p>
|
|
1164
|
+
<pre style="font-size: 0.85em;">
|
|
1165
|
+
@media (forced-colors: active) {
|
|
1166
|
+
/* All custom colors are overridden by system colors */
|
|
1167
|
+
/* Backgrounds become Canvas or ButtonFace */
|
|
1168
|
+
/* All text becomes CanvasText or ButtonText */
|
|
1169
|
+
/* Borders and outlines use system colors automatically */
|
|
1170
|
+
|
|
1171
|
+
.action {
|
|
1172
|
+
/* System enforces color choices for maximum contrast */
|
|
1173
|
+
background-color: ButtonFace;
|
|
1174
|
+
color: ButtonText;
|
|
1175
|
+
border-color: ButtonText;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
.action:hover {
|
|
1179
|
+
/* System provides hover colors */
|
|
1180
|
+
background-color: SelectedItem;
|
|
1181
|
+
color: SelectedItemText;
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
</pre>
|
|
1185
|
+
|
|
1186
|
+
<p><strong>Key behaviors in forced-colors mode:</strong></p>
|
|
1187
|
+
<ul>
|
|
1188
|
+
<li>Browser overrides custom colors with system-defined high-contrast colors</li>
|
|
1189
|
+
<li>All branded color tokens automatically resolve to appropriate system colors</li>
|
|
1190
|
+
<li>Zebra outlines adapt to use system border colors for maximum visibility</li>
|
|
1191
|
+
<li>Background color variations are flattened; state indication relies more on borders and outlines</li>
|
|
1192
|
+
<li><code>color-mix()</code> formulas are bypassed in favor of system color assignments</li>
|
|
1193
|
+
</ul>
|
|
1194
|
+
|
|
1195
|
+
<h4>Advantages of Native Theme</h4>
|
|
1196
|
+
<ul>
|
|
1197
|
+
<li><strong>Accessibility:</strong> Automatically respects user's OS-level accessibility preferences</li>
|
|
1198
|
+
<li><strong>Consistency:</strong> Matches system UI conventions users are familiar with</li>
|
|
1199
|
+
<li><strong>Performance:</strong> No complex color calculations or theme switching logic needed</li>
|
|
1200
|
+
<li><strong>Privacy:</strong> Respects privacy settings like reduced motion and high contrast without detection</li>
|
|
1201
|
+
<li><strong>Future-proof:</strong> Adapts to new system color schemes automatically</li>
|
|
1202
|
+
</ul>
|
|
1203
|
+
|
|
1204
|
+
<h4>Example CSS Implementation</h4>
|
|
1205
|
+
<pre style="font-size: 0.85em;">
|
|
1206
|
+
[data-theme="native"],
|
|
1207
|
+
.cem-theme-native {
|
|
1208
|
+
/* Emotional palette → System colors */
|
|
1209
|
+
--cem-palette-comfort: Canvas;
|
|
1210
|
+
--cem-palette-comfort-text: CanvasText;
|
|
1211
|
+
--cem-palette-trust: Highlight;
|
|
1212
|
+
--cem-palette-trust-text: HighlightText;
|
|
1213
|
+
--cem-palette-creativity: ButtonFace;
|
|
1214
|
+
--cem-palette-creativity-text: ButtonText;
|
|
1215
|
+
|
|
1216
|
+
/* Zebra colors */
|
|
1217
|
+
--cem-zebra-color-0: Canvas;
|
|
1218
|
+
--cem-zebra-color-1: Canvas; /* Changes to CanvasText on :focus */
|
|
1219
|
+
--cem-zebra-color-2: Canvas; /* Changes to SelectedItem on [selected] */
|
|
1220
|
+
--cem-zebra-color-3: Canvas; /* Changes to SelectedItem on :target */
|
|
1221
|
+
}
|
|
1222
|
+
</pre>
|
|
1223
|
+
</fieldset>
|
|
1224
|
+
|
|
1225
|
+
<fieldset>
|
|
1226
|
+
<legend>Light and Dark Themes</legend>
|
|
1227
|
+
<p><strong>Purpose:</strong> Light and Dark themes use the emotional palette with branded colors, automatically switching between light and dark variants based on the user's <code>color-scheme</code> preference or explicit theme selection.</p>
|
|
1228
|
+
|
|
1229
|
+
<h4>Color-Scheme Declarations</h4>
|
|
1230
|
+
<p>The theme switching mechanism relies on the CSS <code>color-scheme</code> property and the <code>light-dark()</code> function:</p>
|
|
1231
|
+
|
|
1232
|
+
<pre style="font-size: 0.85em;">
|
|
1233
|
+
/* Light theme */
|
|
1234
|
+
[data-theme="light"],
|
|
1235
|
+
.cem-theme-light {
|
|
1236
|
+
color-scheme: light;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
/* Dark theme */
|
|
1240
|
+
[data-theme="dark"],
|
|
1241
|
+
.cem-theme-dark {
|
|
1242
|
+
color-scheme: dark;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
/* Automatic (respects user preference) */
|
|
1246
|
+
:root {
|
|
1247
|
+
color-scheme: light dark; /* Supports both schemes */
|
|
1248
|
+
}
|
|
1249
|
+
</pre>
|
|
1250
|
+
|
|
1251
|
+
<p><strong>How it works:</strong></p>
|
|
1252
|
+
<ul>
|
|
1253
|
+
<li>Setting <code>color-scheme: light</code> instructs the browser that the page section uses a light color palette</li>
|
|
1254
|
+
<li>Setting <code>color-scheme: dark</code> instructs the browser that the page section uses a dark color palette</li>
|
|
1255
|
+
<li>Setting <code>color-scheme: light dark</code> allows the browser to choose based on <code>prefers-color-scheme</code> media query</li>
|
|
1256
|
+
<li>The <code>color-scheme</code> property also affects form controls, scrollbars, and browser UI to match the theme</li>
|
|
1257
|
+
</ul>
|
|
1258
|
+
|
|
1259
|
+
<h4>Automatic Theme Switching via <code>light-dark()</code></h4>
|
|
1260
|
+
<p>All emotional palette tokens use the <code>light-dark()</code> CSS function to automatically select appropriate colors based on the active color scheme:</p>
|
|
1261
|
+
|
|
1262
|
+
<pre style="font-size: 0.85em;">
|
|
1263
|
+
/* Comfort palette - switches from light cyan to dark cyan */
|
|
1264
|
+
--cem-palette-comfort: light-dark(
|
|
1265
|
+
var(--cem-color-cyan-xl), /* Light theme: extra light cyan (#f1fefe) */
|
|
1266
|
+
var(--cem-color-cyan-xd) /* Dark theme: extra dark cyan (#001010) */
|
|
1267
|
+
);
|
|
1268
|
+
|
|
1269
|
+
--cem-palette-comfort-text: light-dark(
|
|
1270
|
+
var(--cem-color-cyan-xd), /* Light theme: dark text on light bg */
|
|
1271
|
+
var(--cem-color-cyan-xl) /* Dark theme: light text on dark bg */
|
|
1272
|
+
);
|
|
1273
|
+
|
|
1274
|
+
/* Trust palette - switches from light blue to dark blue */
|
|
1275
|
+
--cem-palette-trust: light-dark(
|
|
1276
|
+
var(--cem-color-blue-l), /* Light theme: light blue (#d7e3ff) */
|
|
1277
|
+
var(--cem-color-blue-d) /* Dark theme: dark blue (#002f65) */
|
|
1278
|
+
);
|
|
1279
|
+
|
|
1280
|
+
/* Danger palette - switches from light red to dark red */
|
|
1281
|
+
--cem-palette-danger: light-dark(
|
|
1282
|
+
var(--cem-color-red-l), /* Light theme: light red (#ba1a1a) */
|
|
1283
|
+
var(--cem-color-red-d) /* Dark theme: dark red (#690005) */
|
|
1284
|
+
);
|
|
1285
|
+
</pre>
|
|
1286
|
+
|
|
1287
|
+
<p><strong>Key principle:</strong> Text colors are inverted relative to background colors to maintain proper contrast:</p>
|
|
1288
|
+
<ul>
|
|
1289
|
+
<li>Light theme: light backgrounds (<code>-xl</code>, <code>-l</code>) with dark text (<code>-xd</code>, <code>-d</code>)</li>
|
|
1290
|
+
<li>Dark theme: dark backgrounds (<code>-xd</code>, <code>-d</code>) with light text (<code>-xl</code>, <code>-l</code>)</li>
|
|
1291
|
+
</ul>
|
|
1292
|
+
|
|
1293
|
+
<h4>Complete Token Switching Pattern</h4>
|
|
1294
|
+
<p>Each emotional palette has four variants that switch in coordinated pairs:</p>
|
|
1295
|
+
|
|
1296
|
+
<table style="font-size: 0.85em;">
|
|
1297
|
+
<thead>
|
|
1298
|
+
<tr>
|
|
1299
|
+
<th>Token</th>
|
|
1300
|
+
<th>Light Theme Value</th>
|
|
1301
|
+
<th>Dark Theme Value</th>
|
|
1302
|
+
<th>Purpose</th>
|
|
1303
|
+
</tr>
|
|
1304
|
+
</thead>
|
|
1305
|
+
<tbody>
|
|
1306
|
+
<tr>
|
|
1307
|
+
<td><code>--cem-palette-trust</code></td>
|
|
1308
|
+
<td><code>blue-l</code> (#d7e3ff)</td>
|
|
1309
|
+
<td><code>blue-d</code> (#002f65)</td>
|
|
1310
|
+
<td>Base color</td>
|
|
1311
|
+
</tr>
|
|
1312
|
+
<tr>
|
|
1313
|
+
<td><code>--cem-palette-trust-text</code></td>
|
|
1314
|
+
<td><code>comfort-text</code> (dark)</td>
|
|
1315
|
+
<td><code>white</code></td>
|
|
1316
|
+
<td>Text on base</td>
|
|
1317
|
+
</tr>
|
|
1318
|
+
<tr>
|
|
1319
|
+
<td><code>--cem-palette-trust-x</code></td>
|
|
1320
|
+
<td><code>blue-d</code> (#002f65)</td>
|
|
1321
|
+
<td><code>blue-l</code> (#d7e3ff)</td>
|
|
1322
|
+
<td>Extreme variant (inverted)</td>
|
|
1323
|
+
</tr>
|
|
1324
|
+
<tr>
|
|
1325
|
+
<td><code>--cem-palette-trust-text-x</code></td>
|
|
1326
|
+
<td><code>comfort-text-x</code> (light)</td>
|
|
1327
|
+
<td><code>comfort-text-x</code> (dark)</td>
|
|
1328
|
+
<td>Text on extreme</td>
|
|
1329
|
+
</tr>
|
|
1330
|
+
</tbody>
|
|
1331
|
+
</table>
|
|
1332
|
+
|
|
1333
|
+
<h4>State Progression in Light/Dark Themes</h4>
|
|
1334
|
+
<p>The <code>color-mix()</code> formulas work consistently across both themes because they mix the base emotional color with its extreme variant:</p>
|
|
1335
|
+
|
|
1336
|
+
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1em; margin: 1em 0;">
|
|
1337
|
+
<div>
|
|
1338
|
+
<h5>Light Theme Progression</h5>
|
|
1339
|
+
<pre style="font-size: 0.75em;">
|
|
1340
|
+
/* Trust palette in light theme */
|
|
1341
|
+
Base: blue-l (#d7e3ff) ──┐
|
|
1342
|
+
│ mix
|
|
1343
|
+
Extreme: blue-d (#002f65) ──┘
|
|
1344
|
+
|
|
1345
|
+
default: 100% blue-l
|
|
1346
|
+
hover: 60% blue-l + 40% blue-d
|
|
1347
|
+
(gets darker)
|
|
1348
|
+
active: 25% blue-l + 75% blue-d
|
|
1349
|
+
(very dark, inverted text)
|
|
1350
|
+
</pre>
|
|
1351
|
+
</div>
|
|
1352
|
+
<div>
|
|
1353
|
+
<h5>Dark Theme Progression</h5>
|
|
1354
|
+
<pre style="font-size: 0.75em;">
|
|
1355
|
+
/* Trust palette in dark theme */
|
|
1356
|
+
Base: blue-d (#002f65) ──┐
|
|
1357
|
+
│ mix
|
|
1358
|
+
Extreme: blue-l (#d7e3ff) ──┘
|
|
1359
|
+
|
|
1360
|
+
default: 100% blue-d
|
|
1361
|
+
hover: 60% blue-d + 40% blue-l
|
|
1362
|
+
(gets lighter)
|
|
1363
|
+
active: 25% blue-d + 75% blue-l
|
|
1364
|
+
(very light, inverted text)
|
|
1365
|
+
</pre>
|
|
1366
|
+
</div>
|
|
1367
|
+
</div>
|
|
1368
|
+
|
|
1369
|
+
<p><strong>Result:</strong> In light themes, interactions make colors darker and more saturated. In dark themes, interactions make colors lighter and more vibrant. The direction is opposite, but the perceptual emphasis (increased contrast and intensity) is consistent.</p>
|
|
1370
|
+
|
|
1371
|
+
<h4>Theme-Specific Overrides</h4>
|
|
1372
|
+
<p>While most tokens use <code>light-dark()</code> for automatic switching, specific cases may require explicit overrides:</p>
|
|
1373
|
+
|
|
1374
|
+
<pre style="font-size: 0.85em;">
|
|
1375
|
+
/* Example: Different shadow styles per theme */
|
|
1376
|
+
[data-theme="light"] {
|
|
1377
|
+
--cem-action-box-shadow-hover: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
[data-theme="dark"] {
|
|
1381
|
+
--cem-action-box-shadow-hover: 0 2px 8px rgba(255, 255, 255, 0.1);
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
/* Example: Adjusting opacity for dark theme */
|
|
1385
|
+
[data-theme="dark"] {
|
|
1386
|
+
--cem-surface-overlay-opacity: 0.12; /* More visible on dark */
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
[data-theme="light"] {
|
|
1390
|
+
--cem-surface-overlay-opacity: 0.08; /* Subtle on light */
|
|
1391
|
+
}
|
|
1392
|
+
</pre>
|
|
1393
|
+
|
|
1394
|
+
<h4>Zebra Outlines in Light/Dark Themes</h4>
|
|
1395
|
+
<p>Zebra stripe colors also adapt to the theme using the same emotional palette tokens:</p>
|
|
1396
|
+
|
|
1397
|
+
<table style="font-size: 0.85em;">
|
|
1398
|
+
<thead>
|
|
1399
|
+
<tr>
|
|
1400
|
+
<th>State</th>
|
|
1401
|
+
<th>Zebra Color Variable</th>
|
|
1402
|
+
<th>Light Theme</th>
|
|
1403
|
+
<th>Dark Theme</th>
|
|
1404
|
+
</tr>
|
|
1405
|
+
</thead>
|
|
1406
|
+
<tbody>
|
|
1407
|
+
<tr>
|
|
1408
|
+
<td>Focus</td>
|
|
1409
|
+
<td><code>--cem-zebra-color-1</code></td>
|
|
1410
|
+
<td><code>comfort-text</code> (dark)</td>
|
|
1411
|
+
<td><code>comfort-text</code> (light)</td>
|
|
1412
|
+
</tr>
|
|
1413
|
+
<tr>
|
|
1414
|
+
<td>Selected</td>
|
|
1415
|
+
<td><code>--cem-zebra-color-2</code></td>
|
|
1416
|
+
<td><code>trust</code> (blue-l)</td>
|
|
1417
|
+
<td><code>trust</code> (blue-d)</td>
|
|
1418
|
+
</tr>
|
|
1419
|
+
<tr>
|
|
1420
|
+
<td>Target</td>
|
|
1421
|
+
<td><code>--cem-zebra-color-3</code></td>
|
|
1422
|
+
<td><code>enthusiasm</code> (orange-l)</td>
|
|
1423
|
+
<td><code>enthusiasm</code> (orange-d)</td>
|
|
1424
|
+
</tr>
|
|
1425
|
+
</tbody>
|
|
1426
|
+
</table>
|
|
1427
|
+
|
|
1428
|
+
<h4>Browser Support and Fallbacks</h4>
|
|
1429
|
+
<p>The <code>light-dark()</code> function is supported in modern browsers (Chrome 123+, Firefox 120+, Safari 17.5+). For older browsers, provide fallbacks:</p>
|
|
1430
|
+
|
|
1431
|
+
<pre style="font-size: 0.85em;">
|
|
1432
|
+
/* Fallback for browsers without light-dark() support */
|
|
1433
|
+
:root {
|
|
1434
|
+
/* Default to light theme values */
|
|
1435
|
+
--cem-palette-comfort: var(--cem-color-cyan-xl);
|
|
1436
|
+
--cem-palette-comfort-text: var(--cem-color-cyan-xd);
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
/* Modern browsers with light-dark() */
|
|
1440
|
+
@supports (color: light-dark(white, black)) {
|
|
1441
|
+
:root {
|
|
1442
|
+
--cem-palette-comfort: light-dark(
|
|
1443
|
+
var(--cem-color-cyan-xl),
|
|
1444
|
+
var(--cem-color-cyan-xd)
|
|
1445
|
+
);
|
|
1446
|
+
--cem-palette-comfort-text: light-dark(
|
|
1447
|
+
var(--cem-color-cyan-xd),
|
|
1448
|
+
var(--cem-color-cyan-xl)
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
/* Legacy dark theme support via media query */
|
|
1454
|
+
@media (prefers-color-scheme: dark) {
|
|
1455
|
+
:root:not([data-theme="light"]) {
|
|
1456
|
+
--cem-palette-comfort: var(--cem-color-cyan-xd);
|
|
1457
|
+
--cem-palette-comfort-text: var(--cem-color-cyan-xl);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
</pre>
|
|
1461
|
+
|
|
1462
|
+
<h4>Example: Switching Between Light and Dark</h4>
|
|
1463
|
+
<div style="display: flex; gap: 1em; margin: 1em 0; flex-wrap: wrap;">
|
|
1464
|
+
<div style="background: var(--cem-palette-comfort); color: var(--cem-palette-comfort-text); padding: 1em; border: 1px solid currentColor; flex: 1; min-width: 200px;">
|
|
1465
|
+
<p><strong>Current Theme</strong></p>
|
|
1466
|
+
<button class="action primary" style="margin: 0.5em 0;">Primary Action</button>
|
|
1467
|
+
<button class="action destructive" style="margin: 0.5em 0;">Delete</button>
|
|
1468
|
+
<p style="font-size: 0.85em;">This box uses <code>light-dark()</code> to automatically adapt.</p>
|
|
1469
|
+
</div>
|
|
1470
|
+
</div>
|
|
1471
|
+
|
|
1472
|
+
<h4>Advantages of Light/Dark Theme System</h4>
|
|
1473
|
+
<ul>
|
|
1474
|
+
<li><strong>Automatic adaptation:</strong> Single token definition works for both light and dark modes</li>
|
|
1475
|
+
<li><strong>DRY principle:</strong> No need to duplicate CSS rules for each theme</li>
|
|
1476
|
+
<li><strong>Consistent logic:</strong> All state transitions use the same formulas regardless of theme</li>
|
|
1477
|
+
<li><strong>User preference:</strong> Automatically respects <code>prefers-color-scheme</code> media query</li>
|
|
1478
|
+
<li><strong>Reduced code:</strong> Eliminates thousands of lines of theme-specific overrides</li>
|
|
1479
|
+
</ul>
|
|
1480
|
+
</fieldset>
|
|
1481
|
+
|
|
1482
|
+
<fieldset>
|
|
1483
|
+
<legend>Contrast Themes (contrast-light, contrast-dark)</legend>
|
|
1484
|
+
<p><strong>Purpose:</strong> High contrast themes are designed for users with visual impairments or those working in challenging lighting conditions. These themes use a fundamentally different approach: <strong>backgrounds are neutralized</strong> to base surface colors, and <strong>zebra stripes become the primary state indicator</strong> for all states, not just focus/selected/target.</p>
|
|
1485
|
+
|
|
1486
|
+
<h4>Core Design Principle: Zebra-Only State Signaling</h4>
|
|
1487
|
+
<p>Unlike standard light/dark themes that use background color changes for most states, contrast themes:</p>
|
|
1488
|
+
<ul>
|
|
1489
|
+
<li><strong>Neutralize backgrounds:</strong> All action backgrounds use the base comfort palette color (canvas)</li>
|
|
1490
|
+
<li><strong>Signal through stripes:</strong> State information is conveyed exclusively through zebra outline colors</li>
|
|
1491
|
+
<li><strong>Increase stripe count:</strong> Use 4-strip zebra pattern (vs 3-strip in normal themes) reflecting increased variations</li>
|
|
1492
|
+
<li><strong>Thicken outlines:</strong> Increase stripe width from 2px to 3-4px for improved perception</li>
|
|
1493
|
+
<li><strong>Preserve color semantics:</strong> Stripe colors match the intent's emotional palette colors</li>
|
|
1494
|
+
</ul>
|
|
1495
|
+
|
|
1496
|
+
<p><strong>Why this approach?</strong> In high contrast environments, subtle background color variations can be difficult to perceive. By neutralizing backgrounds and using bold, high-contrast outlines, all state information remains clearly visible regardless of ambient lighting or visual acuity.</p>
|
|
1497
|
+
|
|
1498
|
+
<h4>Neutralized Backgrounds</h4>
|
|
1499
|
+
<p>All action state backgrounds collapse to the base surface color:</p>
|
|
1500
|
+
|
|
1501
|
+
<pre style="font-size: 0.85em;">
|
|
1502
|
+
/* contrast-light theme */
|
|
1503
|
+
[data-theme="contrast-light"] {
|
|
1504
|
+
/* All intents and states use same neutral background */
|
|
1505
|
+
--cem-action-explicit-default-background: var(--cem-palette-comfort);
|
|
1506
|
+
--cem-action-explicit-hover-background: var(--cem-palette-comfort);
|
|
1507
|
+
--cem-action-explicit-active-background: var(--cem-palette-comfort);
|
|
1508
|
+
|
|
1509
|
+
--cem-action-primary-default-background: var(--cem-palette-comfort);
|
|
1510
|
+
--cem-action-primary-hover-background: var(--cem-palette-comfort);
|
|
1511
|
+
/* ... all other intents and states ... */
|
|
1512
|
+
|
|
1513
|
+
/* Background is always comfort (light canvas) */
|
|
1514
|
+
background-color: var(--cem-palette-comfort); /* #f1fefe in light */
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
/* contrast-dark theme */
|
|
1518
|
+
[data-theme="contrast-dark"] {
|
|
1519
|
+
/* All intents and states use dark neutral background */
|
|
1520
|
+
--cem-action-explicit-default-background: var(--cem-palette-comfort);
|
|
1521
|
+
--cem-action-explicit-hover-background: var(--cem-palette-comfort);
|
|
1522
|
+
/* ... backgrounds stay consistent ... */
|
|
1523
|
+
|
|
1524
|
+
/* Background is always comfort (dark canvas) */
|
|
1525
|
+
background-color: var(--cem-palette-comfort); /* #001010 in dark */
|
|
1526
|
+
}
|
|
1527
|
+
</pre>
|
|
1528
|
+
|
|
1529
|
+
<p><strong>Result:</strong> Instead of hover making a button darker, hover changes the zebra stripe color. Instead of active making a button very dark, active makes the zebra stripe more intense.</p>
|
|
1530
|
+
|
|
1531
|
+
<h4>4-Strip Zebra Pattern</h4>
|
|
1532
|
+
<p>Contrast themes expand the zebra system from 3 stripes to 4 stripes, adding an additional layer for intent signaling:</p>
|
|
1533
|
+
|
|
1534
|
+
<table style="font-size: 0.85em;">
|
|
1535
|
+
<thead>
|
|
1536
|
+
<tr>
|
|
1537
|
+
<th>Stripe Layer</th>
|
|
1538
|
+
<th>Variable</th>
|
|
1539
|
+
<th>Normal Themes (3-strip)</th>
|
|
1540
|
+
<th>Contrast Themes (4-strip)</th>
|
|
1541
|
+
<th>Width</th>
|
|
1542
|
+
</tr>
|
|
1543
|
+
</thead>
|
|
1544
|
+
<tbody>
|
|
1545
|
+
<tr>
|
|
1546
|
+
<td>Layer 0 (innermost)</td>
|
|
1547
|
+
<td><code>--cem-zebra-color-0</code></td>
|
|
1548
|
+
<td>Base surface (invisible)</td>
|
|
1549
|
+
<td><strong>Intent color</strong> (e.g., purple for explicit)</td>
|
|
1550
|
+
<td>3px</td>
|
|
1551
|
+
</tr>
|
|
1552
|
+
<tr>
|
|
1553
|
+
<td>Layer 1</td>
|
|
1554
|
+
<td><code>--cem-zebra-color-1</code></td>
|
|
1555
|
+
<td>Focus indicator</td>
|
|
1556
|
+
<td><strong>Focus indicator</strong> (comfort-text when focused)</td>
|
|
1557
|
+
<td>3px</td>
|
|
1558
|
+
</tr>
|
|
1559
|
+
<tr>
|
|
1560
|
+
<td>Layer 2</td>
|
|
1561
|
+
<td><code>--cem-zebra-color-2</code></td>
|
|
1562
|
+
<td>Selected indicator</td>
|
|
1563
|
+
<td><strong>Selected indicator</strong> (trust color when selected)</td>
|
|
1564
|
+
<td>3px</td>
|
|
1565
|
+
</tr>
|
|
1566
|
+
<tr>
|
|
1567
|
+
<td>Layer 3 (outermost)</td>
|
|
1568
|
+
<td><code>--cem-zebra-color-3</code></td>
|
|
1569
|
+
<td>Target indicator</td>
|
|
1570
|
+
<td><strong>Target indicator</strong> (enthusiasm color when targeted)</td>
|
|
1571
|
+
<td>3px</td>
|
|
1572
|
+
</tr>
|
|
1573
|
+
</tbody>
|
|
1574
|
+
</table>
|
|
1575
|
+
|
|
1576
|
+
<p><strong>Key difference:</strong> In normal themes, <code>--cem-zebra-color-0</code> is the base surface (invisible). In contrast themes, it becomes the <strong>innermost visible stripe</strong> carrying the intent's emotional color.</p>
|
|
1577
|
+
|
|
1578
|
+
<h4>Zebra Color Assignment in Contrast Themes</h4>
|
|
1579
|
+
<p>Each action intent gets its own base zebra color that matches its emotional palette:</p>
|
|
1580
|
+
|
|
1581
|
+
<pre style="font-size: 0.85em;">
|
|
1582
|
+
/* contrast-light or contrast-dark */
|
|
1583
|
+
[data-theme*="contrast"] {
|
|
1584
|
+
/* Layer 0: Intent-specific base color */
|
|
1585
|
+
.action.explicit {
|
|
1586
|
+
--cem-zebra-color-0: var(--cem-palette-creativity); /* Purple */
|
|
1587
|
+
}
|
|
1588
|
+
.action.primary {
|
|
1589
|
+
--cem-zebra-color-0: var(--cem-palette-trust); /* Blue */
|
|
1590
|
+
}
|
|
1591
|
+
.action.contextual {
|
|
1592
|
+
--cem-zebra-color-0: var(--cem-palette-comfort-text); /* Text color */
|
|
1593
|
+
}
|
|
1594
|
+
.action.alternate {
|
|
1595
|
+
--cem-zebra-color-0: var(--cem-palette-enthusiasm); /* Orange */
|
|
1596
|
+
}
|
|
1597
|
+
.action.destructive {
|
|
1598
|
+
--cem-zebra-color-0: var(--cem-palette-danger); /* Red */
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
/* Layers 1-3: State-dependent (focus, selected, target) */
|
|
1602
|
+
/* These change from transparent to visible when state activates */
|
|
1603
|
+
}
|
|
1604
|
+
</pre>
|
|
1605
|
+
|
|
1606
|
+
<h4>State Variations via Zebra Intensity</h4>
|
|
1607
|
+
<p>Since backgrounds are neutral, state progressions (hover, active, pending) are shown through zebra color mixing:</p>
|
|
1608
|
+
|
|
1609
|
+
<pre style="font-size: 0.85em;">
|
|
1610
|
+
/* Default state: Base intent color in zebra-0 */
|
|
1611
|
+
.action.primary {
|
|
1612
|
+
--cem-zebra-color-0: var(--cem-palette-trust); /* Pure blue */
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
/* Hover state: Mix toward extreme variant */
|
|
1616
|
+
.action.primary:hover {
|
|
1617
|
+
--cem-zebra-color-0: color-mix(
|
|
1618
|
+
in srgb,
|
|
1619
|
+
var(--cem-palette-trust) 60%,
|
|
1620
|
+
var(--cem-palette-trust-x) 40%
|
|
1621
|
+
);
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
/* Active state: Heavy mix toward extreme */
|
|
1625
|
+
.action.primary:active {
|
|
1626
|
+
--cem-zebra-color-0: color-mix(
|
|
1627
|
+
in srgb,
|
|
1628
|
+
var(--cem-palette-trust) 25%,
|
|
1629
|
+
var(--cem-palette-trust-x) 75%
|
|
1630
|
+
);
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
/* Disabled state: Mix toward conservative */
|
|
1634
|
+
.action.primary:disabled {
|
|
1635
|
+
--cem-zebra-color-0: color-mix(
|
|
1636
|
+
in srgb,
|
|
1637
|
+
var(--cem-palette-trust) 30%,
|
|
1638
|
+
var(--cem-palette-conservative-x) 70%
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
</pre>
|
|
1642
|
+
|
|
1643
|
+
<p><strong>Visual effect:</strong> The innermost stripe changes intensity/hue based on state, while maintaining high contrast against the neutral background.</p>
|
|
1644
|
+
|
|
1645
|
+
<h4>Increased Outline Thickness</h4>
|
|
1646
|
+
<p>Contrast themes use thicker stripes for improved visibility:</p>
|
|
1647
|
+
|
|
1648
|
+
<table style="font-size: 0.85em;">
|
|
1649
|
+
<thead>
|
|
1650
|
+
<tr>
|
|
1651
|
+
<th>Theme Type</th>
|
|
1652
|
+
<th>Stripe Width</th>
|
|
1653
|
+
<th>Total Outline Width</th>
|
|
1654
|
+
<th>Stripe Count</th>
|
|
1655
|
+
</tr>
|
|
1656
|
+
</thead>
|
|
1657
|
+
<tbody>
|
|
1658
|
+
<tr>
|
|
1659
|
+
<td>Light / Dark</td>
|
|
1660
|
+
<td>2px per stripe</td>
|
|
1661
|
+
<td>6px (3 × 2px)</td>
|
|
1662
|
+
<td>3 stripes</td>
|
|
1663
|
+
</tr>
|
|
1664
|
+
<tr>
|
|
1665
|
+
<td>Contrast Light / Dark</td>
|
|
1666
|
+
<td>3px per stripe</td>
|
|
1667
|
+
<td>12px (4 × 3px)</td>
|
|
1668
|
+
<td>4 stripes</td>
|
|
1669
|
+
</tr>
|
|
1670
|
+
</tbody>
|
|
1671
|
+
</table>
|
|
1672
|
+
|
|
1673
|
+
<pre style="font-size: 0.85em;">
|
|
1674
|
+
/* Normal themes */
|
|
1675
|
+
--cem-zebra-strip-size: 2px;
|
|
1676
|
+
--cem-action-box-shadow:
|
|
1677
|
+
0 0 0 2px var(--cem-zebra-color-1), /* 2px stripe */
|
|
1678
|
+
0 0 0 4px var(--cem-zebra-color-2), /* 2px stripe */
|
|
1679
|
+
0 0 0 6px var(--cem-zebra-color-3); /* 2px stripe */
|
|
1680
|
+
|
|
1681
|
+
/* Contrast themes */
|
|
1682
|
+
[data-theme*="contrast"] {
|
|
1683
|
+
--cem-zebra-strip-size: 3px;
|
|
1684
|
+
--cem-action-box-shadow:
|
|
1685
|
+
0 0 0 3px var(--cem-zebra-color-0), /* NEW: 3px intent stripe */
|
|
1686
|
+
0 0 0 6px var(--cem-zebra-color-1), /* 3px focus stripe */
|
|
1687
|
+
0 0 0 9px var(--cem-zebra-color-2), /* 3px selected stripe */
|
|
1688
|
+
0 0 0 12px var(--cem-zebra-color-3); /* 3px target stripe */
|
|
1689
|
+
}
|
|
1690
|
+
</pre>
|
|
1691
|
+
|
|
1692
|
+
<h4>Contrast Requirements</h4>
|
|
1693
|
+
<p>High contrast themes enforce stricter contrast ratios to ensure visibility:</p>
|
|
1694
|
+
<ul>
|
|
1695
|
+
<li><strong>Stripe-to-background contrast:</strong> ≥7:1 (AAA level) for all visible stripes</li>
|
|
1696
|
+
<li><strong>Adjacent stripe contrast:</strong> ≥3:1 between neighboring stripes</li>
|
|
1697
|
+
<li><strong>Text contrast:</strong> ≥7:1 against neutral background</li>
|
|
1698
|
+
<li><strong>State distinction:</strong> ≥3:1 contrast change between states (default vs hover)</li>
|
|
1699
|
+
</ul>
|
|
1700
|
+
|
|
1701
|
+
<h4>Visual Comparison: Normal vs Contrast Themes</h4>
|
|
1702
|
+
|
|
1703
|
+
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1em; margin: 1em 0;">
|
|
1704
|
+
<div>
|
|
1705
|
+
<h5>Normal Theme (Light)</h5>
|
|
1706
|
+
<ul style="font-size: 0.85em; list-style: none; padding: 0;">
|
|
1707
|
+
<li>✓ Background colors vary by state</li>
|
|
1708
|
+
<li>✓ 3-strip zebra for focus/selected/target only</li>
|
|
1709
|
+
<li>✓ 2px stripe width</li>
|
|
1710
|
+
<li>✓ Subtle color progressions</li>
|
|
1711
|
+
</ul>
|
|
1712
|
+
<div style="background: #d7e3ff; color: #002f65; padding: 1em; border: 2px solid #002f65;">
|
|
1713
|
+
Primary button (background-driven)
|
|
1714
|
+
</div>
|
|
1715
|
+
</div>
|
|
1716
|
+
<div>
|
|
1717
|
+
<h5>Contrast Theme (contrast-light)</h5>
|
|
1718
|
+
<ul style="font-size: 0.85em; list-style: none; padding: 0;">
|
|
1719
|
+
<li>✓ All backgrounds neutral (same color)</li>
|
|
1720
|
+
<li>✓ 4-strip zebra for ALL states</li>
|
|
1721
|
+
<li>✓ 3px stripe width (thicker)</li>
|
|
1722
|
+
<li>✓ Bold, high-contrast stripes</li>
|
|
1723
|
+
</ul>
|
|
1724
|
+
<div style="background: #f1fefe; color: #001010; padding: 1em; box-shadow: 0 0 0 3px #d7e3ff, 0 0 0 6px transparent, 0 0 0 9px transparent, 0 0 0 12px transparent;">
|
|
1725
|
+
Primary button (zebra-driven)
|
|
1726
|
+
</div>
|
|
1727
|
+
</div>
|
|
1728
|
+
</div>
|
|
1729
|
+
|
|
1730
|
+
<h4>Contrast-Light vs Contrast-Dark</h4>
|
|
1731
|
+
<p>The two contrast theme variants differ only in their base surface color and text inversion:</p>
|
|
1732
|
+
|
|
1733
|
+
<table style="font-size: 0.85em;">
|
|
1734
|
+
<thead>
|
|
1735
|
+
<tr>
|
|
1736
|
+
<th>Aspect</th>
|
|
1737
|
+
<th>contrast-light</th>
|
|
1738
|
+
<th>contrast-dark</th>
|
|
1739
|
+
</tr>
|
|
1740
|
+
</thead>
|
|
1741
|
+
<tbody>
|
|
1742
|
+
<tr>
|
|
1743
|
+
<td>Base background</td>
|
|
1744
|
+
<td><code>--cem-color-cyan-xl</code> (#f1fefe, very light)</td>
|
|
1745
|
+
<td><code>--cem-color-cyan-xd</code> (#001010, very dark)</td>
|
|
1746
|
+
</tr>
|
|
1747
|
+
<tr>
|
|
1748
|
+
<td>Base text</td>
|
|
1749
|
+
<td><code>--cem-color-cyan-xd</code> (very dark)</td>
|
|
1750
|
+
<td><code>--cem-color-cyan-xl</code> (very light)</td>
|
|
1751
|
+
</tr>
|
|
1752
|
+
<tr>
|
|
1753
|
+
<td>Zebra stripe colors</td>
|
|
1754
|
+
<td>Use light palette values (blue-l, purple-l, etc.)</td>
|
|
1755
|
+
<td>Use dark palette values (blue-d, purple-d, etc.)</td>
|
|
1756
|
+
</tr>
|
|
1757
|
+
<tr>
|
|
1758
|
+
<td>Stripe visibility</td>
|
|
1759
|
+
<td>Bold colors on white canvas</td>
|
|
1760
|
+
<td>Bold colors on black canvas</td>
|
|
1761
|
+
</tr>
|
|
1762
|
+
<tr>
|
|
1763
|
+
<td>State indication</td>
|
|
1764
|
+
<td colspan="2">Both use same 4-strip zebra system</td>
|
|
1765
|
+
</tr>
|
|
1766
|
+
</tbody>
|
|
1767
|
+
</table>
|
|
1768
|
+
|
|
1769
|
+
<h4>Implementation Example</h4>
|
|
1770
|
+
<pre style="font-size: 0.85em;">
|
|
1771
|
+
[data-theme="contrast-light"],
|
|
1772
|
+
[data-theme="contrast-dark"] {
|
|
1773
|
+
/* Neutralize all backgrounds to comfort */
|
|
1774
|
+
--cem-action-explicit-default-background: var(--cem-palette-comfort);
|
|
1775
|
+
--cem-action-explicit-hover-background: var(--cem-palette-comfort);
|
|
1776
|
+
--cem-action-explicit-active-background: var(--cem-palette-comfort);
|
|
1777
|
+
/* ... repeat for all intents and states ... */
|
|
1778
|
+
|
|
1779
|
+
/* Increase zebra thickness */
|
|
1780
|
+
--cem-zebra-strip-size: 3px;
|
|
1781
|
+
|
|
1782
|
+
/* Add 4th zebra layer */
|
|
1783
|
+
--cem-action-box-shadow:
|
|
1784
|
+
0 0 0 3px var(--cem-zebra-color-0),
|
|
1785
|
+
0 0 0 6px var(--cem-zebra-color-1),
|
|
1786
|
+
0 0 0 9px var(--cem-zebra-color-2),
|
|
1787
|
+
0 0 0 12px var(--cem-zebra-color-3);
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
/* Intent-specific zebra base colors */
|
|
1791
|
+
[data-theme*="contrast"] .action.explicit {
|
|
1792
|
+
--cem-zebra-color-0: var(--cem-palette-creativity);
|
|
1793
|
+
}
|
|
1794
|
+
[data-theme*="contrast"] .action.primary {
|
|
1795
|
+
--cem-zebra-color-0: var(--cem-palette-trust);
|
|
1796
|
+
}
|
|
1797
|
+
[data-theme*="contrast"] .action.destructive {
|
|
1798
|
+
--cem-zebra-color-0: var(--cem-palette-danger);
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
/* State modifiers adjust zebra-color-0 intensity */
|
|
1802
|
+
[data-theme*="contrast"] .action:hover {
|
|
1803
|
+
--cem-zebra-color-0: color-mix(
|
|
1804
|
+
in srgb,
|
|
1805
|
+
var(--cem-zebra-color-0) 60%,
|
|
1806
|
+
var(--cem-palette-comfort-text) 40%
|
|
1807
|
+
);
|
|
1808
|
+
}
|
|
1809
|
+
</pre>
|
|
1810
|
+
|
|
1811
|
+
<h4>Accessibility Benefits</h4>
|
|
1812
|
+
<ul>
|
|
1813
|
+
<li><strong>Maximum contrast:</strong> Always uses extreme color pairs (AAA level, ≥7:1)</li>
|
|
1814
|
+
<li><strong>Clear state indication:</strong> Bold outlines are easier to perceive than subtle background changes</li>
|
|
1815
|
+
<li><strong>Consistent surface:</strong> Neutral backgrounds reduce visual noise and cognitive load</li>
|
|
1816
|
+
<li><strong>Multiple cues:</strong> 4 stripe layers provide redundant state information</li>
|
|
1817
|
+
<li><strong>Intent preservation:</strong> Color semantics maintained through zebra colors, not backgrounds</li>
|
|
1818
|
+
<li><strong>Low vision friendly:</strong> Thick outlines remain visible even with reduced acuity</li>
|
|
1819
|
+
<li><strong>Screen reader compatible:</strong> State information also conveyed through ARIA attributes</li>
|
|
1820
|
+
</ul>
|
|
1821
|
+
|
|
1822
|
+
<h4>When to Use Contrast Themes</h4>
|
|
1823
|
+
<p>Contrast themes are recommended for:</p>
|
|
1824
|
+
<ul>
|
|
1825
|
+
<li>Users with low vision or visual impairments</li>
|
|
1826
|
+
<li>Environments with poor lighting conditions (very bright or very dim)</li>
|
|
1827
|
+
<li>Users with light sensitivity (photophobia)</li>
|
|
1828
|
+
<li>Compliance with WCAG AAA standards</li>
|
|
1829
|
+
<li>Display devices with poor color reproduction</li>
|
|
1830
|
+
<li>Users who enable "High Contrast" mode in their operating system</li>
|
|
1831
|
+
</ul>
|
|
1832
|
+
|
|
1833
|
+
<p><strong>Auto-activation:</strong> Contrast themes can be automatically enabled when the system reports high contrast preferences:</p>
|
|
1834
|
+
<pre style="font-size: 0.85em;">
|
|
1835
|
+
@media (prefers-contrast: more) {
|
|
1836
|
+
:root {
|
|
1837
|
+
/* Auto-switch to contrast theme */
|
|
1838
|
+
/* Respects prefers-color-scheme for light vs dark */
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
</pre>
|
|
1842
|
+
</fieldset>
|
|
1843
|
+
|
|
1844
|
+
</figure>
|
|
1845
|
+
|
|
1846
|
+
<figure>
|
|
1847
|
+
<figcaption>Dimensional Tokens</figcaption>
|
|
1848
|
+
<p>Dimensional tokens control the physical appearance and depth of UI elements through border radius, shadows, and font weight. These tokens work consistently across all themes while adapting to specific theme requirements.</p>
|
|
1849
|
+
|
|
1850
|
+
<fieldset>
|
|
1851
|
+
<legend>Bend/Border-Radius Tokens</legend>
|
|
1852
|
+
<p><strong>Purpose:</strong> The bend token system provides consistent corner styling across all action elements and containers. The term "bend" reflects the visual metaphor of bending a flat surface to create rounded corners.</p>
|
|
1853
|
+
|
|
1854
|
+
<h4>Bend Token Values</h4>
|
|
1855
|
+
<p>Three predefined bend styles are available, each serving different design needs:</p>
|
|
1856
|
+
|
|
1857
|
+
<dl>
|
|
1858
|
+
<dt><code>--cem-bend-smooth</code> — <strong>0.5rem</strong></dt>
|
|
1859
|
+
<dd>
|
|
1860
|
+
Gentle rounded corners that soften the appearance without being overly rounded. This is the default bend style.
|
|
1861
|
+
<br/><strong>Use cases:</strong> Standard buttons, input fields, cards, panels
|
|
1862
|
+
<br/><strong>Visual effect:</strong> Professional, modern, approachable
|
|
1863
|
+
<div style="background: var(--cem-palette-trust); color: var(--cem-palette-trust-text); padding: 0.75em 1.5em; display: inline-block; margin-top: 0.5em; border-radius: 0.5rem;">
|
|
1864
|
+
Button with smooth corners
|
|
1865
|
+
</div>
|
|
1866
|
+
</dd>
|
|
1867
|
+
|
|
1868
|
+
<dt><code>--cem-bend-round</code> — <strong>50cqh</strong> (50% container query height)</dt>
|
|
1869
|
+
<dd>
|
|
1870
|
+
Fully rounded/pill-shaped corners. The <code>cqh</code> unit ensures the element becomes a perfect pill regardless of dimensions.
|
|
1871
|
+
<br/><strong>Use cases:</strong> Toggle buttons, chips, tags, floating action buttons
|
|
1872
|
+
<br/><strong>Visual effect:</strong> Playful, friendly, highly interactive
|
|
1873
|
+
<br/><strong>Note:</strong> Falls back to <code>50%</code> in browsers without container query support
|
|
1874
|
+
<div style="background: var(--cem-palette-enthusiasm); color: var(--cem-palette-enthusiasm-text); padding: 0.75em 1.5em; display: inline-block; margin-top: 0.5em; border-radius: 50cqh;">
|
|
1875
|
+
Pill-shaped button
|
|
1876
|
+
</div>
|
|
1877
|
+
</dd>
|
|
1878
|
+
|
|
1879
|
+
<dt><code>--cem-bend-sharp</code> — <strong>0</strong></dt>
|
|
1880
|
+
<dd>
|
|
1881
|
+
No rounding, sharp 90-degree corners. Minimalist and geometric.
|
|
1882
|
+
<br/><strong>Use cases:</strong> Technical interfaces, data tables, terminal-style UIs, strict grid layouts
|
|
1883
|
+
<br/><strong>Visual effect:</strong> Precise, technical, no-nonsense
|
|
1884
|
+
<div style="background: var(--cem-palette-creativity); color: var(--cem-palette-creativity-text); padding: 0.75em 1.5em; display: inline-block; margin-top: 0.5em; border-radius: 0;">
|
|
1885
|
+
Sharp-cornered button
|
|
1886
|
+
</div>
|
|
1887
|
+
</dd>
|
|
1888
|
+
</dl>
|
|
1889
|
+
|
|
1890
|
+
<h4>Usage Pattern</h4>
|
|
1891
|
+
<p>The <code>--cem-bend</code> token serves as the active bend value, defaulting to <code>--cem-bend-smooth</code>:</p>
|
|
1892
|
+
|
|
1893
|
+
<pre style="font-size: 0.85em;">
|
|
1894
|
+
/* Default bend */
|
|
1895
|
+
:root {
|
|
1896
|
+
--cem-bend-smooth: 0.5rem;
|
|
1897
|
+
--cem-bend-round: 50cqh;
|
|
1898
|
+
--cem-bend-sharp: 0;
|
|
1899
|
+
|
|
1900
|
+
--cem-bend: var(--cem-bend-smooth); /* Default */
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
/* Apply to action elements */
|
|
1904
|
+
.action {
|
|
1905
|
+
--cem-action-border-radius: var(--cem-bend);
|
|
1906
|
+
border-radius: var(--cem-action-border-radius);
|
|
1907
|
+
}
|
|
1908
|
+
</pre>
|
|
1909
|
+
|
|
1910
|
+
<h4>Changing Bend Style</h4>
|
|
1911
|
+
<p>Override the bend style at any scope using CSS classes or custom properties:</p>
|
|
1912
|
+
|
|
1913
|
+
<pre style="font-size: 0.85em;">
|
|
1914
|
+
/* Via utility classes */
|
|
1915
|
+
<button class="action primary cem-bend-round">Pill Button</button>
|
|
1916
|
+
<button class="action primary cem-bend-sharp">Sharp Button</button>
|
|
1917
|
+
|
|
1918
|
+
/* Via CSS override */
|
|
1919
|
+
.my-component {
|
|
1920
|
+
--cem-bend: var(--cem-bend-round);
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
/* Per element */
|
|
1924
|
+
button.special {
|
|
1925
|
+
--cem-action-border-radius: 1rem; /* Custom radius */
|
|
1926
|
+
}
|
|
1927
|
+
</pre>
|
|
1928
|
+
|
|
1929
|
+
<h4>Bend Classes</h4>
|
|
1930
|
+
<p>Pre-defined utility classes for easy application:</p>
|
|
1931
|
+
|
|
1932
|
+
<table style="font-size: 0.85em;">
|
|
1933
|
+
<thead>
|
|
1934
|
+
<tr>
|
|
1935
|
+
<th>Class</th>
|
|
1936
|
+
<th>Sets <code>--cem-bend</code> to</th>
|
|
1937
|
+
<th>Visual Result</th>
|
|
1938
|
+
</tr>
|
|
1939
|
+
</thead>
|
|
1940
|
+
<tbody>
|
|
1941
|
+
<tr>
|
|
1942
|
+
<td><code>.cem-bend-smooth</code></td>
|
|
1943
|
+
<td><code>var(--cem-bend-smooth)</code> (0.5rem)</td>
|
|
1944
|
+
<td>Gentle rounded corners</td>
|
|
1945
|
+
</tr>
|
|
1946
|
+
<tr>
|
|
1947
|
+
<td><code>.cem-bend-round</code></td>
|
|
1948
|
+
<td><code>var(--cem-bend-round)</code> (50cqh)</td>
|
|
1949
|
+
<td>Fully rounded/pill shape</td>
|
|
1950
|
+
</tr>
|
|
1951
|
+
<tr>
|
|
1952
|
+
<td><code>.cem-bend-sharp</code></td>
|
|
1953
|
+
<td><code>var(--cem-bend-sharp)</code> (0)</td>
|
|
1954
|
+
<td>Sharp 90° corners</td>
|
|
1955
|
+
</tr>
|
|
1956
|
+
</tbody>
|
|
1957
|
+
</table>
|
|
1958
|
+
|
|
1959
|
+
<h4>Visual Examples</h4>
|
|
1960
|
+
<div style="display: flex; gap: 1em; flex-wrap: wrap; margin: 1em 0;">
|
|
1961
|
+
<button class="action primary" style="border-radius: 0.5rem; padding: 0.75em 1.5em;">
|
|
1962
|
+
Smooth (0.5rem)
|
|
1963
|
+
</button>
|
|
1964
|
+
<button class="action explicit" style="border-radius: 50cqh; padding: 0.75em 1.5em;">
|
|
1965
|
+
Round (50cqh)
|
|
1966
|
+
</button>
|
|
1967
|
+
<button class="action alternate" style="border-radius: 0; padding: 0.75em 1.5em;">
|
|
1968
|
+
Sharp (0)
|
|
1969
|
+
</button>
|
|
1970
|
+
</div>
|
|
1971
|
+
|
|
1972
|
+
<h4>Container Query Units</h4>
|
|
1973
|
+
<p>The <code>50cqh</code> value for <code>--cem-bend-round</code> uses container query height units, making pill shapes automatically adapt:</p>
|
|
1974
|
+
|
|
1975
|
+
<pre style="font-size: 0.85em;">
|
|
1976
|
+
/* Small button: 2em tall */
|
|
1977
|
+
<button style="height: 2em; border-radius: 50cqh;">
|
|
1978
|
+
/* border-radius computes to 1em (50% of 2em) */
|
|
1979
|
+
</button>
|
|
1980
|
+
|
|
1981
|
+
/* Large button: 4em tall */
|
|
1982
|
+
<button style="height: 4em; border-radius: 50cqh;">
|
|
1983
|
+
/* border-radius computes to 2em (50% of 4em) */
|
|
1984
|
+
</button>
|
|
1985
|
+
</pre>
|
|
1986
|
+
|
|
1987
|
+
<p><strong>Browser compatibility:</strong> Container query units are supported in Chrome 105+, Firefox 110+, Safari 16+. For older browsers, provide a fallback:</p>
|
|
1988
|
+
|
|
1989
|
+
<pre style="font-size: 0.85em;">
|
|
1990
|
+
.action.round {
|
|
1991
|
+
border-radius: 50%; /* Fallback */
|
|
1992
|
+
border-radius: 50cqh; /* Modern browsers */
|
|
1993
|
+
}
|
|
1994
|
+
</pre>
|
|
1995
|
+
|
|
1996
|
+
<h4>Design Principles</h4>
|
|
1997
|
+
<ul>
|
|
1998
|
+
<li><strong>Consistency:</strong> Use the same bend style throughout related components</li>
|
|
1999
|
+
<li><strong>Hierarchy:</strong> More important actions can use rounder corners to appear more friendly/inviting</li>
|
|
2000
|
+
<li><strong>Context:</strong> Match bend style to brand personality (playful vs. serious)</li>
|
|
2001
|
+
<li><strong>Accessibility:</strong> Corner radius doesn't affect accessibility, but maintain sufficient padding</li>
|
|
2002
|
+
</ul>
|
|
2003
|
+
</fieldset>
|
|
2004
|
+
|
|
2005
|
+
<fieldset>
|
|
2006
|
+
<legend>Box Shadow Tokens</legend>
|
|
2007
|
+
<p><strong>Purpose:</strong> Box shadow tokens create depth and elevation for interactive elements. Shadows provide visual feedback for different states, making interactions more intuitive and responsive.</p>
|
|
2008
|
+
|
|
2009
|
+
<h4>Shadow Token System</h4>
|
|
2010
|
+
<p>Four state-specific shadow tokens control the appearance of actions across different interaction states:</p>
|
|
2011
|
+
|
|
2012
|
+
<dl>
|
|
2013
|
+
<dt><code>--cem-action-box-shadow</code> (default)</dt>
|
|
2014
|
+
<dd>
|
|
2015
|
+
<strong>Value:</strong> <code>0px 2px 1px -1px rgba(0, 0, 0, .2), 0px 1px 1px 0px rgba(0, 0, 0, .14), 0px 1px 3px 0px rgba(0, 0, 0, .12)</code>
|
|
2016
|
+
<br/><strong>Purpose:</strong> Base shadow for resting state. Provides subtle elevation without being distracting.
|
|
2017
|
+
<br/><strong>Visual effect:</strong> Slight lift from the surface, approximately 2dp elevation (Material Design)
|
|
2018
|
+
<br/><strong>Layers:</strong> Three-layer shadow (ambient, penumbra, umbra) for realistic depth perception
|
|
2019
|
+
</dd>
|
|
2020
|
+
|
|
2021
|
+
<dt><code>--cem-action-box-shadow-hover</code></dt>
|
|
2022
|
+
<dd>
|
|
2023
|
+
<strong>Value:</strong> <code>0px 4px 6px -2px rgba(0, 0, 0, .2), 0px 2px 2px 0px rgba(0, 0, 0, .14), 0px 2px 4px 0px rgba(0, 0, 0, .12)</code>
|
|
2024
|
+
<br/><strong>Purpose:</strong> Elevated shadow on hover. Increases perceived elevation to signal interactivity.
|
|
2025
|
+
<br/><strong>Visual effect:</strong> Medium lift, approximately 4dp elevation
|
|
2026
|
+
<br/><strong>Transition:</strong> Smoothly animates from default shadow, creating a "raising" effect
|
|
2027
|
+
</dd>
|
|
2028
|
+
|
|
2029
|
+
<dt><code>--cem-action-box-shadow-active</code></dt>
|
|
2030
|
+
<dd>
|
|
2031
|
+
<strong>Value:</strong> <code>0px 1px 1px -1px rgba(0, 0, 0, .2), 0px 0px 0px 0px rgba(0, 0, 0, .14), 0px 0px 0px 0px rgba(0, 0, 0, .12)</code>
|
|
2032
|
+
<br/><strong>Purpose:</strong> Reduced shadow when pressed/clicked. Simulates button being pushed into the surface.
|
|
2033
|
+
<br/><strong>Visual effect:</strong> Minimal lift, approximately 1dp elevation
|
|
2034
|
+
<br/><strong>Feedback:</strong> Provides tactile-like visual feedback for press actions
|
|
2035
|
+
</dd>
|
|
2036
|
+
|
|
2037
|
+
<dt><code>--cem-action-box-shadow-pending</code></dt>
|
|
2038
|
+
<dd>
|
|
2039
|
+
<strong>Value:</strong> <code>0px 2px 1px -1px rgba(0, 0, 0, .2), 0px 1px 1px 0px rgba(0, 0, 0, .14), 0px 1px 3px 0px rgba(0, 0, 0, .12)</code> (same as default)
|
|
2040
|
+
<br/><strong>Purpose:</strong> Shadow during async operations. Maintains same elevation as default while background animates.
|
|
2041
|
+
<br/><strong>Visual effect:</strong> Consistent elevation during loading, focus on background animation
|
|
2042
|
+
</dd>
|
|
2043
|
+
</dl>
|
|
2044
|
+
|
|
2045
|
+
<h4>Shadow Progression</h4>
|
|
2046
|
+
<p>Shadows progress through three elevation levels as users interact:</p>
|
|
2047
|
+
|
|
2048
|
+
<figure style="margin: 1em 0;">
|
|
2049
|
+
<figcaption><strong>Shadow State Progression</strong></figcaption>
|
|
2050
|
+
<pre style="font-size: 0.85em; line-height: 1.8;">
|
|
2051
|
+
<strong>default</strong> → <strong>hover</strong> → <strong>active</strong> → <strong>pending</strong>
|
|
2052
|
+
(2dp) (4dp) (1dp) (2dp)
|
|
2053
|
+
|
|
2054
|
+
▭ ▭ ▬ ▭
|
|
2055
|
+
subtle elevated pressed loading
|
|
2056
|
+
lift lift down (same as default)
|
|
2057
|
+
</pre>
|
|
2058
|
+
</figure>
|
|
2059
|
+
|
|
2060
|
+
<h4>CSS Implementation</h4>
|
|
2061
|
+
<p>Shadows are applied automatically based on element state:</p>
|
|
2062
|
+
|
|
2063
|
+
<pre style="font-size: 0.85em;">
|
|
2064
|
+
/* Base shadow token */
|
|
2065
|
+
.action {
|
|
2066
|
+
box-shadow: var(--cem-action-box-shadow);
|
|
2067
|
+
transition: box-shadow 0.2s ease-in-out;
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
/* State-specific shadows */
|
|
2071
|
+
.action:hover,
|
|
2072
|
+
.action.hover,
|
|
2073
|
+
.action[hover] {
|
|
2074
|
+
--cem-action-box-shadow: var(--cem-action-box-shadow-hover);
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
.action:active,
|
|
2078
|
+
.action.active,
|
|
2079
|
+
.action[active] {
|
|
2080
|
+
--cem-action-box-shadow: var(--cem-action-box-shadow-active);
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
.action[pending],
|
|
2084
|
+
.action.pending {
|
|
2085
|
+
--cem-action-box-shadow: var(--cem-action-box-shadow-pending);
|
|
2086
|
+
}
|
|
2087
|
+
</pre>
|
|
2088
|
+
|
|
2089
|
+
<h4>Visual Comparison</h4>
|
|
2090
|
+
<div style="display: flex; gap: 2em; flex-wrap: wrap; margin: 1em 0; padding: 2em; background: var(--cem-palette-comfort);">
|
|
2091
|
+
<div style="text-align: center;">
|
|
2092
|
+
<button class="action primary" style="padding: 0.75em 1.5em; box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, .2), 0px 1px 1px 0px rgba(0, 0, 0, .14), 0px 1px 3px 0px rgba(0, 0, 0, .12);">
|
|
2093
|
+
Default
|
|
2094
|
+
</button>
|
|
2095
|
+
<br/><small>2dp elevation</small>
|
|
2096
|
+
</div>
|
|
2097
|
+
<div style="text-align: center;">
|
|
2098
|
+
<button class="action primary" style="padding: 0.75em 1.5em; box-shadow: 0px 4px 6px -2px rgba(0, 0, 0, .2), 0px 2px 2px 0px rgba(0, 0, 0, .14), 0px 2px 4px 0px rgba(0, 0, 0, .12);">
|
|
2099
|
+
Hover
|
|
2100
|
+
</button>
|
|
2101
|
+
<br/><small>4dp elevation</small>
|
|
2102
|
+
</div>
|
|
2103
|
+
<div style="text-align: center;">
|
|
2104
|
+
<button class="action primary" style="padding: 0.75em 1.5em; box-shadow: 0px 1px 1px -1px rgba(0, 0, 0, .2), 0px 0px 0px 0px rgba(0, 0, 0, .14), 0px 0px 0px 0px rgba(0, 0, 0, .12);">
|
|
2105
|
+
Active
|
|
2106
|
+
</button>
|
|
2107
|
+
<br/><small>1dp elevation</small>
|
|
2108
|
+
</div>
|
|
2109
|
+
</div>
|
|
2110
|
+
|
|
2111
|
+
<h4>Contrast Theme Shadow Overrides (Zebra-Based)</h4>
|
|
2112
|
+
<p>In high-contrast themes (<code>contrast-light</code>, <code>contrast-dark</code>), shadows are replaced with zebra outlines for maximum visibility:</p>
|
|
2113
|
+
|
|
2114
|
+
<pre style="font-size: 0.85em;">
|
|
2115
|
+
[data-theme*="contrast"] {
|
|
2116
|
+
/* Replace traditional shadows with zebra outlines */
|
|
2117
|
+
--cem-action-box-shadow:
|
|
2118
|
+
0 0 0 3px var(--cem-zebra-color-0), /* Intent color stripe */
|
|
2119
|
+
0 0 0 6px var(--cem-zebra-color-1), /* Focus stripe */
|
|
2120
|
+
0 0 0 9px var(--cem-zebra-color-2), /* Selected stripe */
|
|
2121
|
+
0 0 0 12px var(--cem-zebra-color-3); /* Target stripe */
|
|
2122
|
+
|
|
2123
|
+
/* State changes affect zebra colors, not shadow depth */
|
|
2124
|
+
.action:hover {
|
|
2125
|
+
/* Zebra-color-0 intensifies, no shadow depth change */
|
|
2126
|
+
--cem-zebra-color-0: color-mix(
|
|
2127
|
+
in srgb,
|
|
2128
|
+
var(--cem-zebra-color-0) 60%,
|
|
2129
|
+
var(--cem-palette-comfort-text) 40%
|
|
2130
|
+
);
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
</pre>
|
|
2134
|
+
|
|
2135
|
+
<p><strong>Why zebra instead of shadows in contrast themes?</strong></p>
|
|
2136
|
+
<ul>
|
|
2137
|
+
<li><strong>Visibility:</strong> Shadows can be difficult to perceive in high-contrast environments</li>
|
|
2138
|
+
<li><strong>Consistency:</strong> Zebra outlines maintain the same visual weight regardless of lighting</li>
|
|
2139
|
+
<li><strong>Accessibility:</strong> High-contrast outlines are more reliable for users with low vision</li>
|
|
2140
|
+
<li><strong>Forced colors:</strong> Browser high-contrast modes may override shadows, but outlines remain visible</li>
|
|
2141
|
+
</ul>
|
|
2142
|
+
|
|
2143
|
+
<h4>Material Design Elevation Mapping</h4>
|
|
2144
|
+
<p>Shadow tokens correspond to Material Design elevation levels:</p>
|
|
2145
|
+
|
|
2146
|
+
<table style="font-size: 0.85em;">
|
|
2147
|
+
<thead>
|
|
2148
|
+
<tr>
|
|
2149
|
+
<th>Token</th>
|
|
2150
|
+
<th>Elevation (dp)</th>
|
|
2151
|
+
<th>Material Design Usage</th>
|
|
2152
|
+
<th>Component Examples</th>
|
|
2153
|
+
</tr>
|
|
2154
|
+
</thead>
|
|
2155
|
+
<tbody>
|
|
2156
|
+
<tr>
|
|
2157
|
+
<td><code>default</code></td>
|
|
2158
|
+
<td>2dp</td>
|
|
2159
|
+
<td>Resting elevation for raised buttons</td>
|
|
2160
|
+
<td>Button, Card (resting)</td>
|
|
2161
|
+
</tr>
|
|
2162
|
+
<tr>
|
|
2163
|
+
<td><code>hover</code></td>
|
|
2164
|
+
<td>4dp</td>
|
|
2165
|
+
<td>Raised elevation on hover</td>
|
|
2166
|
+
<td>Button (hover), FAB (resting)</td>
|
|
2167
|
+
</tr>
|
|
2168
|
+
<tr>
|
|
2169
|
+
<td><code>active</code></td>
|
|
2170
|
+
<td>1dp</td>
|
|
2171
|
+
<td>Pressed state (lower than resting)</td>
|
|
2172
|
+
<td>Button (pressed)</td>
|
|
2173
|
+
</tr>
|
|
2174
|
+
<tr>
|
|
2175
|
+
<td><code>pending</code></td>
|
|
2176
|
+
<td>2dp</td>
|
|
2177
|
+
<td>Maintains resting elevation during async</td>
|
|
2178
|
+
<td>Button (loading)</td>
|
|
2179
|
+
</tr>
|
|
2180
|
+
</tbody>
|
|
2181
|
+
</table>
|
|
2182
|
+
|
|
2183
|
+
<h4>Customizing Shadows</h4>
|
|
2184
|
+
<p>Override shadows at any scope for custom elevation or theme-specific effects:</p>
|
|
2185
|
+
|
|
2186
|
+
<pre style="font-size: 0.85em;">
|
|
2187
|
+
/* Lighter shadows for dark theme */
|
|
2188
|
+
[data-theme="dark"] {
|
|
2189
|
+
--cem-action-box-shadow: 0 2px 8px rgba(255, 255, 255, 0.1);
|
|
2190
|
+
--cem-action-box-shadow-hover: 0 4px 12px rgba(255, 255, 255, 0.15);
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
/* No shadows for flat design */
|
|
2194
|
+
.flat-design {
|
|
2195
|
+
--cem-action-box-shadow: none;
|
|
2196
|
+
--cem-action-box-shadow-hover: none;
|
|
2197
|
+
--cem-action-box-shadow-active: none;
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
/* Custom elevation for specific component */
|
|
2201
|
+
.floating-action-button {
|
|
2202
|
+
--cem-action-box-shadow: 0px 6px 10px -3px rgba(0, 0, 0, .2),
|
|
2203
|
+
0px 4px 4px 0px rgba(0, 0, 0, .14),
|
|
2204
|
+
0px 4px 8px 0px rgba(0, 0, 0, .12); /* 6dp */
|
|
2205
|
+
}
|
|
2206
|
+
</pre>
|
|
2207
|
+
|
|
2208
|
+
<h4>Shadow Anatomy (Three-Layer System)</h4>
|
|
2209
|
+
<p>Each shadow is composed of three layers for realistic depth:</p>
|
|
2210
|
+
|
|
2211
|
+
<dl>
|
|
2212
|
+
<dt><strong>Layer 1: Ambient Shadow</strong> (largest, softest)</dt>
|
|
2213
|
+
<dd>Example: <code>0px 1px 3px 0px rgba(0, 0, 0, .12)</code>
|
|
2214
|
+
<br/>Simulates scattered light, creating overall depth perception</dd>
|
|
2215
|
+
|
|
2216
|
+
<dt><strong>Layer 2: Penumbra Shadow</strong> (medium size, medium softness)</dt>
|
|
2217
|
+
<dd>Example: <code>0px 1px 1px 0px rgba(0, 0, 0, .14)</code>
|
|
2218
|
+
<br/>Transition zone between light and dark, adds realism</dd>
|
|
2219
|
+
|
|
2220
|
+
<dt><strong>Layer 3: Umbra Shadow</strong> (smallest, sharpest)</dt>
|
|
2221
|
+
<dd>Example: <code>0px 2px 1px -1px rgba(0, 0, 0, .2)</code>
|
|
2222
|
+
<br/>Darkest part of shadow directly under element, creates sharp definition</dd>
|
|
2223
|
+
</dl>
|
|
2224
|
+
|
|
2225
|
+
<h4>Animation and Transitions</h4>
|
|
2226
|
+
<p>Shadows should transition smoothly between states:</p>
|
|
2227
|
+
|
|
2228
|
+
<pre style="font-size: 0.85em;">
|
|
2229
|
+
.action {
|
|
2230
|
+
box-shadow: var(--cem-action-box-shadow);
|
|
2231
|
+
transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
2232
|
+
}
|
|
2233
|
+
|
|
2234
|
+
/* Faster transition on press for immediate feedback */
|
|
2235
|
+
.action:active {
|
|
2236
|
+
transition-duration: 100ms;
|
|
2237
|
+
}
|
|
2238
|
+
</pre>
|
|
2239
|
+
|
|
2240
|
+
<h4>Performance Considerations</h4>
|
|
2241
|
+
<ul>
|
|
2242
|
+
<li><strong>Use <code>box-shadow</code>, not <code>filter: drop-shadow()</code></strong> for better performance</li>
|
|
2243
|
+
<li><strong>Limit shadow layers:</strong> Three layers provide good realism without performance cost</li>
|
|
2244
|
+
<li><strong>Avoid excessive blur radius:</strong> Keep blur values under 10px for most cases</li>
|
|
2245
|
+
<li><strong>Hardware acceleration:</strong> Shadows are GPU-accelerated on modern browsers</li>
|
|
2246
|
+
</ul>
|
|
2247
|
+
</fieldset>
|
|
2248
|
+
|
|
2249
|
+
<fieldset>
|
|
2250
|
+
<legend>Thickness/Font-Weight Mapping</legend>
|
|
2251
|
+
<p><strong>Purpose:</strong> The thickness token system provides a semantic way to specify font weights, maintaining consistency with the 7-token design principle. These tokens map directly to CSS <code>font-weight</code> values.</p>
|
|
2252
|
+
|
|
2253
|
+
<h4>Seven Thickness Levels</h4>
|
|
2254
|
+
<p>Based on the <a href="https://creativebeacon.com/typography-guide-part-2-weight-and-width/" target="_blank">Typography Guide</a>, seven standardized font weights provide sufficient variation for all UI needs:</p>
|
|
2255
|
+
|
|
2256
|
+
<table style="font-size: 0.9em;">
|
|
2257
|
+
<thead>
|
|
2258
|
+
<tr>
|
|
2259
|
+
<th>Token</th>
|
|
2260
|
+
<th>Alternative Names</th>
|
|
2261
|
+
<th>CSS Value</th>
|
|
2262
|
+
<th>Sample</th>
|
|
2263
|
+
<th>Common Usage</th>
|
|
2264
|
+
</tr>
|
|
2265
|
+
</thead>
|
|
2266
|
+
<tbody>
|
|
2267
|
+
<tr>
|
|
2268
|
+
<td><code>xx-light</code></td>
|
|
2269
|
+
<td>Thin, Hairline</td>
|
|
2270
|
+
<td><code>100</code></td>
|
|
2271
|
+
<td style="font-weight: 100;">The quick brown fox</td>
|
|
2272
|
+
<td>Large headings, decorative text</td>
|
|
2273
|
+
</tr>
|
|
2274
|
+
<tr>
|
|
2275
|
+
<td><code>x-light</code></td>
|
|
2276
|
+
<td>Extra Light, Ultra Light</td>
|
|
2277
|
+
<td><code>200</code></td>
|
|
2278
|
+
<td style="font-weight: 200;">The quick brown fox</td>
|
|
2279
|
+
<td>Secondary headings, captions</td>
|
|
2280
|
+
</tr>
|
|
2281
|
+
<tr>
|
|
2282
|
+
<td><code>light</code></td>
|
|
2283
|
+
<td>Light</td>
|
|
2284
|
+
<td><code>300</code></td>
|
|
2285
|
+
<td style="font-weight: 300;">The quick brown fox</td>
|
|
2286
|
+
<td>Body text in light themes, metadata</td>
|
|
2287
|
+
</tr>
|
|
2288
|
+
<tr>
|
|
2289
|
+
<td><code>normal</code></td>
|
|
2290
|
+
<td>Regular, Roman, Book</td>
|
|
2291
|
+
<td><code>400</code></td>
|
|
2292
|
+
<td style="font-weight: 400;">The quick brown fox</td>
|
|
2293
|
+
<td>Default body text, paragraphs</td>
|
|
2294
|
+
</tr>
|
|
2295
|
+
<tr>
|
|
2296
|
+
<td><code>bold</code></td>
|
|
2297
|
+
<td>Medium, Semi-Bold</td>
|
|
2298
|
+
<td><code>700</code></td>
|
|
2299
|
+
<td style="font-weight: 700;">The quick brown fox</td>
|
|
2300
|
+
<td>Emphasis, buttons, headings, labels</td>
|
|
2301
|
+
</tr>
|
|
2302
|
+
<tr>
|
|
2303
|
+
<td><code>x-bold</code></td>
|
|
2304
|
+
<td>Extra Bold</td>
|
|
2305
|
+
<td><code>800</code></td>
|
|
2306
|
+
<td style="font-weight: 800;">The quick brown fox</td>
|
|
2307
|
+
<td>Strong emphasis, primary headings</td>
|
|
2308
|
+
</tr>
|
|
2309
|
+
<tr>
|
|
2310
|
+
<td><code>xx-bold</code></td>
|
|
2311
|
+
<td>Ultra Bold, Black, Heavy</td>
|
|
2312
|
+
<td><code>900</code></td>
|
|
2313
|
+
<td style="font-weight: 900;">The quick brown fox</td>
|
|
2314
|
+
<td>Maximum impact, hero headings</td>
|
|
2315
|
+
</tr>
|
|
2316
|
+
</tbody>
|
|
2317
|
+
</table>
|
|
2318
|
+
|
|
2319
|
+
<h4>Design Rationale: Why 7 Levels?</h4>
|
|
2320
|
+
<p>The 7-token system aligns with human perception and cognitive limits:</p>
|
|
2321
|
+
<ul>
|
|
2322
|
+
<li><strong>Pattern Recognition:</strong> <a href="https://blog.firsov.net/2025/04/7-ux-design-tokens.html" target="_blank">7 design tokens</a> match human short-term memory capacity</li>
|
|
2323
|
+
<li><strong>Visual Distinction:</strong> Each level is perceptually different enough to be meaningful</li>
|
|
2324
|
+
<li><strong>Common Fonts:</strong> Most font families provide 7-9 weights, aligning with this system</li>
|
|
2325
|
+
<li><strong>Sufficient Range:</strong> From hairline (100) to black (900) covers all practical needs</li>
|
|
2326
|
+
</ul>
|
|
2327
|
+
|
|
2328
|
+
<h4>Token Naming Convention</h4>
|
|
2329
|
+
<p>Token names follow a symmetric pattern around <code>normal</code> (400):</p>
|
|
2330
|
+
|
|
2331
|
+
<pre style="font-size: 0.85em;">
|
|
2332
|
+
Lighter ← → Heavier
|
|
2333
|
+
|
|
2334
|
+
xx-light x-light light normal bold x-bold xx-bold
|
|
2335
|
+
(100) (200) (300) (400) (700) (800) (900)
|
|
2336
|
+
|
|
2337
|
+
↓ ↓ ↓ ↓ ↓ ↓ ↓
|
|
2338
|
+
Thinnest Default Thickest
|
|
2339
|
+
</pre>
|
|
2340
|
+
|
|
2341
|
+
<p><strong>Note:</strong> CSS provides values 100-900 in 100-unit increments, but the 7-token system skips 500 and 600 as they offer minimal perceptual difference from 400 and 700 respectively.</p>
|
|
2342
|
+
|
|
2343
|
+
<h4>Usage in Theme System</h4>
|
|
2344
|
+
<p>While the theme system doesn't currently expose thickness tokens as CSS custom properties, the values guide font-weight choices throughout the components:</p>
|
|
2345
|
+
|
|
2346
|
+
<pre style="font-size: 0.85em;">
|
|
2347
|
+
/* Example usage in components */
|
|
2348
|
+
.cem-heading-1 {
|
|
2349
|
+
font-weight: 100; /* xx-light for large display text */
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2352
|
+
.cem-heading-2 {
|
|
2353
|
+
font-weight: 300; /* light for secondary headings */
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
body {
|
|
2357
|
+
font-weight: 400; /* normal for body text */
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
.action {
|
|
2361
|
+
font-weight: 700; /* bold for buttons */
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
strong, b {
|
|
2365
|
+
font-weight: 700; /* bold for emphasis */
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
.cem-menu-item.selected {
|
|
2369
|
+
font-weight: 700; /* bold for selected menu items */
|
|
2370
|
+
}
|
|
2371
|
+
</pre>
|
|
2372
|
+
|
|
2373
|
+
<h4>Font Weight and Accessibility</h4>
|
|
2374
|
+
<p>Font weight impacts readability and should be chosen carefully:</p>
|
|
2375
|
+
|
|
2376
|
+
<dl>
|
|
2377
|
+
<dt><strong>Body Text</strong></dt>
|
|
2378
|
+
<dd>
|
|
2379
|
+
Use <code>normal</code> (400) or <code>light</code> (300) for optimal readability
|
|
2380
|
+
<br/>Avoid weights below 300 for body text, especially at small sizes
|
|
2381
|
+
<br/>In dark themes, consider <code>light</code> (300) to compensate for light-on-dark contrast
|
|
2382
|
+
</dd>
|
|
2383
|
+
|
|
2384
|
+
<dt><strong>Headings</strong></dt>
|
|
2385
|
+
<dd>
|
|
2386
|
+
Larger headings (H1, H2) can use lighter weights (100-300) effectively
|
|
2387
|
+
<br/>Smaller headings (H3-H6) should use <code>bold</code> (700) for distinction
|
|
2388
|
+
</dd>
|
|
2389
|
+
|
|
2390
|
+
<dt><strong>Interactive Elements</strong></dt>
|
|
2391
|
+
<dd>
|
|
2392
|
+
Buttons and links benefit from <code>bold</code> (700) for clear affordance
|
|
2393
|
+
<br/>Selected/active states should increase weight for visual feedback
|
|
2394
|
+
</dd>
|
|
2395
|
+
|
|
2396
|
+
<dt><strong>Small Text</strong></dt>
|
|
2397
|
+
<dd>
|
|
2398
|
+
Text below 14px should avoid weights lighter than <code>normal</code> (400)
|
|
2399
|
+
<br/>Thin fonts at small sizes can cause readability issues, especially for low-vision users
|
|
2400
|
+
</dd>
|
|
2401
|
+
</dl>
|
|
2402
|
+
|
|
2403
|
+
<h4>Font Weight Progression</h4>
|
|
2404
|
+
<p>Use weight changes to create visual hierarchy:</p>
|
|
2405
|
+
|
|
2406
|
+
<figure style="margin: 1em 0;">
|
|
2407
|
+
<figcaption><strong>Example: Heading Hierarchy</strong></figcaption>
|
|
2408
|
+
<div style="padding: 1em; background: var(--cem-palette-comfort); color: var(--cem-palette-comfort-text);">
|
|
2409
|
+
<h1 style="font-weight: 100; font-size: 3em; margin: 0.5em 0;">Hero Title (100)</h1>
|
|
2410
|
+
<h2 style="font-weight: 300; font-size: 2em; margin: 0.5em 0;">Section Heading (300)</h2>
|
|
2411
|
+
<h3 style="font-weight: 700; font-size: 1.5em; margin: 0.5em 0;">Subsection (700)</h3>
|
|
2412
|
+
<p style="font-weight: 400; font-size: 1em; margin: 0.5em 0;">Body paragraph text uses normal weight (400) for optimal readability.</p>
|
|
2413
|
+
<p style="font-weight: 700; font-size: 1em; margin: 0.5em 0;"><strong>Emphasized text</strong> uses bold weight (700) to stand out.</p>
|
|
2414
|
+
</div>
|
|
2415
|
+
</figure>
|
|
2416
|
+
|
|
2417
|
+
<h4>Variable Fonts</h4>
|
|
2418
|
+
<p>Modern <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" target="_blank">variable fonts</a> support continuous weight adjustment (100-900), but the 7-token system still provides meaningful checkpoints:</p>
|
|
2419
|
+
|
|
2420
|
+
<pre style="font-size: 0.85em;">
|
|
2421
|
+
/* Variable font with custom weights */
|
|
2422
|
+
@font-face {
|
|
2423
|
+
font-family: 'MyVariableFont';
|
|
2424
|
+
src: url('font.woff2') format('woff2-variations');
|
|
2425
|
+
font-weight: 100 900; /* Supports full range */
|
|
2426
|
+
}
|
|
2427
|
+
|
|
2428
|
+
/* Still use the 7 semantic tokens for consistency */
|
|
2429
|
+
h1 { font-weight: 100; } /* xx-light */
|
|
2430
|
+
h2 { font-weight: 300; } /* light */
|
|
2431
|
+
p { font-weight: 400; } /* normal */
|
|
2432
|
+
strong { font-weight: 700; } /* bold */
|
|
2433
|
+
</pre>
|
|
2434
|
+
|
|
2435
|
+
<h4>Font Weight in Themes</h4>
|
|
2436
|
+
<p>Font weight may need adjustment across different themes:</p>
|
|
2437
|
+
|
|
2438
|
+
<pre style="font-size: 0.85em;">
|
|
2439
|
+
/* Light theme: normal weight sufficient */
|
|
2440
|
+
[data-theme="light"] body {
|
|
2441
|
+
font-weight: 400;
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
/* Dark theme: slightly lighter weight to compensate for contrast */
|
|
2445
|
+
[data-theme="dark"] body {
|
|
2446
|
+
font-weight: 300; /* or keep 400, font-dependent */
|
|
2447
|
+
}
|
|
2448
|
+
|
|
2449
|
+
/* High contrast: use bolder weights for maximum clarity */
|
|
2450
|
+
[data-theme*="contrast"] {
|
|
2451
|
+
body {
|
|
2452
|
+
font-weight: 400; /* Ensure normal weight minimum */
|
|
2453
|
+
}
|
|
2454
|
+
strong, .emphasis {
|
|
2455
|
+
font-weight: 800; /* Extra bold for clear distinction */
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
</pre>
|
|
2459
|
+
|
|
2460
|
+
<h4>Cross-Platform Considerations</h4>
|
|
2461
|
+
<ul>
|
|
2462
|
+
<li><strong>macOS:</strong> System fonts render weights smoothly; thin weights (100-200) work well</li>
|
|
2463
|
+
<li><strong>Windows:</strong> ClearType rendering can make thin weights harder to read; consider 300+ minimum</li>
|
|
2464
|
+
<li><strong>Mobile:</strong> Smaller screens may benefit from slightly bolder default weights</li>
|
|
2465
|
+
<li><strong>Web fonts:</strong> Ensure font files for all 7 weights are loaded to prevent faux-bold rendering</li>
|
|
2466
|
+
</ul>
|
|
2467
|
+
|
|
2468
|
+
<h4>Best Practices</h4>
|
|
2469
|
+
<ul>
|
|
2470
|
+
<li><strong>Consistency:</strong> Use the same weight for similar content types (all buttons bold, all body text normal)</li>
|
|
2471
|
+
<li><strong>Hierarchy:</strong> Create clear distinction between heading levels through weight variation</li>
|
|
2472
|
+
<li><strong>Readability:</strong> Never sacrifice legibility for aesthetic—test with actual users</li>
|
|
2473
|
+
<li><strong>Performance:</strong> Limit font weight variants to 3-4 per page to reduce font file overhead</li>
|
|
2474
|
+
<li><strong>Fallbacks:</strong> Always specify a weight-agnostic fallback font family</li>
|
|
2475
|
+
</ul>
|
|
2476
|
+
</fieldset>
|
|
2477
|
+
|
|
2478
|
+
</figure>
|
|
2479
|
+
|
|
2480
|
+
<figure>
|
|
2481
|
+
<figcaption>Timing Tokens</figcaption>
|
|
2482
|
+
<p>Timing tokens control motion and animation behavior across the design system. Based on Material Design 3 motion principles, these tokens define how UI elements transition between states, ensuring consistent and meaningful animations that enhance user experience.</p>
|
|
2483
|
+
|
|
2484
|
+
<fieldset>
|
|
2485
|
+
<legend>Duration Tokens</legend>
|
|
2486
|
+
<p><strong>Purpose:</strong> Duration tokens define how long transitions take, based on user perception rather than arbitrary millisecond values. The naming reflects how users experience the timing.</p>
|
|
2487
|
+
|
|
2488
|
+
<h4>Three Duration Levels</h4>
|
|
2489
|
+
<dl>
|
|
2490
|
+
<dt><code>--cem-duration-instant</code> — <strong>50ms</strong></dt>
|
|
2491
|
+
<dd>
|
|
2492
|
+
Micro-interactions that should feel immediate. Used when feedback must appear to happen without delay.
|
|
2493
|
+
<br/><strong>Use cases:</strong> Button press feedback, checkbox toggles, ripple effects, input focus
|
|
2494
|
+
<br/><strong>Perception:</strong> "Did that just happen?" — so fast it feels instantaneous
|
|
2495
|
+
</dd>
|
|
2496
|
+
|
|
2497
|
+
<dt><code>--cem-duration-noticeable</code> — <strong>250ms</strong></dt>
|
|
2498
|
+
<dd>
|
|
2499
|
+
Mid-sized UI changes that users should register but not dwell on. The default duration for most transitions.
|
|
2500
|
+
<br/><strong>Use cases:</strong> Menu opening, dropdown expansion, tab switching, color transitions
|
|
2501
|
+
<br/><strong>Perception:</strong> "I saw that change" — noticeable but doesn't interrupt flow
|
|
2502
|
+
</dd>
|
|
2503
|
+
|
|
2504
|
+
<dt><code>--cem-duration-lingering</code> — <strong>300ms</strong></dt>
|
|
2505
|
+
<dd>
|
|
2506
|
+
Larger transitions or emotionally resonant changes that invite attention.
|
|
2507
|
+
<br/><strong>Use cases:</strong> Modal dialogs, page transitions, overlay appearances, route changes
|
|
2508
|
+
<br/><strong>Perception:</strong> "That felt significant" — draws attention to important changes
|
|
2509
|
+
</dd>
|
|
2510
|
+
</dl>
|
|
2511
|
+
|
|
2512
|
+
<h4>CSS Implementation</h4>
|
|
2513
|
+
<pre style="font-size: 0.85em;">
|
|
2514
|
+
:root {
|
|
2515
|
+
--cem-duration-instant: 50ms;
|
|
2516
|
+
--cem-duration-noticeable: 250ms;
|
|
2517
|
+
--cem-duration-lingering: 300ms;
|
|
2518
|
+
|
|
2519
|
+
/* Default duration for general use */
|
|
2520
|
+
--cem-duration: var(--cem-duration-noticeable);
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
/* Usage examples */
|
|
2524
|
+
.action {
|
|
2525
|
+
transition-duration: var(--cem-duration-instant); /* Quick feedback */
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
.menu {
|
|
2529
|
+
transition-duration: var(--cem-duration-noticeable); /* Standard opening */
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
.modal {
|
|
2533
|
+
transition-duration: var(--cem-duration-lingering); /* Significant appearance */
|
|
2534
|
+
}
|
|
2535
|
+
</pre>
|
|
2536
|
+
|
|
2537
|
+
<h4>Reduced Motion Support</h4>
|
|
2538
|
+
<p>For users who prefer reduced motion, durations should be minimized:</p>
|
|
2539
|
+
<pre style="font-size: 0.85em;">
|
|
2540
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2541
|
+
:root {
|
|
2542
|
+
--cem-duration-instant: 0ms;
|
|
2543
|
+
--cem-duration-noticeable: 0ms;
|
|
2544
|
+
--cem-duration-lingering: 0ms;
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
</pre>
|
|
2548
|
+
</fieldset>
|
|
2549
|
+
|
|
2550
|
+
<fieldset>
|
|
2551
|
+
<legend>Easing Tokens</legend>
|
|
2552
|
+
<p><strong>Purpose:</strong> Easing tokens define acceleration curves that shape how animations feel. Named by consumer intent rather than technical implementation.</p>
|
|
2553
|
+
|
|
2554
|
+
<h4>Easing Token System</h4>
|
|
2555
|
+
<table style="font-size: 0.85em;">
|
|
2556
|
+
<thead>
|
|
2557
|
+
<tr>
|
|
2558
|
+
<th>Token</th>
|
|
2559
|
+
<th>Original MD3</th>
|
|
2560
|
+
<th>CSS Value</th>
|
|
2561
|
+
<th>Intended Effect</th>
|
|
2562
|
+
</tr>
|
|
2563
|
+
</thead>
|
|
2564
|
+
<tbody>
|
|
2565
|
+
<tr>
|
|
2566
|
+
<td><code>--cem-easing-smooth</code></td>
|
|
2567
|
+
<td>standard (ease-in-out)</td>
|
|
2568
|
+
<td><code>cubic-bezier(0.4, 0, 0.2, 1)</code></td>
|
|
2569
|
+
<td>Balanced start and end; the "default" feel</td>
|
|
2570
|
+
</tr>
|
|
2571
|
+
<tr>
|
|
2572
|
+
<td><code>--cem-easing-smooth-start</code></td>
|
|
2573
|
+
<td>standard.accelerate (ease-in)</td>
|
|
2574
|
+
<td><code>cubic-bezier(0.4, 0, 1, 1)</code></td>
|
|
2575
|
+
<td>Quickly ramps up; good for entrance animations</td>
|
|
2576
|
+
</tr>
|
|
2577
|
+
<tr>
|
|
2578
|
+
<td><code>--cem-easing-smooth-end</code></td>
|
|
2579
|
+
<td>standard.decelerate (ease-out)</td>
|
|
2580
|
+
<td><code>cubic-bezier(0, 0, 0.2, 1)</code></td>
|
|
2581
|
+
<td>Slows into final state; good for exit animations</td>
|
|
2582
|
+
</tr>
|
|
2583
|
+
<tr>
|
|
2584
|
+
<td><code>--cem-easing-highlighted</code></td>
|
|
2585
|
+
<td>emphasized (ease-in-out)</td>
|
|
2586
|
+
<td><code>cubic-bezier(0.2, 0, 0, 1)</code></td>
|
|
2587
|
+
<td>Adds drama to both start and end; draws attention</td>
|
|
2588
|
+
</tr>
|
|
2589
|
+
<tr>
|
|
2590
|
+
<td><code>--cem-easing-highlighted-start</code></td>
|
|
2591
|
+
<td>emphasized.accelerate (ease-in)</td>
|
|
2592
|
+
<td><code>cubic-bezier(0.3, 0, 0.8, 0.15)</code></td>
|
|
2593
|
+
<td>Dramatic lift-off; emphasizes entry</td>
|
|
2594
|
+
</tr>
|
|
2595
|
+
<tr>
|
|
2596
|
+
<td><code>--cem-easing-highlighted-end</code></td>
|
|
2597
|
+
<td>emphasized.decelerate (ease-out)</td>
|
|
2598
|
+
<td><code>cubic-bezier(0.05, 0.7, 0.1, 1)</code></td>
|
|
2599
|
+
<td>Dramatic finish; emphasizes exit</td>
|
|
2600
|
+
</tr>
|
|
2601
|
+
<tr>
|
|
2602
|
+
<td><code>--cem-easing-uniform</code></td>
|
|
2603
|
+
<td>linear</td>
|
|
2604
|
+
<td><code>linear</code></td>
|
|
2605
|
+
<td>Constant speed; for mechanical or subtle motion</td>
|
|
2606
|
+
</tr>
|
|
2607
|
+
<tr>
|
|
2608
|
+
<td><code>--cem-easing-classic</code></td>
|
|
2609
|
+
<td>legacy</td>
|
|
2610
|
+
<td><code>ease</code></td>
|
|
2611
|
+
<td>Classic curves retained for compatibility</td>
|
|
2612
|
+
</tr>
|
|
2613
|
+
</tbody>
|
|
2614
|
+
</table>
|
|
2615
|
+
|
|
2616
|
+
<h4>Guidance for Use</h4>
|
|
2617
|
+
<dl>
|
|
2618
|
+
<dt><strong>Smooth variants</strong></dt>
|
|
2619
|
+
<dd>Use for everyday transitions where motion should feel natural and unobtrusive.</dd>
|
|
2620
|
+
|
|
2621
|
+
<dt><strong>Highlighted variants</strong></dt>
|
|
2622
|
+
<dd>Use when motion's purpose is to draw the user's eye or emphasize a state change.</dd>
|
|
2623
|
+
|
|
2624
|
+
<dt><strong>Start variants (-start)</strong></dt>
|
|
2625
|
+
<dd>Use for introducing new UI elements — they accelerate into view.</dd>
|
|
2626
|
+
|
|
2627
|
+
<dt><strong>End variants (-end)</strong></dt>
|
|
2628
|
+
<dd>Use for dismissing UI elements — they decelerate as they exit.</dd>
|
|
2629
|
+
|
|
2630
|
+
<dt><strong>Uniform</strong></dt>
|
|
2631
|
+
<dd>Use for neutral motion (progress bars, loading indicators) or when avoiding acceleration/deceleration.</dd>
|
|
2632
|
+
|
|
2633
|
+
<dt><strong>Classic</strong></dt>
|
|
2634
|
+
<dd>Use only when maintaining legacy patterns or supporting older components.</dd>
|
|
2635
|
+
</dl>
|
|
2636
|
+
|
|
2637
|
+
<h4>CSS Implementation</h4>
|
|
2638
|
+
<pre style="font-size: 0.85em;">
|
|
2639
|
+
:root {
|
|
2640
|
+
--cem-easing-smooth: cubic-bezier(0.4, 0, 0.2, 1);
|
|
2641
|
+
--cem-easing-smooth-start: cubic-bezier(0.4, 0, 1, 1);
|
|
2642
|
+
--cem-easing-smooth-end: cubic-bezier(0, 0, 0.2, 1);
|
|
2643
|
+
--cem-easing-highlighted: cubic-bezier(0.2, 0, 0, 1);
|
|
2644
|
+
--cem-easing-highlighted-start: cubic-bezier(0.3, 0, 0.8, 0.15);
|
|
2645
|
+
--cem-easing-highlighted-end: cubic-bezier(0.05, 0.7, 0.1, 1);
|
|
2646
|
+
--cem-easing-uniform: linear;
|
|
2647
|
+
--cem-easing-classic: ease;
|
|
2648
|
+
|
|
2649
|
+
/* Default easing for general use */
|
|
2650
|
+
--cem-easing: var(--cem-easing-smooth);
|
|
2651
|
+
}
|
|
2652
|
+
|
|
2653
|
+
/* Usage examples */
|
|
2654
|
+
.action {
|
|
2655
|
+
transition: all var(--cem-duration) var(--cem-easing);
|
|
2656
|
+
}
|
|
2657
|
+
|
|
2658
|
+
.menu-enter {
|
|
2659
|
+
animation: slideIn var(--cem-duration-noticeable) var(--cem-easing-smooth-start);
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
.menu-exit {
|
|
2663
|
+
animation: slideOut var(--cem-duration-noticeable) var(--cem-easing-smooth-end);
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2666
|
+
.attention-element {
|
|
2667
|
+
animation: pulse var(--cem-duration-lingering) var(--cem-easing-highlighted);
|
|
2668
|
+
}
|
|
2669
|
+
</pre>
|
|
2670
|
+
</fieldset>
|
|
2671
|
+
|
|
2672
|
+
<fieldset>
|
|
2673
|
+
<legend>Spring Tokens</legend>
|
|
2674
|
+
<p><strong>Purpose:</strong> Spring tokens define physics-based motion with damping and stiffness for expressive transitions. Springs create more natural, organic movement than easing curves alone.</p>
|
|
2675
|
+
|
|
2676
|
+
<h4>Spring Token Dimensions</h4>
|
|
2677
|
+
<p>Springs are organized along three axes, creating a 2 × 2 × 3 matrix of combinations:</p>
|
|
2678
|
+
|
|
2679
|
+
<table style="font-size: 0.85em;">
|
|
2680
|
+
<thead>
|
|
2681
|
+
<tr>
|
|
2682
|
+
<th>Axis</th>
|
|
2683
|
+
<th>Original MD3</th>
|
|
2684
|
+
<th>CEM Token</th>
|
|
2685
|
+
<th>Description</th>
|
|
2686
|
+
</tr>
|
|
2687
|
+
</thead>
|
|
2688
|
+
<tbody>
|
|
2689
|
+
<tr>
|
|
2690
|
+
<td rowspan="2"><strong>Focus</strong><br/>(what property)</td>
|
|
2691
|
+
<td>Spatial</td>
|
|
2692
|
+
<td><code>reposition</code></td>
|
|
2693
|
+
<td>Motions that move or resize elements (positions, layouts)</td>
|
|
2694
|
+
</tr>
|
|
2695
|
+
<tr>
|
|
2696
|
+
<td>Effects</td>
|
|
2697
|
+
<td><code>highlight</code></td>
|
|
2698
|
+
<td>Non-spatial changes (opacity, color) that draw attention</td>
|
|
2699
|
+
</tr>
|
|
2700
|
+
<tr>
|
|
2701
|
+
<td rowspan="2"><strong>Feel</strong><br/>(how lively)</td>
|
|
2702
|
+
<td>Standard</td>
|
|
2703
|
+
<td><code>functional</code></td>
|
|
2704
|
+
<td>Little overshoot; for utilitarian interactions</td>
|
|
2705
|
+
</tr>
|
|
2706
|
+
<tr>
|
|
2707
|
+
<td>Expressive</td>
|
|
2708
|
+
<td><code>delight</code></td>
|
|
2709
|
+
<td>Overshoot/bounce; adds emotional emphasis</td>
|
|
2710
|
+
</tr>
|
|
2711
|
+
<tr>
|
|
2712
|
+
<td rowspan="3"><strong>Speed</strong><br/>(how long)</td>
|
|
2713
|
+
<td>Fast</td>
|
|
2714
|
+
<td><code>instant</code></td>
|
|
2715
|
+
<td>Micro-interactions that shouldn't interrupt</td>
|
|
2716
|
+
</tr>
|
|
2717
|
+
<tr>
|
|
2718
|
+
<td>Default</td>
|
|
2719
|
+
<td><code>noticeable</code></td>
|
|
2720
|
+
<td>User should register but not dwell</td>
|
|
2721
|
+
</tr>
|
|
2722
|
+
<tr>
|
|
2723
|
+
<td>Slow</td>
|
|
2724
|
+
<td><code>lingering</code></td>
|
|
2725
|
+
<td>Large or emotionally resonant transitions</td>
|
|
2726
|
+
</tr>
|
|
2727
|
+
</tbody>
|
|
2728
|
+
</table>
|
|
2729
|
+
|
|
2730
|
+
<h4>Spring Token Naming Convention</h4>
|
|
2731
|
+
<p>Tokens combine the three axes: <code>--cem-spring-{focus}-{feel}-{speed}</code></p>
|
|
2732
|
+
|
|
2733
|
+
<pre style="font-size: 0.85em;">
|
|
2734
|
+
/* Example spring token names */
|
|
2735
|
+
--cem-spring-reposition-functional-instant
|
|
2736
|
+
--cem-spring-reposition-functional-noticeable
|
|
2737
|
+
--cem-spring-reposition-functional-lingering
|
|
2738
|
+
--cem-spring-reposition-delight-instant
|
|
2739
|
+
--cem-spring-reposition-delight-noticeable
|
|
2740
|
+
--cem-spring-reposition-delight-lingering
|
|
2741
|
+
--cem-spring-highlight-functional-instant
|
|
2742
|
+
--cem-spring-highlight-functional-noticeable
|
|
2743
|
+
--cem-spring-highlight-functional-lingering
|
|
2744
|
+
--cem-spring-highlight-delight-instant
|
|
2745
|
+
--cem-spring-highlight-delight-noticeable
|
|
2746
|
+
--cem-spring-highlight-delight-lingering
|
|
2747
|
+
</pre>
|
|
2748
|
+
|
|
2749
|
+
<h4>When to Use Springs vs Easing</h4>
|
|
2750
|
+
<dl>
|
|
2751
|
+
<dt><strong>Use Springs for:</strong></dt>
|
|
2752
|
+
<dd>
|
|
2753
|
+
<ul>
|
|
2754
|
+
<li>Drag-and-drop interactions that need physical feedback</li>
|
|
2755
|
+
<li>Bounce effects on notifications or alerts</li>
|
|
2756
|
+
<li>Pull-to-refresh gestures</li>
|
|
2757
|
+
<li>Expressive micro-interactions</li>
|
|
2758
|
+
<li>Elements that should "settle" into place</li>
|
|
2759
|
+
</ul>
|
|
2760
|
+
</dd>
|
|
2761
|
+
|
|
2762
|
+
<dt><strong>Use Easing for:</strong></dt>
|
|
2763
|
+
<dd>
|
|
2764
|
+
<ul>
|
|
2765
|
+
<li>Simple fades and opacity changes</li>
|
|
2766
|
+
<li>Color transitions</li>
|
|
2767
|
+
<li>Legacy component support</li>
|
|
2768
|
+
<li>Reduced-motion fallbacks</li>
|
|
2769
|
+
<li>Cases where overshoot would be distracting</li>
|
|
2770
|
+
</ul>
|
|
2771
|
+
</dd>
|
|
2772
|
+
</dl>
|
|
2773
|
+
|
|
2774
|
+
<h4>CSS Spring Implementation</h4>
|
|
2775
|
+
<p>CSS doesn't natively support spring physics, but can be approximated with keyframes or the Web Animations API:</p>
|
|
2776
|
+
|
|
2777
|
+
<pre style="font-size: 0.85em;">
|
|
2778
|
+
/* CSS Variables for spring parameters */
|
|
2779
|
+
:root {
|
|
2780
|
+
/* Functional springs (little overshoot) */
|
|
2781
|
+
--cem-spring-stiffness-functional: 300;
|
|
2782
|
+
--cem-spring-damping-functional: 25;
|
|
2783
|
+
|
|
2784
|
+
/* Delight springs (expressive overshoot) */
|
|
2785
|
+
--cem-spring-stiffness-delight: 200;
|
|
2786
|
+
--cem-spring-damping-delight: 15;
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2789
|
+
/* Approximated spring animation via CSS */
|
|
2790
|
+
@keyframes spring-bounce {
|
|
2791
|
+
0% { transform: scale(0.95); }
|
|
2792
|
+
40% { transform: scale(1.02); }
|
|
2793
|
+
60% { transform: scale(0.99); }
|
|
2794
|
+
80% { transform: scale(1.005); }
|
|
2795
|
+
100% { transform: scale(1); }
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
.spring-enter {
|
|
2799
|
+
animation: spring-bounce var(--cem-duration-noticeable) var(--cem-easing-highlighted-end);
|
|
2800
|
+
}
|
|
2801
|
+
</pre>
|
|
2802
|
+
|
|
2803
|
+
<h4>JavaScript Spring Usage</h4>
|
|
2804
|
+
<p>For true spring physics, use the Web Animations API or a library:</p>
|
|
2805
|
+
|
|
2806
|
+
<pre style="font-size: 0.85em;">
|
|
2807
|
+
// Using CSS custom properties for spring configuration
|
|
2808
|
+
const springConfig = {
|
|
2809
|
+
reposition: {
|
|
2810
|
+
functional: { stiffness: 300, damping: 25 },
|
|
2811
|
+
delight: { stiffness: 200, damping: 15 }
|
|
2812
|
+
},
|
|
2813
|
+
highlight: {
|
|
2814
|
+
functional: { stiffness: 400, damping: 30 },
|
|
2815
|
+
delight: { stiffness: 250, damping: 18 }
|
|
2816
|
+
}
|
|
2817
|
+
};
|
|
2818
|
+
|
|
2819
|
+
// Apply to animation library of choice
|
|
2820
|
+
element.animate(
|
|
2821
|
+
{ transform: ['translateX(0)', 'translateX(100px)'] },
|
|
2822
|
+
{ duration: 250, easing: 'spring(1, 300, 25, 0)' } // If supported
|
|
2823
|
+
);
|
|
2824
|
+
</pre>
|
|
2825
|
+
</fieldset>
|
|
2826
|
+
|
|
2827
|
+
<fieldset>
|
|
2828
|
+
<legend>Combined Timing Usage</legend>
|
|
2829
|
+
<p><strong>Purpose:</strong> This section shows how duration, easing, and spring tokens work together for cohesive motion design.</p>
|
|
2830
|
+
|
|
2831
|
+
<h4>Standard Action Timing</h4>
|
|
2832
|
+
<pre style="font-size: 0.85em;">
|
|
2833
|
+
.action {
|
|
2834
|
+
/* Combine duration and easing */
|
|
2835
|
+
transition:
|
|
2836
|
+
background-color var(--cem-duration-instant) var(--cem-easing-smooth),
|
|
2837
|
+
box-shadow var(--cem-duration-noticeable) var(--cem-easing-smooth),
|
|
2838
|
+
transform var(--cem-duration-instant) var(--cem-easing-smooth);
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2841
|
+
.action:hover {
|
|
2842
|
+
box-shadow: var(--cem-action-box-shadow-hover);
|
|
2843
|
+
}
|
|
2844
|
+
|
|
2845
|
+
.action:active {
|
|
2846
|
+
transform: scale(0.98);
|
|
2847
|
+
}
|
|
2848
|
+
</pre>
|
|
2849
|
+
|
|
2850
|
+
<h4>Modal/Overlay Timing</h4>
|
|
2851
|
+
<pre style="font-size: 0.85em;">
|
|
2852
|
+
.modal {
|
|
2853
|
+
/* Entry: decelerate into view */
|
|
2854
|
+
animation: modalEnter var(--cem-duration-lingering) var(--cem-easing-highlighted-end);
|
|
2855
|
+
}
|
|
2856
|
+
|
|
2857
|
+
.modal.closing {
|
|
2858
|
+
/* Exit: accelerate out */
|
|
2859
|
+
animation: modalExit var(--cem-duration-noticeable) var(--cem-easing-highlighted-start);
|
|
2860
|
+
}
|
|
2861
|
+
|
|
2862
|
+
@keyframes modalEnter {
|
|
2863
|
+
from {
|
|
2864
|
+
opacity: 0;
|
|
2865
|
+
transform: scale(0.95) translateY(10px);
|
|
2866
|
+
}
|
|
2867
|
+
to {
|
|
2868
|
+
opacity: 1;
|
|
2869
|
+
transform: scale(1) translateY(0);
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
@keyframes modalExit {
|
|
2874
|
+
from {
|
|
2875
|
+
opacity: 1;
|
|
2876
|
+
transform: scale(1) translateY(0);
|
|
2877
|
+
}
|
|
2878
|
+
to {
|
|
2879
|
+
opacity: 0;
|
|
2880
|
+
transform: scale(0.95) translateY(10px);
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
</pre>
|
|
2884
|
+
|
|
2885
|
+
<h4>Timing Token Summary</h4>
|
|
2886
|
+
<table style="font-size: 0.85em;">
|
|
2887
|
+
<thead>
|
|
2888
|
+
<tr>
|
|
2889
|
+
<th>Category</th>
|
|
2890
|
+
<th>Tokens</th>
|
|
2891
|
+
<th>Purpose</th>
|
|
2892
|
+
</tr>
|
|
2893
|
+
</thead>
|
|
2894
|
+
<tbody>
|
|
2895
|
+
<tr>
|
|
2896
|
+
<td><strong>Duration</strong></td>
|
|
2897
|
+
<td>instant, noticeable, lingering</td>
|
|
2898
|
+
<td>How long animations take</td>
|
|
2899
|
+
</tr>
|
|
2900
|
+
<tr>
|
|
2901
|
+
<td><strong>Easing</strong></td>
|
|
2902
|
+
<td>smooth, highlighted × start, end | uniform | classic</td>
|
|
2903
|
+
<td>Acceleration curves</td>
|
|
2904
|
+
</tr>
|
|
2905
|
+
<tr>
|
|
2906
|
+
<td><strong>Spring</strong></td>
|
|
2907
|
+
<td>2 focus × 2 feel × 3 speed</td>
|
|
2908
|
+
<td>Physics-based motion</td>
|
|
2909
|
+
</tr>
|
|
2910
|
+
</tbody>
|
|
2911
|
+
</table>
|
|
2912
|
+
|
|
2913
|
+
<h4>Best Practices</h4>
|
|
2914
|
+
<ul>
|
|
2915
|
+
<li><strong>Consistency:</strong> Use the same timing tokens for similar interactions across the application</li>
|
|
2916
|
+
<li><strong>Purpose:</strong> Choose tokens based on the intent of the motion, not arbitrary aesthetic preference</li>
|
|
2917
|
+
<li><strong>Accessibility:</strong> Always respect <code>prefers-reduced-motion</code> user preference</li>
|
|
2918
|
+
<li><strong>Performance:</strong> Animate only transform and opacity for best performance (GPU-accelerated)</li>
|
|
2919
|
+
<li><strong>Subtlety:</strong> Motion should enhance, not distract — when in doubt, use shorter durations</li>
|
|
2920
|
+
</ul>
|
|
2921
|
+
</fieldset>
|
|
2922
|
+
|
|
2923
|
+
</figure>
|
|
2924
|
+
|
|
2925
|
+
</body>
|
|
2926
|
+
</html>
|