fuji_admin 0.1.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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +143 -0
  4. data/app/assets/javascripts/fuji_admin/base.js +6 -0
  5. data/app/assets/javascripts/fuji_admin/filters.js +282 -0
  6. data/app/assets/javascripts/fuji_admin/floats.js +73 -0
  7. data/app/assets/javascripts/fuji_admin/menu.js +112 -0
  8. data/app/assets/javascripts/fuji_admin/palettes.js +237 -0
  9. data/app/assets/javascripts/fuji_admin/row_actions.js +123 -0
  10. data/app/assets/stylesheets/fuji_admin/_base.scss +23 -0
  11. data/app/assets/stylesheets/fuji_admin/_base_typography.scss +56 -0
  12. data/app/assets/stylesheets/fuji_admin/_grid.scss +111 -0
  13. data/app/assets/stylesheets/fuji_admin/_reset.scss +48 -0
  14. data/app/assets/stylesheets/fuji_admin/components/_buttons.scss +106 -0
  15. data/app/assets/stylesheets/fuji_admin/components/_comments.scss +44 -0
  16. data/app/assets/stylesheets/fuji_admin/components/_components.scss +22 -0
  17. data/app/assets/stylesheets/fuji_admin/components/_date_picker.scss +147 -0
  18. data/app/assets/stylesheets/fuji_admin/components/_dropdown_menu.scss +76 -0
  19. data/app/assets/stylesheets/fuji_admin/components/_filter_chips.scss +71 -0
  20. data/app/assets/stylesheets/fuji_admin/components/_filter_drawer.scss +224 -0
  21. data/app/assets/stylesheets/fuji_admin/components/_filter_form.scss +85 -0
  22. data/app/assets/stylesheets/fuji_admin/components/_flash.scss +55 -0
  23. data/app/assets/stylesheets/fuji_admin/components/_float_labels.scss +77 -0
  24. data/app/assets/stylesheets/fuji_admin/components/_inputs.scss +237 -0
  25. data/app/assets/stylesheets/fuji_admin/components/_menu_toggle.scss +61 -0
  26. data/app/assets/stylesheets/fuji_admin/components/_pagination.scss +70 -0
  27. data/app/assets/stylesheets/fuji_admin/components/_palette_switcher.scss +600 -0
  28. data/app/assets/stylesheets/fuji_admin/components/_panel.scss +44 -0
  29. data/app/assets/stylesheets/fuji_admin/components/_row_actions.scss +110 -0
  30. data/app/assets/stylesheets/fuji_admin/components/_scopes.scss +58 -0
  31. data/app/assets/stylesheets/fuji_admin/components/_select2.scss +194 -0
  32. data/app/assets/stylesheets/fuji_admin/components/_status_tag.scss +59 -0
  33. data/app/assets/stylesheets/fuji_admin/components/_table_tools.scss +14 -0
  34. data/app/assets/stylesheets/fuji_admin/components/_tables.scss +262 -0
  35. data/app/assets/stylesheets/fuji_admin/components/_watchlist_bar.scss +119 -0
  36. data/app/assets/stylesheets/fuji_admin/layouts/_footer.scss +21 -0
  37. data/app/assets/stylesheets/fuji_admin/layouts/_header.scss +80 -0
  38. data/app/assets/stylesheets/fuji_admin/layouts/_layouts.scss +7 -0
  39. data/app/assets/stylesheets/fuji_admin/layouts/_main_content.scss +118 -0
  40. data/app/assets/stylesheets/fuji_admin/layouts/_sidebar.scss +124 -0
  41. data/app/assets/stylesheets/fuji_admin/layouts/_sizes.scss +12 -0
  42. data/app/assets/stylesheets/fuji_admin/layouts/_wrapper.scss +28 -0
  43. data/app/assets/stylesheets/fuji_admin/mixins/_media.scss +30 -0
  44. data/app/assets/stylesheets/fuji_admin/mixins/_mixins.scss +2 -0
  45. data/app/assets/stylesheets/fuji_admin/pages/_form.scss +61 -0
  46. data/app/assets/stylesheets/fuji_admin/pages/_index.scss +77 -0
  47. data/app/assets/stylesheets/fuji_admin/pages/_login.scss +77 -0
  48. data/app/assets/stylesheets/fuji_admin/pages/_pages.scss +5 -0
  49. data/app/assets/stylesheets/fuji_admin/pages/_show.scss +19 -0
  50. data/app/assets/stylesheets/fuji_admin/variables/_breakpoints.scss +25 -0
  51. data/app/assets/stylesheets/fuji_admin/variables/_colors.scss +51 -0
  52. data/app/assets/stylesheets/fuji_admin/variables/_radii.scss +13 -0
  53. data/app/assets/stylesheets/fuji_admin/variables/_shadows.scss +10 -0
  54. data/app/assets/stylesheets/fuji_admin/variables/_spacing.scss +20 -0
  55. data/app/assets/stylesheets/fuji_admin/variables/_typography.scss +25 -0
  56. data/app/assets/stylesheets/fuji_admin/variables/_variables.scss +9 -0
  57. data/lib/fuji_admin/active_admin_patch.rb +19 -0
  58. data/lib/fuji_admin/configuration.rb +29 -0
  59. data/lib/fuji_admin/version.rb +3 -0
  60. data/lib/fuji_admin.rb +24 -0
  61. metadata +124 -0
@@ -0,0 +1,600 @@
1
+ // Palette switcher — floating trigger + panel + live palette overrides.
2
+ //
3
+ // Live overrides repaint primary-coloured components based on `--fuji-primary`
4
+ // (set by fuji_admin/palettes.js on <html>). We use `color-mix()` for tinted
5
+ // variants so a single var powers the whole ramp (hover = darken, surface tint
6
+ // = mix with white, focus ring = mix with transparent).
7
+
8
+ // --- Live overrides -------------------------------------------------------
9
+ // Each rule references `var(--fuji-primary, <fallback>)` so the fallback
10
+ // (our default Fuji Admin indigo) shows when no palette has been chosen.
11
+
12
+ $fuji-primary: var(--fuji-primary, #{$primary-color});
13
+
14
+ // Auto-derived surfaces + text, tinted from the active primary. Defined at
15
+ // :root with color-mix() so every palette gets a coherent mono-chromatic look
16
+ // without requiring hand-curation. JS sets explicit values on <html> for the
17
+ // handful of curated themes (editorial-navy, coastal-sage, etc.) which
18
+ // override these defaults naturally via the cascade.
19
+ :root {
20
+ --fuji-text: color-mix(in srgb, #{$fuji-primary} 20%, black);
21
+ --fuji-text-muted: color-mix(in srgb, #{$fuji-primary} 45%, black);
22
+ --fuji-surface: color-mix(in srgb, #{$fuji-primary} 5%, white);
23
+ --fuji-surface-alt: color-mix(in srgb, #{$fuji-primary} 10%, white);
24
+ --fuji-border: color-mix(in srgb, #{$fuji-primary} 22%, white);
25
+ }
26
+
27
+ // Primary buttons — keep text white regardless of palette/theme.
28
+ form input[type="submit"],
29
+ a.button,
30
+ a:link.button,
31
+ a:visited.button,
32
+ fieldset.actions > ol > li.button_action > button,
33
+ #title_bar #titlebar_right .action_item > a,
34
+ #title_bar #titlebar_right .dropdown_menu > a.dropdown_menu_button,
35
+ .batch_actions_selector > a,
36
+ .table_tools .batch_actions_selector > a,
37
+ .dropdown_menu.batch_actions_selector > a.dropdown_menu_button,
38
+ .table_tools .dropdown_menu.batch_actions_selector > a.dropdown_menu_button,
39
+ form.filter_form input[type="submit"] {
40
+ background-color: #{$fuji-primary};
41
+ border-color: #{$fuji-primary};
42
+ color: #{$primary-color-text};
43
+
44
+ &:hover {
45
+ background-color: color-mix(in srgb, #{$fuji-primary} 82%, black);
46
+ border-color: color-mix(in srgb, #{$fuji-primary} 82%, black);
47
+ color: #{$primary-color-text};
48
+ }
49
+
50
+ &::after {
51
+ border-top-color: #{$primary-color-text};
52
+ }
53
+ }
54
+
55
+ // Links
56
+ a {
57
+ color: #{$fuji-primary};
58
+
59
+ &:hover {
60
+ color: color-mix(in srgb, #{$fuji-primary} 82%, black);
61
+ }
62
+ }
63
+
64
+ // Sidebar active nav item
65
+ body.active_admin.logged_in #tabs > li.current > a {
66
+ color: #{$fuji-primary};
67
+ background-color: color-mix(in srgb, #{$fuji-primary} 10%, white);
68
+ border-left-color: #{$fuji-primary};
69
+ }
70
+
71
+ // Filter chip pills (outside drawer)
72
+ .fuji-filter-chips__pill {
73
+ background-color: color-mix(in srgb, #{$fuji-primary} 10%, white);
74
+ border-color: color-mix(in srgb, #{$fuji-primary} 24%, white);
75
+ color: color-mix(in srgb, #{$fuji-primary} 70%, black);
76
+
77
+ .fuji-filter-chips__remove {
78
+ background-color: color-mix(in srgb, #{$fuji-primary} 18%, white);
79
+ color: color-mix(in srgb, #{$fuji-primary} 70%, black);
80
+ }
81
+
82
+ &:hover {
83
+ background-color: color-mix(in srgb, #{$fuji-primary} 18%, white);
84
+ border-color: color-mix(in srgb, #{$fuji-primary} 38%, white);
85
+ }
86
+ }
87
+
88
+ // Watchlist bar pills and "Add" button
89
+ .fuji-watchlist-bar__item {
90
+ background-color: color-mix(in srgb, #{$fuji-primary} 10%, white);
91
+ border-color: color-mix(in srgb, #{$fuji-primary} 24%, white);
92
+ color: color-mix(in srgb, #{$fuji-primary} 70%, black);
93
+ }
94
+
95
+ .fuji-watchlist-bar__remove {
96
+ background-color: color-mix(in srgb, #{$fuji-primary} 18%, white);
97
+ color: color-mix(in srgb, #{$fuji-primary} 70%, black);
98
+ }
99
+
100
+ .fuji-watchlist-bar__add {
101
+ background-color: #{$fuji-primary};
102
+ border-color: #{$fuji-primary};
103
+
104
+ &:hover {
105
+ background-color: color-mix(in srgb, #{$fuji-primary} 82%, black);
106
+ border-color: color-mix(in srgb, #{$fuji-primary} 82%, black);
107
+ }
108
+ }
109
+
110
+ // Current filters in drawer
111
+ body.active_admin #sidebar li.current_filter {
112
+ background-color: color-mix(in srgb, #{$fuji-primary} 10%, white);
113
+ border-color: color-mix(in srgb, #{$fuji-primary} 24%, white);
114
+
115
+ b {
116
+ color: color-mix(in srgb, #{$fuji-primary} 70%, black);
117
+ }
118
+ }
119
+
120
+ // Filter drawer toggle — active state
121
+ .fuji-filters-toggle--active {
122
+ background-color: color-mix(in srgb, #{$fuji-primary} 10%, white);
123
+ border-color: color-mix(in srgb, #{$fuji-primary} 30%, white);
124
+ color: color-mix(in srgb, #{$fuji-primary} 70%, black);
125
+
126
+ .fuji-filters-toggle__icon {
127
+ color: #{$fuji-primary};
128
+ }
129
+ }
130
+
131
+ .fuji-filters-toggle__count {
132
+ background-color: #{$fuji-primary};
133
+ }
134
+
135
+ // Filter form submit (inside drawer)
136
+ form.filter_form input[type="submit"] {
137
+ background-color: #{$fuji-primary};
138
+ border-color: #{$fuji-primary};
139
+ }
140
+
141
+ // Scopes — selected tab count
142
+ .scopes li.selected a .count,
143
+ .table_tools .scopes li.selected a .count {
144
+ color: #{$fuji-primary};
145
+ }
146
+
147
+ // Pagination current page
148
+ .pagination span.page.current,
149
+ .pagination span.current {
150
+ background-color: #{$fuji-primary};
151
+ border-color: #{$fuji-primary};
152
+
153
+ &:hover {
154
+ background-color: color-mix(in srgb, #{$fuji-primary} 82%, black);
155
+ border-color: color-mix(in srgb, #{$fuji-primary} 82%, black);
156
+ }
157
+ }
158
+
159
+ // Row-action dropdown trigger — active/hover state
160
+ .fuji-row-actions__trigger:hover,
161
+ .fuji-row-actions__trigger[aria-expanded="true"] {
162
+ background-color: color-mix(in srgb, #{$fuji-primary} 10%, white);
163
+ border-color: color-mix(in srgb, #{$fuji-primary} 30%, white);
164
+ color: color-mix(in srgb, #{$fuji-primary} 70%, black);
165
+ }
166
+
167
+ .fuji-row-actions__item:hover {
168
+ color: color-mix(in srgb, #{$fuji-primary} 70%, black);
169
+ }
170
+
171
+ // Float label — focused state
172
+ fieldset.inputs ol > li.fuji-float.fuji-float-focused > label {
173
+ color: #{$fuji-primary};
174
+ }
175
+
176
+ // Form inputs — focused border + ring
177
+ form input[type="text"]:focus,
178
+ form input[type="email"]:focus,
179
+ form input[type="password"]:focus,
180
+ form input[type="number"]:focus,
181
+ form input[type="search"]:focus,
182
+ form input[type="tel"]:focus,
183
+ form input[type="url"]:focus,
184
+ form input[type="date"]:focus,
185
+ form input[type="datetime-local"]:focus,
186
+ form textarea:focus,
187
+ form select:focus {
188
+ border-color: #{$fuji-primary};
189
+ box-shadow: 0 0 0 3px color-mix(in srgb, #{$fuji-primary} 18%, transparent);
190
+ }
191
+
192
+ // Status tags — selected row in index tables
193
+ table.index_table tbody tr.selected {
194
+ background-color: color-mix(in srgb, #{$fuji-primary} 8%, white);
195
+ }
196
+
197
+ // --- Full-theme overrides -------------------------------------------------
198
+ // Only applied when JS has set the `--fuji-surface` / `--fuji-text` / etc.
199
+ // custom properties (i.e. the current palette declared a `theme` block).
200
+ // Each rule uses `var(...)` with the compiled-time default as fallback, so
201
+ // non-themed palettes fall through to the baseline fuji look.
202
+
203
+ // Match base specificity — layouts/_wrapper.scss uses `body.active_admin`
204
+ // which beats a plain `body` selector.
205
+ body.active_admin {
206
+ background-color: var(--fuji-surface-alt, #{$body-background});
207
+ color: var(--fuji-text, #{$text-color});
208
+ }
209
+
210
+ // Top header bar
211
+ body.active_admin.logged_in > .header,
212
+ body.active_admin.logged_in #header {
213
+ background-color: var(--fuji-surface, #{$surface-0});
214
+ border-bottom-color: var(--fuji-border, #{$surface-border});
215
+
216
+ h1.site_title,
217
+ .site_title {
218
+ color: var(--fuji-text, #{$text-color});
219
+ border-right-color: var(--fuji-border, #{$surface-border});
220
+ }
221
+
222
+ #utility_nav li a {
223
+ color: var(--fuji-text-muted, #{$text-color-secondary});
224
+
225
+ &:hover {
226
+ color: var(--fuji-text, #{$text-color});
227
+ background-color: var(--fuji-surface-alt, #{$surface-100});
228
+ }
229
+ }
230
+ }
231
+
232
+ // Sidebar nav (#tabs). Base rule in layouts/_sidebar.scss compiles to three
233
+ // selector branches — match all three so our override wins at equal specificity
234
+ // across the cascade (otherwise `body.active_admin.logged_in .header #tabs`
235
+ // at (0,3,2) beats a single `body.active_admin.logged_in #tabs` at (0,2,2)).
236
+ body.active_admin.logged_in #tabs,
237
+ body.active_admin.logged_in #header #tabs,
238
+ body.active_admin.logged_in .header #tabs {
239
+ background-color: var(--fuji-surface, #{$surface-0});
240
+ border-right-color: var(--fuji-border, #{$surface-border});
241
+
242
+ > li > a {
243
+ color: var(--fuji-text-muted, #{$text-color-secondary});
244
+
245
+ &:hover {
246
+ background-color: var(--fuji-surface-alt, #{$surface-100});
247
+ color: var(--fuji-text, #{$text-color});
248
+ }
249
+ }
250
+
251
+ > li.has_nested > ul {
252
+ background-color: var(--fuji-surface-alt, #{$surface-50});
253
+
254
+ li a {
255
+ color: var(--fuji-text-muted, #{$text-color-secondary});
256
+
257
+ &:hover {
258
+ background-color: color-mix(in srgb, var(--fuji-surface, #{$surface-0}) 80%, black 0%);
259
+ color: var(--fuji-text, #{$text-color});
260
+ }
261
+ }
262
+ }
263
+ }
264
+
265
+ // Main content card
266
+ #main_content {
267
+ background-color: var(--fuji-surface, #{$surface-0});
268
+ }
269
+
270
+ // Title bar
271
+ #title_bar {
272
+ h2,
273
+ #page_title {
274
+ color: var(--fuji-text, #{$text-color});
275
+ }
276
+
277
+ .breadcrumb {
278
+ color: var(--fuji-text-muted, #{$text-color-muted});
279
+
280
+ a { color: var(--fuji-text-muted, #{$text-color-secondary}); }
281
+ }
282
+ }
283
+
284
+ // Panels & cards
285
+ .panel,
286
+ .sidebar_section.panel {
287
+ background-color: var(--fuji-surface, #{$surface-0});
288
+ border-color: var(--fuji-border, #{$surface-border});
289
+
290
+ > h3 {
291
+ color: var(--fuji-text, #{$text-color});
292
+ border-bottom-color: var(--fuji-border, #{$surface-200});
293
+ }
294
+ }
295
+
296
+ #sidebar .sidebar_section.panel > h3 {
297
+ background-color: var(--fuji-surface-alt, #{$surface-50});
298
+ color: var(--fuji-text-muted, #{$text-color-secondary});
299
+ }
300
+
301
+ // Fieldset inputs (form cards with legend header)
302
+ form fieldset.inputs {
303
+ background-color: var(--fuji-surface, #{$surface-0});
304
+ border-color: var(--fuji-border, #{$surface-border});
305
+
306
+ legend {
307
+ background-color: var(--fuji-surface-alt, #{$surface-50});
308
+ color: var(--fuji-text, #{$text-color});
309
+ border-bottom-color: var(--fuji-border, #{$surface-200});
310
+ }
311
+
312
+ ol > li {
313
+ > label {
314
+ color: var(--fuji-text-muted, #{$text-color-secondary});
315
+ }
316
+
317
+ p.inline-hints,
318
+ .inline-hints {
319
+ color: var(--fuji-text-muted, #{$text-color-muted});
320
+ }
321
+ }
322
+ }
323
+
324
+ // Text inputs
325
+ form input[type="text"],
326
+ form input[type="email"],
327
+ form input[type="password"],
328
+ form input[type="number"],
329
+ form input[type="search"],
330
+ form input[type="tel"],
331
+ form input[type="url"],
332
+ form input[type="date"],
333
+ form textarea,
334
+ form select {
335
+ background-color: var(--fuji-surface, #{$surface-0});
336
+ border-color: var(--fuji-border, #{$surface-border});
337
+ color: var(--fuji-text, #{$text-color});
338
+
339
+ &::placeholder { color: var(--fuji-text-muted, #{$text-color-muted}); }
340
+ }
341
+
342
+ // Tables
343
+ table.index_table,
344
+ .panel .panel_contents table:not(.index_table):not(.ui-datepicker-calendar),
345
+ #main_content > table:not(.index_table):not(.ui-datepicker-calendar),
346
+ #main_content table.summary-table {
347
+ background-color: var(--fuji-surface, #{$surface-0});
348
+
349
+ thead {
350
+ background-color: var(--fuji-surface-alt, #{$surface-50});
351
+
352
+ th {
353
+ color: var(--fuji-text-muted, #{$text-color-secondary});
354
+ border-bottom-color: var(--fuji-border, #{$surface-200});
355
+ }
356
+ }
357
+
358
+ tbody {
359
+ tr {
360
+ &:hover { background-color: var(--fuji-surface-alt, #{$surface-50}); }
361
+
362
+ td {
363
+ color: var(--fuji-text, #{$text-color});
364
+ border-bottom-color: var(--fuji-border, #{$surface-200});
365
+ }
366
+ }
367
+ }
368
+ }
369
+
370
+ // Attributes table
371
+ .attributes_table table {
372
+ th {
373
+ color: var(--fuji-text-muted, #{$text-color-muted});
374
+ border-bottom-color: var(--fuji-border, #{$surface-200});
375
+ }
376
+
377
+ td {
378
+ color: var(--fuji-text, #{$text-color});
379
+ border-bottom-color: var(--fuji-border, #{$surface-200});
380
+ }
381
+
382
+ tr:hover {
383
+ background-color: var(--fuji-surface-alt, #{$surface-50});
384
+ }
385
+ }
386
+
387
+ // Scopes pill bar
388
+ .scopes,
389
+ .table_tools .scopes {
390
+ background-color: var(--fuji-surface-alt, #{$surface-100});
391
+
392
+ li a { color: var(--fuji-text-muted, #{$text-color-secondary}); }
393
+
394
+ li.selected a {
395
+ background-color: var(--fuji-surface, #{$surface-0});
396
+ color: var(--fuji-text, #{$text-color});
397
+ }
398
+ }
399
+
400
+ // Paragraphs / pagination info
401
+ .pagination_information {
402
+ color: var(--fuji-text-muted, #{$text-color-muted});
403
+ border-top-color: var(--fuji-border, #{$surface-200});
404
+ }
405
+
406
+ .pagination a,
407
+ .pagination span.page.current,
408
+ .pagination span.current {
409
+ border-color: var(--fuji-border, #{$surface-border});
410
+ }
411
+
412
+ // Drawer
413
+ body.active_admin #sidebar {
414
+ background-color: var(--fuji-surface, #{$surface-0});
415
+ border-left-color: var(--fuji-border, #{$surface-border});
416
+ }
417
+
418
+ .fuji-filters-drawer__header {
419
+ border-bottom-color: var(--fuji-border, #{$surface-200});
420
+ }
421
+
422
+ .fuji-filters-drawer__title {
423
+ color: var(--fuji-text, #{$text-color});
424
+ }
425
+
426
+ body.active_admin #sidebar .sidebar_section.panel:not(#filters_sidebar_section) {
427
+ background-color: var(--fuji-surface-alt, #{$surface-50});
428
+ border-bottom-color: var(--fuji-border, #{$surface-200});
429
+
430
+ .panel_contents > div > h4 {
431
+ color: var(--fuji-text-muted, #{$text-color-muted});
432
+ }
433
+ }
434
+
435
+ // Watchlist bar
436
+ .fuji-watchlist-bar {
437
+ background-color: var(--fuji-surface-alt, #{$surface-50});
438
+ border-color: var(--fuji-border, #{$surface-border});
439
+
440
+ &__label { color: var(--fuji-text-muted, #{$text-color-muted}); }
441
+ &__empty { color: var(--fuji-text-muted, #{$text-color-muted}); }
442
+ }
443
+
444
+ // Download links
445
+ .download_links {
446
+ color: var(--fuji-text-muted, #{$text-color-muted});
447
+ border-top-color: var(--fuji-border, #{$surface-200});
448
+
449
+ a {
450
+ background-color: var(--fuji-surface-alt, #{$surface-100});
451
+ color: var(--fuji-text-muted, #{$text-color-secondary});
452
+ }
453
+ }
454
+
455
+ // Flash banners — keep semantic colour but use themed text against surface
456
+ .flash {
457
+ border-color: var(--fuji-border, transparent);
458
+ }
459
+
460
+ // Footer
461
+ #footer,
462
+ .footer {
463
+ color: var(--fuji-text-muted, #{$text-color-muted});
464
+ }
465
+
466
+ // --- Switcher UI ----------------------------------------------------------
467
+
468
+ .fuji-palette-switcher {
469
+ position: fixed;
470
+ right: $space-5;
471
+ bottom: $space-5;
472
+ z-index: 60;
473
+ font-family: $font-family-body;
474
+
475
+ &__trigger {
476
+ display: inline-flex;
477
+ align-items: center;
478
+ justify-content: center;
479
+ width: 44px;
480
+ height: 44px;
481
+ padding: 0;
482
+ background-color: $surface-0;
483
+ border: 1px solid $surface-border;
484
+ border-radius: $radius-full;
485
+ box-shadow: $shadow-md;
486
+ color: $text-color-secondary;
487
+ cursor: pointer;
488
+ transition: transform 0.15s ease, box-shadow 0.15s ease, color 0.15s ease;
489
+
490
+ &:hover {
491
+ transform: scale(1.05);
492
+ box-shadow: $shadow-lg;
493
+ color: $text-color;
494
+ }
495
+
496
+ &:focus-visible {
497
+ outline: none;
498
+ box-shadow: $shadow-focus;
499
+ }
500
+ }
501
+
502
+ &__panel {
503
+ position: absolute;
504
+ right: 0;
505
+ bottom: calc(100% + #{$space-2});
506
+ width: 320px;
507
+ max-height: #{"min(70vh, 560px)"}; // interpolated so SassC emits raw CSS min()
508
+ overflow-y: auto;
509
+ background-color: $surface-0;
510
+ border: 1px solid $surface-border;
511
+ border-radius: $border-radius-card;
512
+ box-shadow: $shadow-xl;
513
+ padding: $space-4;
514
+
515
+ &[hidden] {
516
+ display: none;
517
+ }
518
+ }
519
+
520
+ &__header {
521
+ display: flex;
522
+ align-items: center;
523
+ justify-content: space-between;
524
+ margin-bottom: $space-3;
525
+ }
526
+
527
+ &__title {
528
+ font-size: $font-size-xs;
529
+ font-weight: $font-weight-semibold;
530
+ text-transform: uppercase;
531
+ letter-spacing: 0.06em;
532
+ color: $text-color-muted;
533
+ }
534
+
535
+ &__grid {
536
+ display: grid;
537
+ grid-template-columns: repeat(2, 1fr);
538
+ gap: $space-2;
539
+ }
540
+
541
+ &__item {
542
+ display: flex;
543
+ flex-direction: column;
544
+ padding: 0;
545
+ background: $surface-0;
546
+ border: 1px solid $surface-border;
547
+ border-radius: $border-radius;
548
+ overflow: hidden;
549
+ cursor: pointer;
550
+ transition:
551
+ transform 0.15s ease,
552
+ border-color 0.15s ease,
553
+ box-shadow 0.15s ease;
554
+ text-align: left;
555
+
556
+ &:hover {
557
+ transform: translateY(-1px);
558
+ border-color: $text-color-secondary;
559
+ box-shadow: $shadow-sm;
560
+ }
561
+
562
+ &--active {
563
+ border-color: var(--fuji-primary, #{$primary-color});
564
+ box-shadow:
565
+ 0 0 0 2px color-mix(in srgb, var(--fuji-primary, #{$primary-color}) 30%, transparent);
566
+ }
567
+ }
568
+
569
+ &__swatches {
570
+ display: flex;
571
+ height: 28px;
572
+ }
573
+
574
+ &__bar {
575
+ flex: 1 1 0;
576
+ min-width: 0;
577
+ }
578
+
579
+ &__label {
580
+ display: flex;
581
+ align-items: center;
582
+ justify-content: space-between;
583
+ gap: $space-1;
584
+ padding: $space-1 $space-2;
585
+ border-top: 1px solid $surface-200;
586
+ font-size: $font-size-xs;
587
+ font-weight: $font-weight-medium;
588
+ color: $text-color;
589
+ white-space: nowrap;
590
+ overflow: hidden;
591
+ }
592
+
593
+ &__badge {
594
+ flex-shrink: 0;
595
+ font-size: $font-size-xs;
596
+ line-height: 1;
597
+ color: $primary-color;
598
+ opacity: 0.7;
599
+ }
600
+ }
@@ -0,0 +1,44 @@
1
+ // Panel — the generic card used for sidebar sections, dashboard tiles, and
2
+ // any `panel` helper from ActiveAdmin DSL.
3
+
4
+ .panel,
5
+ .sidebar_section.panel {
6
+ background-color: $surface-0;
7
+ border: 1px solid $surface-border;
8
+ border-radius: $border-radius-card;
9
+ box-shadow: $shadow-xs;
10
+ margin-bottom: $space-5;
11
+ overflow: hidden;
12
+
13
+ > h3 {
14
+ margin: 0;
15
+ padding: $space-4 $space-5;
16
+ font-size: $font-size-base;
17
+ font-weight: $font-weight-semibold;
18
+ color: $text-color;
19
+ border-bottom: 1px solid $surface-200;
20
+ background-color: transparent;
21
+ }
22
+
23
+ .panel_contents {
24
+ padding: $space-5;
25
+ }
26
+ }
27
+
28
+ // Inside the sidebar, tighten the defaults slightly.
29
+ #sidebar .sidebar_section.panel {
30
+ box-shadow: none;
31
+
32
+ > h3 {
33
+ font-size: $font-size-sm;
34
+ padding: $space-3 $space-4;
35
+ text-transform: uppercase;
36
+ letter-spacing: 0.04em;
37
+ color: $text-color-secondary;
38
+ background-color: $surface-50;
39
+ }
40
+
41
+ .panel_contents {
42
+ padding: $space-4;
43
+ }
44
+ }