layered-ui-rails 0.6.0 → 0.8.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: 8b3fa30f64b14c50db43ea23c4fbdb699903a7f4c2f957a8b22cd85772868a7b
4
- data.tar.gz: 215e0d57d2403591bf31dd9d31ea05c281e5f36f83ebe822a4ae3aa902eabf0b
3
+ metadata.gz: d5abac205810e228d971ffa9c13f2c069c56be3f143c0f25612f02c2d8b6e598
4
+ data.tar.gz: 3dbb48d42029cce15cb92dcbd6cc014046032cb7449f145e63854b4898936d14
5
5
  SHA512:
6
- metadata.gz: 890b8e734f1b573143bf40deda9d3d5c64f1eb358f075a0a5e6608475eaeeb6dd0470675e68b90ac72f55f28f7a688bb19410bc99f5f77e3c590c2025c90ab50
7
- data.tar.gz: 73c86751d4a39d80879c254fa35bae780c74ae4c7a5e45fb9c41c5634a6b69ce60632750e035176439c038646415a98e0b6988f389e8368cf1354348363a4553
6
+ metadata.gz: e39b4bbc08bb0f198320dccf181de35003e0ab2927eabe3666e0f39743e652a3e9ca45dc295d40b3ce22e1a85381392d86bd202dda9d905f1b500f2c837fdb6d
7
+ data.tar.gz: 8efb4d5a510c8ef52541b0d9f1286e13dce5b8d64c90d7f984e4d4eccfc7153f91eafa83c5beadf54911b2a8a405e5b8c54383ea3884dc2ed6c0169c70f283ca
@@ -61,7 +61,7 @@ Populate layout regions with `content_for` (always above the render call):
61
61
  <%# Inject into <head> (e.g. per-tenant theming) %>
62
62
  <% content_for :l_ui_head do %>
63
63
  <style nonce="<%= content_security_policy_nonce %>">
64
- :root { --accent: 220 80% 55%; }
64
+ :root { --accent: oklch(0.58 0.19 255); }
65
65
  </style>
66
66
  <% end %>
67
67
 
@@ -150,17 +150,17 @@ All controllers use the `l-ui--` namespace and are auto-registered via importmap
150
150
 
151
151
  ## Theming
152
152
 
153
- Override CSS custom properties after the engine import. Values are space-separated HSL channels (no `hsl()` wrapper).
153
+ Override CSS custom properties after the engine import. Values are full CSS colors - `oklch()` is recommended for perceptually uniform mixing and consistent contrast, but `#hex`, `rgb()`, and keywords also work. A converter such as https://oklch.com/ can help translate from hex/rgb.
154
154
 
155
155
  ```css
156
156
  @import "./layered_ui";
157
157
 
158
158
  :root {
159
- --accent: 220 80% 55%;
160
- --accent-foreground: 0 0% 100%;
159
+ --accent: oklch(0.58 0.19 255);
160
+ --accent-foreground: oklch(1 0 0);
161
161
  }
162
162
  .dark {
163
- --accent: 220 80% 65%;
163
+ --accent: oklch(0.72 0.14 255);
164
164
  }
165
165
  ```
166
166
 
@@ -170,7 +170,9 @@ Key tokens: `--accent`, `--accent-foreground`, `--background`, `--foreground`, `
170
170
 
171
171
  Place files in `app/assets/images/layered_ui/` to replace engine defaults:
172
172
 
173
- `logo_light.svg`, `logo_dark.svg`, `icon_light.svg`, `icon_dark.svg`, `apple_touch_icon.png`, `panel_icon_light.svg`, `panel_icon_dark.svg`.
173
+ `logo_light.svg`, `logo_dark.svg`, `icon_light.svg`, `icon_dark.svg`, `apple_touch_icon.png`.
174
+
175
+ The panel toggle button uses an inline SVG that inherits `currentColor`. Recolor it by overriding the `--button-primary-icon` Tier 2 token, or replace the image by setting both `@l_ui_panel_icon_light_url` and `@l_ui_panel_icon_dark_url` (per-request).
174
176
 
175
177
  ## Optional integrations
176
178
 
@@ -222,8 +222,9 @@ WCAG 2.2 AA table pattern:
222
222
  .l-ui-panel__button Floating action button
223
223
  .l-ui-panel__button--dragging During drag
224
224
  .l-ui-panel__button--snapping Snapping to edge
225
- .l-ui-panel__icon--light Panel button icon (light)
226
- .l-ui-panel__icon--dark Panel button icon (dark)
225
+ .l-ui-panel__icon Panel button inline SVG icon
226
+ .l-ui-panel__icon--light Panel button icon (light, for custom image override)
227
+ .l-ui-panel__icon--dark Panel button icon (dark, for custom image override)
227
228
  .l-ui-panel__resize-handle Desktop resize handle
228
229
  .l-ui-panel__header Panel header
229
230
  .l-ui-panel__header-heading Panel title
@@ -282,7 +283,7 @@ WCAG 2.2 AA table pattern:
282
283
 
283
284
  ## Theming tokens
284
285
 
285
- All color values are space-separated HSL channels (e.g. `220 80% 55%`). Override after importing the engine CSS.
286
+ All color values are full CSS colors - `oklch()` is recommended for perceptually uniform mixing and consistent contrast (e.g. `oklch(0.58 0.19 255)`), but `#hex`, `rgb()`, and keywords also work. Override after importing the engine CSS. A converter such as https://oklch.com/ can help translate from hex/rgb.
286
287
 
287
288
  Tier 1 - Accent (quick branding):
288
289
  ```
@@ -301,7 +302,8 @@ Tier 2 - Full palette (override individually as needed):
301
302
  --surface Card/surface background
302
303
  --surface-highlighted Highlighted surface
303
304
  --button-primary-bg Primary button background (defaults to --accent)
304
- --button-primary-text Primary button and floating icon text (defaults to --accent-foreground)
305
+ --button-primary-text Primary button text (defaults to --accent-foreground)
306
+ --button-primary-icon Icon color on filled icon buttons (defaults to --button-primary-text)
305
307
  --danger Danger/error color
306
308
  --danger-light Light danger background
307
309
  --danger-text Danger text color
@@ -315,4 +317,4 @@ Tier 2 - Full palette (override individually as needed):
315
317
  --header-height Header height (default 63px)
316
318
  ```
317
319
 
318
- Override --button-primary-text when your accent color needs a different text/icon color on buttons (e.g. a pink accent with white button text in dark mode).
320
+ Override --button-primary-text when your accent color needs a different text/icon color on buttons (e.g. a pink accent with white button text in dark mode). Override --button-primary-icon instead when only the icon color should change.
data/AGENTS.md CHANGED
@@ -6,7 +6,7 @@ Guidance for AI agents working in this repository.
6
6
 
7
7
  - **Entry:** `require "layered-ui-rails"` → `lib/layered/ui.rb` → `lib/layered/ui/engine.rb`
8
8
  - **Engine:** importmap, assets, Pagy helpers when present; helpers: `AuthenticationHelper`, `NavigationHelper`, `PagyHelper`
9
- - **CSS** `app/assets/tailwind/layered/ui/styles.css`: HSL tokens, `.dark` on `<html>`, `@theme` utilities (`bg-background`, etc.), BEM components (`.l-ui-button--primary`, etc.). Layout: 63px header, 240px sidebar, 320px panel. WCAG 2.2 AA.
9
+ - **CSS** `app/assets/tailwind/layered/ui/styles.css`: OKLCH tokens, `.dark` on `<html>`, `@theme` utilities (`bg-background`, etc.), BEM components (`.l-ui-button--primary`, etc.). Layout: 63px header, 240px sidebar, 320px panel. WCAG 2.2 AA.
10
10
  - **CSS `@apply`:** Multi-line with grouping (layout → spacing → typography → colors → effects). Single utilities may stay on one line.
11
11
  - **Generators:** `bin/rails generate layered:ui:install` (copy CSS, import CSS, import JS)
12
12
  - **JS** `app/javascript/layered_ui/`: Stimulus controllers registered as `l-ui--theme`, `l-ui--navigation`, `l-ui--panel`, `l-ui--modal`, `l-ui--tabs`
data/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
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
+ ## [Unreleased]
6
+
7
+ ## [0.8.0] - 2026-04-24
8
+
9
+ ### Changed
10
+
11
+ - **Breaking:** Theme tokens migrated from HSL channels (`220 80% 55%`) to full `oklch()` values for perceptually uniform mixing. `@theme` now references the vars directly instead of wrapping them in `hsl()`. Existing overrides files need to be updated: replace `hue sat% lightness%` with the equivalent `oklch(L C H)` value (or any valid CSS color - `#hex`, `rgb()`, and keywords all work now).
12
+ - `layered:ui:create_overrides` generator and token documentation (`SKILL.md`, `references/CSS.md`, `README.md`, dummy app colour/head pages) updated to reflect the new `oklch()` format.
13
+
14
+ ## [0.7.0] - 2026-04-23
15
+
16
+ ### Added
17
+
18
+ - `--button-primary-icon` Tier 2 token for filled icon buttons (e.g. `l-ui-panel__button`, `l-ui-scroll-to-bottom`). Defaults to `--button-primary-text`; override to recolor icons independently of button text.
19
+ - Inline SVG default for the panel toggle button icon - inherits `currentColor` so it picks up `--button-primary-icon`. Per-request `@l_ui_panel_icon_light_url` / `@l_ui_panel_icon_dark_url` still replace the default image, and each theme falls back to the inline SVG independently when its variable is unset.
20
+ - Documentation of the HSL-channel format for theme tokens (space-separated channels such as `220 80% 55%`) in `SKILL.md`, `references/CSS.md`, and the overrides generator, with a pointer to a hex/rgb converter.
21
+
22
+ ### Changed
23
+
24
+ - `l-ui-scroll-to-bottom` now bakes the chevron-down icon into CSS via `mask-image` (with `-webkit-mask` prefixes and a URL-encoded SVG for Safari compatibility) and colours it with `--button-primary-icon`. Host markup is a plain empty `<button class="l-ui-scroll-to-bottom" aria-label="...">` - no inner `<svg>`/`<img>` required.
25
+
26
+ ### Removed
27
+
28
+ - Static-file panel icon overrides (`panel_icon_light.svg`, `panel_icon_dark.svg` in `app/assets/images/layered_ui/`). Use `@l_ui_panel_icon_light_url` / `@l_ui_panel_icon_dark_url` instance variables to supply a custom image.
29
+
5
30
  ## [0.6.0] - 2026-04-19
6
31
 
7
32
  ### Added
data/README.md CHANGED
@@ -104,14 +104,14 @@ All colors are CSS custom properties on `:root` using a two-tier system:
104
104
  @import "./layered_ui";
105
105
 
106
106
  :root {
107
- --accent: 220 80% 55%;
108
- --accent-foreground: 0 0% 100%;
107
+ --accent: oklch(0.58 0.19 255);
108
+ --accent-foreground: oklch(1 0 0);
109
109
  }
110
110
 
111
111
  .dark {
112
- --accent: 220 80% 65%;
113
- --accent-foreground: 0 0% 9%;
114
- --button-primary-text: 0 0% 100%; /* white icons/text on colored buttons */
112
+ --accent: oklch(0.72 0.14 255);
113
+ --accent-foreground: oklch(0.2044 0 0);
114
+ --button-primary-text: oklch(1 0 0); /* white icons/text on colored buttons */
115
115
  }
116
116
  ```
117
117
 
@@ -120,7 +120,7 @@ For dynamic theming (e.g. per-tenant branding), use `content_for :l_ui_head` to
120
120
  ```erb
121
121
  <% content_for :l_ui_head do %>
122
122
  <style>
123
- :root { --accent: <%= @tenant.accent_hsl %>; --accent-foreground: 0 0% 100%; }
123
+ :root { --accent: <%= @tenant.accent_color %>; --accent-foreground: oklch(1 0 0); }
124
124
  </style>
125
125
  <% end %>
126
126
  ```
@@ -132,7 +132,7 @@ For dynamic theming (e.g. per-tenant branding), use `content_for :l_ui_head` to
132
132
  > ```erb
133
133
  > <% content_for :l_ui_head do %>
134
134
  > <style nonce="<%= content_security_policy_nonce %>">
135
- > :root { --accent: <%= @tenant.accent_hsl %>; --accent-foreground: 0 0% 100%; }
135
+ > :root { --accent: <%= @tenant.accent_color %>; --accent-foreground: oklch(1 0 0); }
136
136
  > </style>
137
137
  > <% end %>
138
138
  > ```
@@ -150,8 +150,6 @@ Replace the defaults by placing files with the same names in `app/assets/images/
150
150
  | `icon_light.svg` | Favicon and header icon (light theme) |
151
151
  | `icon_dark.svg` | Favicon and header icon (dark theme) |
152
152
  | `apple_touch_icon.png` | Apple touch icon |
153
- | `panel_icon_light.svg` | Panel toggle button (light theme) |
154
- | `panel_icon_dark.svg` | Panel toggle button (dark theme) |
155
153
 
156
154
  layered-ui-rails uses two patterns for per-request overrides:
157
155
 
@@ -215,9 +213,7 @@ kamal deploy
215
213
 
216
214
  ## Contributing
217
215
 
218
- This project is still in its early days. We welcome issues, feedback, and ideas - they genuinely help shape the direction of the project. That said, we're holding off on accepting pull requests until after the 1.0 release so we can stay focused on getting the core foundations right. Once we're there, we'd love to open things up to broader contributions. Thanks for your patience and interest!
219
-
220
- - [CLA.md](CLA.md) - contributor license agreement
216
+ This project is still in its early days. We welcome issues, feedback, and ideas - they genuinely help shape the direction of the project. That said, we're holding off on accepting pull requests for now to stay focused on getting the foundations right. Thank you for your patience and interest. See [CLA.md](CLA.md) for the full policy.
221
217
 
222
218
  ## License
223
219
 
@@ -227,4 +223,4 @@ Copyright 2026 LAYERED AI LIMITED (UK company number: 17056830). See [NOTICE](NO
227
223
 
228
224
  ## Trademarks
229
225
 
230
- The source code is fully open, but the layered.ai name, logo, and brand assets are trademarks of LAYERED AI LIMITED. The Apache 2.0 license does not grant rights to use the layered.ai branding. Forks and redistributions must use a distinct name. See [TRADEMARK.md](TRADEMARK.md) for the full policy.
226
+ The source code is fully open, but the layered.ai name, logo, and brand assets are trademarks of LAYERED AI LIMITED. The Apache 2.0 license does not grant rights to use the layered.ai branding. Forks and redistributions must use a distinct name. See [TRADEMARK.md](TRADEMARK.md) for the full policy.
@@ -33,7 +33,7 @@
33
33
  @variant dark (&:where(.dark, .dark *));
34
34
 
35
35
  /*
36
- * Color tokens (HSL channels, e.g. "220 80% 55%")
36
+ * Color tokens (full oklch() values, e.g. "oklch(0.7 0.15 240)")
37
37
  *
38
38
  * Tier 1 - Accent: --accent, --accent-foreground
39
39
  * Tier 2 - Full palette: background, foreground, border, surface, etc.
@@ -48,57 +48,59 @@
48
48
  @layer base {
49
49
  :root {
50
50
  /* Tier 1 - Accent */
51
- --accent: 0 0% 9%;
52
- --accent-foreground: 0 0% 100%;
51
+ --accent: oklch(0.2044 0 0);
52
+ --accent-foreground: oklch(1 0 0);
53
53
  /* Tier 2 - Full palette */
54
- --background: 0 0% 100%;
55
- --foreground: 0 0% 13%;
56
- --foreground-muted: 0 0% 29%;
57
- --border: 0 0% 91%;
58
- --border-control: 0 0% 55%;
59
- --ring: 0 0% 13%;
60
- --surface: 0 0% 96%;
61
- --surface-highlighted: 0 0% 91%;
54
+ --background: oklch(1 0 0);
55
+ --foreground: oklch(0.2484 0 0);
56
+ --foreground-muted: oklch(0.4089 0 0);
57
+ --border: oklch(0.9312 0 0);
58
+ --border-control: oklch(0.6409 0 0);
59
+ --ring: oklch(0.2484 0 0);
60
+ --surface: oklch(0.9696 0 0);
61
+ --surface-highlighted: oklch(0.9312 0 0);
62
62
  --button-primary-bg: var(--accent);
63
63
  --button-primary-text: var(--accent-foreground);
64
- --danger: 0 72% 38%;
65
- --danger-light: 0 100% 97%;
66
- --danger-text: 0 72% 35%;
67
- --success-bg: 142 76% 65%;
68
- --success-text: 142 76% 13%;
69
- --switch-track-checked: 142 70% 38%;
70
- --warning-bg: 48 96% 65%;
71
- --warning-text: 48 96% 15%;
72
- --error-bg: 0 84% 75%;
73
- --error-text: 0 93% 12%;
64
+ --button-primary-icon: var(--button-primary-text);
65
+ --danger: oklch(0.47 0.1742 27.23);
66
+ --danger-light: oklch(0.9663 0.0166 17.44);
67
+ --danger-text: oklch(0.443 0.1634 27.14);
68
+ --success-bg: oklch(0.8395 0.1698 152.91);
69
+ --success-text: oklch(0.3088 0.0763 150.76);
70
+ --switch-track-checked: oklch(0.6334 0.1664 149.75);
71
+ --warning-bg: oklch(0.8908 0.1551 94.86);
72
+ --warning-text: oklch(0.3625 0.0732 93.12);
73
+ --error-bg: oklch(0.748 0.1306 20.64);
74
+ --error-text: oklch(0.2248 0.0874 28.11);
74
75
  --header-height: 63px;
75
76
  }
76
77
 
77
78
  .dark {
78
79
  /* Tier 1 - Accent */
79
- --accent: 0 0% 100%;
80
- --accent-foreground: 0 0% 9%;
80
+ --accent: oklch(1 0 0);
81
+ --accent-foreground: oklch(0.2044 0 0);
81
82
  /* Tier 2 - Full palette */
82
- --background: 0 0% 0%;
83
- --foreground: 0 0% 89%;
84
- --foreground-muted: 0 0% 71%;
85
- --border: 0 0% 16%;
86
- --border-control: 0 0% 40%;
87
- --ring: 0 0% 89%;
88
- --surface: 0 0% 8%;
89
- --surface-highlighted: 0 0% 16%;
83
+ --background: oklch(0 0 0);
84
+ --foreground: oklch(0.9157 0 0);
85
+ --foreground-muted: oklch(0.7733 0 0);
86
+ --border: oklch(0.2801 0 0);
87
+ --border-control: oklch(0.5103 0 0);
88
+ --ring: oklch(0.9157 0 0);
89
+ --surface: oklch(0.193 0 0);
90
+ --surface-highlighted: oklch(0.2801 0 0);
90
91
  --button-primary-bg: var(--accent);
91
92
  --button-primary-text: var(--accent-foreground);
92
- --danger: 0 85% 60%;
93
- --danger-light: 0 93% 15%;
94
- --danger-text: 0 85% 64%;
95
- --success-bg: 142 76% 15%;
96
- --success-text: 142 76% 80%;
97
- --switch-track-checked: 142 70% 45%;
98
- --warning-bg: 48 96% 15%;
99
- --warning-text: 48 96% 80%;
100
- --error-bg: 0 93% 12%;
101
- --error-text: 0 84% 75%;
93
+ --button-primary-icon: var(--button-primary-text);
94
+ --danger: oklch(0.6362 0.2102 25.49);
95
+ --danger-light: oklch(0.2596 0.1021 28.32);
96
+ --danger-text: oklch(0.6607 0.1921 24.02);
97
+ --success-bg: oklch(0.3385 0.0852 150.45);
98
+ --success-text: oklch(0.8999 0.1022 155.94);
99
+ --switch-track-checked: oklch(0.7176 0.1902 149.6);
100
+ --warning-bg: oklch(0.3625 0.0732 93.12);
101
+ --warning-text: oklch(0.9336 0.1 95.79);
102
+ --error-bg: oklch(0.2248 0.0874 28.11);
103
+ --error-text: oklch(0.748 0.1306 20.64);
102
104
  }
103
105
 
104
106
  /* Typography */
@@ -146,7 +148,7 @@
146
148
  .l-ui-body,
147
149
  .l-ui-body * {
148
150
  scrollbar-width: thin;
149
- scrollbar-color: hsl(var(--foreground-muted) / 0.3) transparent;
151
+ scrollbar-color: color-mix(in oklch, var(--foreground-muted) 30%, transparent) transparent;
150
152
  }
151
153
  }
152
154
 
@@ -155,28 +157,29 @@
155
157
  @theme {
156
158
  --font-manrope: 'Manrope', ui-sans-serif, system-ui, sans-serif;
157
159
  --font-inter: 'Inter', ui-sans-serif, system-ui, sans-serif;
158
- --color-accent: hsl(var(--accent));
159
- --color-accent-foreground: hsl(var(--accent-foreground));
160
- --color-background: hsl(var(--background));
161
- --color-foreground: hsl(var(--foreground));
162
- --color-foreground-muted: hsl(var(--foreground-muted));
163
- --color-border: hsl(var(--border));
164
- --color-border-control: hsl(var(--border-control));
165
- --color-surface: hsl(var(--surface));
166
- --color-surface-highlighted: hsl(var(--surface-highlighted));
167
- --color-button-primary-bg: hsl(var(--button-primary-bg));
168
- --color-button-primary-text: hsl(var(--button-primary-text));
169
- --color-danger: hsl(var(--danger));
170
- --color-danger-light: hsl(var(--danger-light));
171
- --color-danger-text: hsl(var(--danger-text));
172
- --color-success-bg: hsl(var(--success-bg));
173
- --color-success-text: hsl(var(--success-text));
174
- --color-switch-track-checked: hsl(var(--switch-track-checked));
175
- --color-warning-bg: hsl(var(--warning-bg));
176
- --color-warning-text: hsl(var(--warning-text));
177
- --color-error-bg: hsl(var(--error-bg));
178
- --color-error-text: hsl(var(--error-text));
179
- --color-ring: hsl(var(--ring));
160
+ --color-accent: var(--accent);
161
+ --color-accent-foreground: var(--accent-foreground);
162
+ --color-background: var(--background);
163
+ --color-foreground: var(--foreground);
164
+ --color-foreground-muted: var(--foreground-muted);
165
+ --color-border: var(--border);
166
+ --color-border-control: var(--border-control);
167
+ --color-surface: var(--surface);
168
+ --color-surface-highlighted: var(--surface-highlighted);
169
+ --color-button-primary-bg: var(--button-primary-bg);
170
+ --color-button-primary-text: var(--button-primary-text);
171
+ --color-button-primary-icon: var(--button-primary-icon);
172
+ --color-danger: var(--danger);
173
+ --color-danger-light: var(--danger-light);
174
+ --color-danger-text: var(--danger-text);
175
+ --color-success-bg: var(--success-bg);
176
+ --color-success-text: var(--success-text);
177
+ --color-switch-track-checked: var(--switch-track-checked);
178
+ --color-warning-bg: var(--warning-bg);
179
+ --color-warning-text: var(--warning-text);
180
+ --color-error-bg: var(--error-bg);
181
+ --color-error-text: var(--error-text);
182
+ --color-ring: var(--ring);
180
183
  }
181
184
 
182
185
  /* Accessibility */
@@ -1089,7 +1092,7 @@ pre.l-ui-surface {
1089
1092
  w-4 h-4
1090
1093
  pointer-events-none;
1091
1094
  content: '';
1092
- background-color: hsl(var(--foreground));
1095
+ background-color: var(--foreground);
1093
1096
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z'/%3E%3C/svg%3E");
1094
1097
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z'/%3E%3C/svg%3E");
1095
1098
  -webkit-mask-size: contain;
@@ -1384,7 +1387,7 @@ pre.l-ui-surface {
1384
1387
  z-40
1385
1388
  cursor-pointer
1386
1389
  bg-button-primary-bg
1387
- text-button-primary-text
1390
+ text-button-primary-icon
1388
1391
  rounded-full
1389
1392
  focus-ring
1390
1393
  transition-all;
@@ -1411,6 +1414,10 @@ pre.l-ui-surface {
1411
1414
  opacity-0 pointer-events-none;
1412
1415
  }
1413
1416
 
1417
+ .l-ui-panel__icon {
1418
+ @apply w-7 h-7;
1419
+ }
1420
+
1414
1421
  .l-ui-panel__icon--light {
1415
1422
  @apply block
1416
1423
  dark:invert-0;
@@ -1655,12 +1662,25 @@ pre.l-ui-surface {
1655
1662
  ml-auto mr-0 -mt-9 h-9 w-9
1656
1663
  rounded-full
1657
1664
  cursor-pointer
1658
- bg-button-primary-bg text-button-primary-text
1665
+ bg-button-primary-bg text-button-primary-icon
1659
1666
  focus-ring
1660
1667
  opacity-0 pointer-events-none
1661
1668
  transition-opacity duration-200;
1662
1669
  }
1663
1670
 
1671
+ .l-ui-scroll-to-bottom::before {
1672
+ content: "";
1673
+ @apply block w-4 h-4 bg-button-primary-icon;
1674
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
1675
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
1676
+ -webkit-mask-size: contain;
1677
+ mask-size: contain;
1678
+ -webkit-mask-repeat: no-repeat;
1679
+ mask-repeat: no-repeat;
1680
+ -webkit-mask-position: center;
1681
+ mask-position: center;
1682
+ }
1683
+
1664
1684
  .l-ui-scroll-to-bottom[data-visible] {
1665
1685
  @apply
1666
1686
  opacity-100 pointer-events-auto;
@@ -65,7 +65,15 @@
65
65
  data-action="click->l-ui--panel-button#toggle mousedown->l-ui--panel-button#startDrag touchstart->l-ui--panel-button#startDrag"
66
66
  data-l-ui--panel-target="actionButton"
67
67
  >
68
- <%= image_tag(@l_ui_panel_icon_light_url.presence || "layered_ui/panel_icon_light.svg", alt: "", class: "l-ui-icon--lg l-ui-panel__icon--light", aria: { hidden: true }) %>
69
- <%= image_tag(@l_ui_panel_icon_dark_url.presence || "layered_ui/panel_icon_dark.svg", alt: "", class: "l-ui-icon--lg l-ui-panel__icon--dark", aria: { hidden: true }) %>
68
+ <% if @l_ui_panel_icon_light_url.present? %>
69
+ <%= image_tag(@l_ui_panel_icon_light_url, alt: "", class: "l-ui-icon--lg l-ui-panel__icon--light", aria: { hidden: true }) %>
70
+ <% else %>
71
+ <svg class="l-ui-panel__icon l-ui-panel__icon--light" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"/></svg>
72
+ <% end %>
73
+ <% if @l_ui_panel_icon_dark_url.present? %>
74
+ <%= image_tag(@l_ui_panel_icon_dark_url, alt: "", class: "l-ui-icon--lg l-ui-panel__icon--dark", aria: { hidden: true }) %>
75
+ <% else %>
76
+ <svg class="l-ui-panel__icon l-ui-panel__icon--dark" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"/></svg>
77
+ <% end %>
70
78
  </button>
71
79
  </div>
@@ -26,8 +26,11 @@ module Layered
26
26
  * This file is NOT overwritten by the install generator, so your
27
27
  * changes are preserved when you upgrade layered-ui-rails.
28
28
  *
29
- * Values are HSL channels: <hue> <saturation>% <lightness>%
30
- * Example: --accent: 220 80% 55%;
29
+ * Values are full `oklch()` colors (e.g. `oklch(0.7 0.15 240)`).
30
+ * Any valid CSS color works too - `#hex`, `rgb(...)`, keywords -
31
+ * but `oklch()` is recommended for perceptually uniform mixing
32
+ * and consistent contrast. A converter such as
33
+ * https://oklch.com/ can help translate from hex/rgb.
31
34
  */
32
35
 
33
36
  /* ----------------------------------------------------------------
@@ -38,17 +41,19 @@ module Layered
38
41
  *
39
42
  * If your accent color needs a different text/icon color on
40
43
  * buttons (e.g. a pink accent with white button text in dark
41
- * mode), override --button-primary-text in Tier 2 below.
44
+ * mode), override --button-primary-text in Tier 2 below. To
45
+ * recolor only the icon (leaving button text unchanged),
46
+ * override --button-primary-icon instead.
42
47
  * ---------------------------------------------------------------- */
43
48
 
44
49
  :root {
45
- /* --accent: 0 0% 9%; */
46
- /* --accent-foreground: 0 0% 100%; */
50
+ /* --accent: oklch(0.2044 0 0); */
51
+ /* --accent-foreground: oklch(1 0 0); */
47
52
  }
48
53
 
49
54
  .dark {
50
- /* --accent: 0 0% 100%; */
51
- /* --accent-foreground: 0 0% 9%; */
55
+ /* --accent: oklch(1 0 0); */
56
+ /* --accent-foreground: oklch(0.2044 0 0); */
52
57
  }
53
58
 
54
59
  /* ----------------------------------------------------------------
@@ -59,47 +64,49 @@ module Layered
59
64
 
60
65
  /*
61
66
  :root {
62
- --background: 0 0% 100%;
63
- --foreground: 0 0% 13%;
64
- --foreground-muted: 0 0% 29%;
65
- --border: 0 0% 91%;
66
- --border-control: 0 0% 55%;
67
- --ring: 0 0% 13%;
68
- --surface: 0 0% 96%;
69
- --surface-highlighted: 0 0% 91%;
67
+ --background: oklch(1 0 0);
68
+ --foreground: oklch(0.2484 0 0);
69
+ --foreground-muted: oklch(0.4089 0 0);
70
+ --border: oklch(0.9312 0 0);
71
+ --border-control: oklch(0.6409 0 0);
72
+ --ring: oklch(0.2484 0 0);
73
+ --surface: oklch(0.9696 0 0);
74
+ --surface-highlighted: oklch(0.9312 0 0);
70
75
  --button-primary-bg: var(--accent);
71
76
  --button-primary-text: var(--accent-foreground);
72
- --danger: 0 72% 38%;
73
- --danger-light: 0 100% 97%;
74
- --danger-text: 0 72% 35%;
75
- --success-bg: 142 76% 65%;
76
- --success-text: 142 76% 13%;
77
- --warning-bg: 48 96% 65%;
78
- --warning-text: 48 96% 15%;
79
- --error-bg: 0 84% 75%;
80
- --error-text: 0 93% 12%;
77
+ --button-primary-icon: var(--button-primary-text);
78
+ --danger: oklch(0.47 0.1742 27.23);
79
+ --danger-light: oklch(0.9663 0.0166 17.44);
80
+ --danger-text: oklch(0.443 0.1634 27.14);
81
+ --success-bg: oklch(0.8395 0.1698 152.91);
82
+ --success-text: oklch(0.3088 0.0763 150.76);
83
+ --warning-bg: oklch(0.8908 0.1551 94.86);
84
+ --warning-text: oklch(0.3625 0.0732 93.12);
85
+ --error-bg: oklch(0.748 0.1306 20.64);
86
+ --error-text: oklch(0.2248 0.0874 28.11);
81
87
  }
82
88
 
83
89
  .dark {
84
- --background: 0 0% 0%;
85
- --foreground: 0 0% 89%;
86
- --foreground-muted: 0 0% 71%;
87
- --border: 0 0% 16%;
88
- --border-control: 0 0% 40%;
89
- --ring: 0 0% 89%;
90
- --surface: 0 0% 8%;
91
- --surface-highlighted: 0 0% 16%;
90
+ --background: oklch(0 0 0);
91
+ --foreground: oklch(0.9157 0 0);
92
+ --foreground-muted: oklch(0.7733 0 0);
93
+ --border: oklch(0.2801 0 0);
94
+ --border-control: oklch(0.5103 0 0);
95
+ --ring: oklch(0.9157 0 0);
96
+ --surface: oklch(0.193 0 0);
97
+ --surface-highlighted: oklch(0.2801 0 0);
92
98
  --button-primary-bg: var(--accent);
93
99
  --button-primary-text: var(--accent-foreground);
94
- --danger: 0 85% 60%;
95
- --danger-light: 0 93% 15%;
96
- --danger-text: 0 85% 64%;
97
- --success-bg: 142 76% 15%;
98
- --success-text: 142 76% 80%;
99
- --warning-bg: 48 96% 15%;
100
- --warning-text: 48 96% 80%;
101
- --error-bg: 0 93% 12%;
102
- --error-text: 0 84% 75%;
100
+ --button-primary-icon: var(--button-primary-text);
101
+ --danger: oklch(0.6362 0.2102 25.49);
102
+ --danger-light: oklch(0.2596 0.1021 28.32);
103
+ --danger-text: oklch(0.6607 0.1921 24.02);
104
+ --success-bg: oklch(0.3385 0.0852 150.45);
105
+ --success-text: oklch(0.8999 0.1022 155.94);
106
+ --warning-bg: oklch(0.3625 0.0732 93.12);
107
+ --warning-text: oklch(0.9336 0.1 95.79);
108
+ --error-bg: oklch(0.2248 0.0874 28.11);
109
+ --error-text: oklch(0.748 0.1306 20.64);
103
110
  }
104
111
  */
105
112
 
@@ -1,5 +1,5 @@
1
1
  module Layered
2
2
  module Ui
3
- VERSION = "0.6.0"
3
+ VERSION = "0.8.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.6.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - layered.ai