active_admin_prism 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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +133 -0
- data/INTEGRATION.md +1012 -0
- data/LICENSE.txt +21 -0
- data/README.md +319 -0
- data/app/assets/javascripts/active_admin_prism/prism.js +1 -0
- data/app/assets/stylesheets/active_admin_prism/_variable_overrides.scss +43 -0
- data/app/assets/stylesheets/active_admin_prism/prism.css +1 -0
- data/app/views/active_admin/devise/confirmations/new.html.erb +26 -0
- data/app/views/active_admin/devise/passwords/edit.html.erb +29 -0
- data/app/views/active_admin/devise/passwords/new.html.erb +26 -0
- data/app/views/active_admin/devise/registrations/new.html.erb +32 -0
- data/app/views/active_admin/devise/sessions/new.html.erb +37 -0
- data/app/views/active_admin/devise/shared/_brand.html.erb +34 -0
- data/app/views/active_admin/devise/unlocks/new.html.erb +25 -0
- data/js-src/prism.js +270 -0
- data/lib/active_admin/views/filters_sidebar.rb +69 -0
- data/lib/active_admin/views/flash_messages.rb +77 -0
- data/lib/active_admin/views/index_table_actions.rb +46 -0
- data/lib/active_admin/views/prism_sidebar.rb +212 -0
- data/lib/active_admin_prism/configuration.rb +180 -0
- data/lib/active_admin_prism/engine.rb +18 -0
- data/lib/active_admin_prism/version.rb +5 -0
- data/lib/active_admin_prism.rb +33 -0
- data/lib/formtastic/inputs/prism_toggle_input.rb +31 -0
- data/lib/generators/active_admin_prism/error_pages/error_pages_generator.rb +49 -0
- data/lib/generators/active_admin_prism/error_pages/templates/404.html +164 -0
- data/lib/generators/active_admin_prism/error_pages/templates/500.html +173 -0
- data/lib/generators/active_admin_prism/install/install_generator.rb +69 -0
- data/lib/prism_icons.rb +82 -0
- data/lib/prism_login_helper.rb +31 -0
- data/lib/prism_toggle_tag.rb +35 -0
- data/scss-src/_base.scss +281 -0
- data/scss-src/_buttons.scss +134 -0
- data/scss-src/_forms.scss +272 -0
- data/scss-src/_icons.scss +27 -0
- data/scss-src/_login.scss +306 -0
- data/scss-src/_panels.scss +249 -0
- data/scss-src/_sidebar.scss +479 -0
- data/scss-src/_tables.scss +142 -0
- data/scss-src/_variables.scss +101 -0
- data/scss-src/prism.scss +15 -0
- metadata +157 -0
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
// Turns ActiveAdmin's #wrapper (normally a single-column, top-nav layout)
|
|
2
|
+
// into a two-column grid: a fixed-width left sidebar (rendered by
|
|
3
|
+
// ActiveAdmin::Views::PrismSidebar in place of the default Header/
|
|
4
|
+
// TabbedNavigation) plus a fluid content column carrying the existing
|
|
5
|
+
// #title_bar / #active_admin_content / #footer stack untouched.
|
|
6
|
+
//
|
|
7
|
+
// ".index #wrapper" is overridden explicitly because ActiveAdmin's own
|
|
8
|
+
// structure/_main_structure.scss sets `display: table` there with higher
|
|
9
|
+
// selector specificity than a bare "#wrapper" rule.
|
|
10
|
+
// ActiveAdmin::Views::Pages::Base#build_page renders, in this order, as
|
|
11
|
+
// direct children of #wrapper: build_unsupported_browser (conditional),
|
|
12
|
+
// header, title_bar, build_flash_messages (-> .flashes), the main
|
|
13
|
+
// #active_admin_content, then footer. Every one of them MUST get an
|
|
14
|
+
// explicit grid-row here — leaving any child to auto-place would shift
|
|
15
|
+
// everything after it into the wrong row via CSS Grid's implicit auto-flow
|
|
16
|
+
// (this is what caused .flashes to land in the "1fr" content row and
|
|
17
|
+
// stretch to fill the whole page).
|
|
18
|
+
//
|
|
19
|
+
// "body:not(.logged_out)" excludes the signed-out layout
|
|
20
|
+
// (layouts/active_admin_logged_out.html.erb), which reuses the same
|
|
21
|
+
// "#wrapper" id for a completely different two-child structure
|
|
22
|
+
// (#content_wrapper + #footer, no sidebar at all) — this grid would
|
|
23
|
+
// otherwise force those two children into side-by-side grid cells. See
|
|
24
|
+
// _login.scss for that layout's own (unrelated) styling.
|
|
25
|
+
body:not(.logged_out) #wrapper,
|
|
26
|
+
body:not(.logged_out).index #wrapper {
|
|
27
|
+
display: grid;
|
|
28
|
+
grid-template-columns: $prism-sidebar-width 1fr;
|
|
29
|
+
grid-template-rows: auto auto auto 1fr auto;
|
|
30
|
+
min-height: 100vh;
|
|
31
|
+
width: 100%;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#header.prism-sidebar {
|
|
35
|
+
grid-column: 1;
|
|
36
|
+
grid-row: 1 / -1;
|
|
37
|
+
display: flex;
|
|
38
|
+
// !important here: AA's own #header rule (a plain ID selector) sets a
|
|
39
|
+
// background-color + background-image gradient with a lower-but-nonzero
|
|
40
|
+
// specificity — this class already wins that fight on specificity alone,
|
|
41
|
+
// but pinning it with !important removes any doubt for the single most
|
|
42
|
+
// visible element on the page.
|
|
43
|
+
background: $prism-bg-sidebar !important;
|
|
44
|
+
background-image: none !important;
|
|
45
|
+
border-right: 1px solid $prism-border-color;
|
|
46
|
+
padding: 0;
|
|
47
|
+
height: auto;
|
|
48
|
+
width: $prism-sidebar-width;
|
|
49
|
+
position: sticky;
|
|
50
|
+
top: 0;
|
|
51
|
+
// Must be "stretch" (the grid default — spelled out here since it's load
|
|
52
|
+
// bearing), not "start": since this spans every row (grid-row: 1 / -1)
|
|
53
|
+
// in a grid whose total height is only guaranteed to reach 100vh via
|
|
54
|
+
// #wrapper's min-height, "start" shrink-wraps this to its own content's
|
|
55
|
+
// height, leaving the page's own background visible below it on any
|
|
56
|
+
// page short enough that the content columns don't reach 100vh on their
|
|
57
|
+
// own. max-height below still caps it at 100vh on taller pages.
|
|
58
|
+
align-self: stretch;
|
|
59
|
+
max-height: 100vh;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
z-index: 100;
|
|
62
|
+
|
|
63
|
+
// Reset the inherited primary-gradient/text-shadow look from AA's default
|
|
64
|
+
// #header rule — this component owns its own visual language.
|
|
65
|
+
text-shadow: none !important;
|
|
66
|
+
box-shadow: none !important;
|
|
67
|
+
-webkit-font-smoothing: antialiased;
|
|
68
|
+
-moz-osx-font-smoothing: grayscale;
|
|
69
|
+
text-rendering: optimizeLegibility;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#title_bar {
|
|
73
|
+
grid-column: 2;
|
|
74
|
+
grid-row: 2;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.flashes {
|
|
78
|
+
grid-column: 2;
|
|
79
|
+
grid-row: 3;
|
|
80
|
+
align-self: start;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#active_admin_content {
|
|
84
|
+
grid-column: 2;
|
|
85
|
+
grid-row: 4;
|
|
86
|
+
min-width: 0;
|
|
87
|
+
// ActiveAdmin's own default is `padding: $horizontal-page-margin` (30px).
|
|
88
|
+
padding: 10px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// The "Powered by Active Admin" text lives in the sidebar instead (see
|
|
92
|
+
// #header.prism-sidebar .prism-sidebar-footer below) when
|
|
93
|
+
// ActiveAdminPrism::Configuration#sidebar_footer is true (the
|
|
94
|
+
// default) — Pages::Base#build_page always renders this original #footer
|
|
95
|
+
// regardless, so it's hidden here rather than suppressed at the Ruby
|
|
96
|
+
// level (a smaller, lower-risk change than overriding build_page itself
|
|
97
|
+
// just to drop one call). "prism-sidebar-footer-disabled" (set in
|
|
98
|
+
// lib/active_admin/views/flash_messages.rb#body_classes) is what actually
|
|
99
|
+
// governs this — the PrismSidebar Ruby code independently skips rendering
|
|
100
|
+
// the sidebar version when that config is off, so this is what keeps the
|
|
101
|
+
// two in sync rather than a redundant visual-only toggle.
|
|
102
|
+
body:not(.prism-sidebar-footer-disabled) #footer {
|
|
103
|
+
display: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Everything below is scoped under "#header.prism-sidebar" (ID + class) —
|
|
107
|
+
// not just ".prism-sidebar-*" classes — specifically because
|
|
108
|
+
// active_admin/_header.scss has `#header a, #header a:link { color:
|
|
109
|
+
// $page-header-text-color }` (a light gray meant for AA's own dark gradient
|
|
110
|
+
// header). That selector is ID-scoped, so it beats ANY class-only selector
|
|
111
|
+
// on specificity alone regardless of load order — a flat ".prism-nav-link"
|
|
112
|
+
// rule can never win that fight. Every real link/icon in here needs at
|
|
113
|
+
// least the "#header" ID on its own selector to reliably override it (this
|
|
114
|
+
// is also why a <span>-based item like the group toggle never showed the
|
|
115
|
+
// bug — #header a only matches actual <a> tags).
|
|
116
|
+
#header.prism-sidebar {
|
|
117
|
+
.prism-sidebar-inner {
|
|
118
|
+
display: flex;
|
|
119
|
+
flex-direction: column;
|
|
120
|
+
width: 100%;
|
|
121
|
+
height: 100%;
|
|
122
|
+
max-height: 100vh;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.prism-sidebar-brand {
|
|
126
|
+
flex: 0 0 auto;
|
|
127
|
+
padding: 20px 24px;
|
|
128
|
+
border-bottom: 1px solid $prism-border-color;
|
|
129
|
+
|
|
130
|
+
#site_title {
|
|
131
|
+
margin: 0;
|
|
132
|
+
padding: 0;
|
|
133
|
+
font-size: 1.15em;
|
|
134
|
+
font-weight: 700;
|
|
135
|
+
color: $prism-text-heading;
|
|
136
|
+
|
|
137
|
+
a {
|
|
138
|
+
color: inherit;
|
|
139
|
+
text-decoration: none;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// "Languages" dropdown (ActiveAdminPrismTheme::Configuration
|
|
145
|
+
// #language_switcher/#languages) — sits between the brand and the Pages
|
|
146
|
+
// nav list. Positioned relative so .prism-lang-menu (an absolutely
|
|
147
|
+
// positioned popover, toggled open/closed by prism.js) anchors to it
|
|
148
|
+
// rather than to the whole sidebar.
|
|
149
|
+
.prism-sidebar-lang {
|
|
150
|
+
position: relative;
|
|
151
|
+
flex: 0 0 auto;
|
|
152
|
+
padding: 10px 12px;
|
|
153
|
+
border-bottom: 1px solid $prism-border-color;
|
|
154
|
+
|
|
155
|
+
&.open {
|
|
156
|
+
.prism-chevron {
|
|
157
|
+
transform: rotate(180deg);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.prism-lang-menu {
|
|
161
|
+
display: block;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.prism-lang-toggle {
|
|
167
|
+
display: flex;
|
|
168
|
+
align-items: center;
|
|
169
|
+
gap: 8px;
|
|
170
|
+
width: 100%;
|
|
171
|
+
padding: 8px 10px;
|
|
172
|
+
border-radius: $prism-radius-sm;
|
|
173
|
+
color: $prism-text-body;
|
|
174
|
+
font-size: 0.85em;
|
|
175
|
+
font-weight: 600;
|
|
176
|
+
cursor: pointer;
|
|
177
|
+
user-select: none;
|
|
178
|
+
transition: background $prism-transition-fast;
|
|
179
|
+
|
|
180
|
+
&:hover {
|
|
181
|
+
background: $prism-bg-page;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.prism-nav-icon {
|
|
185
|
+
flex: 0 0 auto;
|
|
186
|
+
color: $prism-text-muted;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.prism-chevron {
|
|
190
|
+
flex: 0 0 auto;
|
|
191
|
+
margin-left: auto;
|
|
192
|
+
transition: transform $prism-transition-fast;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.prism-lang-current {
|
|
197
|
+
flex: 1 1 auto;
|
|
198
|
+
overflow: hidden;
|
|
199
|
+
text-overflow: ellipsis;
|
|
200
|
+
white-space: nowrap;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.prism-lang-menu {
|
|
204
|
+
display: none;
|
|
205
|
+
list-style: none;
|
|
206
|
+
margin: 4px 0 0;
|
|
207
|
+
padding: 4px;
|
|
208
|
+
position: absolute;
|
|
209
|
+
left: 12px;
|
|
210
|
+
right: 12px;
|
|
211
|
+
z-index: 50;
|
|
212
|
+
background: $prism-bg-card;
|
|
213
|
+
border: 1px solid $prism-border-color;
|
|
214
|
+
border-radius: $prism-radius-sm;
|
|
215
|
+
box-shadow: $prism-shadow-popover;
|
|
216
|
+
|
|
217
|
+
li {
|
|
218
|
+
margin: 0;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.prism-lang-option {
|
|
223
|
+
display: block;
|
|
224
|
+
padding: 8px 10px;
|
|
225
|
+
border-radius: $prism-radius-sm;
|
|
226
|
+
color: $prism-text-body;
|
|
227
|
+
font-size: 0.85em;
|
|
228
|
+
font-weight: 600;
|
|
229
|
+
text-decoration: none;
|
|
230
|
+
|
|
231
|
+
&:hover {
|
|
232
|
+
background: $prism-bg-page;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
&.active {
|
|
236
|
+
background: $prism-color-primary-light;
|
|
237
|
+
color: $prism-color-primary-dark;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.prism-sidebar-scroll {
|
|
242
|
+
flex: 1 1 auto;
|
|
243
|
+
overflow-y: auto;
|
|
244
|
+
padding: 20px 12px;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.prism-sidebar-utility {
|
|
248
|
+
flex: 0 0 auto;
|
|
249
|
+
padding: 12px;
|
|
250
|
+
border-top: 1px solid $prism-border-color;
|
|
251
|
+
|
|
252
|
+
ul.prism-nav-utility {
|
|
253
|
+
background: $prism-bg-page;
|
|
254
|
+
border-radius: $prism-radius;
|
|
255
|
+
padding: 4px;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.prism-nav-item {
|
|
259
|
+
margin: 0;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// ActiveAdmin's default utility menu (Namespace#build_default_utility_nav)
|
|
263
|
+
// always uses these two ids for the signed-in-user row and the logout
|
|
264
|
+
// link — style them as an "account" row rather than plain nav items.
|
|
265
|
+
#prism_nav_current_user {
|
|
266
|
+
> .prism-nav-link {
|
|
267
|
+
padding: 10px 10px 6px;
|
|
268
|
+
font-weight: 600;
|
|
269
|
+
color: $prism-text-heading;
|
|
270
|
+
font-size: 0.88em;
|
|
271
|
+
|
|
272
|
+
&:hover {
|
|
273
|
+
background: transparent;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.prism-nav-label {
|
|
277
|
+
white-space: normal;
|
|
278
|
+
word-break: break-word;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
#prism_nav_logout {
|
|
284
|
+
> .prism-nav-link {
|
|
285
|
+
padding: 6px 10px 8px;
|
|
286
|
+
font-size: 0.85em;
|
|
287
|
+
color: $prism-text-muted;
|
|
288
|
+
|
|
289
|
+
&:hover {
|
|
290
|
+
color: $prism-color-danger;
|
|
291
|
+
background: transparent;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// "Powered by Active Admin X.Y.Z" — moved here from the page's own
|
|
298
|
+
// #footer (hidden above) so it stays pinned below the nav/account area
|
|
299
|
+
// regardless of how long the menu grows, instead of trailing after the
|
|
300
|
+
// main content. flex: 0 0 auto (like .prism-sidebar-utility above) keeps
|
|
301
|
+
// it a fixed-height footer rather than something the flex column could
|
|
302
|
+
// stretch or that .prism-sidebar-scroll's growth could push down.
|
|
303
|
+
.prism-sidebar-footer {
|
|
304
|
+
flex: 0 0 auto;
|
|
305
|
+
padding: 10px 16px;
|
|
306
|
+
border-top: 1px solid $prism-border-color;
|
|
307
|
+
color: $prism-text-muted;
|
|
308
|
+
font-size: 0.72em;
|
|
309
|
+
line-height: 1.4;
|
|
310
|
+
text-align: center;
|
|
311
|
+
|
|
312
|
+
a {
|
|
313
|
+
color: $prism-text-muted;
|
|
314
|
+
text-decoration: underline;
|
|
315
|
+
|
|
316
|
+
&:hover {
|
|
317
|
+
color: $prism-color-primary;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.prism-nav-section-label {
|
|
323
|
+
padding: 0 12px 8px;
|
|
324
|
+
font-size: 0.72em;
|
|
325
|
+
font-weight: 700;
|
|
326
|
+
letter-spacing: 0.08em;
|
|
327
|
+
text-transform: uppercase;
|
|
328
|
+
color: $prism-text-muted;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
ul.prism-nav {
|
|
332
|
+
list-style: none;
|
|
333
|
+
margin: 0;
|
|
334
|
+
padding: 0;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.prism-nav-item {
|
|
338
|
+
margin: 2px 0;
|
|
339
|
+
|
|
340
|
+
> .prism-nav-link,
|
|
341
|
+
> .prism-nav-group-toggle {
|
|
342
|
+
display: flex;
|
|
343
|
+
align-items: center;
|
|
344
|
+
gap: 10px;
|
|
345
|
+
padding: 9px 12px;
|
|
346
|
+
border-radius: $prism-radius-sm;
|
|
347
|
+
color: $prism-text-heading;
|
|
348
|
+
font-size: 0.92em;
|
|
349
|
+
font-weight: 600;
|
|
350
|
+
text-decoration: none;
|
|
351
|
+
cursor: pointer;
|
|
352
|
+
-webkit-font-smoothing: antialiased;
|
|
353
|
+
text-rendering: optimizeLegibility;
|
|
354
|
+
transition: background $prism-transition-fast, color $prism-transition-fast;
|
|
355
|
+
|
|
356
|
+
&:hover {
|
|
357
|
+
background: $prism-bg-page;
|
|
358
|
+
color: $prism-text-heading;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
&.active {
|
|
363
|
+
> .prism-nav-link,
|
|
364
|
+
> .prism-nav-group-toggle {
|
|
365
|
+
background: $prism-color-primary-light;
|
|
366
|
+
color: $prism-color-primary-dark;
|
|
367
|
+
font-weight: 700;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.prism-nav-icon {
|
|
372
|
+
flex: 0 0 auto;
|
|
373
|
+
color: inherit;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.prism-nav-label {
|
|
377
|
+
flex: 1 1 auto;
|
|
378
|
+
overflow: hidden;
|
|
379
|
+
text-overflow: ellipsis;
|
|
380
|
+
white-space: nowrap;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.prism-chevron {
|
|
384
|
+
flex: 0 0 auto;
|
|
385
|
+
transition: transform $prism-transition-fast;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
&.open > .prism-nav-group-toggle .prism-chevron {
|
|
389
|
+
transform: rotate(180deg);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.prism-nav-submenu {
|
|
393
|
+
list-style: none;
|
|
394
|
+
margin: 2px 0 2px 30px;
|
|
395
|
+
padding: 0;
|
|
396
|
+
display: none;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
&.open > .prism-nav-submenu {
|
|
400
|
+
display: block;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
&.has-children > .prism-nav-submenu .prism-nav-item > .prism-nav-link {
|
|
404
|
+
font-size: 0.88em;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.prism-nav-utility .prism-nav-item > .prism-nav-link,
|
|
409
|
+
.prism-nav-utility .prism-nav-item > .prism-nav-group-toggle {
|
|
410
|
+
color: $prism-text-muted;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.nav-badge {
|
|
414
|
+
display: inline-flex;
|
|
415
|
+
align-items: center;
|
|
416
|
+
justify-content: center;
|
|
417
|
+
min-width: 20px;
|
|
418
|
+
height: 20px;
|
|
419
|
+
padding: 0 6px;
|
|
420
|
+
margin-left: auto;
|
|
421
|
+
border-radius: $prism-radius-pill;
|
|
422
|
+
background: $prism-color-primary;
|
|
423
|
+
color: $prism-text-inverse;
|
|
424
|
+
font-size: 0.72em;
|
|
425
|
+
font-weight: 700;
|
|
426
|
+
line-height: 20px;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.prism-sidebar-mobile-toggle {
|
|
431
|
+
display: none;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Off-canvas on narrow viewports: collapsed by default, toggled by
|
|
435
|
+
// `.prism-sidebar-open` on <body> (see active_admin_prism/prism.js).
|
|
436
|
+
@media (max-width: 900px) {
|
|
437
|
+
.prism-sidebar-mobile-toggle {
|
|
438
|
+
display: flex;
|
|
439
|
+
align-items: center;
|
|
440
|
+
justify-content: center;
|
|
441
|
+
position: fixed;
|
|
442
|
+
top: 14px;
|
|
443
|
+
left: 14px;
|
|
444
|
+
width: 38px;
|
|
445
|
+
height: 38px;
|
|
446
|
+
border-radius: $prism-radius-sm;
|
|
447
|
+
background: $prism-bg-card;
|
|
448
|
+
color: $prism-text-body;
|
|
449
|
+
box-shadow: $prism-shadow-card;
|
|
450
|
+
cursor: pointer;
|
|
451
|
+
z-index: 200;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
#wrapper,
|
|
455
|
+
.index #wrapper {
|
|
456
|
+
grid-template-columns: 1fr;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
#header.prism-sidebar {
|
|
460
|
+
position: fixed;
|
|
461
|
+
left: 0;
|
|
462
|
+
top: 0;
|
|
463
|
+
bottom: 0;
|
|
464
|
+
transform: translateX(-100%);
|
|
465
|
+
transition: transform $prism-transition-fast;
|
|
466
|
+
box-shadow: $prism-shadow-popover;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
#title_bar,
|
|
470
|
+
.flashes,
|
|
471
|
+
#active_admin_content,
|
|
472
|
+
#footer {
|
|
473
|
+
grid-column: 1;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
body.prism-sidebar-open #header.prism-sidebar {
|
|
477
|
+
transform: translateX(0);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// ActiveAdmin wraps the index table + pagination in this container —
|
|
2
|
+
// letting it scroll horizontally, rather than the columns visually
|
|
3
|
+
// colliding, is the robust fallback on narrow viewports.
|
|
4
|
+
.paginated_collection_contents {
|
|
5
|
+
overflow-x: auto;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
table.index_table {
|
|
9
|
+
background: $prism-bg-card;
|
|
10
|
+
border: 1px solid $prism-border-color;
|
|
11
|
+
border-radius: $prism-radius;
|
|
12
|
+
border-spacing: 0;
|
|
13
|
+
border-collapse: separate;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
|
|
16
|
+
th,
|
|
17
|
+
td {
|
|
18
|
+
padding: 12px 16px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
th {
|
|
22
|
+
background: $prism-bg-page;
|
|
23
|
+
color: $prism-text-muted;
|
|
24
|
+
font-size: 0.78em;
|
|
25
|
+
font-weight: 700;
|
|
26
|
+
letter-spacing: 0.04em;
|
|
27
|
+
text-transform: uppercase;
|
|
28
|
+
border: none;
|
|
29
|
+
border-bottom: 1px solid $prism-border-color;
|
|
30
|
+
white-space: nowrap;
|
|
31
|
+
|
|
32
|
+
a {
|
|
33
|
+
white-space: nowrap;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&:last-child {
|
|
37
|
+
border-right: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&.sorted-asc,
|
|
41
|
+
&.sorted-desc {
|
|
42
|
+
background: $prism-bg-page;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
td {
|
|
47
|
+
border-bottom: 1px solid $prism-border-color;
|
|
48
|
+
color: $prism-text-body;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
tr:last-child td {
|
|
52
|
+
border-bottom: none;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
tr.even td {
|
|
56
|
+
background: transparent;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
tr.selected td {
|
|
60
|
+
background: $prism-color-primary-light;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
tbody tr:hover td {
|
|
64
|
+
background: $prism-bg-page;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
td.col-actions {
|
|
68
|
+
white-space: nowrap;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Row-level View/Edit/Delete icon buttons (see
|
|
73
|
+
// lib/active_admin/views/index_table_actions.rb, which swaps the default
|
|
74
|
+
// text links' content for an icon + visually-hidden label).
|
|
75
|
+
.table_actions {
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
gap: 4px;
|
|
79
|
+
|
|
80
|
+
a {
|
|
81
|
+
display: inline-flex;
|
|
82
|
+
align-items: center;
|
|
83
|
+
justify-content: center;
|
|
84
|
+
width: 30px;
|
|
85
|
+
height: 30px;
|
|
86
|
+
border-radius: $prism-radius-sm;
|
|
87
|
+
transition: background $prism-transition-fast, color $prism-transition-fast;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Color-coded by action, always on — not just on hover — so the row
|
|
91
|
+
// reads at a glance (view = info blue, edit = brand purple, delete = red).
|
|
92
|
+
a.view_link {
|
|
93
|
+
color: $prism-color-info;
|
|
94
|
+
|
|
95
|
+
&:hover {
|
|
96
|
+
background: rgba($prism-color-info, 0.12);
|
|
97
|
+
color: darken($prism-color-info, 10%);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
a.edit_link {
|
|
102
|
+
color: $prism-color-primary;
|
|
103
|
+
|
|
104
|
+
&:hover {
|
|
105
|
+
background: $prism-color-primary-light;
|
|
106
|
+
color: $prism-color-primary-dark;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
a.delete_link {
|
|
111
|
+
color: $prism-color-danger;
|
|
112
|
+
|
|
113
|
+
&:hover {
|
|
114
|
+
background: $prism-color-danger-light;
|
|
115
|
+
color: darken($prism-color-danger, 10%);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.prism-action-icon {
|
|
120
|
+
margin: 0;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.status_tag {
|
|
125
|
+
border-radius: $prism-radius-pill;
|
|
126
|
+
background: $prism-border-color-strong;
|
|
127
|
+
color: $prism-text-heading;
|
|
128
|
+
text-transform: none;
|
|
129
|
+
letter-spacing: 0;
|
|
130
|
+
font-weight: 600;
|
|
131
|
+
padding: 3px 10px;
|
|
132
|
+
|
|
133
|
+
&.yes {
|
|
134
|
+
background: $prism-color-success-light;
|
|
135
|
+
color: darken($prism-color-success, 15%);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
&.no {
|
|
139
|
+
background: $prism-color-danger-light;
|
|
140
|
+
color: darken($prism-color-danger, 5%);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Prism design tokens. All !default so a host can override any of these by
|
|
2
|
+
// setting the variable before @import "active_admin_prism/prism" in
|
|
3
|
+
// their own scss-src (source-level override only — the committed prism.css
|
|
4
|
+
// is what actually ships; see README for the override workflow).
|
|
5
|
+
|
|
6
|
+
$prism-color-primary: #6d5bd0 !default;
|
|
7
|
+
$prism-color-primary-dark: #5949b8 !default;
|
|
8
|
+
$prism-color-primary-light: #f2ecfd !default;
|
|
9
|
+
|
|
10
|
+
$prism-color-success: #22c55e !default;
|
|
11
|
+
$prism-color-success-light: #e8f9ee !default;
|
|
12
|
+
$prism-color-danger: #ef4444 !default;
|
|
13
|
+
$prism-color-danger-light: #fdecec !default;
|
|
14
|
+
$prism-color-warning: #f59e0b !default;
|
|
15
|
+
$prism-color-info: #3b82f6 !default;
|
|
16
|
+
|
|
17
|
+
$prism-bg-page: #f4f5f7 !default;
|
|
18
|
+
$prism-bg-card: #ffffff !default;
|
|
19
|
+
$prism-bg-sidebar: #ffffff !default;
|
|
20
|
+
|
|
21
|
+
$prism-text-heading: #1a1f36 !default;
|
|
22
|
+
$prism-text-body: #384250 !default;
|
|
23
|
+
$prism-text-muted: #6b7280 !default;
|
|
24
|
+
$prism-text-inverse: #ffffff !default;
|
|
25
|
+
|
|
26
|
+
$prism-border-color: #e6e8ec !default;
|
|
27
|
+
$prism-border-color-strong: #d6d9e0 !default;
|
|
28
|
+
|
|
29
|
+
$prism-sidebar-width: 264px !default;
|
|
30
|
+
$prism-radius: 10px !default;
|
|
31
|
+
$prism-radius-sm: 6px !default;
|
|
32
|
+
$prism-radius-pill: 999px !default;
|
|
33
|
+
|
|
34
|
+
$prism-shadow-card: 0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 6px rgba(16, 24, 40, 0.04) !default;
|
|
35
|
+
$prism-shadow-popover: 0 4px 6px rgba(16, 24, 40, 0.05), 0 10px 24px rgba(16, 24, 40, 0.08) !default;
|
|
36
|
+
|
|
37
|
+
$prism-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
|
|
38
|
+
sans-serif !default;
|
|
39
|
+
|
|
40
|
+
$prism-transition-fast: 120ms ease !default;
|
|
41
|
+
|
|
42
|
+
// Shared button skins — defined here (rather than in _buttons.scss) since
|
|
43
|
+
// _base.scss (flash banners, the jQuery UI confirm dialog) needs them too,
|
|
44
|
+
// and _base.scss loads before _buttons.scss.
|
|
45
|
+
//
|
|
46
|
+
// !important on background/border-color/color specifically: ActiveAdmin's
|
|
47
|
+
// own basic-button mixin (mixins/_buttons.scss) wraps EVERY button's
|
|
48
|
+
// hover/active state in "&:not(.disabled) { &:hover {...} &:active {...} }"
|
|
49
|
+
// — that :not(.disabled) adds a specificity point our hover/active rules
|
|
50
|
+
// don't have, so AA's own hover gradient (e.g. light-button's white-to-gray)
|
|
51
|
+
// wins even when our base (non-hover) rule correctly wins on specificity +
|
|
52
|
+
// load order. This bit us twice (Cancel button shape, then "New Resource"
|
|
53
|
+
// button turning white on hover) in two different button contexts before
|
|
54
|
+
// being fixed here once, at the source, for every button using these mixins.
|
|
55
|
+
@mixin prism-button-primary {
|
|
56
|
+
background: $prism-color-primary !important;
|
|
57
|
+
background-image: none !important;
|
|
58
|
+
border: 1px solid $prism-color-primary;
|
|
59
|
+
border-radius: $prism-radius-sm;
|
|
60
|
+
color: $prism-text-inverse !important;
|
|
61
|
+
text-shadow: none;
|
|
62
|
+
box-shadow: none;
|
|
63
|
+
font-weight: 600;
|
|
64
|
+
padding: 9px 16px;
|
|
65
|
+
transition: background $prism-transition-fast, border-color $prism-transition-fast;
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
background: $prism-color-primary-dark !important;
|
|
69
|
+
border-color: $prism-color-primary-dark;
|
|
70
|
+
color: $prism-text-inverse !important;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&:active {
|
|
74
|
+
background: $prism-color-primary-dark !important;
|
|
75
|
+
box-shadow: none;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@mixin prism-button-secondary {
|
|
80
|
+
background: $prism-bg-card !important;
|
|
81
|
+
background-image: none !important;
|
|
82
|
+
border: 1px solid $prism-border-color-strong;
|
|
83
|
+
border-radius: $prism-radius-sm;
|
|
84
|
+
color: $prism-text-body !important;
|
|
85
|
+
text-shadow: none;
|
|
86
|
+
box-shadow: none;
|
|
87
|
+
font-weight: 600;
|
|
88
|
+
padding: 8px 15px;
|
|
89
|
+
transition: background $prism-transition-fast, border-color $prism-transition-fast;
|
|
90
|
+
|
|
91
|
+
&:hover {
|
|
92
|
+
background: $prism-bg-page !important;
|
|
93
|
+
border-color: $prism-text-muted;
|
|
94
|
+
color: $prism-text-heading !important;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
&:active {
|
|
98
|
+
background: $prism-bg-page !important;
|
|
99
|
+
box-shadow: none;
|
|
100
|
+
}
|
|
101
|
+
}
|