trestle 0.10.0.pre → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +26 -0
  3. data/.github/workflows/rspec.yml +6 -2
  4. data/Gemfile +14 -5
  5. data/README.md +1 -1
  6. data/app/assets/bundle/trestle/admin.css +9 -9
  7. data/app/assets/bundle/trestle/admin.js +13 -13
  8. data/app/assets/bundle/trestle/fa-brands-400.ttf +0 -0
  9. data/app/assets/bundle/trestle/fa-brands-400.woff2 +0 -0
  10. data/app/assets/bundle/trestle/fa-regular-400.ttf +0 -0
  11. data/app/assets/bundle/trestle/fa-regular-400.woff2 +0 -0
  12. data/app/assets/bundle/trestle/fa-solid-900.ttf +0 -0
  13. data/app/assets/bundle/trestle/fa-solid-900.woff2 +0 -0
  14. data/app/assets/bundle/trestle/photoswipe-063ce7be40e10b3e6848.digested.js +6 -0
  15. data/app/assets/sprockets/trestle/icons/font-awesome.css.erb +1 -1
  16. data/app/controllers/concerns/trestle/controller/modal.rb +3 -1
  17. data/app/controllers/concerns/trestle/controller/turbo_stream.rb +12 -0
  18. data/app/controllers/concerns/trestle/resource/controller/actions.rb +3 -3
  19. data/app/controllers/trestle/application_controller.rb +1 -1
  20. data/app/helpers/trestle/modal_helper.rb +0 -5
  21. data/app/helpers/trestle/turbo/frame_helper.rb +29 -0
  22. data/app/helpers/trestle/turbo/stream_helper.rb +9 -0
  23. data/app/helpers/trestle/turbo/tag_builder.rb +21 -0
  24. data/app/helpers/trestle/url_helper.rb +2 -2
  25. data/app/views/layouts/trestle/admin.html.erb +1 -1
  26. data/app/views/layouts/trestle/admin.turbo_stream.erb +2 -9
  27. data/app/views/trestle/application/_header.html.erb +12 -10
  28. data/app/views/trestle/resource/create.turbo_stream.erb +1 -5
  29. data/app/views/trestle/resource/destroy.turbo_stream.erb +1 -1
  30. data/app/views/trestle/resource/edit.html.erb +2 -0
  31. data/app/views/trestle/resource/index.html.erb +5 -0
  32. data/app/views/trestle/resource/new.html.erb +5 -0
  33. data/app/views/trestle/resource/show.html.erb +2 -0
  34. data/app/views/trestle/resource/update.turbo_stream.erb +1 -5
  35. data/app/views/trestle/shared/_sidebar.html.erb +2 -2
  36. data/frontend/css/components/_alerts.scss +22 -20
  37. data/frontend/css/components/_avatar.scss +12 -12
  38. data/frontend/css/components/_background.scss +1 -1
  39. data/frontend/css/components/_breadcrumbs.scss +8 -29
  40. data/frontend/css/components/_buttons.scss +3 -3
  41. data/frontend/css/components/_datepicker.scss +3 -3
  42. data/frontend/css/components/_dropdown.scss +18 -26
  43. data/frontend/css/components/_forms.scss +4 -4
  44. data/frontend/css/components/_grid.scss +29 -0
  45. data/frontend/css/components/_media-grid.scss +1 -1
  46. data/frontend/css/components/_modal.scss +4 -4
  47. data/frontend/css/components/_pagination.scss +4 -8
  48. data/frontend/css/components/_popover.scss +1 -1
  49. data/frontend/css/components/_scopes.scss +4 -10
  50. data/frontend/css/components/_select.scss +8 -9
  51. data/frontend/css/components/_sort.scss +1 -1
  52. data/frontend/css/components/_table.scss +5 -5
  53. data/frontend/css/components/_tabs.scss +11 -18
  54. data/frontend/css/components/_tags.scss +16 -6
  55. data/frontend/css/components/_toolbars.scss +9 -9
  56. data/frontend/css/core/_functions.scss +0 -8
  57. data/frontend/css/core/_theme.scss +3 -0
  58. data/frontend/css/core/_typography.scss +12 -19
  59. data/frontend/css/index.scss +3 -1
  60. data/frontend/css/layout/_base.scss +4 -2
  61. data/frontend/css/layout/_content-header.scss +71 -0
  62. data/frontend/css/layout/_footer.scss +5 -7
  63. data/frontend/css/layout/_main-content.scss +107 -0
  64. data/frontend/css/layout/_navigation.scss +111 -49
  65. data/frontend/css/layout/_sidebar.scss +60 -34
  66. data/frontend/css/variables/_bootstrap.scss +30 -21
  67. data/frontend/css/variables/_trestle.scss +20 -17
  68. data/frontend/js/controllers/batch_action_controller.js +59 -0
  69. data/frontend/js/controllers/checkbox_select_controller.js +3 -0
  70. data/frontend/js/controllers/confirm_delete_controller.js +4 -4
  71. data/frontend/js/controllers/gallery_controller.js +2 -0
  72. data/frontend/js/controllers/lightbox_controller.js +0 -2
  73. data/lib/trestle/engine.rb +18 -16
  74. data/lib/trestle/form/renderer.rb +1 -1
  75. data/lib/trestle/resource/toolbar.rb +18 -8
  76. data/lib/trestle/sprockets_compressor.rb +16 -0
  77. data/lib/trestle/toolbar/context.rb +7 -4
  78. data/lib/trestle/toolbar/menu.rb +8 -5
  79. data/lib/trestle/version.rb +1 -1
  80. data/package.json +1 -1
  81. data/trestle.gemspec +5 -9
  82. data/yarn.lock +350 -363
  83. metadata +35 -70
  84. data/app/assets/bundle/trestle/photoswipe-7aa1aec9c3c1fd65c382.digested.js +0 -6
  85. data/app/controllers/concerns/trestle/controller/turbo.rb +0 -21
  86. data/app/helpers/trestle/turbo_frame_helper.rb +0 -34
  87. data/frontend/css/layout/_content.scss +0 -173
@@ -1,7 +1,3 @@
1
- html {
2
- font-size: 14px;
3
- }
4
-
5
1
  body {
6
2
  @include font-smoothing;
7
3
  }
@@ -14,6 +10,15 @@ img {
14
10
  max-width: 100%;
15
11
  }
16
12
 
13
+ .error-iframe {
14
+ display: block;
15
+ width: 100%;
16
+ border: 0;
17
+ flex: 1;
18
+ min-height: 60vh;
19
+ max-height: 75vh;
20
+ }
21
+
17
22
  .empty, .blank {
18
23
  font-style: italic;
19
24
  opacity: 0.5;
@@ -28,12 +33,7 @@ img {
28
33
  }
29
34
 
30
35
  .main-content-header {
31
- h1, .h1 { font-size: $h1-font-size * $header-font-size-scale; }
32
- h2, .h2 { font-size: $h2-font-size * $header-font-size-scale; }
33
- h3, .h3 { font-size: $h3-font-size * $header-font-size-scale; }
34
- h4, .h4 { font-size: $h4-font-size * $header-font-size-scale; }
35
- h5, .h5 { font-size: $h5-font-size * $header-font-size-scale; }
36
- h6, .h6 { font-size: $h6-font-size * $header-font-size-scale; }
36
+ font-size: 1rem * $header-font-size-scale;
37
37
  }
38
38
 
39
39
  .main-content-sidebar {
@@ -42,20 +42,13 @@ img {
42
42
  h1, h2, h3, h4, h5, h6,
43
43
  .h1, .h2, .h3, .h4, .h5, .h6 {
44
44
  border-bottom: $headings-border;
45
- padding-bottom: 0.325rem;
45
+ padding-bottom: 0.275rem;
46
46
 
47
47
  &:not(:first-child) {
48
- margin-top: 1.75rem;
48
+ margin-top: 1.5rem;
49
49
  }
50
50
  }
51
51
 
52
- h1, .h1 { font-size: $h1-font-size * $sidebar-font-size-scale; }
53
- h2, .h2 { font-size: $h2-font-size * $sidebar-font-size-scale; }
54
- h3, .h3 { font-size: $h3-font-size * $sidebar-font-size-scale; }
55
- h4, .h4 { font-size: $h4-font-size * $sidebar-font-size-scale; }
56
- h5, .h5 { font-size: $h5-font-size * $sidebar-font-size-scale; }
57
- h6, .h6 { font-size: $h6-font-size * $sidebar-font-size-scale; }
58
-
59
52
  .card-header,
60
53
  .card-body,
61
54
  .card-footer {
@@ -26,7 +26,8 @@
26
26
  @import "layout/footer";
27
27
  @import "layout/sidebar";
28
28
  @import "layout/navigation";
29
- @import "layout/content";
29
+ @import "layout/content-header";
30
+ @import "layout/main-content";
30
31
 
31
32
  // Components
32
33
  @import "components/alerts";
@@ -38,6 +39,7 @@
38
39
  @import "components/datepicker";
39
40
  @import "components/dropdown";
40
41
  @import "components/forms";
42
+ @import "components/grid";
41
43
  @import "components/media-grid";
42
44
  @import "components/modal";
43
45
  @import "components/pagination";
@@ -1,5 +1,5 @@
1
1
  html, body {
2
- min-height: 100vh;
2
+ min-height: 100dvh;
3
3
  height: 100%;
4
4
  }
5
5
 
@@ -8,7 +8,6 @@ html {
8
8
  }
9
9
 
10
10
  body {
11
- display: flex;
12
11
  overflow: hidden;
13
12
  }
14
13
 
@@ -22,7 +21,10 @@ body {
22
21
  overflow: hidden;
23
22
 
24
23
  width: 100%;
24
+ height: 100%;
25
+
25
26
  min-width: 0;
27
+ min-height: 100dvh;
26
28
  }
27
29
 
28
30
  .app-container {
@@ -0,0 +1,71 @@
1
+ .content-header {
2
+ display: grid;
3
+ grid-template-columns: auto auto;
4
+ grid-template-areas: "title toolbars"
5
+ "breadcrumbs toolbars";
6
+ align-items: start;
7
+
8
+ background: $content-header-bg;
9
+ padding: 0.875rem 1.25rem;
10
+
11
+ @include media-breakpoint-down(md) {
12
+ padding: 0.625rem;
13
+ }
14
+
15
+ @include media-breakpoint-down(sm) {
16
+ grid-template-areas: "title toolbars"
17
+ "breadcrumbs breadcrumbs";
18
+ }
19
+ }
20
+
21
+ .content-header-title {
22
+ grid-area: title;
23
+
24
+ margin: 0.25rem 0 1.125rem;
25
+
26
+ @include media-breakpoint-down(md) {
27
+ margin-top: 0.125rem;
28
+ }
29
+
30
+ h1 {
31
+ font-size: 2.125rem;
32
+ font-weight: 200;
33
+
34
+ margin: 0;
35
+
36
+ @include media-breakpoint-down(md) {
37
+ font-size: 2rem;
38
+ }
39
+
40
+ @include media-breakpoint-down(md) {
41
+ font-size: 1.75rem;
42
+ }
43
+ }
44
+ }
45
+
46
+ .content-header-toolbars {
47
+ grid-area: toolbars;
48
+
49
+ display: grid;
50
+ gap: 0.5rem;
51
+
52
+ .btn {
53
+ white-space: nowrap;
54
+ }
55
+
56
+ .btn-toolbar {
57
+ flex-direction: row-reverse;
58
+ }
59
+
60
+ @include media-breakpoint-down(md) {
61
+ gap: 0.25rem;
62
+ }
63
+ }
64
+
65
+ .content-header-breadcrumbs {
66
+ grid-area: breadcrumbs;
67
+
68
+ .breadcrumb {
69
+ margin: 0;
70
+ }
71
+ }
@@ -4,16 +4,14 @@
4
4
  background: $footer-bg;
5
5
  color: $footer-color;
6
6
 
7
- padding: 0.5rem 1.4rem;
8
- font-size: 0.75rem;
7
+ padding: $footer-padding;
8
+ font-size: 0.625rem;
9
9
 
10
10
  display: flex;
11
11
  justify-content: space-between;
12
- }
13
12
 
14
- @include media-breakpoint-down(md) {
15
- .app-footer {
16
- padding-left: 10px;
17
- padding-right: 10px;
13
+ @include media-breakpoint-down(md) {
14
+ padding-left: 0.625rem;
15
+ padding-right: 0.625rem;
18
16
  }
19
17
  }
@@ -0,0 +1,107 @@
1
+ .main-content-area {
2
+ --content-area-margin: 1.25rem;
3
+ --content-area-padding: 1.25rem;
4
+
5
+ --content-area-sidebar-width: #{$content-sidebar-width};
6
+ --content-area-sidebar-bg: #{$content-sidebar-bg};
7
+
8
+ --content-area-header-padding: 0.625rem 1.125rem;
9
+ --content-area-header-bg: #{$main-content-header-bg};
10
+ --content-area-header-border: #{$main-content-header-border};
11
+
12
+ --content-area-footer-padding: 0.625rem 1.125rem;
13
+ --content-area-footer-bg: #{$main-content-footer-bg};
14
+ --content-area-footer-border: #{$main-content-footer-border};
15
+
16
+ margin: var(--content-area-margin);
17
+ scroll-margin: var(--content-area-margin);
18
+ }
19
+
20
+ .main-content-container {
21
+ background: white;
22
+ display: flex;
23
+ }
24
+
25
+ .main-content,
26
+ .main-content-sidebar {
27
+ padding: var(--content-area-padding);
28
+ }
29
+
30
+ .main-content {
31
+ // Allow nesting of tab panes directly within
32
+ @extend .tab-content;
33
+
34
+ flex: 1;
35
+ min-width: 0;
36
+ }
37
+
38
+ .main-content-header,
39
+ .main-content-footer {
40
+ display: flex;
41
+ justify-content: space-between;
42
+ }
43
+
44
+ .main-content-header {
45
+ margin: calc(var(--content-area-padding) * -1) calc(var(--content-area-padding) * -1) var(--content-area-padding) !important;
46
+ padding: var(--content-area-header-padding);
47
+ background: var(--content-area-header-bg);
48
+ border-bottom: var(--content-area-header-border)
49
+ }
50
+
51
+ .main-content-footer {
52
+ margin: var(--content-area-padding) calc(var(--content-area-padding) * -1) calc(var(--content-area-padding) * -1) !important;
53
+ padding: var(--content-area-footer-padding);
54
+ background: var(--content-area-footer-bg);
55
+ border-top: var(--content-area-footer-border);
56
+ }
57
+
58
+ .main-content,
59
+ .main-content-sidebar,
60
+ .tab-pane {
61
+ > *:first-child {
62
+ margin-top: 0;
63
+ }
64
+
65
+ > *:last-child {
66
+ margin-bottom: 0;
67
+ }
68
+ }
69
+
70
+ .main-content-sidebar {
71
+ background: var(--content-area-sidebar-bg);
72
+ flex: 0 0 var(--content-area-sidebar-width);
73
+ max-width: var(--content-area-sidebar-width);
74
+ }
75
+
76
+ .utilities {
77
+ display: flex;
78
+ justify-content: flex-start;
79
+ margin-bottom: 0.75rem;
80
+ }
81
+
82
+ @include media-breakpoint-down(lg) {
83
+ .main-content-container {
84
+ flex-direction: column;
85
+ }
86
+
87
+ .main-content-sidebar {
88
+ flex-basis: 0;
89
+ max-width: none;
90
+ }
91
+ }
92
+
93
+ @include media-breakpoint-down(md) {
94
+ .main-content-area {
95
+ --content-area-margin: 0.625rem;
96
+ --content-area-padding: 0.875rem;
97
+
98
+ --content-area-header-padding: 0.625rem 0.875rem;
99
+ --content-area-footer-padding: 0.625rem 0.875rem;
100
+ }
101
+
102
+ .main-content-header,
103
+ .main-content-footer {
104
+ flex-direction: column;
105
+ align-items: center;
106
+ }
107
+ }
@@ -1,24 +1,28 @@
1
1
  .app-nav {
2
2
  flex: 1;
3
- padding: 10px 0;
3
+ padding: 0.625rem 0;
4
4
 
5
5
  &, a {
6
6
  color: $sidebar-link-color;
7
7
  }
8
8
 
9
9
  ul {
10
- margin: 10px 0;
10
+ margin: 0.625rem 0;
11
11
  padding: 0;
12
12
  list-style: none;
13
13
  }
14
14
 
15
- a {
16
- display: block;
15
+ .nav-item a {
16
+ display: flex;
17
+ align-items: center;
18
+ gap: 0.625rem;
17
19
 
18
20
  font-weight: normal;
19
- font-size: 0.9rem;
21
+ font-size: 0.8125rem;
20
22
 
21
- padding: 12px 18px;
23
+ padding: 0.75rem 1rem;
24
+
25
+ position: relative;
22
26
 
23
27
  &:hover, &:focus {
24
28
  color: $sidebar-link-color;
@@ -31,12 +35,31 @@
31
35
  }
32
36
  }
33
37
 
38
+ .nav-item.active a {
39
+ border-left: $sidebar-active-border solid var(--primary);
40
+ padding-left: calc(1rem - #{$sidebar-active-border});
41
+
42
+ background: $sidebar-active-bg;
43
+ color: white;
44
+ }
45
+
34
46
  .nav-icon {
35
- display: inline-block;
36
- text-align: center;
37
- width: 18px;
38
- margin-right: 8px;
39
- vertical-align: 0;
47
+ flex-shrink: 0;
48
+
49
+ display: inline-flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+
53
+ width: 1.25rem;
54
+ }
55
+
56
+ .nav-label {
57
+ white-space: nowrap;
58
+ overflow: hidden;
59
+ text-overflow: ellipsis;
60
+
61
+ opacity: 1;
62
+ transition: opacity var(--sidebar-transition-duration) var(--sidebar-transition-timing);
40
63
  }
41
64
 
42
65
  .nav-header a {
@@ -47,39 +70,38 @@
47
70
  font-weight: bold;
48
71
  line-height: 1;
49
72
 
50
- font-size: 11px;
51
- padding: 8px 20px;
73
+ font-size: 0.6875rem;
74
+ padding: 0.5rem 1.125rem;
52
75
 
53
- &::after {
54
- @include icon-fa($fa-var-caret-down);
76
+ display: flex;
77
+ justify-content: space-between;
78
+ align-items: center;
79
+
80
+ white-space: nowrap;
55
81
 
56
- float: right;
57
- margin-top: 2px;
82
+ span {
83
+ opacity: 1;
84
+ transition: opacity var(--sidebar-transition-duration) var(--sidebar-transition-timing);
85
+ }
58
86
 
87
+ &::after {
88
+ @include icon-fa($fa-var-caret-down);
59
89
  opacity: 0.75;
60
90
  }
61
91
 
62
- &:hover, &:focus {
92
+ &:hover,
93
+ &:focus {
63
94
  background: none;
64
95
 
65
- &::before, &::after {
66
- opacity: 1 !important;
96
+ &::before,
97
+ &::after {
98
+ opacity: 1;
67
99
  }
68
100
  }
69
101
  }
70
102
 
71
- .active a {
72
- border-left: $sidebar-active-border solid var(--primary);
73
- padding-left: 18px - $sidebar-active-border;
74
-
75
- background: $sidebar-active-bg;
76
- color: white;
77
- }
78
-
79
103
  .badge {
80
- float: right;
81
- position: relative;
82
- top: 1px;
104
+ margin-left: auto;
83
105
  }
84
106
 
85
107
  .collapsed {
@@ -98,17 +120,17 @@
98
120
  }
99
121
 
100
122
  @mixin collapsed-nav-header {
101
- height: 0;
102
- padding: 13px 15px 14px;
103
- text-indent: -99999px;
123
+ span {
124
+ opacity: 0;
125
+ }
104
126
 
105
127
  &::after {
106
128
  display: none;
107
129
 
108
130
  position: absolute;
109
- top: 4px;
131
+ top: 50%;
110
132
  left: 50%;
111
- margin-left: -3px;
133
+ translate: -50% -5px;
112
134
 
113
135
  text-indent: 0;
114
136
  }
@@ -117,24 +139,42 @@
117
139
  content: "";
118
140
 
119
141
  position: absolute;
120
- left: 15px;
121
- right: 15px;
122
142
  top: 50%;
123
- margin-top: -4px;
143
+ left: 1rem;
144
+ right: 1rem;
145
+ margin-top: -2px;
124
146
 
125
147
  border-bottom: 1px solid $sidebar-active-bg;
126
148
  opacity: 0.75;
127
149
  }
128
150
  }
129
151
 
152
+ @mixin collapsed-nav-label {
153
+ opacity: 0;
154
+ }
155
+
156
+ @mixin collapsed-nav-badge {
157
+ text-indent: -99999px;
158
+ position: absolute;
159
+ width: 0.5rem;
160
+ height: 0.5rem;
161
+ padding: 0;
162
+ top: 0.625rem;
163
+ left: 2rem;
164
+ }
165
+
130
166
  @include media-breakpoint-between(md, xl) {
131
167
  .nav-tooltip {
132
168
  display: block !important;
133
169
  }
134
170
 
135
171
  .app-nav {
136
- .nav-label, .badge {
137
- display: none;
172
+ .nav-label {
173
+ @include collapsed-nav-label;
174
+ }
175
+
176
+ .badge {
177
+ @include collapsed-nav-badge;
138
178
  }
139
179
 
140
180
  .nav-header a {
@@ -151,9 +191,9 @@
151
191
  .sidebar-expanded {
152
192
  .app-nav {
153
193
  .nav-header a {
154
- height: auto;
155
- padding: 8px 20px;
156
- text-indent: 0;
194
+ span {
195
+ opacity: 1;
196
+ }
157
197
 
158
198
  &::before {
159
199
  display: none;
@@ -162,12 +202,21 @@
162
202
  &::after {
163
203
  display: block;
164
204
  position: static;
165
- margin-left: 0;
205
+ translate: 0;
166
206
  }
167
207
  }
168
208
 
169
- .nav-label { display: inline; }
170
- .badge { display: block; }
209
+ .nav-label {
210
+ opacity: 1;
211
+ }
212
+
213
+ .badge {
214
+ position: static;
215
+ width: auto;
216
+ height: auto;
217
+ text-indent: 0;
218
+ padding: var(--#{$prefix}badge-padding-y) var(--#{$prefix}badge-padding-x);
219
+ }
171
220
  }
172
221
 
173
222
  .nav-tooltip {
@@ -179,8 +228,12 @@
179
228
  @include media-breakpoint-up(xl) {
180
229
  .sidebar-collapsed {
181
230
  .app-nav {
182
- .nav-label, .badge {
183
- display: none;
231
+ .nav-label {
232
+ @include collapsed-nav-label;
233
+ }
234
+
235
+ .badge {
236
+ @include collapsed-nav-badge;
184
237
  }
185
238
 
186
239
  .nav-header a {
@@ -199,3 +252,12 @@
199
252
  }
200
253
  }
201
254
  }
255
+
256
+ @media (prefers-reduced-motion) {
257
+ .app-nav {
258
+ .nav-label,
259
+ .nav-header a span {
260
+ transition: none;
261
+ }
262
+ }
263
+ }