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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +143 -0
- data/app/assets/javascripts/fuji_admin/base.js +6 -0
- data/app/assets/javascripts/fuji_admin/filters.js +282 -0
- data/app/assets/javascripts/fuji_admin/floats.js +73 -0
- data/app/assets/javascripts/fuji_admin/menu.js +112 -0
- data/app/assets/javascripts/fuji_admin/palettes.js +237 -0
- data/app/assets/javascripts/fuji_admin/row_actions.js +123 -0
- data/app/assets/stylesheets/fuji_admin/_base.scss +23 -0
- data/app/assets/stylesheets/fuji_admin/_base_typography.scss +56 -0
- data/app/assets/stylesheets/fuji_admin/_grid.scss +111 -0
- data/app/assets/stylesheets/fuji_admin/_reset.scss +48 -0
- data/app/assets/stylesheets/fuji_admin/components/_buttons.scss +106 -0
- data/app/assets/stylesheets/fuji_admin/components/_comments.scss +44 -0
- data/app/assets/stylesheets/fuji_admin/components/_components.scss +22 -0
- data/app/assets/stylesheets/fuji_admin/components/_date_picker.scss +147 -0
- data/app/assets/stylesheets/fuji_admin/components/_dropdown_menu.scss +76 -0
- data/app/assets/stylesheets/fuji_admin/components/_filter_chips.scss +71 -0
- data/app/assets/stylesheets/fuji_admin/components/_filter_drawer.scss +224 -0
- data/app/assets/stylesheets/fuji_admin/components/_filter_form.scss +85 -0
- data/app/assets/stylesheets/fuji_admin/components/_flash.scss +55 -0
- data/app/assets/stylesheets/fuji_admin/components/_float_labels.scss +77 -0
- data/app/assets/stylesheets/fuji_admin/components/_inputs.scss +237 -0
- data/app/assets/stylesheets/fuji_admin/components/_menu_toggle.scss +61 -0
- data/app/assets/stylesheets/fuji_admin/components/_pagination.scss +70 -0
- data/app/assets/stylesheets/fuji_admin/components/_palette_switcher.scss +600 -0
- data/app/assets/stylesheets/fuji_admin/components/_panel.scss +44 -0
- data/app/assets/stylesheets/fuji_admin/components/_row_actions.scss +110 -0
- data/app/assets/stylesheets/fuji_admin/components/_scopes.scss +58 -0
- data/app/assets/stylesheets/fuji_admin/components/_select2.scss +194 -0
- data/app/assets/stylesheets/fuji_admin/components/_status_tag.scss +59 -0
- data/app/assets/stylesheets/fuji_admin/components/_table_tools.scss +14 -0
- data/app/assets/stylesheets/fuji_admin/components/_tables.scss +262 -0
- data/app/assets/stylesheets/fuji_admin/components/_watchlist_bar.scss +119 -0
- data/app/assets/stylesheets/fuji_admin/layouts/_footer.scss +21 -0
- data/app/assets/stylesheets/fuji_admin/layouts/_header.scss +80 -0
- data/app/assets/stylesheets/fuji_admin/layouts/_layouts.scss +7 -0
- data/app/assets/stylesheets/fuji_admin/layouts/_main_content.scss +118 -0
- data/app/assets/stylesheets/fuji_admin/layouts/_sidebar.scss +124 -0
- data/app/assets/stylesheets/fuji_admin/layouts/_sizes.scss +12 -0
- data/app/assets/stylesheets/fuji_admin/layouts/_wrapper.scss +28 -0
- data/app/assets/stylesheets/fuji_admin/mixins/_media.scss +30 -0
- data/app/assets/stylesheets/fuji_admin/mixins/_mixins.scss +2 -0
- data/app/assets/stylesheets/fuji_admin/pages/_form.scss +61 -0
- data/app/assets/stylesheets/fuji_admin/pages/_index.scss +77 -0
- data/app/assets/stylesheets/fuji_admin/pages/_login.scss +77 -0
- data/app/assets/stylesheets/fuji_admin/pages/_pages.scss +5 -0
- data/app/assets/stylesheets/fuji_admin/pages/_show.scss +19 -0
- data/app/assets/stylesheets/fuji_admin/variables/_breakpoints.scss +25 -0
- data/app/assets/stylesheets/fuji_admin/variables/_colors.scss +51 -0
- data/app/assets/stylesheets/fuji_admin/variables/_radii.scss +13 -0
- data/app/assets/stylesheets/fuji_admin/variables/_shadows.scss +10 -0
- data/app/assets/stylesheets/fuji_admin/variables/_spacing.scss +20 -0
- data/app/assets/stylesheets/fuji_admin/variables/_typography.scss +25 -0
- data/app/assets/stylesheets/fuji_admin/variables/_variables.scss +9 -0
- data/lib/fuji_admin/active_admin_patch.rb +19 -0
- data/lib/fuji_admin/configuration.rb +29 -0
- data/lib/fuji_admin/version.rb +3 -0
- data/lib/fuji_admin.rb +24 -0
- metadata +124 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// Watchlist bar — rendered by omnia above show-page details for Company and
|
|
2
|
+
// Person records. Shows current watchlist membership as removable pills plus
|
|
3
|
+
// a primary "Add to Watchlist" button.
|
|
4
|
+
|
|
5
|
+
.fuji-watchlist-bar {
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-wrap: wrap;
|
|
8
|
+
align-items: center;
|
|
9
|
+
gap: $space-3;
|
|
10
|
+
padding: $space-3 $space-4;
|
|
11
|
+
margin-bottom: $space-5;
|
|
12
|
+
background-color: $surface-50;
|
|
13
|
+
border: 1px solid $surface-border;
|
|
14
|
+
border-radius: $border-radius;
|
|
15
|
+
font-size: $font-size-sm;
|
|
16
|
+
|
|
17
|
+
&__label {
|
|
18
|
+
display: inline-flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
font-size: $font-size-xs;
|
|
21
|
+
font-weight: $font-weight-semibold;
|
|
22
|
+
text-transform: uppercase;
|
|
23
|
+
letter-spacing: 0.06em;
|
|
24
|
+
color: $text-color-muted;
|
|
25
|
+
flex-shrink: 0;
|
|
26
|
+
|
|
27
|
+
&::after {
|
|
28
|
+
content: ":";
|
|
29
|
+
margin-left: 2px;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&__items {
|
|
34
|
+
display: inline-flex;
|
|
35
|
+
flex-wrap: wrap;
|
|
36
|
+
align-items: center;
|
|
37
|
+
gap: $space-2;
|
|
38
|
+
flex: 1 1 auto;
|
|
39
|
+
min-width: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&__item {
|
|
43
|
+
display: inline-flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
gap: $space-1;
|
|
46
|
+
padding: $space-1 $space-2 $space-1 $space-3;
|
|
47
|
+
background-color: $primary-50;
|
|
48
|
+
border: 1px solid $primary-100;
|
|
49
|
+
border-radius: $radius-full;
|
|
50
|
+
color: $primary-700;
|
|
51
|
+
font-size: $font-size-xs;
|
|
52
|
+
font-weight: $font-weight-medium;
|
|
53
|
+
line-height: 1.4;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
&__remove {
|
|
57
|
+
display: inline-flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
justify-content: center;
|
|
60
|
+
width: 18px;
|
|
61
|
+
height: 18px;
|
|
62
|
+
margin-left: $space-1;
|
|
63
|
+
padding: 0;
|
|
64
|
+
background-color: $primary-100;
|
|
65
|
+
color: $primary-700;
|
|
66
|
+
border-radius: $radius-full;
|
|
67
|
+
font-size: $font-size-sm;
|
|
68
|
+
font-weight: $font-weight-semibold;
|
|
69
|
+
line-height: 1;
|
|
70
|
+
text-decoration: none;
|
|
71
|
+
transition: background-color 0.15s ease, color 0.15s ease;
|
|
72
|
+
|
|
73
|
+
&:hover {
|
|
74
|
+
background-color: rgba($color-danger, 0.14);
|
|
75
|
+
color: $color-danger;
|
|
76
|
+
text-decoration: none;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
&__empty {
|
|
81
|
+
color: $text-color-muted;
|
|
82
|
+
font-style: italic;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
&__add {
|
|
86
|
+
display: inline-flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
gap: $space-1;
|
|
89
|
+
padding: $space-1 $space-3;
|
|
90
|
+
margin-left: auto; // push to the right on wide layouts
|
|
91
|
+
background-color: $primary-color;
|
|
92
|
+
color: $primary-color-text;
|
|
93
|
+
border: 1px solid $primary-color;
|
|
94
|
+
border-radius: $border-radius;
|
|
95
|
+
font-size: $font-size-xs;
|
|
96
|
+
font-weight: $font-weight-semibold;
|
|
97
|
+
line-height: 1.6;
|
|
98
|
+
text-decoration: none;
|
|
99
|
+
transition: background-color 0.15s ease, border-color 0.15s ease;
|
|
100
|
+
|
|
101
|
+
&:hover {
|
|
102
|
+
background-color: $primary-700;
|
|
103
|
+
border-color: $primary-700;
|
|
104
|
+
color: $primary-color-text;
|
|
105
|
+
text-decoration: none;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&:focus-visible {
|
|
109
|
+
outline: none;
|
|
110
|
+
box-shadow: $shadow-focus;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
&::before {
|
|
114
|
+
content: "+";
|
|
115
|
+
font-size: $font-size-sm;
|
|
116
|
+
font-weight: $font-weight-bold;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Footer — quiet attribution strip at the bottom of the viewport.
|
|
2
|
+
|
|
3
|
+
#footer,
|
|
4
|
+
.footer {
|
|
5
|
+
padding: $space-4 $content-padding-mobile;
|
|
6
|
+
color: $text-color-muted;
|
|
7
|
+
font-size: $font-size-sm;
|
|
8
|
+
text-align: center;
|
|
9
|
+
|
|
10
|
+
@include media-up(md) {
|
|
11
|
+
padding: $space-4 $content-padding;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
a {
|
|
15
|
+
color: $text-color-secondary;
|
|
16
|
+
|
|
17
|
+
&:hover {
|
|
18
|
+
color: $primary-color;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Top header bar — brand/title on the left, utility nav (user, logout) on
|
|
2
|
+
// the right. Fixed so it stays visible while scrolling.
|
|
3
|
+
|
|
4
|
+
body.active_admin.logged_in > .header,
|
|
5
|
+
body.active_admin.logged_in #header {
|
|
6
|
+
position: fixed;
|
|
7
|
+
top: 0;
|
|
8
|
+
left: 0;
|
|
9
|
+
right: 0;
|
|
10
|
+
z-index: 20;
|
|
11
|
+
height: $header-height-mobile;
|
|
12
|
+
background-color: $surface-0;
|
|
13
|
+
border-bottom: 1px solid $surface-border;
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
|
|
17
|
+
@include media-up(md) {
|
|
18
|
+
height: $header-height;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Site title / brand
|
|
22
|
+
h1.site_title,
|
|
23
|
+
.site_title {
|
|
24
|
+
margin: 0;
|
|
25
|
+
padding: 0 $space-4;
|
|
26
|
+
font-size: $font-size-lg;
|
|
27
|
+
font-weight: $font-weight-semibold;
|
|
28
|
+
line-height: 1;
|
|
29
|
+
color: $text-color;
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
height: 100%;
|
|
33
|
+
|
|
34
|
+
@include media-up(lg) {
|
|
35
|
+
width: $sidebar-width;
|
|
36
|
+
padding: 0 $space-5;
|
|
37
|
+
border-right: 1px solid $surface-border;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
a {
|
|
41
|
+
color: inherit;
|
|
42
|
+
text-decoration: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#site_title_image {
|
|
46
|
+
max-height: 32px;
|
|
47
|
+
width: auto;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Utility nav (user menu, logout). AA also adds `.header-item` to the
|
|
52
|
+
// left-nav (#tabs), so we target the right-nav by its specific id only.
|
|
53
|
+
#utility_nav {
|
|
54
|
+
margin: 0 0 0 auto;
|
|
55
|
+
padding: 0 $space-4;
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
list-style: none;
|
|
59
|
+
gap: $space-2;
|
|
60
|
+
|
|
61
|
+
li {
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
|
|
65
|
+
a {
|
|
66
|
+
color: $text-color-secondary;
|
|
67
|
+
padding: $space-2 $space-3;
|
|
68
|
+
border-radius: $radius-md;
|
|
69
|
+
font-size: $font-size-sm;
|
|
70
|
+
transition: background-color 0.15s ease, color 0.15s ease;
|
|
71
|
+
|
|
72
|
+
&:hover {
|
|
73
|
+
background-color: $surface-100;
|
|
74
|
+
color: $text-color;
|
|
75
|
+
text-decoration: none;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Main content area — the breathing room around the page, plus the title
|
|
2
|
+
// bar (breadcrumb + page heading + action items) and the content card.
|
|
3
|
+
|
|
4
|
+
#active_admin_content {
|
|
5
|
+
padding: $space-5 $content-padding-mobile $content-padding-mobile;
|
|
6
|
+
|
|
7
|
+
@include media-up(md) {
|
|
8
|
+
padding: $space-5 $content-padding $content-padding;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Sidebar is repositioned as a right drawer (see components/_filter_drawer.scss),
|
|
12
|
+
// so `.with_sidebar` doesn't need an inline two-column layout.
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Edit / view / new pages benefit from maximising content width on narrow
|
|
16
|
+
// screens — forms and attribute tables look better edge-to-edge. Index pages
|
|
17
|
+
// keep their padded card so list tables sit in a clear container.
|
|
18
|
+
body.show,
|
|
19
|
+
body.edit,
|
|
20
|
+
body.new {
|
|
21
|
+
@include media-down(md) {
|
|
22
|
+
#active_admin_content {
|
|
23
|
+
padding: $space-5 0 $space-4;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#title_bar {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-wrap: wrap;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: space-between;
|
|
33
|
+
gap: $space-3;
|
|
34
|
+
padding: $space-5 $content-padding-mobile 0;
|
|
35
|
+
margin: 0;
|
|
36
|
+
|
|
37
|
+
@include media-up(md) {
|
|
38
|
+
padding: $space-6 $content-padding 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
#titlebar_left {
|
|
42
|
+
display: flex;
|
|
43
|
+
flex-direction: column;
|
|
44
|
+
gap: $space-1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.breadcrumb {
|
|
48
|
+
font-size: $font-size-sm;
|
|
49
|
+
color: $text-color-muted;
|
|
50
|
+
|
|
51
|
+
a {
|
|
52
|
+
color: $text-color-secondary;
|
|
53
|
+
|
|
54
|
+
&:hover {
|
|
55
|
+
color: $primary-color;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
h2,
|
|
61
|
+
#page_title {
|
|
62
|
+
margin: 0;
|
|
63
|
+
font-size: $font-size-2xl;
|
|
64
|
+
font-weight: $font-weight-semibold;
|
|
65
|
+
color: $text-color;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#titlebar_right {
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-wrap: wrap;
|
|
71
|
+
gap: $space-2;
|
|
72
|
+
align-items: center;
|
|
73
|
+
|
|
74
|
+
// `display: contents` lets action_items flatten into titlebar_right's flex
|
|
75
|
+
// flow. Without this, .action_items would wrap as one block beside Filters,
|
|
76
|
+
// and its own children would wrap *inside* that block — breaking the left
|
|
77
|
+
// alignment with the Filters button on a second row.
|
|
78
|
+
.action_items {
|
|
79
|
+
display: contents;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.action_item {
|
|
83
|
+
display: inline-flex;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#main_content_wrapper {
|
|
89
|
+
flex: 1 1 auto;
|
|
90
|
+
min-width: 0; // allow shrink below content width (prevents overflow)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#main_content {
|
|
94
|
+
background-color: $surface-0;
|
|
95
|
+
border-radius: $border-radius-card;
|
|
96
|
+
box-shadow: $shadow-sm;
|
|
97
|
+
padding: $space-4;
|
|
98
|
+
|
|
99
|
+
@include media-up(md) {
|
|
100
|
+
padding: $space-5;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// On edit / view / new pages, flatten the card at mobile sizes so the form
|
|
105
|
+
// or attributes table reaches the viewport edges.
|
|
106
|
+
body.show,
|
|
107
|
+
body.edit,
|
|
108
|
+
body.new {
|
|
109
|
+
@include media-down(md) {
|
|
110
|
+
#main_content {
|
|
111
|
+
padding: 0;
|
|
112
|
+
border-radius: 0;
|
|
113
|
+
box-shadow: none;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// #sidebar layout now lives in components/_filter_drawer.scss.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// Left sidebar — main navigation (ActiveAdmin renders as `#tabs` inside the
|
|
2
|
+
// header). Fixed to the viewport at lg+, hidden below that breakpoint.
|
|
3
|
+
// (Mobile drawer behaviour is a future enhancement.)
|
|
4
|
+
|
|
5
|
+
body.active_admin.logged_in {
|
|
6
|
+
#tabs,
|
|
7
|
+
#header #tabs,
|
|
8
|
+
.header #tabs {
|
|
9
|
+
display: block; // AA tags #tabs with `.header-item` which our
|
|
10
|
+
flex-direction: column; // header rules would otherwise flex-row.
|
|
11
|
+
position: fixed;
|
|
12
|
+
top: $header-height-mobile;
|
|
13
|
+
left: -#{$sidebar-width};
|
|
14
|
+
bottom: 0;
|
|
15
|
+
width: $sidebar-width;
|
|
16
|
+
padding: $space-4 0;
|
|
17
|
+
background-color: $surface-0;
|
|
18
|
+
border-right: 1px solid $surface-border;
|
|
19
|
+
overflow-y: auto;
|
|
20
|
+
list-style: none;
|
|
21
|
+
margin: 0;
|
|
22
|
+
z-index: 16; // above backdrop (14) and content
|
|
23
|
+
transition: left 0.25s ease;
|
|
24
|
+
|
|
25
|
+
@include media-up(md) {
|
|
26
|
+
top: $header-height;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Off-canvas drawer on mobile — slides in when body.fuji-menu-open.
|
|
30
|
+
&.tabs_open {
|
|
31
|
+
left: 0;
|
|
32
|
+
box-shadow: $shadow-lg;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@include media-up(lg) {
|
|
36
|
+
left: 0;
|
|
37
|
+
transition: none;
|
|
38
|
+
box-shadow: none;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
> li {
|
|
42
|
+
display: block;
|
|
43
|
+
margin: 0;
|
|
44
|
+
|
|
45
|
+
> a {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: $space-3;
|
|
49
|
+
padding: $space-3 $space-5;
|
|
50
|
+
color: $text-color-secondary;
|
|
51
|
+
font-size: $font-size-sm;
|
|
52
|
+
font-weight: $font-weight-medium;
|
|
53
|
+
border-left: 3px solid transparent;
|
|
54
|
+
transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
|
55
|
+
|
|
56
|
+
&:hover {
|
|
57
|
+
background-color: $surface-100;
|
|
58
|
+
color: $text-color;
|
|
59
|
+
text-decoration: none;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&.current > a {
|
|
64
|
+
color: $primary-color;
|
|
65
|
+
background-color: $primary-50;
|
|
66
|
+
border-left-color: $primary-color;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Nested submenus — collapsed by default, expanded on .open or .current.
|
|
70
|
+
&.has_nested {
|
|
71
|
+
> a::after {
|
|
72
|
+
content: "";
|
|
73
|
+
display: inline-block;
|
|
74
|
+
margin-left: auto;
|
|
75
|
+
width: 0;
|
|
76
|
+
height: 0;
|
|
77
|
+
border-left: 4px solid transparent;
|
|
78
|
+
border-right: 4px solid transparent;
|
|
79
|
+
border-top: 5px solid currentColor;
|
|
80
|
+
transition: transform 0.2s ease;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
&.open > a::after,
|
|
84
|
+
&.current > a::after {
|
|
85
|
+
transform: rotate(180deg);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
> ul {
|
|
89
|
+
display: none;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
&.open > ul,
|
|
93
|
+
&.current > ul {
|
|
94
|
+
display: block;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
&.has_nested > ul {
|
|
99
|
+
list-style: none;
|
|
100
|
+
padding: 0;
|
|
101
|
+
margin: 0;
|
|
102
|
+
background-color: $surface-50;
|
|
103
|
+
|
|
104
|
+
li a {
|
|
105
|
+
display: block;
|
|
106
|
+
padding: $space-2 $space-5 $space-2 $space-8;
|
|
107
|
+
color: $text-color-secondary;
|
|
108
|
+
font-size: $font-size-sm;
|
|
109
|
+
|
|
110
|
+
&:hover {
|
|
111
|
+
background-color: $surface-100;
|
|
112
|
+
color: $text-color;
|
|
113
|
+
text-decoration: none;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
li.current a {
|
|
118
|
+
color: $primary-color;
|
|
119
|
+
font-weight: $font-weight-medium;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Layout-specific sizes. Keep these here rather than in variables/ because
|
|
2
|
+
// they describe the theme's chrome, not design tokens a consumer would
|
|
3
|
+
// override from their app.
|
|
4
|
+
|
|
5
|
+
$header-height: 64px;
|
|
6
|
+
$header-height-mobile: 56px;
|
|
7
|
+
|
|
8
|
+
$sidebar-width: 240px; // wide, labeled (default)
|
|
9
|
+
$sidebar-width-collapsed: 72px; // future icon-only rail
|
|
10
|
+
|
|
11
|
+
$content-padding: $space-6; // 24px — desktop
|
|
12
|
+
$content-padding-mobile: $space-3; // 12px — tighter on phones so cards breathe
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Body + #wrapper. Offsets account for fixed header/sidebar so content
|
|
2
|
+
// never flows under them.
|
|
3
|
+
|
|
4
|
+
body.active_admin {
|
|
5
|
+
background-color: $body-background;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
body.active_admin.logged_in {
|
|
9
|
+
padding-top: $header-height-mobile;
|
|
10
|
+
|
|
11
|
+
@include media-up(md) {
|
|
12
|
+
padding-top: $header-height;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@include media-up(lg) {
|
|
16
|
+
padding-left: $sidebar-width;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#wrapper {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
min-height: calc(100vh - #{$header-height-mobile});
|
|
24
|
+
|
|
25
|
+
@include media-up(md) {
|
|
26
|
+
min-height: calc(100vh - #{$header-height});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Responsive media-query mixins keyed off the breakpoint map.
|
|
2
|
+
// Usage:
|
|
3
|
+
// @include media-up(md) { ... } // min-width: 768px
|
|
4
|
+
// @include media-down(md) { ... } // max-width: 767.98px
|
|
5
|
+
// @include media-between(sm, lg) { ... }
|
|
6
|
+
|
|
7
|
+
@mixin media-up($name) {
|
|
8
|
+
$min: map-get($breakpoints, $name);
|
|
9
|
+
@if $min == null {
|
|
10
|
+
@error "Unknown breakpoint `#{$name}`.";
|
|
11
|
+
}
|
|
12
|
+
@media (min-width: $min) { @content; }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@mixin media-down($name) {
|
|
16
|
+
$max: map-get($breakpoints, $name);
|
|
17
|
+
@if $max == null {
|
|
18
|
+
@error "Unknown breakpoint `#{$name}`.";
|
|
19
|
+
}
|
|
20
|
+
@media (max-width: $max - 0.02px) { @content; }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@mixin media-between($lower, $upper) {
|
|
24
|
+
$min: map-get($breakpoints, $lower);
|
|
25
|
+
$max: map-get($breakpoints, $upper);
|
|
26
|
+
@if $min == null or $max == null {
|
|
27
|
+
@error "Unknown breakpoint(s) `#{$lower}` / `#{$upper}`.";
|
|
28
|
+
}
|
|
29
|
+
@media (min-width: $min) and (max-width: $max - 0.02px) { @content; }
|
|
30
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Resource new/edit form page. Input styling comes from
|
|
2
|
+
// components/_inputs.scss; this adds nested has_many blocks and a few
|
|
3
|
+
// form-layout tweaks.
|
|
4
|
+
|
|
5
|
+
form.formtastic {
|
|
6
|
+
fieldset.inputs + fieldset.inputs {
|
|
7
|
+
margin-top: $space-5;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// has_many nested forms (children of a parent record)
|
|
11
|
+
ol > li.has_many_container {
|
|
12
|
+
padding: 0;
|
|
13
|
+
margin-bottom: $space-4;
|
|
14
|
+
|
|
15
|
+
h3 {
|
|
16
|
+
margin: 0 0 $space-3;
|
|
17
|
+
font-size: $font-size-base;
|
|
18
|
+
font-weight: $font-weight-semibold;
|
|
19
|
+
color: $text-color-secondary;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
fieldset.inputs {
|
|
23
|
+
background-color: $surface-50;
|
|
24
|
+
border-style: dashed;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.has_many_add {
|
|
28
|
+
@include fuji-button-secondary;
|
|
29
|
+
margin-top: $space-2;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.has_many_remove {
|
|
33
|
+
@include fuji-button-secondary;
|
|
34
|
+
color: $color-danger;
|
|
35
|
+
border-color: rgba($color-danger, 0.3);
|
|
36
|
+
|
|
37
|
+
&:hover {
|
|
38
|
+
background-color: rgba($color-danger, 0.08);
|
|
39
|
+
border-color: $color-danger;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Fragment fieldsets (nested attribute sets inside a single field).
|
|
45
|
+
fieldset > ol > li fieldset.fragments {
|
|
46
|
+
padding: 0;
|
|
47
|
+
border: 0;
|
|
48
|
+
background: transparent;
|
|
49
|
+
|
|
50
|
+
ol {
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-wrap: wrap;
|
|
53
|
+
gap: $space-3;
|
|
54
|
+
|
|
55
|
+
li {
|
|
56
|
+
flex: 1 1 auto;
|
|
57
|
+
padding: 0;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Resource index pages — .paginated_collection wraps the table + pagination
|
|
2
|
+
// in a bordered card, nested inside #main_content. We drop the index_table's
|
|
3
|
+
// own border/radius so only one ring is visible.
|
|
4
|
+
|
|
5
|
+
// .paginated_collection is a structural wrapper only — `#main_content` is
|
|
6
|
+
// the visual card, so adding a border here just creates a double-card
|
|
7
|
+
// sandwich (noticeable on register_page index views that already contain
|
|
8
|
+
// nested panels and bordered summary tables).
|
|
9
|
+
.paginated_collection {
|
|
10
|
+
background-color: transparent;
|
|
11
|
+
border: 0;
|
|
12
|
+
border-radius: 0;
|
|
13
|
+
margin: 0;
|
|
14
|
+
|
|
15
|
+
table.index_table {
|
|
16
|
+
border: 0;
|
|
17
|
+
border-radius: 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.paginated_collection_contents {
|
|
21
|
+
overflow-x: auto;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.pagination_information,
|
|
25
|
+
.pagination {
|
|
26
|
+
padding: $space-3 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.pagination_information {
|
|
30
|
+
border-top: 1px solid $surface-200;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Batch-actions checkbox column width.
|
|
35
|
+
table.index_table tbody td.col-selectable {
|
|
36
|
+
width: 32px;
|
|
37
|
+
padding-right: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Download format links — rendered below the paginated table. Horizontal
|
|
41
|
+
// padding is 0 now that .paginated_collection has no inner card (main_content
|
|
42
|
+
// provides the gutter).
|
|
43
|
+
.download_links {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-wrap: wrap;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: $space-2;
|
|
48
|
+
padding: $space-3 0 0;
|
|
49
|
+
border-top: 1px solid $surface-200;
|
|
50
|
+
margin-top: $space-3;
|
|
51
|
+
font-size: $font-size-xs;
|
|
52
|
+
color: $text-color-muted;
|
|
53
|
+
|
|
54
|
+
span {
|
|
55
|
+
text-transform: uppercase;
|
|
56
|
+
letter-spacing: 0.04em;
|
|
57
|
+
font-weight: $font-weight-medium;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
a {
|
|
61
|
+
display: inline-flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
padding: $space-1 $space-2;
|
|
64
|
+
color: $text-color-secondary;
|
|
65
|
+
background-color: $surface-100;
|
|
66
|
+
border-radius: $radius-sm;
|
|
67
|
+
font-weight: $font-weight-medium;
|
|
68
|
+
text-decoration: none;
|
|
69
|
+
transition: background-color 0.15s ease, color 0.15s ease;
|
|
70
|
+
|
|
71
|
+
&:hover {
|
|
72
|
+
background-color: $primary-50;
|
|
73
|
+
color: $primary-color;
|
|
74
|
+
text-decoration: none;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|