lostcoords-ui 0.4.1 → 0.6.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 +4 -4
- data/README.md +364 -96
- data/app/assets/tailwind/lostcoords/ui/avatar.css +6 -6
- data/app/assets/tailwind/lostcoords/ui/base.css +45 -0
- data/app/assets/tailwind/lostcoords/ui/card.css +23 -22
- data/app/assets/tailwind/lostcoords/ui/choice.css +39 -0
- data/app/assets/tailwind/lostcoords/ui/code-block.css +10 -0
- data/app/assets/tailwind/lostcoords/ui/{disclosure.css → collapsible.css} +6 -6
- data/app/assets/tailwind/lostcoords/ui/components/code-block.css +5 -0
- data/app/assets/tailwind/lostcoords/ui/components/collapsible.css +5 -0
- data/app/assets/tailwind/lostcoords/ui/components/dialog.css +9 -0
- data/app/assets/tailwind/lostcoords/ui/components/emoji-picker.css +5 -0
- data/app/assets/tailwind/lostcoords/ui/components/menu.css +5 -0
- data/app/assets/tailwind/lostcoords/ui/components/prose.css +3 -0
- data/app/assets/tailwind/lostcoords/ui/components/table.css +3 -0
- data/app/assets/tailwind/lostcoords/ui/components/toast.css +5 -0
- data/app/assets/tailwind/lostcoords/ui/components/tooltip.css +4 -0
- data/app/assets/tailwind/lostcoords/ui/components.css +12 -0
- data/app/assets/tailwind/lostcoords/ui/copy-button.css +9 -9
- data/app/assets/tailwind/lostcoords/ui/core.css +21 -0
- data/app/assets/tailwind/lostcoords/ui/dialog.css +17 -17
- data/app/assets/tailwind/lostcoords/ui/emoji-picker.css +86 -88
- data/app/assets/tailwind/lostcoords/ui/field.css +2 -2
- data/app/assets/tailwind/lostcoords/ui/glass.css +9 -8
- data/app/assets/tailwind/lostcoords/ui/layout.css +2 -2
- data/app/assets/tailwind/lostcoords/ui/popover.css +14 -14
- data/app/assets/tailwind/lostcoords/ui/prose.css +66 -0
- data/app/assets/tailwind/lostcoords/ui/sheet.css +62 -63
- data/app/assets/tailwind/lostcoords/ui/squircle.css +7 -27
- data/app/assets/tailwind/lostcoords/ui/table.css +51 -0
- data/app/assets/tailwind/lostcoords/ui/theme.css +209 -225
- data/app/assets/tailwind/lostcoords/ui/toast.css +23 -0
- data/app/assets/tailwind/lostcoords/ui/tooltip.css +51 -0
- data/app/assets/tailwind/lostcoords/ui/typography.css +31 -61
- data/app/assets/tailwind/lostcoords/ui/ui.css +2 -21
- data/app/assets/tailwind/lostcoords/ui/utilities.css +14 -22
- data/app/helpers/lostcoords/ui/badge_helper.rb +67 -110
- data/app/helpers/lostcoords/ui/button_helper.rb +44 -35
- data/app/helpers/lostcoords/ui/card_helper.rb +9 -52
- data/app/helpers/lostcoords/ui/choice_helper.rb +87 -0
- data/app/helpers/lostcoords/ui/code_block_helper.rb +22 -0
- data/app/helpers/lostcoords/ui/collapsible_helper.rb +9 -0
- data/app/helpers/lostcoords/ui/copy_button_helper.rb +7 -7
- data/app/helpers/lostcoords/ui/description_list_helper.rb +12 -0
- data/app/helpers/lostcoords/ui/dialog_helper.rb +15 -17
- data/app/helpers/lostcoords/ui/emoji_picker_helper.rb +6 -0
- data/app/helpers/lostcoords/ui/feedback_helper.rb +25 -6
- data/app/helpers/lostcoords/ui/form_helper.rb +36 -59
- data/app/helpers/lostcoords/ui/glass_helper.rb +7 -7
- data/app/helpers/lostcoords/ui/layout_helper.rb +13 -11
- data/app/helpers/lostcoords/ui/menu_helper.rb +45 -10
- data/app/helpers/lostcoords/ui/navigation_helper.rb +144 -0
- data/app/helpers/lostcoords/ui/primitives_helper.rb +39 -61
- data/app/helpers/lostcoords/ui/reading_helper.rb +2 -2
- data/app/helpers/lostcoords/ui/render_attributes_helper.rb +17 -1
- data/app/helpers/lostcoords/ui/sheet_helper.rb +7 -45
- data/app/helpers/lostcoords/ui/structures_helper.rb +26 -125
- data/app/helpers/lostcoords/ui/table_helper.rb +11 -0
- data/app/helpers/lostcoords/ui/tailwind_helper.rb +13 -4
- data/app/helpers/lostcoords/ui/toast_helper.rb +22 -0
- data/app/helpers/lostcoords/ui/tooltip_helper.rb +17 -0
- data/app/helpers/lostcoords/ui/typography_helper.rb +41 -11
- data/app/javascript/lostcoords/ui/controllers/lc_code_block_controller.js +23 -0
- data/app/javascript/lostcoords/ui/controllers/{disclosure_controller.js → lc_collapsible_controller.js} +4 -4
- data/app/javascript/lostcoords/ui/controllers/{confirm_dialog_controller.js → lc_confirm_dialog_controller.js} +4 -4
- data/app/javascript/lostcoords/ui/controllers/{modal_controller.js → lc_dialog_controller.js} +1 -1
- data/app/javascript/lostcoords/ui/controllers/{emoji_picker_controller.js → lc_emoji_picker_controller.js} +38 -10
- data/app/javascript/lostcoords/ui/controllers/lc_kbd_controller.js +12 -0
- data/app/javascript/lostcoords/ui/controllers/{row_menu_controller.js → lc_menu_controller.js} +25 -3
- data/app/javascript/lostcoords/ui/controllers/{ui_popover_controller.js → lc_popover_controller.js} +1 -1
- data/app/javascript/lostcoords/ui/controllers/{ui_selection_controller.js → lc_selection_controller.js} +7 -15
- data/app/javascript/lostcoords/ui/controllers/{sheet_controller.js → lc_sheet_controller.js} +17 -17
- data/app/javascript/lostcoords/ui/controllers/lc_shortcut_controller.js +45 -0
- data/app/javascript/lostcoords/ui/controllers/lc_tabs_controller.js +42 -0
- data/app/javascript/lostcoords/ui/controllers/{toast_controller.js → lc_toast_controller.js} +2 -2
- data/app/javascript/lostcoords/ui/controllers/lc_toast_region_controller.js +62 -0
- data/app/javascript/lostcoords/ui/controllers/lc_tooltip_controller.js +54 -0
- data/app/javascript/lostcoords/ui/helpers/catalog_picker.js +77 -25
- data/app/javascript/lostcoords/ui/helpers/context_dialog.js +6 -6
- data/app/javascript/lostcoords/ui/helpers/dialog.js +2 -2
- data/app/javascript/lostcoords/ui/helpers/dismiss_stack.js +30 -7
- data/app/javascript/lostcoords/ui/helpers/floating_panel.js +7 -8
- data/app/javascript/lostcoords/ui/helpers/menu_keys.js +19 -18
- data/app/javascript/lostcoords/ui/helpers/roving_focus.js +175 -0
- data/app/javascript/lostcoords/ui/helpers/sheet_motion.js +4 -4
- data/app/javascript/lostcoords/ui/helpers/shortcuts.js +162 -0
- data/app/javascript/lostcoords/ui/helpers/top_layer.js +48 -10
- data/app/javascript/lostcoords/ui/index.js +57 -0
- data/app/views/lostcoords/ui/components/_emoji_picker.html.erb +46 -46
- data/app/views/lostcoords/ui/components/_emoji_picker_grid.html.erb +3 -3
- data/app/views/lostcoords/ui/components/_lc_code_block.html.erb +18 -0
- data/app/views/lostcoords/ui/components/_lc_collapsible.html.erb +5 -0
- data/app/views/lostcoords/ui/components/_lc_dialog.html.erb +11 -8
- data/app/views/lostcoords/ui/components/_lc_floating_panel.html.erb +8 -0
- data/config/importmap.rb +10 -2
- data/config/locales/en.yml +23 -0
- data/config/locales/es.yml +23 -0
- data/config/locales/ja.yml +23 -0
- data/lib/lostcoords/ui/action_view.rb +6 -3
- data/lib/lostcoords/ui/builders.rb +2 -2
- data/lib/lostcoords/ui/form_builder.rb +126 -0
- data/lib/lostcoords/ui/parts.rb +154 -0
- data/lib/lostcoords/ui/stylesheets.rb +25 -0
- data/lib/lostcoords/ui/tokens.rb +24 -1
- data/lib/lostcoords/ui/version.rb +1 -1
- data/lib/tasks/lostcoords_ui.rake +11 -0
- metadata +54 -21
- data/app/assets/tailwind/lostcoords/ui/reading.css +0 -60
- data/app/views/lostcoords/ui/components/_form_alert.html.erb +0 -4
- data/app/views/lostcoords/ui/components/_lc_disclosure.html.erb +0 -5
- data/app/views/lostcoords/ui/components/_skeleton.html.erb +0 -4
- data/app/views/lostcoords/ui/components/_spinner.html.erb +0 -10
- data/app/views/lostcoords/ui/components/_ui_floating_panel.html.erb +0 -8
- data/config/helper_renames.json +0 -113
- data/script/migrate_helpers.rb +0 -136
- /data/app/javascript/lostcoords/ui/controllers/{ui_copy_controller.js → lc_copy_controller.js} +0 -0
- /data/app/javascript/lostcoords/ui/controllers/{ui_toggle_controller.js → lc_toggle_controller.js} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: be63d4a81a906b754a7dda9d321d5e0d79b45ac4ca18b39dc3e542d8b10a9822
|
|
4
|
+
data.tar.gz: 2073ae1b254f4f6aa61c4665bf1d3e4123d756b0bcfdb345ee1f5182452f6c14
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7c00c795e03e402e554532c542b4d6ac748b9efb61dad9e057b5698a99a70ac9f49671f211ce7fd467d5b2d12693d63d2243583f6bd94bd454da2cd24b77ba13
|
|
7
|
+
data.tar.gz: 9333e9c1cdf9a7e7a35ca00ad411be173578203af5c82deedd1f432e812361a9b01f22e74f5234aae75351a1e115e57cb1675b3b76239c6eae770a89106144d7
|
data/README.md
CHANGED
|
@@ -21,7 +21,7 @@ its gem version, so publishing a library update does not upgrade consumers.
|
|
|
21
21
|
## Install
|
|
22
22
|
|
|
23
23
|
```ruby
|
|
24
|
-
gem "lostcoords-ui", "~> 0.
|
|
24
|
+
gem "lostcoords-ui", "~> 0.6.0"
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
The engine adds its rendering helpers to host views, its JavaScript to the asset paths and its pins to
|
|
@@ -49,29 +49,52 @@ Standalone applications compile Tailwind and register Stimulus controllers throu
|
|
|
49
49
|
pipeline. `Lostcoords::Ui.root` locates the gem's source assets. Rails applications receive automatic
|
|
50
50
|
registration; use `require "lostcoords/ui/rails"` explicitly if Rails loads after the components.
|
|
51
51
|
|
|
52
|
-
###
|
|
52
|
+
### Standalone assets
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
your
|
|
54
|
+
Import `app/assets/tailwind/lostcoords/ui/components.css` from the Bundler-resolved gem root
|
|
55
|
+
into your Tailwind build. This entry includes component rules, default tokens and source scanning.
|
|
56
|
+
It does not set body styles, heading defaults, global inline-code styles or document corner radii.
|
|
57
|
+
Map the library's tokens to your app's theme and keep your Tailwind theme declarations after the import.
|
|
58
|
+
The full `ui.css` entry includes those document defaults and remains the Rails default.
|
|
59
|
+
|
|
60
|
+
Tailwind always ships component rules, used or not, and generates every utility the scanned helpers
|
|
61
|
+
mention. For a smaller build, import `core.css` and the opt-in components you render instead of
|
|
62
|
+
everything. Each entry carries the rules and scans the sources of its own component only. In Rails,
|
|
63
|
+
every Tailwind build writes stable paths for them next to the engine's own import:
|
|
56
64
|
|
|
57
65
|
```css
|
|
58
|
-
|
|
66
|
+
/* app/assets/tailwind/application.css, instead of ../builds/tailwind/lostcoords_ui.css */
|
|
67
|
+
@import "../builds/tailwind/lostcoords_ui/base.css";
|
|
68
|
+
@import "../builds/tailwind/lostcoords_ui/core.css";
|
|
69
|
+
@import "../builds/tailwind/lostcoords_ui/components/dialog.css";
|
|
70
|
+
@import "../builds/tailwind/lostcoords_ui/components/menu.css";
|
|
71
|
+
```
|
|
59
72
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
73
|
+
Outside Rails, import the same files from `app/assets/tailwind/lostcoords/ui/` in the gem.
|
|
74
|
+
`base.css` holds the document defaults that `ui.css` adds; skip it when the host owns its base styles.
|
|
75
|
+
`core.css` holds the tokens, buttons, badges, avatars, cards, alerts, form controls, choices,
|
|
76
|
+
toggles, layout, typography and navigation. The opt-in entries are `dialog` (with the phone sheet),
|
|
77
|
+
`menu` (menus and popovers), `toast`, `tooltip`, `collapsible`, `code-block`,
|
|
78
|
+
`emoji-picker`, `table` and `prose`. A component whose entry is missing renders unstyled.
|
|
63
79
|
|
|
64
|
-
|
|
80
|
+
Start one Stimulus application in the host, then register the controllers you use:
|
|
65
81
|
|
|
66
|
-
|
|
82
|
+
```javascript
|
|
83
|
+
import { Application } from "@hotwired/stimulus"
|
|
84
|
+
import { registerControllers } from "lostcoords/ui"
|
|
85
|
+
|
|
86
|
+
const application = Application.start()
|
|
87
|
+
registerControllers(application, { only: ["lc-copy", "lc-collapsible"] })
|
|
67
88
|
```
|
|
68
89
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
`
|
|
73
|
-
|
|
74
|
-
|
|
90
|
+
Resolve `lostcoords/ui/*` to the gem's `app/javascript/lostcoords/ui/*` and `@hotwired/stimulus` to
|
|
91
|
+
the host's installed package. `registerControllers` imports every controller, so a bundle carries
|
|
92
|
+
them all; to bundle only some, import them directly:
|
|
93
|
+
`import Dialog from "lostcoords/ui/controllers/lc_dialog_controller"` and
|
|
94
|
+
`application.register("lc-dialog", Dialog)`. Build configuration belongs to the host. The entry does not start
|
|
95
|
+
Stimulus or register anything on import. Omit `only` to register all library controllers. Register
|
|
96
|
+
defaults before application overrides. Repeated calls on the same application preserve later
|
|
97
|
+
overrides; unknown controller identifiers raise before registration.
|
|
75
98
|
|
|
76
99
|
The gem's stylesheets write into the `components` and `modules` layers, so the host declares that layer order.
|
|
77
100
|
The theme defines the `dark:` variant with `html[data-theme="dark"]`. `ui.css` carries its own `@source` lines, so Tailwind
|
|
@@ -79,36 +102,94 @@ scans the gem's helpers, views and JavaScript wherever the gem is installed.
|
|
|
79
102
|
|
|
80
103
|
### Theming
|
|
81
104
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
To customize the theme, add CSS variable overrides after the engine import:
|
|
105
|
+
Colors use [shadcn/ui](https://ui.shadcn.com/docs/theming) names, so a shadcn or tweakcn theme drops in.
|
|
106
|
+
Set `data-theme="dark"` on `<html>` for dark mode; your app owns the switch and saved preference.
|
|
107
|
+
Override any of these after the engine import:
|
|
87
108
|
|
|
88
109
|
```css
|
|
89
110
|
:root {
|
|
90
|
-
--
|
|
91
|
-
--
|
|
92
|
-
--
|
|
111
|
+
--primary: oklch(46% 0.14 155);
|
|
112
|
+
--radius: 0.625rem; /* every corner scales from this */
|
|
113
|
+
--lc-density: 0.875; /* semantic spacing and control heights */
|
|
93
114
|
}
|
|
94
115
|
|
|
95
116
|
html[data-theme="dark"] {
|
|
96
|
-
--
|
|
97
|
-
--sky-deep: oklch(70% 0.14 155);
|
|
98
|
-
--sky-soft: color-mix(in oklab, var(--sky) 18%, var(--paper));
|
|
117
|
+
--primary: oklch(75% 0.14 155);
|
|
99
118
|
}
|
|
100
119
|
```
|
|
101
120
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
`
|
|
105
|
-
|
|
121
|
+
| Setting | Default | Drives |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `--background` `--foreground` | white, near black | page and body text |
|
|
124
|
+
| `--card` `--card-foreground` | light gray | cards |
|
|
125
|
+
| `--popover` `--popover-foreground` | page background | menus, popovers, dialogs |
|
|
126
|
+
| `--primary` `--primary-foreground` | near black, white | primary actions, links, selection, focus |
|
|
127
|
+
| `--secondary` `--secondary-foreground` | gray | secondary buttons |
|
|
128
|
+
| `--muted` `--muted-foreground` | light gray, mid gray | subtle fills; secondary text, hints, placeholders |
|
|
129
|
+
| `--accent` `--accent-foreground` | gray | hovered rows and menu items, inline code |
|
|
130
|
+
| `--destructive` `--success` `--warning` | | status; soft fills such as `bg-success-soft` are generated |
|
|
131
|
+
| `--border` `--input` `--ring` | | dividers, input fills, focus ring |
|
|
132
|
+
| `--radius` | `0.5rem` | `rounded-sm` to `rounded-3xl` and `rounded-pill`; the default keeps Tailwind's own sizes |
|
|
133
|
+
| `--lc-density` | `1` | the semantic spacing and control heights below |
|
|
134
|
+
| `--lc-inset` | `1.25rem` | padding of cards, dialogs and popovers |
|
|
135
|
+
| `--font-sans` `--font-display` `--font-mono` | system | font families |
|
|
136
|
+
|
|
137
|
+
Defaults live in `app/assets/tailwind/lostcoords/ui/theme.css`. `Lostcoords::Ui::TOKENS` lists the
|
|
138
|
+
public colors and fonts. Library-internal settings use the `--lc-` prefix.
|
|
139
|
+
|
|
140
|
+
### Foundations
|
|
141
|
+
|
|
142
|
+
Components never set outer margin. Layout helpers own the space between things, and components pad
|
|
143
|
+
themselves from `--lc-inset`. Every token is a Tailwind utility:
|
|
144
|
+
|
|
145
|
+
| Spacing | Default | Use |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| `tight` | 4px | icon and label |
|
|
148
|
+
| `related` | 8px | label and control, button groups |
|
|
149
|
+
| `heading` | 12px | a heading and its content |
|
|
150
|
+
| `content` | 16px | blocks and fields |
|
|
151
|
+
| `inset` | `--lc-inset` | container padding and the gaps between its blocks |
|
|
152
|
+
| `section` | 32px | sections on a page |
|
|
153
|
+
|
|
154
|
+
Use them as `gap-related`, `p-inset`, `py-section` and so on. Setting `--lc-inset` on an element
|
|
155
|
+
changes the padding of every card or dialog inside it.
|
|
156
|
+
|
|
157
|
+
| Type role | Size / line height | Use |
|
|
158
|
+
| --- | --- | --- |
|
|
159
|
+
| `text-display` | 36 / 40px, bold | hero |
|
|
160
|
+
| `text-title` | 30 / 36px, bold | page title |
|
|
161
|
+
| `text-heading` | 20 / 28px, bold | section title |
|
|
162
|
+
| `text-subheading` | 18 / 24px, semibold | card and dialog titles |
|
|
163
|
+
| `text-body` | 16 / 24px | text |
|
|
164
|
+
| `text-small` | 14 / 20px | hints and secondary text |
|
|
165
|
+
| `text-label` | 14 / 20px, medium | labels, buttons, menu items |
|
|
166
|
+
| `text-caption` | 12 / 16px | metadata, table headers |
|
|
167
|
+
|
|
168
|
+
Each role sets size, line height, tracking and weight together. `lc-trim` trims the space above the
|
|
169
|
+
capital letters and below the baseline where the browser supports `text-box`.
|
|
170
|
+
|
|
171
|
+
Buttons, inputs, selects, toggles and icon buttons share heights: `h-control-sm` (32px),
|
|
172
|
+
`h-control-md` (40px) and `h-control-lg` (48px). On touch screens the small and medium sizes grow to
|
|
173
|
+
at least 40 and 44px. Containers use `max-w-page`, `max-w-reading` and `max-w-form`, and the page
|
|
174
|
+
container pads with `px-gutter`.
|
|
106
175
|
|
|
107
176
|
### Importmap
|
|
108
177
|
|
|
109
|
-
The engine pins its modules under
|
|
110
|
-
`
|
|
111
|
-
|
|
178
|
+
The engine pins its modules under `lostcoords/ui/*`. Controllers are also pinned under the host's
|
|
179
|
+
`controllers/*` key with an `lc_` prefix, so Rails' controller loading registers them as `lc-dialog`,
|
|
180
|
+
`lc-menu`, `lc-copy` and so on. Load them lazily, so a page downloads only the controllers it uses,
|
|
181
|
+
the first time their `data-controller` appears:
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
// app/javascript/controllers/index.js
|
|
185
|
+
import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
|
|
186
|
+
import { application } from "controllers/application"
|
|
187
|
+
|
|
188
|
+
lazyLoadControllersFrom("controllers", application)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`eagerLoadControllersFrom` also works and downloads all of them on every page. A host file with the
|
|
192
|
+
same name, such as `app/javascript/controllers/lc_dialog_controller.js`, replaces the gem's.
|
|
112
193
|
|
|
113
194
|
## Components
|
|
114
195
|
|
|
@@ -117,7 +198,17 @@ in its code panel. The API reference reads signatures from the helper definition
|
|
|
117
198
|
[API JSON](https://ui.lostcoords.com/api.json) and [llms.txt](https://ui.lostcoords.com/llms.txt)
|
|
118
199
|
include those signatures and the runnable examples.
|
|
119
200
|
|
|
120
|
-
Buttons use `primary`, `secondary`, `ghost` or `destructive`, with `sm`, `
|
|
201
|
+
Buttons use `primary`, `secondary`, `outline`, `ghost`, `glass` or `destructive`, with `sm`, `md` or `lg` sizes.
|
|
202
|
+
Primary, secondary and destructive buttons have visible filled surfaces. Ghost buttons and the
|
|
203
|
+
`lc_icon_button` toolbar action are transparent at rest and show their full shape on hover.
|
|
204
|
+
Primary, secondary and destructive buttons are flat. Secondary buttons use a soft neutral fill distinct from page and card backgrounds.
|
|
205
|
+
Outline buttons have a transparent fill and a visible edge. Glass buttons use the shared translucent material, rim and shadow for floating controls.
|
|
206
|
+
The default light theme uses white pages and softly shaded cards, with no visible card borders or resting shadows.
|
|
207
|
+
Popover triggers accept `trigger_variant` using the same button variants.
|
|
208
|
+
Button hover and press fills mix 94% of the base background with 6% of its foreground in OKLab.
|
|
209
|
+
Ghost and icon buttons stay transparent at rest and use the secondary base for that calculation.
|
|
210
|
+
Apps can override `--secondary` for the neutral base, or `--lc-button-bg` and `--lc-button-ink` on individual buttons.
|
|
211
|
+
Inputs use `--input` and `--lc-input-hover`.
|
|
121
212
|
`lc_button_to` preserves Rails' form, HTTP method and CSRF behavior. Block helpers capture ERB content.
|
|
122
213
|
Use `icon: "plus"` for a leading Heroicon or `icon_position: :end` for a trailing one. Custom icons and
|
|
123
214
|
spinners use `data-icon="inline-start"` or `data-icon="inline-end"`; buttons adjust that edge's padding.
|
|
@@ -137,6 +228,188 @@ theme tokens to restyle the library. `lc_field` yields the input's `id` and vali
|
|
|
137
228
|
labels, hints and errors stay connected. Linked cards use `lc_card(href: ...)`; cards containing
|
|
138
229
|
buttons or fields remain ordinary containers.
|
|
139
230
|
|
|
231
|
+
`lc_table` renders a native table with a shaded header and subtle row dividers. Supply the caption, header cells and body in its block.
|
|
232
|
+
Wrap wide tables in an app-owned horizontal scroll region with an accessible name and keyboard focus.
|
|
233
|
+
Use `lc_table_class` when an existing table renderer owns the markup.
|
|
234
|
+
|
|
235
|
+
Cards share one API: `lc_card(padding: :md)`, with `:sm` and `:none` for tighter or custom spacing. Padding sizes set `--lc-inset`, so content inside follows the card.
|
|
236
|
+
Inputs keep their `--input` fill inside cards; set `--lc-field-bg` to change it in one context. Cards provide avatar cutouts and a validation border when they contain errors. Fills that are muted on the page switch so they stay visible on the card: choice tiles, alerts, neutral badges and skeletons take the page background (`--lc-tile-bg`), and toggle group and tab tracks take the accent fill (`--lc-track-bg`). Set either variable to apply the same context to your own muted surface.
|
|
237
|
+
Add `class: "@container"` when a card owns its width and its children use container queries.
|
|
238
|
+
Use `--lc-card-bg`, `--lc-card-border`, `--lc-card-radius` and `--lc-card-shadow` for local appearance overrides.
|
|
239
|
+
|
|
240
|
+
`lc_badge` handles labels, counts and status. Use `class: "rounded-full"` for a rounded status label.
|
|
241
|
+
`lc_icon_badge` handles decorative icon containers, with `shape: :square` or `:circle` and `sm`, `md`, `lg` or `xl` sizes.
|
|
242
|
+
Badge, icon badge, Alert and Toast share `neutral`, `primary`, `success`, `warning` and `destructive` tones.
|
|
243
|
+
|
|
244
|
+
`lc_toggle` renders a pressed button. Use `lc_toggle_group` with `lc_toggle_group_item` for mutually exclusive
|
|
245
|
+
choices and a native submitted value. Navigation uses `lc_button_link_to` and `aria-current`, so links keep their native behavior.
|
|
246
|
+
`lc_collapsible` expands content through a native `<details>` element. `lc_alert` renders persistent inline feedback;
|
|
247
|
+
`lc_toast` adds timed dismissal.
|
|
248
|
+
|
|
249
|
+
### Parts and slots
|
|
250
|
+
|
|
251
|
+
Compound components yield a builder, so their parts are scoped and discoverable. A card stacks its
|
|
252
|
+
parts with the same gap it pads with:
|
|
253
|
+
|
|
254
|
+
```erb
|
|
255
|
+
<%= lc_card do |card| %>
|
|
256
|
+
<%= card.header title: "Members", description: "People in this workspace" do %>
|
|
257
|
+
<%= lc_button "Invite", size: :sm %>
|
|
258
|
+
<% end %>
|
|
259
|
+
<%= card.content do %>…<% end %>
|
|
260
|
+
<%= card.footer do %><%= lc_button "Save" %><% end %>
|
|
261
|
+
<% end %>
|
|
262
|
+
|
|
263
|
+
<%= lc_alert "Your card was declined.", title: "Payment failed" do |alert| %>
|
|
264
|
+
<%= alert.actions do %><%= lc_button "Update payment", size: :sm %><% end %>
|
|
265
|
+
<% end %>
|
|
266
|
+
|
|
267
|
+
<%= lc_dialog id: "new-project", title: "Create project", description: "Projects group pages." do |dialog| %>
|
|
268
|
+
…
|
|
269
|
+
<%= dialog.footer do %><%= dialog.close %><%= lc_button "Create" %><% end %>
|
|
270
|
+
<% end %>
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Every component root and part carries `data-slot`, plus `data-variant`, `data-size` or `data-tone`
|
|
274
|
+
where they apply, so a context can restyle parts without matching utility classes:
|
|
275
|
+
`[data-slot=card-footer] { justify-content: start }`.
|
|
276
|
+
|
|
277
|
+
### Forms
|
|
278
|
+
|
|
279
|
+
`lc_form_with` is `form_with` with `Lostcoords::Ui::FormBuilder`. Standard helpers keep their Rails
|
|
280
|
+
signatures and render library controls; `field` adds the label, hint and the attribute's errors, and
|
|
281
|
+
sets `aria-invalid` on the control. Rails' `field_with_errors` wrapper does not affect the layout.
|
|
282
|
+
|
|
283
|
+
```erb
|
|
284
|
+
<%= lc_form_with model: @project, class: "flex flex-col gap-content" do |form| %>
|
|
285
|
+
<%= form.field :name, hint: "Shown to members" %>
|
|
286
|
+
<%= form.field :email, as: :email_field %>
|
|
287
|
+
<%= form.switch :public %>
|
|
288
|
+
<%= form.submit "Save project" %>
|
|
289
|
+
<% end %>
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
A symbol `size:` such as `size: :sm` picks the control height; an integer still sets the HTML
|
|
293
|
+
attribute. Pass `builder: Lostcoords::Ui::FormBuilder` to `form_with` directly, or call `lc_field`
|
|
294
|
+
with `error: record.errors.full_messages_for(:name)` when you keep your own builder.
|
|
295
|
+
|
|
296
|
+
`lc_checkbox`, `lc_radio` and `lc_switch` render native inputs with a label and optional hint.
|
|
297
|
+
Checkboxes and switches submit an unchecked value like Rails' `check_box`; pass `unchecked_value: nil`
|
|
298
|
+
to omit it. `lc_choice_group` groups them in a fieldset with a legend, hint and error.
|
|
299
|
+
|
|
300
|
+
### Navigation and overlays
|
|
301
|
+
|
|
302
|
+
```erb
|
|
303
|
+
<%= lc_breadcrumb [ [ "Projects", projects_path ], @project.name ] %>
|
|
304
|
+
|
|
305
|
+
<%= lc_tabs id: "project-tabs", label: "Project" do |tabs| %>
|
|
306
|
+
<% tabs.panel "Overview" do %>…<% end %>
|
|
307
|
+
<% tabs.panel "Activity", value: :activity do %>…<% end %>
|
|
308
|
+
<% end %>
|
|
309
|
+
|
|
310
|
+
<%= lc_tooltip "Copy a link", id: "copy-tip" do |tip| %>
|
|
311
|
+
<%= lc_icon_button "Copy link", icon: "link", **tip %>
|
|
312
|
+
<% end %>
|
|
313
|
+
|
|
314
|
+
<%= lc_description_list do |list| %>
|
|
315
|
+
<%= list.item "Owner", @project.owner.name %>
|
|
316
|
+
<%= list.item("Plan") { lc_badge @project.plan } %>
|
|
317
|
+
<% end %>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Tabs follow the ARIA tabs pattern with arrow key, Home and End navigation, and dispatch
|
|
321
|
+
`lc-tabs:change`. `orientation: :vertical` stacks the tabs beside their panels and moves with Arrow Up
|
|
322
|
+
and Down; `activation: :manual` moves focus with the arrows and selects with Enter or Space. Tooltips show on hover and keyboard focus, Escape hides them, and they describe
|
|
323
|
+
their trigger, in the top layer; keep essential information visible. Description lists stack on phones and use two
|
|
324
|
+
columns from `sm`.
|
|
325
|
+
|
|
326
|
+
```erb
|
|
327
|
+
<%= lc_skip_link %>
|
|
328
|
+
|
|
329
|
+
<%= lc_nav_list label: "Settings" do |nav| %>
|
|
330
|
+
<%= nav.group "Workspace" do %>
|
|
331
|
+
<%= nav.link "General", settings_path, current: current_page?(settings_path) %>
|
|
332
|
+
<%= nav.link "Members", members_path %>
|
|
333
|
+
<% end %>
|
|
334
|
+
<% end %>
|
|
335
|
+
|
|
336
|
+
<%= lc_pager previous: [ "Install", install_path ], next: [ "Theming", theming_path ] %>
|
|
337
|
+
|
|
338
|
+
Read the <%= lc_link "guide", guide_path %>.
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
`lc_nav_list` marks the current link with `aria-current="page"`; `compact: true` is the quieter
|
|
342
|
+
style for an "On this page" list, and `indent: true` nests a link. `lc_pager` takes `[title, url]`
|
|
343
|
+
for each side and `compact: true` for icon buttons. `lc_link` has `inherit`, `muted` and `primary`
|
|
344
|
+
tones; `lc_link_class` styles links you render yourself. `lc_skip_link` targets `#main` by default.
|
|
345
|
+
Pass `card: true` to `lc_radio` or `lc_checkbox` for selectable tiles; a block adds content, such as a
|
|
346
|
+
preview, under the label.
|
|
347
|
+
|
|
348
|
+
This documentation site is built with these components and two copyable blocks: the application
|
|
349
|
+
header and the documentation layout.
|
|
350
|
+
|
|
351
|
+
`lc_dialog` handles modal content and the mobile sheet layout. Set `detents: "medium large"` or `"large"`
|
|
352
|
+
to choose mobile height stops; the default is `"fit"`. Icon buttons, avatar groups, motion and mobile dialogs
|
|
353
|
+
appear with their parent component examples.
|
|
354
|
+
|
|
355
|
+
### Keyboard
|
|
356
|
+
|
|
357
|
+
Every interactive component works from the keyboard without extra code:
|
|
358
|
+
|
|
359
|
+
| Component | Keys |
|
|
360
|
+
|---|---|
|
|
361
|
+
| Menu | Arrow Down or Up on the button opens on the first or last item. Arrows move and wrap, Home and End jump, a letter jumps to the next item that starts with it, Enter or Space activates, Escape closes and returns focus. |
|
|
362
|
+
| Tabs | Arrows along the tab list's orientation, Home and End. Automatic tabs select on focus; manual tabs on Enter or Space. |
|
|
363
|
+
| Toggle group | One Tab stop. All four arrows move and select, wrapping; Left and Right follow the text direction. |
|
|
364
|
+
| Emoji picker | Arrow Down from the search enters the grid, arrows move through it by row, Arrow Up from the top row returns to the search, and Enter in the search picks the best match. The grid is one Tab stop. |
|
|
365
|
+
| Dialogs, sheets, popovers, menus, tooltips | Escape closes the topmost one and returns focus to what opened it; an open tooltip closes before the menu or dialog around it. Escape in a search field with text clears it first. |
|
|
366
|
+
|
|
367
|
+
Page-wide shortcuts focus a field or press a button. Merge `lc_shortcut_data` into the element's data and
|
|
368
|
+
show the keys with `lc_kbd`:
|
|
369
|
+
|
|
370
|
+
```erb
|
|
371
|
+
<%= lc_input type: :search, name: "q", aria: { label: "Search" }, data: lc_shortcut_data("mod+k") %>
|
|
372
|
+
<%= lc_button data: lc_shortcut_data("n", action: "projects#new") do %>
|
|
373
|
+
New project <%= lc_kbd "n", aria: { hidden: true } %>
|
|
374
|
+
<% end %>
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Keys are joined with `+`: `mod` is ⌘ on Apple platforms and Ctrl elsewhere, and `ctrl`, `alt`, `shift`
|
|
378
|
+
and `meta` name the others. Separate alternatives with spaces. The element announces its keys through
|
|
379
|
+
`aria-keyshortcuts`. Shortcuts without `mod`, `ctrl` or `alt` don't fire while typing in a field, only
|
|
380
|
+
shortcuts inside an open modal dialog respond, and when two visible elements share keys the first wins
|
|
381
|
+
and the console warns. `lc_kbd` renders the Ctrl form and switches to Apple symbols once JavaScript runs.
|
|
382
|
+
|
|
383
|
+
Custom widgets can use the same navigation: `navigate(event, items, { orientation, wrap, typeahead })`
|
|
384
|
+
from `lostcoords/ui/helpers/roving_focus` handles vertical, horizontal and grid layouts, right-to-left
|
|
385
|
+
text, Home and End, and typeahead; `rove(items, current)` keeps a single Tab stop.
|
|
386
|
+
|
|
387
|
+
### Layers
|
|
388
|
+
|
|
389
|
+
Overlays never need a z-index. Dialogs and sheets open as modal `<dialog>` elements; menus,
|
|
390
|
+
popovers, pickers and tooltips move into the browser's top layer while they are open; toasts go in
|
|
391
|
+
`lc_toast_region`, which does the same. The top layer paints above every z-index, `overflow` clip
|
|
392
|
+
and stacking context on the page, so a sticky header, a `transform` or a glass `backdrop-filter`
|
|
393
|
+
can't cover them. A modal dialog makes the rest of the page inert, so while one is open the toast
|
|
394
|
+
region moves inside it and back when it closes. The region is the live region that announces its
|
|
395
|
+
toasts; destructive toasts are alerts. Where the Popover API is missing overlays stay in place,
|
|
396
|
+
ordered by `--lc-z-popover`, `--lc-z-overlay` and `--lc-z-toast`.
|
|
397
|
+
|
|
398
|
+
```erb
|
|
399
|
+
<%# In the layout, once %>
|
|
400
|
+
<%= lc_toast_region id: "toasts" do %>
|
|
401
|
+
<% flash.each do |type, message| %><%= lc_toast message, tone: type == "alert" ? :destructive : :success %><% end %>
|
|
402
|
+
<% end %>
|
|
403
|
+
|
|
404
|
+
<%# From a controller or job %>
|
|
405
|
+
<%= turbo_stream.append "toasts" do %><%= lc_toast "Project saved." %><% end %>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Two in-page layers remain: `z-sticky` keeps app chrome such as a sticky header above content, and
|
|
409
|
+
`z-raised` lifts an element over its neighbours. Put `isolate` on the main content area, so any z-index
|
|
410
|
+
inside it stays below the chrome. Tailwind drops a `z-*` class it can't resolve without a warning, so
|
|
411
|
+
use these two names, a number or `z-(--a-defined-variable)`.
|
|
412
|
+
|
|
140
413
|
## Copy feedback and motion
|
|
141
414
|
|
|
142
415
|
```erb
|
|
@@ -157,17 +430,31 @@ Default labels are translated in English, Japanese and Spanish. Use `label` (the
|
|
|
157
430
|
`copied_label:` and `error_label:` to customize visible text, and `aria: { label: ... }` for a contextual name.
|
|
158
431
|
Normal button variants, sizes, classes, disabled state and attributes are supported.
|
|
159
432
|
|
|
160
|
-
The component emits bubbling `
|
|
161
|
-
from its wrapper. Listen on an ancestor to connect application behavior.
|
|
162
|
-
|
|
433
|
+
The component emits bubbling `lc-copy:copied` (`detail.text`) and `lc-copy:error` (`detail.error`) events
|
|
434
|
+
from its wrapper. Listen on an ancestor to connect application behavior.
|
|
435
|
+
|
|
436
|
+
```erb
|
|
437
|
+
<%= lc_code_block "puts 'Hello'", id: "ruby-example", language: :ruby %>
|
|
438
|
+
<%= lc_code_block source, id: "file-example", language: :ruby, title: "app/helpers/greeting_helper.rb" %>
|
|
439
|
+
<%= lc_code_block source, id: "long-example", language: :ruby, max_lines: 5 %>
|
|
440
|
+
```
|
|
163
441
|
|
|
164
|
-
|
|
165
|
-
|
|
442
|
+
Code blocks escape plain source, preserve whitespace, and include a floating icon-only copy button.
|
|
443
|
+
The copy control appears on hover or keyboard focus and stays visible on touch devices and during copy feedback.
|
|
444
|
+
Snippets have no header by default; use `title:` for a compact filename or heading. `language:` sets code metadata
|
|
445
|
+
without adding a visible label. Snippets longer
|
|
446
|
+
than `max_lines:` (10 by default) can expand and collapse; use `max_lines: nil` to show all lines.
|
|
447
|
+
Copy failures expand clipped source for manual selection. Labels are translated in English, Japanese and Spanish.
|
|
448
|
+
An optional block receives the raw source and can return highlighted markup from the app's syntax highlighter.
|
|
449
|
+
For selective JavaScript registration, include both `lc-code-block` and `lc-copy`.
|
|
450
|
+
|
|
451
|
+
Buttons include hover and press feedback. Override `--lc-motion-quick` (140ms), `--lc-motion-control` (180ms),
|
|
452
|
+
`--lc-motion-feedback` (160ms), `--lc-press-scale` (0.96) and `--lc-ease-out` in your theme or on a container.
|
|
166
453
|
Reduced motion removes control movement and makes copy feedback immediate. Your application owns the
|
|
167
454
|
pending, success and failure states of network actions such as saving a form.
|
|
168
455
|
|
|
169
456
|
[Try the copy button](https://ui.lostcoords.com/components/copy_button.html) ·
|
|
170
|
-
[Motion reference](https://ui.lostcoords.com/components/
|
|
457
|
+
[Motion reference](https://ui.lostcoords.com/components/foundations.html#motion)
|
|
171
458
|
|
|
172
459
|
### Icons
|
|
173
460
|
|
|
@@ -185,18 +472,17 @@ Pass SVG attributes through `options:` and existing path attributes through `pat
|
|
|
185
472
|
|
|
186
473
|
### Typography and layout
|
|
187
474
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
blocks keep their block styling.
|
|
475
|
+
Heading level controls document structure independently of its visual size. Layout parents own the
|
|
476
|
+
spacing between children, including fields. Inline `<code>` elements get a shared monospace style;
|
|
477
|
+
`<pre><code>` blocks keep their block styling.
|
|
192
478
|
|
|
193
479
|
```erb
|
|
194
480
|
<%= lc_stack gap: :section do %>
|
|
195
|
-
<%= lc_heading "Workspace", level: 1, size: :
|
|
481
|
+
<%= lc_heading "Workspace", level: 1, size: :title %>
|
|
196
482
|
<%= lc_section title: "Members" do %>
|
|
197
483
|
<%= lc_card do %>
|
|
198
484
|
<%= lc_stack gap: :related do %>
|
|
199
|
-
<%= lc_heading "Design team", level: 3, size: :
|
|
485
|
+
<%= lc_heading "Design team", level: 3, size: :subheading %>
|
|
200
486
|
<%= lc_text "Three people share this workspace.", tone: :muted %>
|
|
201
487
|
<% end %>
|
|
202
488
|
<% end %>
|
|
@@ -204,16 +490,12 @@ blocks keep their block styling.
|
|
|
204
490
|
<% end %>
|
|
205
491
|
```
|
|
206
492
|
|
|
207
|
-
Heading sizes are `
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
`
|
|
212
|
-
|
|
213
|
-
Fonts and colours come from the shared theme and your app's overrides. Optional custom properties override the shared defaults:
|
|
214
|
-
`--ui-space-section`, `--ui-heading-page-size`, `--ui-heading-page-line-height`, `--ui-page-max`,
|
|
215
|
-
`--ui-gutter` and `--ui-reading-measure`. Set them in the host theme or on a container. Japanese headings
|
|
216
|
-
inherit `lang="ja"` and use natural letter spacing.
|
|
493
|
+
Heading sizes are `display`, `title`, `heading` and `subheading`. Text sizes are `body`, `small`,
|
|
494
|
+
`label` and `caption`, with `default` and `muted` tones. Pass `trim: true` to trim the text box.
|
|
495
|
+
Stacks and inline groups take the spacing names from [Foundations](#foundations). `lc_section` leaves
|
|
496
|
+
`heading` below its title and `content` between blocks. `lc_container` provides `page`, `reading` and
|
|
497
|
+
`form` widths; only the page container adds gutters. Japanese headings inherit `lang="ja"` and use
|
|
498
|
+
natural letter spacing.
|
|
217
499
|
|
|
218
500
|
[Browse the foundations examples](https://ui.lostcoords.com/components/foundations.html).
|
|
219
501
|
|
|
@@ -237,7 +519,7 @@ Rails' normal escaping rules; sanitise rendered user content before marking it s
|
|
|
237
519
|
<% end %>
|
|
238
520
|
```
|
|
239
521
|
|
|
240
|
-
Override `--
|
|
522
|
+
Override `--lc-reading-size`, `--lc-reading-leading`, `--lc-reading-flow` and `--lc-reading-measure`
|
|
241
523
|
to tune a reading context. Use `not-prose` for embedded components.
|
|
242
524
|
|
|
243
525
|
### Class helpers
|
|
@@ -254,23 +536,20 @@ Class helpers remain available for custom markup. The application owns its seman
|
|
|
254
536
|
Generated by `bin/rails lostcoords:ui:builders`; `bin/lint` checks this list against the style helpers.
|
|
255
537
|
|
|
256
538
|
<!-- builders -->
|
|
257
|
-
- `lc_icon_badge_class(size: :
|
|
258
|
-
- `
|
|
259
|
-
- `lc_avatar_class(size: :base, ink: false, linked: false, extra: nil)` (BadgeHelper)
|
|
539
|
+
- `lc_icon_badge_class(size: :md, shape: :square, tone: :neutral, extra: nil)` (BadgeHelper)
|
|
540
|
+
- `lc_avatar_class(size: :md, ink: false, linked: false, extra: nil)` (BadgeHelper)
|
|
260
541
|
- `lc_avatar_stack_class(compact: false, extra: nil)` (BadgeHelper)
|
|
261
542
|
- `lc_avatar_stack_row_class(extra: nil)` (BadgeHelper)
|
|
262
|
-
- `lc_eyebrow_class(extra: nil)` (BadgeHelper)
|
|
263
543
|
- `lc_badge_class(tone: :neutral, extra: nil)` (BadgeHelper)
|
|
264
|
-
- `
|
|
265
|
-
- `
|
|
266
|
-
- `
|
|
267
|
-
- `
|
|
268
|
-
- `
|
|
269
|
-
- `
|
|
270
|
-
- `
|
|
271
|
-
- `
|
|
544
|
+
- `lc_toggle_class(active: false, ghost: false, size: :md, extra: nil)` (BadgeHelper)
|
|
545
|
+
- `lc_button_class(variant: :primary, size: :md, block: false, extra: nil)` (ButtonHelper)
|
|
546
|
+
- `lc_icon_button_class(shape: :square, size: :md, extra: nil)` (ButtonHelper)
|
|
547
|
+
- `lc_card_class(interactive: false, padding: :md, extra: nil)` (CardHelper)
|
|
548
|
+
- `lc_choice_label_class(card: false, extra: nil)` (ChoiceHelper)
|
|
549
|
+
- `lc_checkbox_class(extra: nil)` (ChoiceHelper)
|
|
550
|
+
- `lc_radio_class(extra: nil)` (ChoiceHelper)
|
|
551
|
+
- `lc_switch_class(extra: nil)` (ChoiceHelper)
|
|
272
552
|
- `lc_dialog_class(kind = :modal, extra: nil)` (DialogHelper)
|
|
273
|
-
- `lc_dialog_surface_class(extra: nil)` (DialogHelper)
|
|
274
553
|
- `lc_emoji_picker_groups` (EmojiPickerHelper)
|
|
275
554
|
- `lc_emoji_picker_count` (EmojiPickerHelper)
|
|
276
555
|
- `lc_emoji_picker_version` (EmojiPickerHelper)
|
|
@@ -278,20 +557,18 @@ Generated by `bin/rails lostcoords:ui:builders`; `bin/lint` checks this list aga
|
|
|
278
557
|
- `lc_emoji_picker_search_name(emoji)` (EmojiPickerHelper)
|
|
279
558
|
- `lc_emoji_picker_search_labels(emoji)` (EmojiPickerHelper)
|
|
280
559
|
- `lc_emoji_picker_toneable?(emoji)` (EmojiPickerHelper)
|
|
281
|
-
- `
|
|
560
|
+
- `lc_alert_class(extra: nil)` (FeedbackHelper)
|
|
561
|
+
- `lc_alert_icon(tone: :destructive)` (FeedbackHelper)
|
|
562
|
+
- `lc_spinner_class(size: :md, extra: nil)` (FeedbackHelper)
|
|
282
563
|
- `lc_skeleton_class(extra: nil)` (FeedbackHelper)
|
|
283
564
|
- `lc_empty_state_class(extra: nil)` (FeedbackHelper)
|
|
284
|
-
- `
|
|
285
|
-
- `
|
|
286
|
-
- `lc_input_class(size: :
|
|
287
|
-
- `
|
|
288
|
-
- `lc_select_class(size: :base, extra: nil)` (FormHelper)
|
|
565
|
+
- `lc_toggle_group_class(extra: nil)` (FormHelper)
|
|
566
|
+
- `lc_toggle_group_item_class(active: false, extra: nil)` (FormHelper)
|
|
567
|
+
- `lc_input_class(size: :md, extra: nil)` (FormHelper)
|
|
568
|
+
- `lc_select_class(size: :md, extra: nil)` (FormHelper)
|
|
289
569
|
- `lc_textarea_class(extra: nil)` (FormHelper)
|
|
290
570
|
- `lc_field_class(extra: nil)` (FormHelper)
|
|
291
571
|
- `lc_field_label_class(extra: nil)` (FormHelper)
|
|
292
|
-
- `lc_form_actions_class(extra: nil)` (FormHelper)
|
|
293
|
-
- `lc_form_alert_class(extra: nil)` (FormHelper)
|
|
294
|
-
- `lc_form_alert_icon(tone: :error)` (FormHelper)
|
|
295
572
|
- `lc_glass_class(shape: :bar, thick: false, extra: nil)` (GlassHelper)
|
|
296
573
|
- `lc_stack_class(gap: :content, extra: nil)` (LayoutHelper)
|
|
297
574
|
- `lc_inline_class(gap: :related, extra: nil)` (LayoutHelper)
|
|
@@ -300,16 +577,16 @@ Generated by `bin/rails lostcoords:ui:builders`; `bin/lint` checks this list aga
|
|
|
300
577
|
- `lc_popover_class(align: :end, extra: nil)` (MenuHelper)
|
|
301
578
|
- `lc_menu_popover_class(align: :end, extra: nil)` (MenuHelper)
|
|
302
579
|
- `lc_menu_option_class(tone: :default, extra: nil)` (MenuHelper)
|
|
580
|
+
- `lc_link_class(tone: :inherit, extra: nil)` (NavigationHelper)
|
|
581
|
+
- `lc_nav_link_class(compact: false, extra: nil)` (NavigationHelper)
|
|
303
582
|
- `lc_prose_class(extra: nil)` (ReadingHelper)
|
|
304
583
|
- `lc_sheet_data(data = {}, detents: "fit")` (SheetHelper)
|
|
305
|
-
- `
|
|
306
|
-
- `lc_sheet_row_label_class(extra: nil)` (SheetHelper)
|
|
307
|
-
- `lc_sheet_chip_class(active: false, member: false, extra: nil)` (SheetHelper)
|
|
308
|
-
- `lc_sheet_datetime_input_class(extra: nil)` (SheetHelper)
|
|
309
|
-
- `lc_sheet_text_input_class(extra: nil)` (SheetHelper)
|
|
584
|
+
- `lc_table_class(extra: nil)` (TableHelper)
|
|
310
585
|
- `lc_tw(*classes)` (TailwindHelper)
|
|
311
|
-
- `lc_heading_class(size: :
|
|
312
|
-
- `lc_text_class(size: :body, tone: :default, extra: nil)` (TypographyHelper)
|
|
586
|
+
- `lc_heading_class(size: :heading, trim: false, extra: nil)` (TypographyHelper)
|
|
587
|
+
- `lc_text_class(size: :body, tone: :default, trim: false, extra: nil)` (TypographyHelper)
|
|
588
|
+
- `lc_kbd_class(extra: nil)` (TypographyHelper)
|
|
589
|
+
- `lc_shortcut_data(keys, data = {})` (TypographyHelper)
|
|
313
590
|
<!-- /builders -->
|
|
314
591
|
|
|
315
592
|
## Blocks
|
|
@@ -339,14 +616,5 @@ bin/test
|
|
|
339
616
|
bin/lint
|
|
340
617
|
```
|
|
341
618
|
|
|
342
|
-
The helper migration tool updates Ruby calls, ERB code, and Ruby/ERB Markdown examples to the `lc_`
|
|
343
|
-
namespace. Run it in a consumer checkout to preview changes, then add `--write` to apply them.
|
|
344
|
-
Review dynamic method names stored in strings separately.
|
|
345
|
-
|
|
346
|
-
```sh
|
|
347
|
-
ruby "$(bundle show lostcoords-ui)/script/migrate_helpers.rb" .
|
|
348
|
-
ruby "$(bundle show lostcoords-ui)/script/migrate_helpers.rb" . --write
|
|
349
|
-
```
|
|
350
|
-
|
|
351
619
|
The icon catalog and its MIT license live in `vendor/heroicons`. Regenerate them from the pinned
|
|
352
620
|
upstream archive with `ruby bin/update-icons`.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/* A linked avatar's ring draws inside its own footprint, so it takes exactly the space of an
|
|
2
2
|
unlinked one: the outline sits on the edge, over any cutout border, and the inset shadow
|
|
3
3
|
paints the gap in the surface colour. Contexts that already cut the avatar out with a
|
|
4
|
-
border set --avatar-ring-inset (or --avatar-ring-gap) so the gap doesn't double up. */
|
|
5
|
-
@utility avatar-ring {
|
|
6
|
-
--avatar-ring: clamp(1.5px, calc(var(--avatar-size, var(--avatar-size-default, --spacing(8))) * 0.06), 3px);
|
|
4
|
+
border set --lc-avatar-ring-inset (or --lc-avatar-ring-gap) so the gap doesn't double up. */
|
|
5
|
+
@utility lc-avatar-ring {
|
|
6
|
+
--lc-avatar-ring: clamp(1.5px, calc(var(--lc-avatar-size, var(--lc-avatar-size-default, --spacing(8))) * 0.06), 3px);
|
|
7
7
|
|
|
8
|
-
outline: var(--avatar-ring) solid color-mix(in oklab, var(--
|
|
9
|
-
outline-offset: calc(var(--avatar-ring) * -1);
|
|
10
|
-
box-shadow: inset 0 0 0 var(--avatar-ring-inset, calc(var(--avatar-ring) * var(--avatar-ring-gap, 2))) var(--avatar-cutout, var(--
|
|
8
|
+
outline: var(--lc-avatar-ring) solid color-mix(in oklab, var(--primary) 74%, var(--background));
|
|
9
|
+
outline-offset: calc(var(--lc-avatar-ring) * -1);
|
|
10
|
+
box-shadow: inset 0 0 0 var(--lc-avatar-ring-inset, calc(var(--lc-avatar-ring) * var(--lc-avatar-ring-gap, 2))) var(--lc-avatar-cutout, var(--background));
|
|
11
11
|
}
|