active_admin_prism 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 856ce99225e35f41d012115c829406cb1de886ef7d36af3aa5b9e12978afe057
4
- data.tar.gz: f7698fb938f3ea46bb86496ce3f80cc7cfaa74fd887a9425b8b46b7711f38a13
3
+ metadata.gz: 72cc73689e83be856fdc1e2e321df486dc8cb6033bcca1380aae1d7aed8a15b0
4
+ data.tar.gz: 999e31015012d3dcb58de142de2fe050754fba7903612f259f8ab92709388c05
5
5
  SHA512:
6
- metadata.gz: add5ff5ce0bae255af731412b88af58dad8f9572323acf09f58ed8830253b44e13f269418a83ee796a50f0f19411ba7ea692893215e683379abd55acda003b9c
7
- data.tar.gz: 4f4554adf93c92eb6cc090b7b7116b54bad8fdab489dfa84d59c5aded4f3282a40c2d864b6b01011d78dd786178a2d27042fc260eb73aa68f37917a9c91cc10c
6
+ metadata.gz: f94ead774c60a6c285fa59c624c0f472cd7eb31c2a21d970a7609a74bb3f948d86754d32050d416c7fdfc2fb9fdaa915c3071f998a7832dacb02027ecc606052
7
+ data.tar.gz: b71bbf23aceebcf5febdc7690b4b27064d4d1b9dfe050254e931b15060398a35b55ea0a228220386098fd061e57633ab7e1d00ec3bc5af350db520bfdbb2f23f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,126 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.3
4
+
5
+ - A hamburger icon button next to the brand, at the top of the Prism
6
+ sidebar (`config.sidebar_collapsible`, default `true`), collapses it to
7
+ a narrow icon-only rail on desktop, expanding back to full width (with
8
+ labels) on another click — state persists across page loads. Purely a
9
+ desktop feature; the existing off-canvas mobile toggle below 900px is
10
+ unaffected either way. Every nav item keeps a native tooltip (its label,
11
+ on hover) so it stays identifiable while collapsed. Set
12
+ `config.sidebar_collapsible = false` to render no toggle at all — the
13
+ sidebar is always full width, matching this gem's behavior before this
14
+ flag existed.
15
+ - Flash messages now render as floating toast cards (icon + message +
16
+ dismiss button + a countdown progress bar), pinned to the top-right
17
+ corner of the viewport and stacking if more than one is active, instead
18
+ of ActiveAdmin's plain inline banner. A type-colored icon
19
+ (`:check_circle`/`:alert_triangle`/`:alert_circle`/`:info`) is selected
20
+ from the flash's key — `:notice`/`:success`, `:alert`/`:warning`,
21
+ `:error`, and anything else, respectively. While `flash_auto_dismiss`
22
+ is on, a bar along the card's bottom edge visually counts down over
23
+ `flash_auto_dismiss_seconds`; hovering the card pauses both that bar
24
+ and the actual removal timer in lockstep (not just the animation), so a
25
+ flash a visitor is mid-read can't vanish out from under them. This
26
+ applies identically to Devise's sign-in/password/etc pages, which
27
+ needed a small layout override of their own — see
28
+ `app/views/layouts/active_admin_logged_out.html.erb` — since those
29
+ route through a completely separate layout ActiveAdmin itself ships
30
+ rather than through this gem's usual Arbre-based override point.
31
+ - The active filters bar is now itself a shortcut to the Filters form —
32
+ clicking anywhere on it opens the (possibly collapsed) Filters panel and
33
+ scrolls it into view, instead of only the separate funnel icon doing
34
+ that.
35
+ - Fixed: the active filters bar fell 12px short of the table's own right
36
+ edge instead of aligning flush with it — `.table_tools`'s `gap` and the
37
+ bar's `margin-left: auto` (used to push it to the row's far end) are on
38
+ the same axis, and a nonzero column-gap there gets double-counted by
39
+ the auto margin's free-space math, leaving exactly one gap's worth of
40
+ space unclaimed after the last item. Switched to `row-gap` (still
41
+ spaces Batch Actions from the bar vertically if they wrap onto separate
42
+ lines on a narrow viewport, without the bug).
43
+ - Fixed: the rail-collapsed sidebar (`config.sidebar_collapsible`) had two
44
+ space issues — a group left open before collapsing kept rendering its
45
+ full submenu (every child's icon *and* label) spilling out past the
46
+ 76px rail instead of collapsing to just the parent's own icon (a
47
+ `.prism-nav-item.open > .prism-nav-submenu` rule was more specific than
48
+ the one meant to hide it); and any menu item with no `icon:` set (see
49
+ [Sidebar navigation: icons & badges] in INTEGRATION.md) rendered as
50
+ either an empty color-highlighted box (if `.active`) or a totally blank
51
+ row once its label was hidden, reading as broken dead space. Menu items
52
+ without an icon now get a small dot instead, once collapsed.
53
+ - Fixed: the mobile off-canvas sidebar toggle (`.prism-sidebar-mobile-toggle`,
54
+ ≤900px viewports) was rendered completely off-screen and unclickable —
55
+ it's a `position: fixed` descendant of `#header.prism-sidebar`, and that
56
+ element's own `transform: translateX(-100%)` (used to slide the closed
57
+ sidebar off-screen) made it the containing block for that fixed
58
+ descendant too, dragging the toggle button off-screen right along with
59
+ the hidden sidebar. The off-canvas slide now animates `left` instead of
60
+ `transform`, which carries no such side effect.
61
+ - The "current scope + active filters" summary (ActiveAdmin core's own
62
+ "Search status" sidebar section, auto-added to every resource) now
63
+ renders as a highlighted pill bar in the same row as the Batch Actions
64
+ button/scope tabs, instead of inside `#sidebar`
65
+ (`config.active_filters_bar`, default `true`) — tinted with the theme's
66
+ primary color so it reads as a clear, eye-catching signal rather than
67
+ another gray panel. It used to get squeezed down to the same 72px icon
68
+ gutter as the Filters form whenever `collapsible_filters` had it
69
+ collapsed, and its content had nowhere to fit in 72px — it overflowed
70
+ out over the table instead of shrinking cleanly. Set
71
+ `config.active_filters_bar = false` to restore ActiveAdmin's stock
72
+ sidebar-based behavior.
73
+ - Fixed: a Select2-enhanced `<select>` in the main form (`config.select2`,
74
+ or any field opted in individually) rendered full-width on its own line
75
+ below its label instead of beside it, like every other field. The BFC
76
+ sizing trick used to fit it into ActiveAdmin core's floated-label layout
77
+ only works when the element's width is `auto` — but Select2 always sets
78
+ an inline `width: 100%` on `.select2-container` itself (prism.js's
79
+ auto-init passes `{ width: "100%" }`, and a host's own manual
80
+ `.select2()` call hits the same code path at its default width), so that
81
+ trick never actually engaged. Matches ActiveAdmin core's own input width
82
+ instead.
83
+ - Fixed: a field row whose label this theme deliberately doesn't float
84
+ (e.g. a boolean checkbox, or `as: :prism_toggle`) could let the *next*
85
+ row's floated label render up alongside it instead of starting on its
86
+ own line below, since the short row's un-cleared float left no height
87
+ for the next label to clear against. Every field row now clears its own
88
+ floats.
89
+
90
+ ## 0.1.2
91
+
92
+ - Adds [Select2](https://select2.org) support (`config.select2`, default
93
+ `false` — the only opt-in-by-default flag in this gem) — reskinned to
94
+ match the theme, and now vendored inside the gem's own assets (no
95
+ separate gem/npm dependency, no JS of your own required). Turn it on to
96
+ auto-enhance *every* plain `<select>` (filters, form inputs, association
97
+ pickers) into a searchable widget with zero per-field setup; or leave it
98
+ off and opt individual fields in yourself the same way you would in any
99
+ other Rails app (`input_html: { class: "..." }` + your own `.select2()`
100
+ call) — both approaches coexist without double-initializing the same
101
+ element. Covers single-select, multi-select ("tags"/pill chips), and the
102
+ open dropdown/search box/results list — see
103
+ [Select2](INTEGRATION.md#select2) in INTEGRATION.md. Without the CSS
104
+ half of this, a Select2-enhanced select rendered at its tiny unstyled
105
+ default size, and its open dropdown could clash with the theme entirely.
106
+ - Fixed: the collapsible Filters sidebar panel kept `overflow: hidden`
107
+ even while expanded, clipping/garbling any dropdown (Select2 or AA's own
108
+ "select + search" filter widget) that needed to render outside its own
109
+ input's bounds. `&.open`/the `collapsible_filters: false` backstop now
110
+ reset `overflow` back to `visible`.
111
+ - Fixed: the Cancel button (and any other `fieldset.actions`/
112
+ `fieldset.buttons` link styled via `prism-button-secondary`) rendered
113
+ with ActiveAdmin's own pill-shaped `border-radius: 200px` instead of
114
+ Prism's — a more specific AA selector was winning on that one property
115
+ even though Prism's color/background already won via `!important`. Both
116
+ button mixins now mark `border-radius` `!important` too.
117
+ - Fixed: form action buttons (Create/Update + Cancel) could stack
118
+ vertically instead of sitting side by side. ActiveAdmin lays them out
119
+ via `float: left` on each `<li>`, which is fragile (a longer button
120
+ label, or a host's own CSS, can lose the float); the actions `<ol>` is
121
+ now a flex row instead, which floats have no effect on regardless of
122
+ specificity or content width.
123
+
3
124
  ## 0.1.1
4
125
 
5
126
  - A search box renders at the top of the sidebar's "Pages" nav
data/INTEGRATION.md CHANGED
@@ -116,6 +116,7 @@ ActiveAdminPrism.configure do |config|
116
116
  config.colorize_action_icons = true # default: true
117
117
  config.styled_confirms = true # default: true
118
118
  config.collapsible_filters = true # default: true
119
+ config.active_filters_bar = true # default: true
119
120
  config.sidebar_footer = true # default: true
120
121
  config.flash_dismissible = true # default: true
121
122
  config.flash_auto_dismiss = true # default: true
@@ -131,6 +132,9 @@ ActiveAdminPrism.configure do |config|
131
132
  { label: "Español", locale: :es },
132
133
  { label: "Français", locale: :fr }
133
134
  ]
135
+ config.menu_search = true # default: true
136
+ config.select2 = false # default: false (opt-in — see below)
137
+ config.sidebar_collapsible = true # default: true
134
138
  end
135
139
 
136
140
  ActiveAdminPrism.enable!
@@ -142,6 +146,7 @@ ActiveAdminPrism.enable!
142
146
  | `colorize_action_icons` | `true` | Index-table View/Edit/Delete render as ActiveAdmin's plain text links instead of color-coded icon buttons. |
143
147
  | `styled_confirms` | `true` | Row-level `data-confirm` links (View/Edit/Delete, or anything else using Rails UJS's `data-confirm`) fall back to the browser's native `confirm()`. Batch Actions confirms are unaffected either way — they always use ActiveAdmin's own dialog. |
144
148
  | `collapsible_filters` | `true` | The "Filters" sidebar panel always renders fully expanded (ActiveAdmin's own default) instead of collapsing to a single icon button that expands on click. |
149
+ | `active_filters_bar` | `true` | The current scope/active-filters summary renders inside `#sidebar` as its own panel (ActiveAdmin's own default) instead of as a highlighted bar beside Batch Actions — see [Active filters bar](#active-filters-bar). |
145
150
  | `sidebar_footer` | `true` | "Powered by Active Admin" (or your own `config.footer`) stays in ActiveAdmin's original page-level `#footer` instead of moving into the sidebar. |
146
151
  | `flash_dismissible` | `true` | Flash messages render as ActiveAdmin's original plain `<div>` (no dismiss button). |
147
152
  | `flash_auto_dismiss` | `true` | Flash messages stay on screen until the next page load (ActiveAdmin's default) instead of disappearing on their own. |
@@ -153,6 +158,9 @@ ActiveAdminPrism.enable!
153
158
  | `login_tagline` | `"Sign in to your admin dashboard"` | `nil` renders no tagline at all. |
154
159
  | `language_switcher` | `true` | No "Languages" dropdown renders in the sidebar at all — see [Language switcher](#language-switcher). |
155
160
  | `languages` | 3 entries (English/Español/Français) | The list the dropdown renders; an empty array (`[]`) has the same effect as `language_switcher = false`. |
161
+ | `menu_search` | `true` | No search box renders above the sidebar's "Pages" nav — see [Menu search](#menu-search). |
162
+ | `select2` | `false` | **Opposite polarity from every other flag above — opt-in, not opt-out.** `false` (the default) leaves every `<select>` exactly as ActiveAdmin renders it. `true` auto-enhances *every* plain `<select>` (filters, form inputs, association pickers — no per-field setup) into a searchable Select2 widget — see [Select2](#select2). |
163
+ | `sidebar_collapsible` | `true` | No hamburger toggle button renders next to the brand — the sidebar is always full width, with no way to collapse it to an icon-only rail. Desktop-only either way; the mobile off-canvas toggle is unaffected — see [Collapsible sidebar rail](#collapsible-sidebar-rail). |
156
164
 
157
165
  **How this crosses the server/client boundary.** `sidebar`,
158
166
  `colorize_action_icons`, and the `login_*` flags are pure server-side
@@ -284,6 +292,23 @@ passes this hash through untouched) accepts: `:dashboard`, `:users`,
284
292
  `:home`, `:list`, `:folder`, `:bell`, `:search`, `:menu`, `:logout`,
285
293
  `:check`, `:x`, `:chevron_down`, `:eye`, `:pencil`, `:trash`, `:filter`.
286
294
 
295
+ ### Collapsible sidebar rail
296
+
297
+ A hamburger icon button next to the brand, at the top of the sidebar,
298
+ collapses it to a narrow icon-only rail — labels, the search box, language
299
+ switcher, and section headings all hide, leaving just the icons (each
300
+ still identifiable via a native tooltip on hover). Clicking again expands
301
+ it back to full width. The choice persists across page loads
302
+ (`localStorage`, like the per-group nav expand/collapse state already
303
+ does). Desktop-only: below the 900px mobile breakpoint the sidebar is
304
+ already off-canvas (a full-width drawer toggled by its own separate
305
+ hamburger button, `.prism-sidebar-mobile-toggle`), and collapsing to a
306
+ rail there wouldn't make sense — this toggle has no effect on that
307
+ behavior either way. Turn it off with
308
+ `config.sidebar_collapsible = false` to remove the toggle entirely (the
309
+ sidebar is then always full width, ActiveAdmin's own implicit default
310
+ before this flag existed).
311
+
287
312
  ### Parent groups & submenus (nested navigation)
288
313
 
289
314
  Nested groups (e.g. an "E-Commerce" group containing "Products" and
@@ -421,6 +446,40 @@ ActiveAdmin's own `Menu`/`MenuItem`/`build_menu` machinery — see
421
446
  [Language switcher markup](#language-switcher-markup) for why, and for the
422
447
  full class/id reference.
423
448
 
449
+ ### Menu search
450
+
451
+ A search box renders at the top of the sidebar, between the language
452
+ switcher (if any) and the "Pages" nav — no setup required beyond the
453
+ default `config.menu_search = true`. It filters your existing `menu do |m|
454
+ ... end` items by label as you type; there's no server round trip and no
455
+ change to how those blocks are authored in `app/admin/*.rb` — see
456
+ `lib/active_admin/views/prism_sidebar.rb#render_search_box` for the markup
457
+ and `js-src/prism.js` for the filtering logic itself.
458
+
459
+ Matching is case-insensitive and works at any nesting depth, since the
460
+ whole menu tree is already rendered up front and the filtering happens
461
+ purely client-side over the existing DOM:
462
+
463
+ - A submenu item that matches keeps its parent group visible **and
464
+ expanded**, even though the parent's own label doesn't match — so a
465
+ match buried a couple of levels deep is never hidden behind a collapsed
466
+ group.
467
+ - A parent whose own label matches reveals its **entire** submenu,
468
+ expanded, regardless of whether any individual child also matches.
469
+ - Items that don't match (and have no matching descendant) get
470
+ `.prism-nav-hidden`; if nothing in the whole nav matches, a
471
+ `.prism-nav-empty` "No matching menu items" message takes their place.
472
+
473
+ Clearing the input — via the "x" button (`data-prism-nav-search-clear`,
474
+ only shown while there's a query) or pressing <kbd>Escape</kbd> while the
475
+ input has focus and a value — resets the nav back to its normal
476
+ expand/collapse state (whatever `.open`/`.active` state it already had
477
+ from user-toggling or the current page, unrelated to search).
478
+
479
+ Turn it off with `config.menu_search = false` — no search box renders at
480
+ all, and the "Pages" nav starts directly below the brand/language
481
+ switcher, matching this gem's behavior before the feature existed.
482
+
424
483
  ### Icon helper
425
484
 
426
485
  Available anywhere in your admin views (not just the sidebar):
@@ -461,6 +520,92 @@ end
461
520
  Explicit opt-in per column/row — ActiveAdmin's default `status_tag`
462
521
  "Yes"/"No" pill is untouched everywhere you don't call it.
463
522
 
523
+ ### Select2
524
+
525
+ Prism reskins [Select2](https://select2.org) — the jQuery widget that makes
526
+ a `<select>` searchable — and ships it vendored inside its own assets
527
+ (`vendor/select2`, MIT licensed), so there's no separate gem/npm dependency
528
+ or JS of your own to add either way. Two ways to use it:
529
+
530
+ **1. Every select, automatically — `config.select2 = true`.** Opt-in
531
+ (default `false`, the only flag in this gem with that polarity — see
532
+ [Configuration reference](#configuration-reference)):
533
+
534
+ ```ruby
535
+ ActiveAdminPrism.configure do |config|
536
+ config.select2 = true
537
+ end
538
+ ```
539
+
540
+ With this on, *every* plain `<select>` ActiveAdmin renders — filters, form
541
+ inputs, association pickers, ransack predicate dropdowns, date-part
542
+ selects, all of it, no per-field setup — becomes a searchable Select2
543
+ widget. There's no way to exclude individual selects from this today; if
544
+ you only want it on specific fields, use the next approach instead.
545
+
546
+ **2. Specific fields only — bring your own `.select2()` call.** Leave
547
+ `config.select2` at its default `false` and initialize Select2 yourself,
548
+ the same way you would in any other Rails app (this still works whether or
549
+ not you also load your own separate copy of Select2 — Prism's vendored
550
+ copy and a host's own don't conflict, they just both define
551
+ `jQuery.fn.select2` and the last one loaded wins, harmlessly):
552
+
553
+ ```ruby
554
+ # app/admin/teachers.rb
555
+ filter :subject, input_html: { class: "your-select2-class" }
556
+
557
+ form do |f|
558
+ f.input :subject, input_html: { class: "your-select2-class" }
559
+ end
560
+ ```
561
+
562
+ ```js
563
+ $(".your-select2-class").select2({ width: "100%" })
564
+ ```
565
+
566
+ Either way, any element Select2 replaces picks up Prism's border/radius/
567
+ focus-ring styling automatically, matching every other input in the
568
+ theme; its open dropdown (search box, results list) is styled to match
569
+ Prism's popover look — see [Select2 markup](#select2-markup) for the
570
+ class reference. The auto-init (approach 1) skips any `<select>` a host
571
+ already initialized manually (approach 2) — see `js-src/prism.js` — so
572
+ the two can coexist: turn `config.select2` on globally and still hand-roll
573
+ one particular field's Select2 options (`tags: true`, a custom
574
+ `ajax:`, etc.) yourself, since your own `.select2()` call runs first and
575
+ the auto-init recognizes it's already initialized.
576
+
577
+ **Multi-select ("tags") mode** — e.g. a `has_many`/`has_and_belongs_to_many`
578
+ association — is themed too, as pill-shaped chips instead of Select2's own
579
+ default boxed/absolute-positioned look:
580
+
581
+ ```ruby
582
+ f.input :subjects, as: :select, multiple: true, input_html: { class: "your-select2-class" }, collection: Subject.all
583
+ ```
584
+
585
+ Everything above (width handling, dropdown styling) applies the same way
586
+ regardless of single/multiple mode, and regardless of which of the two
587
+ approaches initialized it.
588
+
589
+ **Why width behaves differently in the sidebar Filters panel vs. a form.**
590
+ The Filters panel and standalone filter forms stack each field's label
591
+ above it (no float), so Select2 renders at a flat `width: 100%` there,
592
+ matching `.sidebar_section select`'s own width rule. A `fieldset.inputs`
593
+ form (the main new/edit form) instead floats the label to the *left* and
594
+ gives text inputs an explicit `calc(80% - padding)` width so they sit
595
+ beside it — a padding value this gem has no access to at compile time
596
+ (its CSS is compiled standalone from `scss-src/*.scss`, without
597
+ ActiveAdmin's own Sass variables in its load path; see
598
+ [Customizing colors](#customizing-colors)). Rather than hardcode an
599
+ equivalent, Prism gives the field its own block formatting context
600
+ (`overflow: hidden`, no explicit width) there instead — the CSS spec
601
+ requires a box like that not to overlap a preceding float's box, so the
602
+ browser sizes it to exactly the remaining space automatically, no magic
603
+ number needed. If you render a Select2 field somewhere using neither of
604
+ these two layout conventions, you may need your own `width`/`overflow`
605
+ override alongside it — without one, a full-width Select2 box will render
606
+ *underneath* a floated label rather than beside it, visually hiding the
607
+ label.
608
+
464
609
  ### Row-level action icons
465
610
 
466
611
  View/Edit/Delete on index pages render as color-coded icon buttons (blue
@@ -493,12 +638,46 @@ The reflow relies on the CSS `:has()` selector (broadly supported in
493
638
  current browsers); without it, the Filters panel still collapses/expands
494
639
  correctly, it just won't reclaim the extra width.
495
640
 
641
+ ### Active filters bar
642
+
643
+ Once at least one filter or scope is active, a summary ("Scope: All",
644
+ "Bank code contains BCA", etc.) renders as a highlighted pill bar in the
645
+ same row as the Batch Actions button/scope tabs (AA core's own
646
+ `.table_tools`, pushed to the row's far end), instead of inside
647
+ ActiveAdmin's own `#sidebar` as its own panel. Tinted with the theme's
648
+ primary color (a colored left border + tinted background, distinct from
649
+ the plain gray panels elsewhere) so an active filter reads as a clear,
650
+ eye-catching signal rather than blending in as more chrome. It's also
651
+ clickable — clicking anywhere on it opens the Filters panel (expanding it
652
+ if `collapsible_filters` has it collapsed) and scrolls it into view,
653
+ a shortcut to editing the filters currently producing this exact result
654
+ set, rather than only the separate funnel icon doing that. This is also
655
+ the fix for that sidebar summary overflowing out whenever the collapsible
656
+ Filters panel (above) is collapsed to its 72px icon gutter — there's
657
+ nowhere in 72px for a sentence-length filter description to fit. Turn it
658
+ off with `config.active_filters_bar = false` to restore ActiveAdmin's own
659
+ stock sidebar-based rendering (only sensible if `collapsible_filters` is
660
+ also `false`, since otherwise the two flags combined bring the overflow
661
+ back).
662
+
496
663
  ### Flash messages
497
664
 
498
- Flash messages get a dismiss button, auto-hide after a configurable delay,
499
- and fade/slide out with a smooth, configurable transition see
500
- [Configuration reference](#configuration-reference) for
501
- `flash_dismissible`, `flash_auto_dismiss(_seconds)`, and
665
+ Flash messages render as floating toast cards, pinned to the top-right
666
+ corner of the viewport (stacking if more than one is active) instead of
667
+ ActiveAdmin's plain inline banner — a type-colored icon
668
+ (`:check_circle`/`:alert_triangle`/`:alert_circle`/`:info` depending on
669
+ the flash key: `:notice`/`:success`, `:alert`/`:warning`, `:error`, and
670
+ anything else respectively), the message, a dismiss button, and — while
671
+ `flash_auto_dismiss` is on — a countdown bar along the card's bottom edge
672
+ that visually empties out over `flash_auto_dismiss_seconds`, pausing
673
+ (along with the actual auto-dismiss timer, not just its own animation) as
674
+ long as the pointer is over the card, so a flash a visitor is mid-read
675
+ never vanishes out from under them. Fades/slides out with a smooth,
676
+ configurable transition on dismiss (manual or automatic) either way. This
677
+ applies identically on Devise's sign-in/password/etc pages — see
678
+ [Flash messages markup](#flash-messages-markup) for why that needed its
679
+ own layout override. See [Configuration reference](#configuration-reference)
680
+ for `flash_dismissible`, `flash_auto_dismiss(_seconds)`, and
502
681
  `flash_transition_ms`.
503
682
 
504
683
  ### Sidebar footer ("Powered by Active Admin")
@@ -641,15 +820,24 @@ Ruby view files under `lib/active_admin/views/`.
641
820
  span.prism-sidebar-mobile-toggle <- hamburger, ≤900px viewports only
642
821
  div.prism-sidebar-inner
643
822
  div.prism-sidebar-brand
823
+ span.prism-sidebar-collapse-toggle[role=button][data-prism-toggle-sidebar-collapse] <- only if config.sidebar_collapsible
824
+ svg.prism-sidebar-collapse-icon <- the :menu (hamburger) icon
644
825
  #site_title <- AA's own site_title verb, unchanged
645
826
  div.prism-sidebar-lang <- only if config.language_switcher and #languages is non-empty
827
+ div.prism-sidebar-search <- only if config.menu_search
828
+ svg.prism-nav-icon.prism-search-icon
829
+ input.prism-nav-search-input[type=search][data-prism-nav-search]
830
+ span.prism-nav-search-clear[data-prism-nav-search-clear]
831
+ svg.prism-nav-icon <- the :x icon
646
832
  div.prism-sidebar-scroll
647
833
  div.prism-nav-section-label <- "PAGES"
648
834
  ul.prism-nav
649
835
  li.prism-nav-item[#prism_nav_<id>]
650
836
  [.has-children] <- item.items.any?
651
837
  [.active] <- item.current?(current_tab)
652
- [.open] <- has-children && active, or user-toggled
838
+ [.open] <- has-children && active, or user-toggled, or search match (see below)
839
+ [.prism-nav-hidden] <- filtered out by menu search, toggled client-side
840
+ [.prism-search-open] <- this item or a descendant matches the current search query
653
841
  span.prism-nav-group-toggle <- only when .has-children
654
842
  svg.prism-nav-icon
655
843
  span.prism-nav-label
@@ -658,6 +846,7 @@ Ruby view files under `lib/active_admin/views/`.
658
846
  svg.prism-nav-icon
659
847
  span.prism-nav-label
660
848
  ul.prism-nav-submenu <- only when .has-children, nested li.prism-nav-item...
849
+ div.prism-nav-empty[.prism-nav-empty-visible] <- "No matching menu items", shown when search yields zero results
661
850
  div.prism-sidebar-utility <- only if the utility menu has items
662
851
  ul.prism-nav.prism-nav-utility
663
852
  li#prism_nav_current_user
@@ -680,8 +869,16 @@ Notes:
680
869
  built-in styling of its own beyond what you see in `_sidebar.scss` — it's
681
870
  just an example class name, feel free to use your own.
682
871
  - Body-level state: `body.prism-sidebar-open` (mobile off-canvas open,
683
- toggled by `prism.js`), `body.prism-sidebar-footer-disabled` (set when
684
- `config.sidebar_footer` is `false` — see [Configuration reference](#configuration-reference)).
872
+ toggled by `prism.js`), `body.prism-sidebar-collapsed` (desktop rail
873
+ collapsed, also toggled by `prism.js` and persisted to `localStorage` —
874
+ see [Collapsible sidebar rail](#collapsible-sidebar-rail)),
875
+ `body.prism-sidebar-footer-disabled` (set when `config.sidebar_footer` is
876
+ `false` — see [Configuration reference](#configuration-reference)).
877
+ - Every `a.prism-nav-link` / `span.prism-nav-group-toggle` also carries a
878
+ plain `title="<label>"` attribute (a host's own explicit `:title` via
879
+ `html_options` wins instead) — inert most of the time, but the only way
880
+ left to identify an item by hovering once `.prism-nav-label` itself is
881
+ hidden by the rail-collapsed state above.
685
882
 
686
883
  ### Language switcher markup
687
884
 
@@ -708,6 +905,37 @@ than being fixed at boot the way the sidebar's own header-swap
708
905
  registration is (see [Sign-in page](#sign-in-page) for the other example
709
906
  of that "built once at boot vs. re-read every request" distinction).
710
907
 
908
+ ### Menu search markup
909
+
910
+ ```
911
+ div.prism-sidebar-search
912
+ svg.prism-nav-icon.prism-search-icon
913
+ input.prism-nav-search-input[type=search][data-prism-nav-search][placeholder="Search menu"]
914
+ span.prism-nav-search-clear[data-prism-nav-search-clear][.prism-nav-search-clear-visible]
915
+ svg.prism-nav-icon <- the :x icon
916
+ ```
917
+
918
+ All filtering state lives on the existing `li.prism-nav-item` tree
919
+ rendered by [Sidebar](#sidebar-activeadminviewsprismsidebar) — `prism.js`
920
+ reads `[data-prism-nav-search]`'s value on every `input` event and, per
921
+ item, toggles:
922
+
923
+ - `.prism-nav-hidden` — item (and every descendant) doesn't match and has
924
+ no matching descendant; hidden via CSS.
925
+ - `.prism-search-open` — item itself matches, or has a matching
926
+ descendant; combined with `.has-children`, this is what keeps a group
927
+ expanded during a search independently of its own user-toggled `.open`
928
+ state.
929
+ - `.prism-nav-search-clear-visible` on the clear button, and
930
+ `.prism-nav-empty-visible` on `div.prism-nav-empty`, both mirroring
931
+ whether the query is non-empty / yields zero matches.
932
+
933
+ <kbd>Escape</kbd> while the input is focused and non-empty, or a click on
934
+ `[data-prism-nav-search-clear]`, clears the value and re-triggers the same
935
+ filtering pass (an empty query matches everything, restoring the nav's
936
+ prior expand/collapse state). None of this touches the server — the menu
937
+ tree itself is rendered once, same as without `config.menu_search`.
938
+
711
939
  ### Panels & cards
712
940
 
713
941
  Pure CSS reskin of AA's existing `Panel`/`Component` markup — no new
@@ -774,6 +1002,39 @@ read-only tag — same pill/thumb CSS, driven by a sibling `:checked`
774
1002
  selector in the form case and by the `.on`/`.off` class in the read-only
775
1003
  case (there's no real `<input>` on an index/show page).
776
1004
 
1005
+ ### Select2 markup
1006
+
1007
+ Only rendered if your app's own JS actually calls `.select2()` on an
1008
+ element — see [Select2](#select2). This is
1009
+ Select2's own markup, reskinned by targeting its own class names, not
1010
+ anything Prism itself renders:
1011
+
1012
+ ```
1013
+ .select2-container <- replaces the original (now hidden) <select>
1014
+ .select2-selection--single <- single-select: the visible closed-state box
1015
+ .select2-selection__rendered <- selected option's text
1016
+ .select2-selection__placeholder
1017
+ .select2-selection__arrow
1018
+ .select2-selection__clear <- the "x" clear button (allowClear: true)
1019
+ .select2-selection--multiple <- multiple: true instead — a row of pill "chips"
1020
+ .select2-selection__rendered
1021
+ li.select2-selection__choice <- one per selected option
1022
+ .select2-selection__choice__display <- its label text
1023
+ .select2-selection__choice__remove <- its own "x" remove button
1024
+ .select2-search--inline
1025
+ input.select2-search__field <- the free-typing search box inline with the chips
1026
+ [.select2-container--open] <- while its dropdown is open
1027
+ [.select2-container--focus] <- multiple mode: while focused (not necessarily open)
1028
+ [.select2-container--disabled]
1029
+
1030
+ .select2-dropdown <- the open dropdown, appended to <body> (or `dropdownParent`)
1031
+ .select2-search--dropdown
1032
+ input.select2-search__field <- the built-in search box
1033
+ ul.select2-results
1034
+ li.select2-results__option[.select2-results__option--highlighted][aria-selected="true"]
1035
+ li.select2-results__message <- "No results found" etc.
1036
+ ```
1037
+
777
1038
  ### Filters sidebar panel (`#filters_sidebar_section`)
778
1039
 
779
1040
  Only this specific `SidebarSection` (AA's built-in id for the Filters
@@ -799,21 +1060,70 @@ panel) gets the extra icon/collapse markup — any other sidebar section
799
1060
  `body.prism-filters-collapsible-disabled` is the backstop class that forces
800
1061
  the panel back to always-expanded.
801
1062
 
1063
+ ### Active filters bar (`#prism_active_filters_bar`)
1064
+
1065
+ Only present once at least one filter or scope is active
1066
+ (`config.active_filters_bar`, default `true` — see
1067
+ [Active filters bar](#active-filters-bar)); reuses ActiveAdmin core's own
1068
+ `ActiveAdmin::Views::ActiveFiltersSidebarContent` markup/i18n wholesale, so
1069
+ the `h4`/`b`/`ul`/`li` structure below is AA's, not Prism's own:
1070
+
1071
+ ```
1072
+ #main_content
1073
+ .index_content
1074
+ .table_tools <- AA core's own — Batch Actions/scope tabs row
1075
+ .table_tools_actions <- only if any_table_tools? — wraps the controls AA core itself renders here
1076
+ .dropdown_menu <- Batch Actions button
1077
+ .scopes <- scope tabs, if any are defined
1078
+ #prism_active_filters_bar.prism-active-filters-bar <- only if a scope/filter is active; pushed to the row's far end
1079
+ h4 + b.current_scope_name <- only if a scope is active
1080
+ div
1081
+ h4 <- "Current filters:"
1082
+ ul
1083
+ li[class="current_filter_*"] <- one per active filter/scope value
1084
+ span <- filter label + predicate
1085
+ b <- the filter's value
1086
+ ```
1087
+
802
1088
  ### Flash messages markup
803
1089
 
1090
+ Rendered twice over — once from `lib/active_admin/views/flash_messages.rb`
1091
+ (Arbre, for every logged-in page) and once, identically, from
1092
+ `app/views/layouts/active_admin_logged_out.html.erb` (plain ERB, for
1093
+ Devise's sign-in/password/etc pages, which route through a completely
1094
+ separate layout ActiveAdmin itself ships rather than through
1095
+ `Pages::Base`/Arbre at all — the Ruby-side override alone never reaches
1096
+ them, which is why this gem ships a full layout override just for this).
1097
+ Both share the same icon-selection logic
1098
+ (`ActiveAdminPrism::Icons.flash_icon_name`, in `lib/prism_icons.rb`) and
1099
+ duration math (`ActiveAdminPrism::Configuration#flash_auto_dismiss_ms`)
1100
+ rather than duplicating either:
1101
+
804
1102
  ```
805
- .flashes[data-prism-transition-ms][data-prism-auto-dismiss-ms]
806
- .flash.flash_notice / .flash_error / .flash_alert [.prism-flash-hide]
1103
+ .flashes[data-prism-transition-ms][data-prism-auto-dismiss-ms] <- position: fixed toast stack, top-right
1104
+ .flash.flash_notice / .flash_success / .flash_alert / .flash_warning / .flash_error / .flash_info [.prism-flash-hide]
1105
+ [style="--prism-flash-duration: <ms>"] <- only if config.flash_auto_dismiss
1106
+ svg.prism-flash-icon <- :check_circle / :alert_triangle / :alert_circle / :info, by type
807
1107
  span.prism-flash-message
808
- button.prism-flash-dismiss[data-prism-flash-dismiss] <- only if config.flash_dismissible
1108
+ button.prism-flash-dismiss[data-prism-flash-dismiss] <- only if config.flash_dismissible
809
1109
  svg.prism-flash-dismiss-icon
1110
+ div.prism-flash-progress <- only if config.flash_auto_dismiss — the countdown bar
810
1111
  ```
811
1112
 
812
1113
  `flash_notice`/`flash_error`/`flash_alert` are ActiveAdmin's own type
813
- classes (from `flash_messages.each { |type, ...| }`); Prism just colors
814
- each one distinctly. `.prism-flash-hide` is added by `prism.js` right
815
- before removal (opacity/transform transition), timed against the
816
- `data-prism-transition-ms` attribute see
1114
+ classes (from `flash_messages.each { |type, ...| }`); `flash_success`/
1115
+ `flash_warning`/`flash_info` are the same convention extended to a host
1116
+ setting those keys directly (`flash[:warning] = "..."`, etc) Prism
1117
+ colors each of the four icon/progress-bar combinations distinctly, all
1118
+ five type classes included. `.prism-flash-hide` is added by `prism.js`
1119
+ right before removal (opacity/transform transition), timed against the
1120
+ `data-prism-transition-ms` attribute. `.prism-flash-progress`'s width
1121
+ animates via CSS (`@keyframes prism-flash-countdown`, `transform: scaleX`)
1122
+ against the same duration `prism.js` uses for the actual removal timer —
1123
+ hovering a card pauses both in lockstep (`animation-play-state` for the
1124
+ bar, a tracked remaining-time restart for the timer itself) rather than
1125
+ just the visual, so a paused bar can't silently disagree with a flash
1126
+ that's still counting down underneath it. See
817
1127
  [Flash messages](#flash-messages) / [Configuration reference](#configuration-reference).
818
1128
 
819
1129
  ### Confirm dialog (jQuery UI)