@mlola-ui/engine 1.0.9 → 1.0.11

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.
@@ -255,6 +255,10 @@
255
255
  "name": "ml-chart-heading",
256
256
  "note": ""
257
257
  },
258
+ {
259
+ "name": "ml-check-list",
260
+ "note": "A list of benefits, each after a check. Pricing tiers and feature rows share it."
261
+ },
258
262
  {
259
263
  "name": "ml-cluster",
260
264
  "note": ""
@@ -361,7 +365,7 @@
361
365
  },
362
366
  {
363
367
  "name": "ml-section",
364
- "note": ""
368
+ "note": "A section a link jumps to clears the sticky navigation bar."
365
369
  },
366
370
  {
367
371
  "name": "ml-section-description",
@@ -127,10 +127,12 @@ Compose pages from these before writing layout CSS: sections, stacks,
127
127
  clusters, grids, headings, forms, stats. They read the same tokens as every
128
128
  component, so a page built from them themes with the rest.
129
129
 
130
- `.ml-actions` `.ml-brand` `.ml-brand-mark` `.ml-brand-name` `.ml-chart` `.ml-chart-bar` `.ml-chart-bars` `.ml-chart-heading` `.ml-cluster` `.ml-definition-list` `.ml-display` `.ml-divider` `.ml-empty-state` `.ml-eyebrow` `.ml-filter-chip` `.ml-filter-group` `.ml-fine-print` `.ml-form` `.ml-form-message` `.ml-form-options` `.ml-grid` `.ml-heading` `.ml-icon-chip` `.ml-inline-form` `.ml-inline-form-field` `.ml-label` `.ml-lede` `.ml-link` `.ml-page-shell` `.ml-person` `.ml-person-copy` `.ml-positive` `.ml-price` `.ml-required-mark` `.ml-section` `.ml-section-description` `.ml-section-header` `.ml-section-header-centered` `.ml-section-muted` `.ml-section-shell` `.ml-stack` `.ml-stat` `.ml-stat-card` `.ml-stat-grid` `.ml-stat-list` `.ml-stat-meta` `.ml-stat-value` `.ml-text-primary` `.ml-value`
130
+ `.ml-actions` `.ml-brand` `.ml-brand-mark` `.ml-brand-name` `.ml-chart` `.ml-chart-bar` `.ml-chart-bars` `.ml-chart-heading` `.ml-check-list` `.ml-cluster` `.ml-definition-list` `.ml-display` `.ml-divider` `.ml-empty-state` `.ml-eyebrow` `.ml-filter-chip` `.ml-filter-group` `.ml-fine-print` `.ml-form` `.ml-form-message` `.ml-form-options` `.ml-grid` `.ml-heading` `.ml-icon-chip` `.ml-inline-form` `.ml-inline-form-field` `.ml-label` `.ml-lede` `.ml-link` `.ml-page-shell` `.ml-person` `.ml-person-copy` `.ml-positive` `.ml-price` `.ml-required-mark` `.ml-section` `.ml-section-description` `.ml-section-header` `.ml-section-header-centered` `.ml-section-muted` `.ml-section-shell` `.ml-stack` `.ml-stat` `.ml-stat-card` `.ml-stat-grid` `.ml-stat-list` `.ml-stat-meta` `.ml-stat-value` `.ml-text-primary` `.ml-value`
131
131
 
132
+ - `.ml-check-list` — A list of benefits, each after a check. Pricing tiers and feature rows share it.
132
133
  - `.ml-link` — A glyph inside a link flows with the text instead of breaking the line.
133
134
  - `.ml-page-shell` — A full page: header, main and footer stacked on the page background.
135
+ - `.ml-section` — A section a link jumps to clears the sticky navigation bar.
134
136
 
135
137
  ## Elements and their attributes
136
138
 
@@ -145,10 +145,38 @@
145
145
  gap: var(--ml-space-2);
146
146
  }
147
147
 
148
+ /* A list of benefits, each after a check. Pricing tiers and feature rows share it. */
149
+ .ml-check-list {
150
+ margin: 0;
151
+ padding: 0;
152
+ list-style: none;
153
+ display: grid;
154
+ gap: var(--ml-space-2);
155
+ }
156
+
157
+ .ml-check-list li {
158
+ display: flex;
159
+ align-items: flex-start;
160
+ gap: var(--ml-space-2);
161
+ font-size: var(--ml-type-base);
162
+ color: var(--ml-text-muted);
163
+ }
164
+
165
+ .ml-check-list li > svg {
166
+ flex: none;
167
+ margin-top: 0.2em;
168
+ color: var(--ml-success-text);
169
+ }
170
+
148
171
  .ml-section {
149
172
  padding-block: clamp(3.5rem,8vw,6.5rem);
150
173
  }
151
174
 
175
+ /* A section a link jumps to clears the sticky navigation bar. */
176
+ .ml-section[id] {
177
+ scroll-margin-block-start: calc(var(--ml-control-md) + var(--ml-space-6));
178
+ }
179
+
152
180
  .ml-section-shell {
153
181
  width: min(100% - 2rem,72rem);
154
182
  margin-inline: auto;
@@ -3449,6 +3477,13 @@
3449
3477
  pointer-events: none;
3450
3478
  }
3451
3479
 
3480
+ /* A text affix ("https://", a domain, a unit) reads at the size of what is typed beside it. */
3481
+ .ml-input-leading,
3482
+ .ml-input-trailing {
3483
+ font-size: var(--ml-type-base);
3484
+ line-height: var(--ml-leading-snug);
3485
+ }
3486
+
3452
3487
  /* components/kbd */
3453
3488
  .ml-kbd {
3454
3489
  display: inline-grid;
@@ -4486,6 +4521,8 @@
4486
4521
  position: relative;
4487
4522
  display: grid;
4488
4523
  grid-template-columns: minmax(0, 1fr);
4524
+ /* In a form row taller than itself, the trigger keeps a field's height instead of stretching. */
4525
+ align-content: start;
4489
4526
  gap: var(--ml-space-1-5);
4490
4527
  width: 100%;
4491
4528
  min-width: 0;
@@ -4510,6 +4547,10 @@
4510
4547
  border: var(--ml-border-width) solid var(--ml-border);
4511
4548
  border-radius: var(--ml-radius-md);
4512
4549
  box-shadow: var(--ml-shadow-xs);
4550
+ /* The same type as a text field, so a select and an input sit level in a row. */
4551
+ font-family: var(--ml-font-sans);
4552
+ font-size: var(--ml-type-base);
4553
+ line-height: var(--ml-leading-snug);
4513
4554
  cursor: pointer;
4514
4555
  text-align: start;
4515
4556
  transition: border-color var(--ml-duration-fast),box-shadow var(--ml-duration-fast);
@@ -54,7 +54,7 @@
54
54
  "id": "atelier",
55
55
  "label": "Atelier Umami",
56
56
  "name": "Atelier Umami",
57
- "swatch": "oklch(0.638 0.153 58)",
57
+ "swatch": "oklch(0.532 0.127 58)",
58
58
  "material": "paper",
59
59
  "theme": {
60
60
  "type": 0.82,
@@ -267,9 +267,9 @@
267
267
  --ml-text-faint: oklch(0.492 0.018 260);
268
268
  --ml-border: oklch(0.878 0.023 80);
269
269
  --ml-border-subtle: oklch(0.916 0.018 80);
270
- --ml-primary: oklch(0.638 0.153 58);
271
- --ml-primary-foreground: oklch(0.18 0.02 58);
272
- --ml-primary-hover: oklch(0.678 0.141 58);
270
+ --ml-primary: oklch(0.532 0.127 58);
271
+ --ml-primary-foreground: oklch(0.99 0 0);
272
+ --ml-primary-hover: oklch(0.482 0.115 58);
273
273
  --ml-primary-text: oklch(0.497 0.119 58);
274
274
  --ml-primary-subtle: oklch(0.95 0.031 58);
275
275
  --ml-success: oklch(0.507 0.14 150);
@@ -1361,8 +1361,8 @@
1361
1361
  "$value": {
1362
1362
  "colorSpace": "oklch",
1363
1363
  "components": [
1364
- 0.638,
1365
- 0.153,
1364
+ 0.532,
1365
+ 0.127,
1366
1366
  58
1367
1367
  ],
1368
1368
  "alpha": 1
@@ -1373,9 +1373,9 @@
1373
1373
  "$value": {
1374
1374
  "colorSpace": "oklch",
1375
1375
  "components": [
1376
- 0.18,
1377
- 0.02,
1378
- 58
1376
+ 0.99,
1377
+ 0,
1378
+ 0
1379
1379
  ],
1380
1380
  "alpha": 1
1381
1381
  }
@@ -1385,8 +1385,8 @@
1385
1385
  "$value": {
1386
1386
  "colorSpace": "oklch",
1387
1387
  "components": [
1388
- 0.678,
1389
- 0.141,
1388
+ 0.482,
1389
+ 0.115,
1390
1390
  58
1391
1391
  ],
1392
1392
  "alpha": 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mlola-ui/engine",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "Framework-free CSS, spring easings, and the machine-readable contract for Mlola UI",
5
5
  "type": "module",
6
6
  "sideEffects": [
package/src/palette.mjs CHANGED
@@ -126,13 +126,15 @@ const isAchromatic = (color) => color.C < 0.03;
126
126
 
127
127
  /**
128
128
  * WCAG 2's ratio favours dark ink on mid-tone saturated colors, but eyes read
129
- * white on a violet, blue, green or red far better. In light mode a chromatic,
130
- * non-warm fill darkens a little (at most 0.12 L) so white clears the target;
131
- * yellows and oranges keep dark ink, as convention expects.
129
+ * white on a violet, blue, green, red or burnt orange far better: dark ink on
130
+ * a mid orange reads as dark on dark. In light mode a chromatic fill darkens a
131
+ * little (at most 0.12 L) so white clears the target. Ambers and yellows keep
132
+ * dark ink, as convention expects, and so does an orange too bright to reach
133
+ * white within that step.
132
134
  */
133
135
  function deepenForWhite(fill, mode) {
134
- const warm = fill.H > 40 && fill.H < 130;
135
- if (mode !== "light" || isAchromatic(fill) || warm || contrast(WHITE, fill) >= TARGETS.body) return fill;
136
+ const yellow = fill.H >= 65 && fill.H < 130;
137
+ if (mode !== "light" || isAchromatic(fill) || yellow || contrast(WHITE, fill) >= TARGETS.body) return fill;
136
138
  const deeper = solveLightness(fill, WHITE, TARGETS.body, "darker");
137
139
  return fill.L - deeper.L <= 0.12 ? deeper : fill;
138
140
  }