@threadlabs/looma 0.6.5 → 0.7.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.6.5",
3
+ "version": "0.7.1",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -1,15 +1,23 @@
1
1
  /* Generated by HTML Next 1.0.0-alpha.3. Do not edit. */
2
2
  @scope ([data-component~="ui-button"]) to ([data-component], [data-slotted]) {
3
3
  :scope {
4
+ --_hue: var(--ui-accent);
5
+ --_hue-hover: var(--ui-accent-hover);
6
+ --_hue-active: var(--ui-accent-active);
7
+ --_hue-text: var(--ui-accent-active);
8
+ --_on-hue: var(--ui-on-accent);
9
+
10
+ --_tone: var(--_hue);
11
+ --_tone-hover: var(--_hue-hover);
12
+ --_tone-active: var(--_hue-active);
13
+ --_tone-text: var(--_hue-text);
14
+ --_on-tone: var(--_on-hue);
15
+
4
16
  display: inline-flex;
5
17
  align-items: center;
6
18
  justify-content: center;
7
19
  vertical-align: middle;
8
- color: var(--ui-action-secondary-text, var(--ui-text-primary));
9
- }
10
-
11
- :scope[data-ui-button-state~="variant=solid"] {
12
- color: var(--ui-action-primary-text, var(--ui-text-on-accent));
20
+ color: var(--_tone-text);
13
21
  }
14
22
 
15
23
  :scope[data-ui-button-state~="align=start"] {
@@ -25,23 +33,24 @@
25
33
  :scope {
26
34
  appearance: none;
27
35
  min-block-size: var(--ui-button-min-block-size, var(--ui-control-size-md));
28
- border: 1px solid var(--ui-button-border, var(--ui-border-strong));
36
+ border-style: solid;
37
+ border-width: 1px;
38
+ border-color: var(--ui-button-border, var(--_tone));
29
39
  border-radius: var(--ui-button-radius, var(--ui-radius-md));
30
- background: var(--ui-button-surface, var(--ui-surface-elevated));
31
- color: var(--ui-button-text, var(--ui-action-secondary-text, var(--ui-text-primary)));
40
+ background-color: var(--ui-button-surface, oklch(from var(--_tone) l c h / 5%));
41
+ color: var(--ui-button-text, var(--_tone-text));
32
42
  font: inherit;
33
43
  font-weight: var(--ui-font-medium);
34
44
  line-height: var(--ui-line-height-tight);
35
45
  padding: var(--ui-space-2) var(--ui-space-3);
36
46
  background-image: var(--ui-raised-highlight);
37
- box-shadow: var(--ui-button-shadow, var(--ui-raised, var(--ui-shadow-xs)));
47
+ box-shadow: var(--ui-button-shadow, var(--ui-raised));
38
48
  cursor: pointer;
39
49
  transition:
40
50
  background-color var(--ui-motion-fast) var(--ui-motion-ease),
41
51
  border-color var(--ui-motion-fast) var(--ui-motion-ease),
42
52
  color var(--ui-motion-fast) var(--ui-motion-ease),
43
- box-shadow var(--ui-motion-fast) var(--ui-motion-ease),
44
- transform var(--ui-motion-fast) var(--ui-motion-ease);
53
+ box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
45
54
  margin: 0;
46
55
  }
47
56
 
@@ -65,128 +74,141 @@
65
74
  }
66
75
 
67
76
  :scope:hover:enabled {
68
- background: var(--ui-action-secondary-surface-hover, var(--ui-surface-muted));
69
- border-color: var(--ui-control-border-hover, var(--ui-border-strong));
77
+ border-color: var(--ui-button-hover-border, var(--_tone-hover));
78
+ background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));
70
79
  }
71
80
 
81
+ /* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */
72
82
  :scope:active:enabled {
73
- background: var(--ui-surface-subtle);
74
- }
75
-
76
- :scope[data-ui-button-state~="variant=solid"] {
77
- border-color: var(--ui-action-primary-surface, var(--ui-accent-solid));
78
- background: var(--ui-action-primary-surface, var(--ui-accent-solid));
79
- color: var(--ui-action-primary-text, var(--ui-text-on-accent));
80
- box-shadow: var(--ui-button-solid-shadow, inset 0 1px rgb(255 255 255 / 0.16), var(--ui-shadow-xs));
83
+ background-color: var(--ui-button-active-surface, oklch(from var(--_tone) l c h / 18%));
84
+ background-image: none;
85
+ box-shadow: var(--ui-pressed);
81
86
  }
82
87
 
83
- :scope[data-ui-button-state~="variant=solid"]:hover:enabled {
84
- background: var(--ui-action-primary-surface-hover, var(--ui-accent-hover));
85
- border-color: var(--ui-action-primary-surface-hover, var(--ui-accent-hover));
86
- box-shadow: var(--ui-shadow-sm);
87
- transform: translateY(-1px);
88
+ :scope[data-ui-button-state~="variant=solid"], :scope[data-ui-button-state~="variant=danger"] {
89
+ border-color: var(--_tone);
90
+ background-color: var(--_tone);
91
+ color: var(--_on-tone);
92
+ box-shadow: var(--ui-button-solid-shadow, var(--ui-raised));
88
93
  }
89
94
 
90
- :scope[data-ui-button-state~="variant=solid"]:active:enabled {
91
- background: var(--ui-action-primary-surface-active, var(--ui-accent-active));
92
- border-color: var(--ui-action-primary-surface-active, var(--ui-accent-active));
93
- box-shadow: none;
94
- transform: translateY(0);
95
+ :is(:scope[data-ui-button-state~="variant=solid"], :scope[data-ui-button-state~="variant=danger"]):hover:enabled {
96
+ background-color: var(--_tone-hover);
97
+ border-color: var(--_tone-hover);
95
98
  }
96
99
 
97
- :scope[data-ui-button-state~="variant=danger"] {
98
- border-color: var(--ui-danger-solid);
99
- background: var(--ui-danger-solid);
100
- color: var(--ui-text-on-accent);
101
- box-shadow: var(--ui-button-danger-shadow, inset 0 1px rgb(255 255 255 / 0.14), var(--ui-shadow-xs));
100
+ :is(:scope[data-ui-button-state~="variant=solid"], :scope[data-ui-button-state~="variant=danger"]):active:enabled {
101
+ background-color: var(--_tone-active);
102
+ border-color: var(--_tone-active);
103
+ background-image: none;
104
+ box-shadow: var(--ui-pressed);
102
105
  }
103
106
 
104
- :scope[data-ui-button-state~="variant=danger"]:hover:enabled {
105
- background: var(--ui-danger-hover);
106
- border-color: var(--ui-danger-hover);
107
- box-shadow: var(--ui-shadow-sm);
108
- transform: translateY(-1px);
107
+ /* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a
108
+ destructive secondary action, not a special case. */
109
+ :scope[data-ui-button-state~="tone=neutral"] {
110
+ --_hue: var(--ui-text);
111
+ --_hue-hover: var(--ui-text);
112
+ --_hue-active: var(--ui-text);
113
+ --_hue-text: var(--ui-text);
114
+ --_on-hue: var(--ui-surface);
109
115
  }
110
116
 
111
- :scope[data-ui-button-state~="variant=danger"]:active:enabled {
112
- box-shadow: none;
113
- transform: translateY(0);
117
+ :scope[data-ui-button-state~="tone=danger"], :scope[data-ui-button-state~="variant=danger"] {
118
+ --_hue: var(--ui-danger);
119
+ --_hue-hover: var(--ui-danger-hover);
120
+ --_hue-active: var(--ui-danger-hover);
121
+ --_hue-text: var(--ui-danger-hover);
122
+ --_on-hue: var(--ui-on-danger);
114
123
  }
115
124
 
116
- /* An accent-tinted secondary action: the outline, ghost, and link variants in the accent colour.
117
- Solid and danger already carry their own intent. */
118
- :scope[data-ui-button-state~="tone=accent"]:scope[data-ui-button-state~="variant=outline"] {
119
- border-color: var(--ui-button-accent-border, var(--ui-accent));
120
- background: var(--ui-button-accent-surface, var(--ui-accent-subtle));
121
- color: var(--ui-button-accent-text, var(--ui-accent-active));
125
+ :scope[data-ui-button-state~="tone=success"] {
126
+ --_hue: var(--ui-success);
127
+ --_hue-hover: color-mix(in srgb, var(--ui-success) 85%, #000);
128
+ --_hue-active: color-mix(in srgb, var(--ui-success) 75%, #000);
129
+ --_hue-text: color-mix(in srgb, var(--ui-success) 85%, #000);
130
+ --_on-hue: var(--ui-surface);
122
131
  }
123
132
 
124
- :scope[data-ui-button-state~="tone=accent"]:scope[data-ui-button-state~="variant=outline"]:hover:enabled {
125
- border-color: var(--ui-button-accent-hover-border, var(--ui-accent-hover));
126
- background: var(--ui-button-accent-hover-surface, color-mix(in srgb, var(--ui-accent) 16%, var(--ui-surface)));
133
+ :scope[data-ui-button-state~="tone=warning"] {
134
+ --_hue: var(--ui-warning);
135
+ --_hue-hover: color-mix(in srgb, var(--ui-warning) 85%, #000);
136
+ --_hue-active: color-mix(in srgb, var(--ui-warning) 75%, #000);
137
+ --_hue-text: color-mix(in srgb, var(--ui-warning) 85%, #000);
138
+ --_on-hue: var(--ui-surface);
127
139
  }
128
140
 
129
- :scope[data-ui-button-state~="tone=accent"]:is(:scope[data-ui-button-state~="variant=ghost"], :scope[data-ui-button-state~="variant=link"]) {
130
- color: var(--ui-button-accent-text, var(--ui-accent-active));
141
+ :scope[data-ui-button-state~="tone=info"] {
142
+ --_hue: var(--ui-info);
143
+ --_hue-hover: color-mix(in srgb, var(--ui-info) 85%, #000);
144
+ --_hue-active: color-mix(in srgb, var(--ui-info) 75%, #000);
145
+ --_hue-text: color-mix(in srgb, var(--ui-info) 85%, #000);
146
+ --_on-hue: var(--ui-surface);
131
147
  }
132
148
 
133
149
  :scope[data-ui-button-state~="variant=ghost"] {
134
150
  border-color: transparent;
135
151
  background: transparent;
136
152
  box-shadow: none;
137
- color: var(--ui-button-ghost-text, var(--ui-action-secondary-text, var(--ui-text-primary)));
153
+ color: var(--ui-button-ghost-text, var(--_tone-text));
138
154
  }
139
155
 
140
156
  /* Tints derive from the text colour, not a surface token, so hover and press show on any background. */
141
157
  :scope[data-ui-button-state~="variant=ghost"]:hover:enabled {
142
- background: var(--ui-button-ghost-hover-surface, color-mix(in srgb, currentColor 8%, transparent));
158
+ background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));
143
159
  border-color: transparent;
144
160
  }
145
161
 
146
162
  :scope[data-ui-button-state~="variant=ghost"]:active:enabled {
147
- background: var(--ui-button-ghost-active-surface, color-mix(in srgb, currentColor 14%, transparent));
163
+ background-color: var(--ui-button-ghost-active-surface, oklch(from var(--_tone) l c h / 16%));
148
164
  border-color: transparent;
165
+ box-shadow: var(--ui-pressed);
149
166
  }
150
167
 
151
168
  /* A soft halo that transitions in with the other box-shadow changes, layered on the raised shadow. */
152
169
  :scope:focus-visible {
153
170
  outline: none;
154
171
  box-shadow:
155
- var(--ui-button-shadow, var(--ui-raised, var(--ui-shadow-xs))),
172
+ var(--ui-button-shadow, var(--ui-raised)),
156
173
  var(--ui-focus-halo);
157
174
  }
158
175
 
159
176
  :scope[data-ui-button-state~="variant=solid"]:focus-visible {
160
177
  box-shadow:
161
- var(--ui-button-solid-shadow, inset 0 1px rgb(255 255 255 / 0.16), var(--ui-shadow-xs)),
178
+ var(--ui-button-solid-shadow, var(--ui-raised)),
162
179
  var(--ui-focus-halo);
163
180
  }
164
181
 
165
- /* Disabled colours fall back to each variant's own; ghost and link take only the text colour. */
182
+ /* Disabled drops the tone rather than the shape: every variant keeps its own structure, so a
183
+ disabled outline is still an outline and a disabled ghost is still text. Intent goes — an
184
+ unavailable action says "unavailable", not "unavailable, and destructive" — and so do the
185
+ highlight and shadow, because nothing that cannot be pressed should look raised. */
166
186
  :scope:disabled {
187
+ /* Derived from the tone itself, not from a separate disabled palette: faded toward the
188
+ page, which desaturates it at the same time. Toward the page rather than toward white,
189
+ so a dark theme dims where a light one lightens — the same rule, both schemes. */
190
+ --_tone: color-mix(in oklab, var(--_hue) 58%, var(--ui-surface));
191
+ --_tone-hover: var(--_tone);
192
+ --_tone-active: var(--_tone);
193
+ --_tone-text: color-mix(in oklab, var(--_hue-text) 72%, var(--ui-surface));
194
+ --_on-tone: var(--_tone-text);
195
+
167
196
  opacity: var(--ui-button-disabled-opacity, 1);
168
197
  cursor: not-allowed;
169
- border-color: var(--ui-button-disabled-border, var(--ui-border));
170
- background-color: var(--ui-button-disabled-surface, var(--ui-disabled-surface));
171
- color: var(--ui-button-disabled-text, var(--ui-disabled-text));
172
- }
173
-
174
- :scope[data-ui-button-state~="variant=solid"]:disabled {
175
- border-color: var(--ui-button-disabled-border, var(--ui-border));
176
- background-color: var(--ui-button-disabled-surface, var(--ui-disabled-surface));
177
- color: var(--ui-button-disabled-text, var(--ui-disabled-text));
198
+ background-image: none;
199
+ box-shadow: none;
178
200
  }
179
201
 
180
- :scope[data-ui-button-state~="variant=danger"]:disabled {
181
- border-color: var(--ui-button-disabled-border, var(--ui-border));
182
- background-color: var(--ui-button-disabled-surface, var(--ui-disabled-surface));
183
- color: var(--ui-button-disabled-text, var(--ui-disabled-text));
202
+ /* A filled button keeps its fill, faded further so its text stays legible on it. */
203
+ :is(:scope[data-ui-button-state~="variant=solid"], :scope[data-ui-button-state~="variant=danger"]):disabled {
204
+ --_tone: color-mix(in oklab, var(--_hue) 34%, var(--ui-surface));
184
205
  }
185
206
 
207
+ /* Ghost has no hover to fall back on, so disabled is the one state it has to state outright:
208
+ it takes a surface, light and tinted, rather than reading as plain text. */
186
209
  :scope[data-ui-button-state~="variant=ghost"]:disabled {
187
- background: none;
210
+ background-color: color-mix(in oklab, var(--_hue) 28%, var(--ui-surface));
188
211
  border-color: transparent;
189
- color: var(--ui-button-disabled-text, var(--ui-disabled-text));
190
212
  }
191
213
 
192
214
  @media (pointer: coarse) {
@@ -248,14 +270,24 @@
248
270
  @supports (text-box-trim: trim-both) {
249
271
  }
250
272
 
251
- /* An accent-tinted secondary action: the outline, ghost, and link variants in the accent colour.
252
- Solid and danger already carry their own intent. */
273
+ /* Pressed reads as pressed in: the highlight goes, and the shadow moves inside. */
274
+
275
+ /* Tone is the colour, variant is the volume. Every pairing works: a danger outline is a
276
+ destructive secondary action, not a special case. */
253
277
 
254
278
  /* Tints derive from the text colour, not a surface token, so hover and press show on any background. */
255
279
 
256
280
  /* A soft halo that transitions in with the other box-shadow changes, layered on the raised shadow. */
257
281
 
258
- /* Disabled colours fall back to each variant's own; ghost and link take only the text colour. */
282
+ /* Disabled drops the tone rather than the shape: every variant keeps its own structure, so a
283
+ disabled outline is still an outline and a disabled ghost is still text. Intent goes — an
284
+ unavailable action says "unavailable", not "unavailable, and destructive" — and so do the
285
+ highlight and shadow, because nothing that cannot be pressed should look raised. */
286
+
287
+ /* A filled button keeps its fill, faded further so its text stays legible on it. */
288
+
289
+ /* Ghost has no hover to fall back on, so disabled is the one state it has to state outright:
290
+ it takes a surface, light and tinted, rather than reading as plain text. */
259
291
 
260
292
  @media (pointer: coarse) {
261
293
  }
@@ -52,7 +52,10 @@
52
52
  margin: auto;
53
53
  inline-size: 0.32rem;
54
54
  block-size: 0.58rem;
55
- border: solid var(--ui-text-on-accent);
55
+ /* Longhands, not `border: solid var(...)`: lowering drops a shorthand that omits a
56
+ component, which left the tick with no style and no colour. */
57
+ border-style: solid;
58
+ border-color: var(--ui-text-on-accent);
56
59
  border-width: 0 0.125rem 0.125rem 0;
57
60
  opacity: 1;
58
61
  transform: translateY(-0.11rem) rotate(45deg);
@@ -208,6 +208,39 @@
208
208
  }
209
209
  }
210
210
 
211
+ /* Multiple mode: every option carries a checkbox, so a list that takes several answers says so
212
+ before anything is picked. aria-selected is the state; this draws it.
213
+ Longhands, not shorthands: lowering drops a shorthand that omits a component. */
214
+ :scope[data-ui-combobox-state~="multiple"] .option {
215
+ display: flex;
216
+ gap: var(--ui-space-2);
217
+ align-items: center;
218
+ }
219
+
220
+ :scope[data-ui-combobox-state~="multiple"] .option::before {
221
+ content: "";
222
+ flex: none;
223
+ inline-size: 1.125rem;
224
+ block-size: 1.125rem;
225
+ border-style: solid;
226
+ border-width: 1px;
227
+ border-color: var(--ui-control-border-hover, var(--ui-border-strong));
228
+ border-radius: var(--ui-radius-sm);
229
+ background-color: var(--ui-control-surface, var(--ui-surface-default));
230
+ background-repeat: no-repeat;
231
+ background-position: center;
232
+ background-size: 0.7rem;
233
+ }
234
+
235
+ :scope[data-ui-combobox-state~="multiple"] .option[aria-selected="true"]::before {
236
+ border-color: var(--ui-accent-solid);
237
+ background-color: var(--ui-accent-solid);
238
+ background-image: var(
239
+ --ui-combobox-option-check,
240
+ url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-9'/%3E%3C/svg%3E")
241
+ );
242
+ }
243
+
211
244
  /* Multiple mode: chips wrap before the cursor on one flexible field line. */
212
245
  :scope[data-ui-combobox-state~="multiple"] .field {
213
246
  flex-wrap: wrap;
@@ -258,6 +291,10 @@
258
291
  @media (forced-colors: active) {
259
292
  }
260
293
 
294
+ /* Multiple mode: every option carries a checkbox, so a list that takes several answers says so
295
+ before anything is picked. aria-selected is the state; this draws it.
296
+ Longhands, not shorthands: lowering drops a shorthand that omits a component. */
297
+
261
298
  /* Multiple mode: chips wrap before the cursor on one flexible field line. */
262
299
 
263
300
  /* A component that sets its display still honours the hidden attribute on its root. */
@@ -1,6 +1,8 @@
1
1
  /* Generated by HTML Next 1.0.0-alpha.3. Do not edit. */
2
2
  @scope ([data-component~="ui-editor-table-context-menu"]) to ([data-component], [data-slotted]) {
3
3
  :scope {
4
+ /* The max-width is a promise about the menu's footprint, so it counts padding and border. */
5
+ box-sizing: border-box;
4
6
  min-width: 14rem;
5
7
  max-width: min(17rem, calc(100vw - 24px));
6
8
  max-height: min(28rem, calc(100vh - 24px));
@@ -22,9 +22,9 @@
22
22
  background-color var(--ui-motion-fast) var(--ui-motion-ease);
23
23
  }
24
24
 
25
- /* Single selects draw their own chevron: the native caret cannot be inset or sized consistently.
25
+ /* The select draws its own chevron: the native caret cannot be inset or sized consistently.
26
26
  * The root stays a native <s-lect>, so the icon is a background image rather than an element. */
27
- :scope:not([multiple]) {
27
+ :scope {
28
28
  appearance: none;
29
29
  padding-inline-end: calc(var(--ui-space-3) + 1.5rem);
30
30
  background-image: var(
@@ -65,7 +65,6 @@
65
65
  cursor: not-allowed;
66
66
  }
67
67
 
68
- :scope[multiple],
69
68
  :scope[size]:not([size="1"]) {
70
69
  min-block-size: 7rem;
71
70
  padding: var(--ui-space-2);
@@ -77,7 +76,7 @@
77
76
  }
78
77
  }
79
78
  @scope ([data-component~="ui-select"]) to ([data-component]) {
80
- /* Single selects draw their own chevron: the native caret cannot be inset or sized consistently.
79
+ /* The select draws its own chevron: the native caret cannot be inset or sized consistently.
81
80
  * The root stays a native <s-lect>, so the icon is a background image rather than an element. */
82
81
 
83
82
  /* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */
package/theme-dark.css CHANGED
@@ -2,30 +2,18 @@
2
2
  @media (prefers-color-scheme: dark) {
3
3
  :root:not([data-theme]) {
4
4
  color-scheme: dark;
5
+ /* The same eleven seeds the light theme sets. Every neutral, tint, hover, and disabled
6
+ colour is mixed from these, and the mixes read the scheme from them: toward this ink
7
+ brightens here, where it darkened there. */
5
8
  --ui-surface: #1a1a1a;
6
9
  --ui-surface-raised: #2a2a2a;
7
10
  --ui-surface-sunken: #2e2e2e;
8
-
9
11
  --ui-text: #f0f0ec;
10
- --ui-text-secondary: #a0a09c;
11
- --ui-text-muted: #6a6a66;
12
- --ui-disabled-surface: #242424;
13
- --ui-disabled-text: #6a6a66;
14
12
  --ui-on-accent: #1a1a1a;
15
13
  --ui-on-danger: #1a1a1a;
16
14
 
17
- --ui-border: #333330;
18
- --ui-border-strong: #4a4a46;
19
- --ui-focus-ring: #a99bf5;
20
- --ui-control-border: #6f6f69;
21
-
22
15
  --ui-accent: #a99bf5;
23
- --ui-accent-hover: #b9adff;
24
- --ui-accent-active: #c8beff;
25
- --ui-accent-subtle: #282342;
26
-
27
16
  --ui-danger: #ef6f86;
28
- --ui-danger-hover: #f58a9d;
29
17
  --ui-success: #33cc66;
30
18
  --ui-warning: #ffaa22;
31
19
  --ui-info: #4d9fff;
@@ -42,30 +30,18 @@
42
30
 
43
31
  [data-theme="dark"] {
44
32
  color-scheme: dark;
33
+ /* The same eleven seeds the light theme sets. Every neutral, tint, hover, and disabled
34
+ colour is mixed from these, and the mixes read the scheme from them: toward this ink
35
+ brightens here, where it darkened there. */
45
36
  --ui-surface: #1a1a1a;
46
37
  --ui-surface-raised: #2a2a2a;
47
38
  --ui-surface-sunken: #2e2e2e;
48
-
49
39
  --ui-text: #f0f0ec;
50
- --ui-text-secondary: #a0a09c;
51
- --ui-text-muted: #6a6a66;
52
- --ui-disabled-surface: #242424;
53
- --ui-disabled-text: #6a6a66;
54
40
  --ui-on-accent: #1a1a1a;
55
41
  --ui-on-danger: #1a1a1a;
56
42
 
57
- --ui-border: #333330;
58
- --ui-border-strong: #4a4a46;
59
- --ui-focus-ring: #a99bf5;
60
- --ui-control-border: #6f6f69;
61
-
62
43
  --ui-accent: #a99bf5;
63
- --ui-accent-hover: #b9adff;
64
- --ui-accent-active: #c8beff;
65
- --ui-accent-subtle: #282342;
66
-
67
44
  --ui-danger: #ef6f86;
68
- --ui-danger-hover: #f58a9d;
69
45
  --ui-success: #33cc66;
70
46
  --ui-warning: #ffaa22;
71
47
  --ui-info: #4d9fff;
@@ -2,46 +2,56 @@
2
2
  @media (prefers-contrast: more) {
3
3
  :root:not([data-contrast]) {
4
4
  color-scheme: light;
5
+ /* The seeds, as in every theme. */
5
6
  --ui-surface: #ffffff;
6
7
  --ui-surface-raised: #ffffff;
7
8
  --ui-surface-sunken: #f0f0ec;
8
9
  --ui-text: #000000;
9
- --ui-text-secondary: #111111;
10
- --ui-text-muted: #222222;
11
- --ui-disabled-surface: #e6e6e6;
12
- --ui-disabled-text: #333333;
10
+ --ui-on-accent: #ffffff;
11
+ --ui-on-danger: #ffffff;
12
+ --ui-accent: #0000cc;
13
+ --ui-danger: #8b0000;
14
+ --ui-success: #006400;
15
+ --ui-warning: #7a3d00;
16
+ --ui-info: #00008b;
17
+
18
+ /* The deliberate divergence, and the whole point of this theme: a mixed border is a grey
19
+ one, and high contrast asks for an edge that is drawn rather than implied. Text steps
20
+ stay closer to the ink than the mixes put them. */
13
21
  --ui-border: #000000;
14
22
  --ui-border-strong: #000000;
15
23
  --ui-control-border: #000000;
24
+ --ui-text-secondary: #111111;
25
+ --ui-text-muted: #222222;
26
+ --ui-disabled-text: #333333;
16
27
  --ui-focus-ring: #0000ff;
17
- --ui-accent: #0000cc;
18
- --ui-accent-hover: #000080;
19
- --ui-accent-active: #000066;
20
- --ui-accent-subtle: #e6e6ff;
21
- --ui-danger: #8b0000;
22
- --ui-danger-hover: #5c0000;
23
28
  }
24
29
  }
25
30
 
26
31
  [data-contrast="high"] {
27
32
  color-scheme: light;
33
+ /* The seeds, as in every theme. */
28
34
  --ui-surface: #ffffff;
29
35
  --ui-surface-raised: #ffffff;
30
36
  --ui-surface-sunken: #f0f0ec;
31
37
  --ui-text: #000000;
32
- --ui-text-secondary: #111111;
33
- --ui-text-muted: #222222;
34
- --ui-disabled-surface: #e6e6e6;
35
- --ui-disabled-text: #333333;
38
+ --ui-on-accent: #ffffff;
39
+ --ui-on-danger: #ffffff;
40
+ --ui-accent: #0000cc;
41
+ --ui-danger: #8b0000;
42
+ --ui-success: #006400;
43
+ --ui-warning: #7a3d00;
44
+ --ui-info: #00008b;
45
+
46
+ /* The deliberate divergence, and the whole point of this theme: a mixed border is a grey
47
+ one, and high contrast asks for an edge that is drawn rather than implied. Text steps
48
+ stay closer to the ink than the mixes put them. */
36
49
  --ui-border: #000000;
37
50
  --ui-border-strong: #000000;
38
51
  --ui-control-border: #000000;
52
+ --ui-text-secondary: #111111;
53
+ --ui-text-muted: #222222;
54
+ --ui-disabled-text: #333333;
39
55
  --ui-focus-ring: #0000ff;
40
- --ui-accent: #0000cc;
41
- --ui-accent-hover: #000080;
42
- --ui-accent-active: #000066;
43
- --ui-accent-subtle: #e6e6ff;
44
- --ui-danger: #8b0000;
45
- --ui-danger-hover: #5c0000;
46
56
  }
47
57
  }
package/theme-light.css CHANGED
@@ -2,31 +2,17 @@
2
2
  :root:not([data-theme]),
3
3
  [data-theme="light"] {
4
4
  color-scheme: light;
5
+ /* The seeds, and only the seeds. Neutrals, hovers, tints, and disabled colours are mixed from
6
+ these in tokens.css, so a product themes Looma by changing these eleven values. */
5
7
  --ui-surface: #ffffff;
6
8
  --ui-surface-raised: #ffffff;
7
9
  --ui-surface-sunken: #f0f0ec;
8
-
9
10
  --ui-text: #1a1a1a;
10
- --ui-text-secondary: #5c5c5c;
11
- --ui-text-muted: #9b9b9b;
12
- --ui-disabled-surface: #f0f0ec;
13
- --ui-disabled-text: #8a8a86;
14
11
  --ui-on-accent: #ffffff;
15
12
  --ui-on-danger: #ffffff;
16
13
 
17
- --ui-border: #e4e4e0;
18
- --ui-border-strong: #c8c8c4;
19
- --ui-focus-ring: #5b55d6;
20
- /* A control needs a visible 3:1 boundary; general dividers stay quieter. */
21
- --ui-control-border: #858580;
22
-
23
14
  --ui-accent: #5b55d6;
24
- --ui-accent-hover: #4b45bd;
25
- --ui-accent-active: #3e399e;
26
- --ui-accent-subtle: #efeffc;
27
-
28
15
  --ui-danger: #b4233f;
29
- --ui-danger-hover: #941d35;
30
16
  --ui-success: #007a33;
31
17
  /* Deep amber, so a solid warning surface carries white text like the other tones (5:1). */
32
18
  --ui-warning: #b45309;