baldur 0.1.7 → 0.2.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 +78 -376
- data/TODO.md +47 -5
- data/app/assets/javascripts/baldur/controllers/confirmation_controller.js +23 -0
- data/app/assets/stylesheets/baldur/application/components/confirmation.css +11 -0
- data/app/assets/stylesheets/baldur/application/components/sidebar.css +234 -0
- data/app/assets/stylesheets/baldur.css +1 -0
- data/app/helpers/baldur/ui_helper.rb +25 -0
- data/app/views/baldur/components/_confirmation_modal.html.erb +99 -0
- data/app/views/baldur/components/_modal_host.html.erb +10 -0
- data/app/views/baldur/components/_sidebar.html.erb +30 -30
- data/baldur.gemspec +4 -4
- data/lib/baldur/version.rb +1 -1
- data/lib/generators/baldur/install/install_generator.rb +1 -0
- data/test/confirmation_modal_helper_test.rb +241 -0
- data/test/test_helper.rb +1 -1
- data/test/tmp/install_generator/app/javascript/controllers/confirmation_controller.js +1 -0
- metadata +16 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 633d727781f1701dcac870818b72d1c8df5ea9392cee702502ce5bd45aa1ef8a
|
|
4
|
+
data.tar.gz: aa155789ea73b321dff4cb7d795e5291c7613cbcff8b24142558c8b9cd0e3700
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 00f499098c0a6cd6bd35aa0819e9978e63648f23d3c7e1b1e57f90c3b6775338beb54fbf956e3e1185666b89362e523e39fadb9403c7722b1d97c4353530a568
|
|
7
|
+
data.tar.gz: e45efa594d08c3271fa53a2b56319d92e97e270c2610595c5ff01ce16b9a8d3e7a6b4ece4da564d82ccb8b5e42f80c0160611dc2ae92a51c7e855be9c94a4113
|
data/README.md
CHANGED
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
# Baldur
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://badge.fury.io/rb/baldur) [](https://github.com/varunmurkar/baldur/actions)
|
|
4
4
|
|
|
5
|
-
- Rails
|
|
5
|
+
Batteries-included opinionated Rails UI engine for the importmap, Stimulus, Tailwind stack. Baldur helps Rails teams ship polished UI faster with install generators, reusable ui_* helpers, Tailwind components, and Stimulus wiring for apps using Propshaft, importmap-rails, stimulus-rails, and tailwindcss-rails.
|
|
6
|
+
|
|
7
|
+
## Supported Stack
|
|
8
|
+
|
|
9
|
+
- **Ruby** `>= 3.3`
|
|
10
|
+
- **Rails** `>= 7.0`
|
|
6
11
|
- Propshaft
|
|
7
12
|
- `importmap-rails`
|
|
8
13
|
- `stimulus-rails`
|
|
9
|
-
- `tailwindcss-rails`
|
|
14
|
+
- `tailwindcss-rails` `>= 4.3.0`
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
It ships install generators, ready `ui_*` helpers, Tailwind components, and Stimulus controllers so host teams can skip rebuilding common UI primitives per app.
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
## Install
|
|
14
19
|
|
|
15
|
-
|
|
20
|
+
Add to your `Gemfile`:
|
|
16
21
|
|
|
17
22
|
```ruby
|
|
18
23
|
gem "baldur", ">= 0.1.3"
|
|
19
24
|
```
|
|
20
25
|
|
|
21
|
-
|
|
26
|
+
Run:
|
|
22
27
|
|
|
23
28
|
```sh
|
|
24
29
|
bundle install
|
|
@@ -26,93 +31,24 @@ bundle exec rails tailwindcss:engines
|
|
|
26
31
|
bundle exec rails generate baldur:install
|
|
27
32
|
```
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
Rebuild Tailwind:
|
|
30
35
|
|
|
31
36
|
```sh
|
|
32
37
|
bundle exec rails tailwindcss:build
|
|
33
38
|
```
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
If the host app already runs `tailwindcss:build` or `tailwindcss:watch`, those commands will also create the engine build automatically once the engine entrypoint exists.
|
|
38
|
-
|
|
39
|
-
4. Install optional surfaces as needed:
|
|
40
|
+
Optional surfaces:
|
|
40
41
|
|
|
41
42
|
```sh
|
|
42
43
|
bundle exec rails generate baldur:install_panel_secondary
|
|
43
44
|
bundle exec rails generate baldur:install_google_auth
|
|
44
45
|
```
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
The generators above are still optional and only required when using those specific surfaces.
|
|
49
|
-
|
|
50
|
-
Default install behavior keeps Geist loaded through the host `fonts.css` scaffold. If a host app wants a different stack, it should update `fonts.css` and then map the loaded families in `theme.css`.
|
|
51
|
-
|
|
52
|
-
## Security
|
|
53
|
-
|
|
54
|
-
- New Baldur releases require MFA for RubyGems owners via gem metadata starting with `0.1.2`.
|
|
55
|
-
- Release artifacts should be installed from RubyGems or GitHub releases and can be verified with the published `.sha512` checksum file.
|
|
56
|
-
- Report vulnerabilities privately through GitHub Security Advisories.
|
|
57
|
-
|
|
58
|
-
To verify a release artifact manually:
|
|
59
|
-
|
|
60
|
-
```sh
|
|
61
|
-
sha512sum -c baldur-0.1.3.gem.sha512
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Styling Ownership
|
|
47
|
+
## Example
|
|
65
48
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- Import host `fonts.css` before Tailwind so the host controls what font families get loaded.
|
|
69
|
-
- Import the generated Baldur Tailwind engine build into the host Tailwind entrypoint.
|
|
70
|
-
- Import host `theme.css` after the Baldur build to override only the base palette inputs and font-token mapping.
|
|
71
|
-
- Treat host `fonts.css` as the project-specific font loading layer.
|
|
72
|
-
- Treat host `theme.css` as the project-specific override layer for palette, font-token mapping, and other brand inputs, not as a place to fork Baldur-owned primitive styles.
|
|
73
|
-
- Add host-app styles only for app-specific surfaces after Baldur.
|
|
74
|
-
- Do not re-import or override host-local copies of Baldur-owned primitives such as buttons, forms, snackbars, or tables.
|
|
75
|
-
- Keep shared elevation semantics in Baldur-owned `--elev-*` tokens. If a host app needs softer or stronger shared shadows, change the Baldur token source instead of swapping raw Tailwind shadow utilities into Baldur-owned primitives.
|
|
76
|
-
- Do not keep duplicate copies of Baldur-owned primitives under `app/assets/stylesheets/application/`; leave only app-specific files there.
|
|
77
|
-
- Do not keep host copies of Baldur semantic theme files such as `theme/light.css` or `theme/dark.css`.
|
|
78
|
-
|
|
79
|
-
## What The Installer Assumes
|
|
80
|
-
|
|
81
|
-
- Tailwind entrypoint exists at `app/assets/tailwind/application.css`
|
|
82
|
-
- Host app gets `tailwindcss-rails` through Baldur or its own Gemfile and uses engine builds
|
|
83
|
-
- Host app uses importmap Stimulus boot with `app/javascript/controllers`
|
|
84
|
-
- Host app gets `app/assets/stylesheets/fonts.css` for font loading and `app/assets/stylesheets/theme.css` for brand and font-token overrides
|
|
85
|
-
- Host app can import `app/assets/builds/tailwind/baldur.css` from `app/assets/tailwind/application.css`
|
|
86
|
-
|
|
87
|
-
## Building UI
|
|
88
|
-
|
|
89
|
-
Canonical Ruby internals live under `Baldur::*`, but the default DX is `ui_*` helpers through the generated `UiHelper` include.
|
|
90
|
-
|
|
91
|
-
Not every `ui_*` helper is part of the base install. Some helpers belong to optional surfaces and require the matching generator. `ui_auth_page` is part of the default install; `ui_panel_secondary` and google-auth helpers are optional.
|
|
92
|
-
|
|
93
|
-
For authenticated application shells, use `ui_sidebar`. It is part of the base install and includes:
|
|
94
|
-
|
|
95
|
-
- desktop sidebar shell markup
|
|
96
|
-
- mobile sidebar shell markup
|
|
97
|
-
- `sidebar` and `mobile-sidebar` controller wiring
|
|
98
|
-
- default brand rendering from `config.marketing_brand`
|
|
99
|
-
- default nav rendering for primary and secondary links
|
|
100
|
-
|
|
101
|
-
Host apps provide the route arrays, active-state logic, and any optional slot content.
|
|
102
|
-
|
|
103
|
-
Examples:
|
|
49
|
+
Render a sidebar with navigation and a main content area:
|
|
104
50
|
|
|
105
51
|
```erb
|
|
106
|
-
<%= ui_button(label: "Save", href: "#") %>
|
|
107
|
-
|
|
108
|
-
<%= ui_card(title: "Revenue") do %>
|
|
109
|
-
<p>Content</p>
|
|
110
|
-
<% end %>
|
|
111
|
-
|
|
112
|
-
<%= ui_panel_secondary(id: "assistant", title: "Assistant", trigger_label: "Open") do %>
|
|
113
|
-
<p>Panel content</p>
|
|
114
|
-
<% end %>
|
|
115
|
-
|
|
116
52
|
<%= ui_sidebar(
|
|
117
53
|
brand_path: root_path,
|
|
118
54
|
primary_links: [
|
|
@@ -125,321 +61,87 @@ Examples:
|
|
|
125
61
|
<% end %>
|
|
126
62
|
```
|
|
127
63
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
- `name` required label text
|
|
131
|
-
- `path` required destination
|
|
132
|
-
- `icon` optional Lucide icon name, defaults to `circle`
|
|
133
|
-
- `active` optional boolean for `aria-current="page"`
|
|
134
|
-
- `title` optional hover title
|
|
135
|
-
- `method` optional Rails link method
|
|
136
|
-
- `data` optional data attributes hash
|
|
137
|
-
- `html_options` optional extra HTML attributes hash
|
|
138
|
-
|
|
139
|
-
Default brand behavior:
|
|
140
|
-
|
|
141
|
-
- `brand_name`, `brand_wordmark`, and `brand_logo` are optional
|
|
142
|
-
- when omitted, Baldur resolves them from `config.marketing_brand`
|
|
143
|
-
- `brand_path` defaults to `#` if the host app does not provide one
|
|
144
|
-
|
|
145
|
-
Mobile behavior:
|
|
146
|
-
|
|
147
|
-
- mobile nav mirrors desktop primary and secondary links automatically
|
|
148
|
-
- the install generator now ships both `sidebar_controller.js` and `mobile_sidebar_controller.js`
|
|
149
|
-
|
|
150
|
-
You can adopt `ui_sidebar` with no slots. The block content becomes the main app surface beside the sidebar:
|
|
151
|
-
|
|
152
|
-
```erb
|
|
153
|
-
<%= ui_sidebar(
|
|
154
|
-
brand_path: root_path,
|
|
155
|
-
primary_links: sidebar_primary_links,
|
|
156
|
-
secondary_links: sidebar_secondary_links,
|
|
157
|
-
secondary_label: "Admin"
|
|
158
|
-
) do |_sidebar| %>
|
|
159
|
-
<main id="main-content" class="flex-1 p-6">
|
|
160
|
-
<%= yield %>
|
|
161
|
-
</main>
|
|
162
|
-
<% end %>
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
For host-specific sidebar surfaces, prefer slots. `*_content` params are also supported for incremental adoption.
|
|
166
|
-
|
|
167
|
-
```erb
|
|
168
|
-
<%= ui_sidebar(
|
|
169
|
-
brand_path: root_path,
|
|
170
|
-
primary_links: sidebar_primary_links,
|
|
171
|
-
secondary_links: sidebar_secondary_links,
|
|
172
|
-
secondary_label: "Admin"
|
|
173
|
-
) do |sidebar| %>
|
|
174
|
-
<% sidebar.with_header do %>
|
|
175
|
-
<%= render "layouts/tenant_switcher" %>
|
|
176
|
-
<% end %>
|
|
177
|
-
|
|
178
|
-
<% sidebar.with_footer do %>
|
|
179
|
-
<div class="space-y-2">
|
|
180
|
-
<p class="text-sm text-muted"><%= current_user.email %></p>
|
|
181
|
-
<%= ui_button(label: "Sign out", href: logout_path, method: :delete, variant: :text, size: :sm, icon: "log-out") %>
|
|
182
|
-
</div>
|
|
183
|
-
<% end %>
|
|
184
|
-
<% end %>
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
Host apps own:
|
|
188
|
-
|
|
189
|
-
- route definitions
|
|
190
|
-
- active-state logic
|
|
191
|
-
- app-specific header/footer content
|
|
192
|
-
|
|
193
|
-
Baldur owns:
|
|
194
|
-
|
|
195
|
-
- desktop and mobile sidebar shell markup
|
|
196
|
-
- toggle behavior wiring
|
|
197
|
-
- default brand rendering
|
|
198
|
-
- default nav rendering
|
|
199
|
-
|
|
200
|
-
External triggers can open a Baldur panel declaratively:
|
|
201
|
-
|
|
202
|
-
```erb
|
|
203
|
-
<button
|
|
204
|
-
type="button"
|
|
205
|
-
data-open-panel="#assistant"
|
|
206
|
-
data-panel-payload="<%= json_escape({ source: "dashboard" }.to_json) %>">
|
|
207
|
-
Open assistant
|
|
208
|
-
</button>
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
`panel-secondary` emits `baldur:panel:opened` and `baldur:panel:closed` on the panel shell and `window`. The event detail includes `id`, `selector`, `trigger`, and parsed `payload`.
|
|
212
|
-
|
|
213
|
-
For modals, prefer `ui_modal` directly:
|
|
214
|
-
|
|
215
|
-
```erb
|
|
216
|
-
<%= ui_modal(id: "confirm-delete", title: "Delete item") do %>
|
|
217
|
-
<p>This action cannot be undone.</p>
|
|
218
|
-
<% end %>
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
For auth layouts, use `ui_auth_page` (available after `baldur:install`):
|
|
222
|
-
|
|
223
|
-
```erb
|
|
224
|
-
<%= ui_auth_page(title: "Sign in", description: nil, brand_path: root_path) do %>
|
|
225
|
-
<%= yield %>
|
|
226
|
-
<% end %>
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
Auth flash messaging can be rendered inside the card by passing `notice:` / `alert:`:
|
|
230
|
-
|
|
231
|
-
```erb
|
|
232
|
-
<%= ui_auth_page(title: "Sign in", description: nil, brand_path: root_path, notice: notice, alert: alert) do %>
|
|
233
|
-
<%= yield %>
|
|
234
|
-
<% end %>
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
If a host app keeps a shared wrapper partial around `ui_modal`, treat `modal_body:` as the wrapper-local input and let the wrapper pass that content into `ui_modal`. Avoid calling a wrapper with `body:` through `render`, since `body` collides with Rails render options.
|
|
238
|
-
|
|
239
|
-
For horizontal primary/secondary CTA groups, prefer `ui_action_row`:
|
|
240
|
-
|
|
241
|
-
```erb
|
|
242
|
-
<%= ui_action_row(
|
|
243
|
-
secondary_button: { label: "Back", variant: :outline, href: settings_path },
|
|
244
|
-
primary_button: { label: "Save", variant: :primary, type: :submit }
|
|
245
|
-
) %>
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
The action row owns the responsive layout and keeps the primary CTA last on the right.
|
|
249
|
-
|
|
250
|
-
Use `ui_alert` for inline status surfaces. Alerts support optional inline actions and opt-in collapsed state:
|
|
251
|
-
|
|
252
|
-
```erb
|
|
253
|
-
<%= ui_alert(
|
|
254
|
-
variant: :warning,
|
|
255
|
-
title: "Data freshness warning",
|
|
256
|
-
actions: ui_button(label: "Upload Latest Data", href: new_ecommerce_import_path, variant: :primary, size: :sm),
|
|
257
|
-
collapsible: true,
|
|
258
|
-
collapse_key: "tenant-#{current_tenant.id}-executive-pulse-stale-data"
|
|
259
|
-
) do %>
|
|
260
|
-
<p>Latest available data is 10 days old.</p>
|
|
261
|
-
<% end %>
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
Collapsed alerts stay inline and can be re-expanded with the built-in `More` summary action.
|
|
265
|
-
|
|
266
|
-
## Tables
|
|
267
|
-
|
|
268
|
-
Use the table helpers as a small composition system:
|
|
269
|
-
|
|
270
|
-
- `ui_table` is the table atom.
|
|
271
|
-
- `ui_table_card` is the card shell for title, controls, table body, and footer.
|
|
272
|
-
- `ui_table_footer` owns the `Show [x] items per page` control and the `Showing x-y of z` status line.
|
|
273
|
-
- `ui_pagination` is the page-navigation atom and is usually composed through `ui_table_footer`.
|
|
274
|
-
|
|
275
|
-
If a table has title, controls, rows, and pagination, render them inside the same `ui_table_card`.
|
|
276
|
-
|
|
277
|
-
Use `ui_table` directly for embedded or simple tables:
|
|
278
|
-
|
|
279
|
-
```erb
|
|
280
|
-
<%= ui_table(
|
|
281
|
-
columns: [
|
|
282
|
-
{ label: "SKU", key: :sku },
|
|
283
|
-
{ label: "Status", key: :status },
|
|
284
|
-
{ label: "Revenue", key: :revenue, header_class: "text-right", cell_class: "text-right" }
|
|
285
|
-
],
|
|
286
|
-
rows: [
|
|
287
|
-
{ sku: "SKU-001", status: "Active", revenue: number_to_currency(12_500) },
|
|
288
|
-
{ sku: "SKU-002", status: "Draft", revenue: number_to_currency(3_800) }
|
|
289
|
-
],
|
|
290
|
-
empty_state: "No SKUs found"
|
|
291
|
-
) %>
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
Use `ui_table_card` when the table is a standalone surface:
|
|
295
|
-
|
|
296
|
-
```erb
|
|
297
|
-
<% table_controls = capture do %>
|
|
298
|
-
<div class="flex items-end gap-3">
|
|
299
|
-
<%= ui_menu_select_tag :status,
|
|
300
|
-
options: [
|
|
301
|
-
{ label: "All", value: "all" },
|
|
302
|
-
{ label: "Active", value: "active" },
|
|
303
|
-
{ label: "Draft", value: "draft" }
|
|
304
|
-
],
|
|
305
|
-
selected: params[:status].presence || "all",
|
|
306
|
-
label: "Status" %>
|
|
307
|
-
</div>
|
|
308
|
-
<% end %>
|
|
309
|
-
|
|
310
|
-
<%= ui_table_card(
|
|
311
|
-
title: "Products",
|
|
312
|
-
description: "Track inventory and performance in one place.",
|
|
313
|
-
controls: table_controls,
|
|
314
|
-
controls_position: :header,
|
|
315
|
-
footer: ui_table_footer(
|
|
316
|
-
current_page: @pagination[:current_page],
|
|
317
|
-
total_pages: @pagination[:total_pages],
|
|
318
|
-
total_count: @pagination[:total_count],
|
|
319
|
-
per_page: @pagination[:per_page],
|
|
320
|
-
path_builder: ->(page) { products_path(request.query_parameters.merge(page: page, per_page: @pagination[:per_page])) },
|
|
321
|
-
rows_per_page_param: "per_page",
|
|
322
|
-
rows_per_page_options: [10, 20, 50],
|
|
323
|
-
rows_per_page_selected: @pagination[:per_page]
|
|
324
|
-
)
|
|
325
|
-
) do %>
|
|
326
|
-
<%= ui_table(
|
|
327
|
-
sort: { key: params[:sort], direction: params[:direction] },
|
|
328
|
-
sort_path_builder: ->(sort_key, direction) { products_path(request.query_parameters.merge(sort: sort_key, direction: direction, page: 1)) },
|
|
329
|
-
columns: [
|
|
330
|
-
{ label: "SKU", key: :sku, sortable: true, sort_key: "sku" },
|
|
331
|
-
{ label: "Status", key: :status },
|
|
332
|
-
{
|
|
333
|
-
label: "Revenue",
|
|
334
|
-
key: :revenue,
|
|
335
|
-
sortable: true,
|
|
336
|
-
sort_key: "revenue",
|
|
337
|
-
header_class: "text-right",
|
|
338
|
-
cell_class: "text-right",
|
|
339
|
-
header_tooltip: "Total revenue attributed to the current filter window."
|
|
340
|
-
}
|
|
341
|
-
],
|
|
342
|
-
rows: @rows,
|
|
343
|
-
empty_state: "No products found"
|
|
344
|
-
) %>
|
|
345
|
-
<% end %>
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
Use `controls_position: :header` for compact data-view controls that belong in the top-right header zone. Keep the default `:row` placement for wider filter bars. You can also pass `title_meta:` to render subdued inline metadata beside the title, for example `title_meta: "24 rows"`.
|
|
64
|
+
## Getting Started
|
|
349
65
|
|
|
350
|
-
|
|
66
|
+
- See [docs/installation.md](docs/installation.md) for install steps.
|
|
67
|
+
- See [docs/sidebar.md](docs/sidebar.md) and [docs/auth.md](docs/auth.md) for common usage patterns.
|
|
351
68
|
|
|
352
|
-
|
|
69
|
+
## Documentation
|
|
353
70
|
|
|
354
|
-
|
|
71
|
+
- [Installation](docs/installation.md)
|
|
72
|
+
- [Styling](docs/styling.md)
|
|
73
|
+
- [Sidebar](docs/sidebar.md)
|
|
74
|
+
- [Auth](docs/auth.md)
|
|
75
|
+
- [Modals and Panels](docs/modals-and-panels.md)
|
|
76
|
+
- [Alerts and Snackbars](docs/alerts-and-snackbars.md)
|
|
77
|
+
- [Tables](docs/tables.md)
|
|
78
|
+
- [Marketing](docs/marketing.md)
|
|
79
|
+
- [Security](docs/security.md)
|
|
355
80
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
Current canonical marketing helpers:
|
|
359
|
-
|
|
360
|
-
- `ui_marketing_top_nav`
|
|
361
|
-
- `ui_marketing_hero_section(variant: :solar_system, ...)`
|
|
362
|
-
- `ui_marketing_features_section`
|
|
363
|
-
- `ui_marketing_testimonials_section(variant: :bento, ...)`
|
|
364
|
-
- `ui_marketing_faq_section`
|
|
365
|
-
- `ui_marketing_cta_banner`
|
|
366
|
-
- `ui_marketing_pricing_tables`
|
|
367
|
-
- `ui_marketing_footer`
|
|
81
|
+
## Security
|
|
368
82
|
|
|
369
|
-
|
|
83
|
+
See [docs/security.md](docs/security.md) for artifact verification, MFA requirements, and vulnerability reporting.
|
|
370
84
|
|
|
371
|
-
|
|
85
|
+
## Available Now
|
|
372
86
|
|
|
373
|
-
|
|
87
|
+
- [x] Host app brand theming via `theme.css` and `config.marketing_brand`
|
|
88
|
+
- [x] Reusable auth page shell for sign-in, sign-up, and password reset
|
|
89
|
+
- [x] Core UI helpers, Tailwind components, and Stimulus wiring
|
|
374
90
|
|
|
375
|
-
|
|
91
|
+
## Roadmap
|
|
376
92
|
|
|
377
|
-
|
|
93
|
+
### Installing
|
|
94
|
+
- Harden `baldur:install` so host assumptions are reduced
|
|
95
|
+
- Expand `script/verify_host_install` coverage
|
|
96
|
+
- Add end-to-end install verification in dummy app
|
|
378
97
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
primary_action: { label: "Book a Demo", variant: :primary, href: dashboard_path },
|
|
385
|
-
secondary_action: { label: "See Use Cases", variant: :outline, href: "#use-cases" },
|
|
386
|
-
supporting_action: { href: "#", label: "Watch walkthrough", data: { open_modal: "#walkthrough-modal" } },
|
|
387
|
-
callouts: [
|
|
388
|
-
{ label: "Unified decision context" },
|
|
389
|
-
{ label: "Prioritized recommendations" },
|
|
390
|
-
{ label: "Impact-aware next actions" }
|
|
391
|
-
],
|
|
392
|
-
orbit_sources: [
|
|
393
|
-
{ name: "Shopify", asset_path: "/landing/source-logos/shopify.svg" },
|
|
394
|
-
{ name: "HubSpot", asset_path: "/landing/source-logos/hubspot.svg" }
|
|
395
|
-
],
|
|
396
|
-
centerpiece_image: { src: "/branding/logo.png", alt: "Acme logo" }
|
|
397
|
-
) %>
|
|
398
|
-
```
|
|
98
|
+
### Showcase
|
|
99
|
+
- Add a dedicated dummy app for visual smoke checks
|
|
100
|
+
- Add component inventory/showcase page in dummy app
|
|
101
|
+
- Add interaction showcase pages for modal, sidebar, menu select, snackbar, and panel_secondary
|
|
102
|
+
- Add copy-paste examples for core surfaces from the showcase app back into docs
|
|
399
103
|
|
|
400
|
-
|
|
104
|
+
### Starter Templates
|
|
105
|
+
- Add dedicated password reset templates
|
|
106
|
+
- Add magic link templates
|
|
107
|
+
- Add error/system pages
|
|
108
|
+
- Add starter settings page layout
|
|
109
|
+
- Add starter CRUD index/show/form templates
|
|
110
|
+
- Add starter dashboard shell/page templates
|
|
401
111
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
tabs: [
|
|
407
|
-
{
|
|
408
|
-
value: "ecommerce",
|
|
409
|
-
label: "E-commerce",
|
|
410
|
-
selected: true,
|
|
411
|
-
panel_title: "E-commerce",
|
|
412
|
-
panel_body: "Priority ROI plays for commerce teams.",
|
|
413
|
-
cards: [
|
|
414
|
-
{ title: "Which products should I run campaigns for?", body: "Rank SKUs by incremental margin potential." }
|
|
415
|
-
]
|
|
416
|
-
}
|
|
417
|
-
],
|
|
418
|
-
cta: { label: "Get a demo tailored for you", variant: :primary, href: dashboard_path }
|
|
419
|
-
) %>
|
|
420
|
-
```
|
|
112
|
+
### Forms
|
|
113
|
+
- Add Rails form-builder integration for Baldur fields
|
|
114
|
+
- Bind labels, hints, errors, and invalid states automatically
|
|
115
|
+
- Document model-bound form usage
|
|
421
116
|
|
|
422
|
-
|
|
117
|
+
### Tables and Resource Screens
|
|
118
|
+
- Add a higher-level resource index pattern on top of existing table primitives
|
|
119
|
+
- Support search, filters, row actions, bulk select, and empty states
|
|
120
|
+
- Document recommended resource index composition
|
|
423
121
|
|
|
424
|
-
|
|
122
|
+
### Theming
|
|
123
|
+
- Add a small set of starter theme presets
|
|
124
|
+
- Improve dark-mode/theme controller documentation
|
|
125
|
+
- Document brand-token customization more clearly
|
|
425
126
|
|
|
426
|
-
|
|
427
|
-
-
|
|
428
|
-
-
|
|
429
|
-
-
|
|
127
|
+
### Accessibility
|
|
128
|
+
- Audit keyboard and focus behavior across interactive components
|
|
129
|
+
- Add accessibility-focused tests for core surfaces
|
|
130
|
+
- Document a11y guarantees and known gaps
|
|
430
131
|
|
|
431
|
-
|
|
132
|
+
### Internationalization
|
|
133
|
+
- Add I18n-friendly labels/messages for reusable helpers
|
|
134
|
+
- Remove hard-coded helper copy where practical
|
|
135
|
+
- Document translation override points
|
|
432
136
|
|
|
433
|
-
##
|
|
137
|
+
## Contributing
|
|
434
138
|
|
|
435
|
-
|
|
139
|
+
Open an issue or PR. Before you start, read [CONTRIBUTING.md](CONTRIBUTING.md) and [docs/security.md](docs/security.md).
|
|
436
140
|
|
|
437
|
-
|
|
438
|
-
bundle exec ruby "$(bundle show baldur)/script/verify_host_install"
|
|
439
|
-
```
|
|
141
|
+
## Changelog
|
|
440
142
|
|
|
441
|
-
|
|
143
|
+
See [CHANGELOG.md](CHANGELOG.md).
|
|
442
144
|
|
|
443
|
-
##
|
|
145
|
+
## License
|
|
444
146
|
|
|
445
|
-
|
|
147
|
+
MIT. See [LICENSE](LICENSE).
|
data/TODO.md
CHANGED
|
@@ -1,8 +1,50 @@
|
|
|
1
1
|
# Baldur TODO
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
-
|
|
3
|
+
## Install and Verification
|
|
4
|
+
- [ ] Harden `baldur:install` so host assumptions are reduced
|
|
5
|
+
- [ ] Audit generated controller shims against all shipped components
|
|
6
|
+
- [ ] Expand `script/verify_host_install` coverage
|
|
7
|
+
- [ ] Add end-to-end install verification in dummy app
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
- Add a
|
|
8
|
-
- Add a
|
|
9
|
+
## Showcase App and Docs
|
|
10
|
+
- [ ] Add a dedicated dummy app in the extracted gem repo for visual smoke checks
|
|
11
|
+
- [ ] Add a component inventory/showcase page in that dummy app
|
|
12
|
+
- [ ] Add interaction showcase pages for modal, sidebar, menu select, snackbar, and `panel_secondary`
|
|
13
|
+
- [ ] Add copy-paste examples for core surfaces from the showcase app back into docs
|
|
14
|
+
|
|
15
|
+
## Starter Templates
|
|
16
|
+
- [ ] Add dedicated password reset templates
|
|
17
|
+
- [ ] Add magic link templates
|
|
18
|
+
- [ ] Add error/system pages
|
|
19
|
+
- [ ] Add starter settings page layout
|
|
20
|
+
- [ ] Add starter CRUD index/show/form templates
|
|
21
|
+
- [ ] Add starter dashboard shell/page templates
|
|
22
|
+
|
|
23
|
+
## Forms
|
|
24
|
+
- [ ] Add Rails form-builder integration for Baldur fields
|
|
25
|
+
- [ ] Bind labels, hints, errors, and invalid states automatically
|
|
26
|
+
- [ ] Document model-bound form usage
|
|
27
|
+
|
|
28
|
+
## Tables and Resource Screens
|
|
29
|
+
- [ ] Add a higher-level resource index pattern on top of existing table primitives
|
|
30
|
+
- [ ] Support search, filters, row actions, bulk select, and empty states
|
|
31
|
+
- [ ] Document recommended resource index composition
|
|
32
|
+
|
|
33
|
+
## Theming
|
|
34
|
+
- [ ] Add a small set of starter theme presets
|
|
35
|
+
- [ ] Improve dark-mode/theme controller documentation
|
|
36
|
+
- [ ] Document brand-token customization more clearly
|
|
37
|
+
|
|
38
|
+
## Accessibility
|
|
39
|
+
- [ ] Audit keyboard and focus behavior across interactive components
|
|
40
|
+
- [ ] Add accessibility-focused tests for core surfaces
|
|
41
|
+
- [ ] Document a11y guarantees and known gaps
|
|
42
|
+
|
|
43
|
+
## Internationalization
|
|
44
|
+
- [ ] Add I18n-friendly labels/messages for reusable helpers
|
|
45
|
+
- [ ] Remove hard-coded helper copy where practical
|
|
46
|
+
- [ ] Document translation override points
|
|
47
|
+
|
|
48
|
+
## Contributor and Agent Guidance
|
|
49
|
+
- [ ] Add `.agents/AGENTS.md` with project conventions and reference files for LLM agents
|
|
50
|
+
- [ ] Keep `.agents/AGENTS.md` in sync with actual project conventions
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
|
2
|
+
|
|
3
|
+
export default class ConfirmationController extends Controller {
|
|
4
|
+
static targets = ["input", "submit", "expectedText"];
|
|
5
|
+
static values = { caseSensitive: { type: Boolean, default: true } };
|
|
6
|
+
|
|
7
|
+
connect() {
|
|
8
|
+
this.validate();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
validate() {
|
|
12
|
+
if (!this.hasSubmitTarget || !this.hasInputTarget) return;
|
|
13
|
+
|
|
14
|
+
const input = this.inputTarget.value.trim();
|
|
15
|
+
const expected = this.hasExpectedTextTarget ? this.expectedTextTarget.textContent.trim() : "";
|
|
16
|
+
|
|
17
|
+
const matches = this.caseSensitiveValue
|
|
18
|
+
? input === expected
|
|
19
|
+
: input.toLowerCase() === expected.toLowerCase();
|
|
20
|
+
|
|
21
|
+
this.submitTarget.disabled = !matches;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
.confirmation-modal__input-wrapper {
|
|
3
|
+
margin-top: var(--space-4);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
[data-confirmation] .text-field__control:focus {
|
|
7
|
+
border-color: var(--color-primary);
|
|
8
|
+
outline: none;
|
|
9
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary) 24%, transparent);
|
|
10
|
+
}
|
|
11
|
+
}
|