layered-ui-rails 0.25.0 → 0.26.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d892f7efaed58d161179cc5478eaf0961b4b31c2e822aaba4063143343aeac31
4
- data.tar.gz: 28e37164714d1a354b255a10a3833069b94f6202480082b29e70fcc23a485ffa
3
+ metadata.gz: 63d902f842afed6b1e9d7784677a2a748d3775ef9884bb27f9ed6439133b3638
4
+ data.tar.gz: 25d8cf1f06bfadd24dc8e97efd1cc14f4d818ce5285e4da980dcd65f21d96ea9
5
5
  SHA512:
6
- metadata.gz: d2d3c833c03dd9c56d88bf578fb69f27ddf0eda03baf31ebb0953e6de0bb9b5ae1248d444e77c362d18e4288aad6adbae28a4959f95c68a392b373417c23040d
7
- data.tar.gz: 661964c07f3d03e1d4ee937a9f4b3f3d456491fadb9ee67778cee063d9eda535fbf02a276bcfe1a3c0a1b67579ece03afda66a5e1d98c90ebe6b232de6c05731
6
+ metadata.gz: 97a9c888d83d7a4a2317eae38fdd77e91dcb8eeab33b76b85bb7dc8afb9c7d8349ff5f9b693633f16218b8a906d3f2029b1753a6f730910a83f47169d523f4e0
7
+ data.tar.gz: 80572d1c7b424944cc9a7b324b749a01bc3708f0251eacc0ea2f4faa6be864bfbc8249b4ea6ed68961878a2f29bd1d516acb84f6af7cd50d73123bb09302c062
@@ -11,11 +11,14 @@ Two patterns deviate from strict BEM by design - leave them in place rather than
11
11
  **Bare-link styling.** `.l-ui-page` and `.l-ui-panel__body` style descendant `<a>` elements that do not already carry an `l-ui-` class:
12
12
 
13
13
  ```css
14
- .l-ui-page a:not([class*="l-ui-"]),
15
- .l-ui-panel__body a:not([class*="l-ui-"]) { ... }
14
+ :where(.l-ui-page, .l-ui-panel__body) :where(a:not([class*="l-ui-"])) { ... }
16
15
  ```
17
16
 
18
- This gives author-written links inside long-form content (Markdown, prose, ad-hoc views) consistent underline/colour treatment without forcing an explicit class on every link. Engine elements opt out automatically because their class names contain `l-ui-`. Side effect: any host-app class containing the substring `l-ui-` will also opt an `<a>` out of bare-link styling.
17
+ This gives author-written links inside long-form content (Markdown, prose, ad-hoc views) consistent underline/colour treatment without forcing an explicit class on every link. Engine elements opt out automatically because their class names contain `l-ui-`.
18
+
19
+ The whole selector is wrapped in `:where()`, so it has zero specificity. That matters: host apps build their own components, and those class names do not contain `l-ui-`, so their links are caught by this rule. With zero specificity a single host-app class (`.calculator-rail__link { ... }`) overrides it by ordinary cascade rules, with no `!important` and no specificity games. Keep it that way - this is a default, and a default must never beat author styles. Note the `focus-ring` state styles still carry the specificity of their own `:focus-visible` pseudo-class.
20
+
21
+ Side effect: any host-app class containing the substring `l-ui-` will also opt an `<a>` out of bare-link styling.
19
22
 
20
23
  ## Body modifiers
21
24
 
@@ -346,6 +349,8 @@ The listbox and filtered-out options are hidden with the `hidden` attribute, so
346
349
  .l-ui-popover__menu-divider Horizontal rule separating groups of items (apply to an <hr>)
347
350
  ```
348
351
 
352
+ The panel takes `overflow: visible`, overriding the UA stylesheet's `overflow: auto` for `[popover]`. It is `height: fit-content` with no max-height, so in-flow content can't overflow it anyway, and the UA rule only did harm: it made the panel a scroll container that clipped any child painting outside it - a combobox's absolutely positioned listbox above all, which is out of flow and so never counted in the panel's height. A popover lives in the top layer, so a child hanging past its edge paints cleanly over the page. Give a popover that genuinely needs to scroll its own `max-height` and `overflow-y`.
353
+
349
354
  ## Breadcrumbs
350
355
 
351
356
  ```
@@ -526,6 +531,7 @@ Tier 2 - Full palette (override individually as needed):
526
531
  --button-primary-text Primary button text (defaults to --accent-foreground)
527
532
  --button-primary-icon Icon color on filled icon buttons (defaults to --button-primary-text)
528
533
  --danger Danger/error color
534
+ --danger-foreground Text/icon color on solid danger buttons
529
535
  --danger-light Light danger background
530
536
  --danger-text Danger text color
531
537
  --success-bg Success background
data/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. This project follows [Semantic Versioning](https://semver.org/).
4
4
 
5
+ ## [0.26.0] - 2026-09-19
6
+
7
+ ### Added
8
+
9
+ - `--danger-foreground`: the text and icon colour on a solid danger button, split out of the hard-coded `text-white` on `.l-ui-button--danger`. It mirrors the way `--accent-foreground` pairs with `--accent` - white in light mode (7.47:1 on `#A71B1B`), near-black in dark mode (4.75:1 on `#F04242`). The previous white label in dark mode gave 3.78:1, short of the 4.5:1 WCAG 2.2 AA needs for the button's 14px text.
10
+
11
+ ### Changed
12
+
13
+ - Bare-link prose styling carries zero specificity: the selector on `.l-ui-page` and `.l-ui-panel__body` descendant links is now wrapped in `:where()`. It is a default, so a single host-app class overrides it by ordinary cascade order, with no `!important` and no specificity games. The `focus-ring` state styles still carry the specificity of their own `:focus-visible` pseudo-class.
14
+ - Breaking: a host that overrides `--danger` to a darker red in dark mode now gets the near-black label from `--danger-foreground`, and should set `--danger-foreground: oklch(1 0 0)` to restore white.
15
+
16
+ ## [0.25.1] - 2026-08-28
17
+
18
+ ### Fixed
19
+
20
+ - A popover no longer clips its content. `[popover]` takes `overflow: auto` from the UA stylesheet, which made the panel a scroll container; since the panel is `height: fit-content`, an absolutely positioned child never counted towards its height and so was cut off - a combobox inside a popover showed a listbox clipped to the height of its own label and input. `.l-ui-popover` now sets `overflow: visible`, and a popover that genuinely needs to scroll can set its own `max-height` and `overflow-y`.
21
+
5
22
  ## [0.25.0] - 2026-08-23
6
23
 
7
24
  ### Added
@@ -70,6 +70,7 @@
70
70
  --button-primary-text: var(--accent-foreground);
71
71
  --button-primary-icon: var(--button-primary-text);
72
72
  --danger: oklch(0.47 0.1742 27.23);
73
+ --danger-foreground: oklch(1 0 0);
73
74
  --danger-light: oklch(0.9663 0.0166 17.44);
74
75
  --danger-text: oklch(0.443 0.1634 27.14);
75
76
  --success-bg: oklch(0.8395 0.1698 152.91);
@@ -127,6 +128,7 @@
127
128
  --button-primary-text: var(--accent-foreground);
128
129
  --button-primary-icon: var(--button-primary-text);
129
130
  --danger: oklch(0.6362 0.2102 25.49);
131
+ --danger-foreground: oklch(0.2044 0 0);
130
132
  --danger-light: oklch(0.2596 0.1021 28.32);
131
133
  --danger-text: oklch(0.6607 0.1921 24.02);
132
134
  --success-bg: oklch(0.3385 0.0852 150.45);
@@ -236,6 +238,7 @@
236
238
  --color-button-primary-text: var(--button-primary-text);
237
239
  --color-button-primary-icon: var(--button-primary-icon);
238
240
  --color-danger: var(--danger);
241
+ --color-danger-foreground: var(--danger-foreground);
239
242
  --color-danger-light: var(--danger-light);
240
243
  --color-danger-text: var(--danger-text);
241
244
  --color-success-bg: var(--success-bg);
@@ -515,8 +518,10 @@
515
518
  @apply mx-[calc(var(--l-ui-gutter)*-1)];
516
519
  }
517
520
 
518
- .l-ui-page a:not([class*="l-ui-"]),
519
- .l-ui-panel__body a:not([class*="l-ui-"]) {
521
+ /* Bare-link styling for author-written prose. Wrapped in :where() so the whole selector carries
522
+ zero specificity: it is a default, and any host-app rule (even a single class) must be able to
523
+ win without out-specifying the engine. */
524
+ :where(.l-ui-page, .l-ui-panel__body) :where(a:not([class*="l-ui-"])) {
520
525
  @apply text-foreground underline underline-offset-4 decoration-foreground-muted/60
521
526
  rounded-sm
522
527
  focus-ring;
@@ -1282,7 +1287,7 @@
1282
1287
  }
1283
1288
 
1284
1289
  .l-ui-button--danger {
1285
- @apply text-white
1290
+ @apply text-danger-foreground
1286
1291
  bg-danger;
1287
1292
  }
1288
1293
 
@@ -2647,6 +2652,15 @@ pre.l-ui-surface {
2647
2652
  text-sm text-foreground
2648
2653
  bg-background
2649
2654
  border border-border rounded-sm;
2655
+
2656
+ /* The UA stylesheet gives [popover] `overflow: auto`, which makes the panel
2657
+ a scroll container and so clips any child that paints outside it - a
2658
+ combobox's absolutely positioned listbox, most of all, which is out of
2659
+ flow and therefore never counted in the panel's height. The panel is
2660
+ `height: fit-content` with no max-height, so in-flow content can't
2661
+ overflow it and the UA rule has nothing else to do; a popover lives in the
2662
+ top layer, so a child hanging past its edge paints cleanly over the page. */
2663
+ overflow: visible;
2650
2664
  }
2651
2665
 
2652
2666
  /* A list of actions inside a popover (e.g. a table row's "more" menu).
@@ -1,5 +1,5 @@
1
1
  module Layered
2
2
  module Ui
3
- VERSION = "0.25.0"
3
+ VERSION = "0.26.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: layered-ui-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.25.0
4
+ version: 0.26.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - layered.ai