avo 4.0.0.beta.43 → 4.0.0.beta.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/app/assets/builds/avo/application.css +101 -63
  4. data/app/assets/stylesheets/application.css +0 -1
  5. data/app/assets/stylesheets/css/components/breadcrumbs.css +11 -2
  6. data/app/assets/stylesheets/css/components/color_scheme_switcher.css +7 -1
  7. data/app/assets/stylesheets/css/components/filters.css +1 -1
  8. data/app/assets/stylesheets/css/components/input.css +2 -2
  9. data/app/assets/stylesheets/css/components/ui/card.css +8 -2
  10. data/app/assets/stylesheets/css/components/ui/dropdown.css +1 -1
  11. data/app/assets/stylesheets/css/components/ui/tabs.css +22 -0
  12. data/app/assets/stylesheets/css/layout.css +44 -61
  13. data/app/assets/stylesheets/css/variables.css +4 -0
  14. data/app/components/avo/fields/common/heading_component.html.erb +1 -3
  15. data/app/components/avo/fields/common/heading_component.rb +1 -1
  16. data/app/components/avo/fields/date_field/edit_component.html.erb +3 -2
  17. data/app/components/avo/fields/date_time_field/edit_component.html.erb +3 -2
  18. data/app/components/avo/fields/heading_field/edit_component.html.erb +2 -2
  19. data/app/components/avo/fields/heading_field/show_component.html.erb +1 -1
  20. data/app/components/avo/fields/time_field/edit_component.html.erb +3 -2
  21. data/app/components/avo/views/resource_index_component.html.erb +3 -5
  22. data/app/views/avo/partials/_navbar.html.erb +2 -1
  23. data/lib/avo/configuration.rb +1 -1
  24. data/lib/avo/fields/belongs_to_field.rb +18 -7
  25. data/lib/avo/version.rb +1 -1
  26. data/lib/generators/avo/templates/initializer/avo.tt +1 -1
  27. metadata +1 -2
  28. data/app/assets/stylesheets/css/components/tab_group.css +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48c7b20a4be4b85ecfdc9ddfa3555ff9879a93e198444117995d5114b283008d
4
- data.tar.gz: d616fda1761657b357ca2019b05618113b1082d12e78d955aa64cd50af10e96f
3
+ metadata.gz: 0025b604ab0ca5ff4bdf83b41204be7b6ca2eb6211269b45bb1827f059a731fc
4
+ data.tar.gz: 1f5ac00fe7cf8b1218c4d6ec6657820175e7fce008d027f449ade483126a9791
5
5
  SHA512:
6
- metadata.gz: 766ba7782e99ffe20da840c7c3259efe126558aade7c362eecb9aae00672e09ca95294aa9231530ab724591d7c449976a4911732f1b8eeca2bfefa1995baf168
7
- data.tar.gz: ee155888e963b4d2f417522044d12b3f26507308e19146cdb3bd8100d3e2808fd9dab9842addab04106683ce33e6d474c7b0b38dd64c7d612811b30acdcf15b3
6
+ metadata.gz: 9e26e80cadbb04224a25ce1ae3321545426a334ac195cde6f0880143ef3d38377788e39189d2f77e180ea8c5152c7647874b112e4dd1c6b9931907e6628f82d0
7
+ data.tar.gz: 7d6e56e3c9ddae3a12767064d99166fe603391b2157f792ef79107943e068cd035e11241d32f1f0929a4bcc472e01a3b4513ad7d953391f406aecc33667f6dd3
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (4.0.0.beta.43)
4
+ avo (4.0.0.beta.45)
5
5
  actionview (>= 6.1)
6
6
  active_link_to
7
7
  activerecord (>= 6.1)
@@ -349,6 +349,7 @@
349
349
  --color-primary: var(--color-white);
350
350
  --color-secondary: var(--color-avo-neutral-100);
351
351
  --color-tertiary: var(--color-avo-neutral-200);
352
+ --color-quaternary: var(--color-avo-neutral-300);
352
353
  --color-content: var(--color-avo-neutral-950);
353
354
  --color-content-secondary: var(--color-avo-neutral-500);
354
355
  --color-scheme: var(--color-white);
@@ -361,6 +362,8 @@
361
362
  --color-navbar-background: var(--color-avo-neutral-900);
362
363
  --color-main-content-background: var(--color-primary);
363
364
  --color-main-content-border: var(--border-color);
365
+ --radius-card: var(--radius-xl);
366
+ --radius-card-wrapper: var(--radius-lg);
364
367
  --top-navbar-height: 3rem;
365
368
  --navbar-notch-color: var(--color-navbar-background);
366
369
  --border-color: var(--color-tertiary);
@@ -577,6 +580,9 @@
577
580
  .inset-auto {
578
581
  inset: auto;
579
582
  }
583
+ .inset-y-0 {
584
+ inset-block: calc(var(--spacing) * 0);
585
+ }
580
586
  .start {
581
587
  inset-inline-start: var(--spacing);
582
588
  }
@@ -757,6 +763,9 @@
757
763
  .my-auto {
758
764
  margin-block: auto;
759
765
  }
766
+ .-ms-1\.5 {
767
+ margin-inline-start: calc(var(--spacing) * -1.5);
768
+ }
760
769
  .ms-1 {
761
770
  margin-inline-start: calc(var(--spacing) * 1);
762
771
  }
@@ -1963,9 +1972,9 @@
1963
1972
  .rounded-es {
1964
1973
  border-end-start-radius: 0.25rem;
1965
1974
  }
1966
- .rounded-t {
1967
- border-top-left-radius: 0.25rem;
1968
- border-top-right-radius: 0.25rem;
1975
+ .rounded-t-card-wrapper {
1976
+ border-top-left-radius: var(--radius-card-wrapper);
1977
+ border-top-right-radius: var(--radius-card-wrapper);
1969
1978
  }
1970
1979
  .rounded-l {
1971
1980
  border-top-left-radius: 0.25rem;
@@ -2523,6 +2532,9 @@
2523
2532
  .px-2 {
2524
2533
  padding-inline: calc(var(--spacing) * 2);
2525
2534
  }
2535
+ .px-2\.5 {
2536
+ padding-inline: calc(var(--spacing) * 2.5);
2537
+ }
2526
2538
  .px-3 {
2527
2539
  padding-inline: calc(var(--spacing) * 3);
2528
2540
  }
@@ -2748,9 +2760,6 @@
2748
2760
  .text-amber-700 {
2749
2761
  color: var(--color-amber-700);
2750
2762
  }
2751
- .text-black {
2752
- color: var(--color-black);
2753
- }
2754
2763
  .text-blue-500 {
2755
2764
  color: var(--color-blue-500);
2756
2765
  }
@@ -4601,6 +4610,11 @@
4601
4610
  padding-inline: calc(var(--spacing) * 24);
4602
4611
  }
4603
4612
  }
4613
+ .lg\:ms-0 {
4614
+ @media (width >= 64rem) {
4615
+ margin-inline-start: calc(var(--spacing) * 0);
4616
+ }
4617
+ }
4604
4618
  .lg\:flex {
4605
4619
  @media (width >= 64rem) {
4606
4620
  display: flex;
@@ -4954,6 +4968,7 @@ tag.tagify__tag {
4954
4968
  --color-primary: var(--color-avo-neutral-950);
4955
4969
  --color-secondary: var(--color-avo-neutral-800);
4956
4970
  --color-tertiary: var(--color-avo-neutral-700);
4971
+ --color-quaternary: var(--color-avo-neutral-600);
4957
4972
  --color-content: var(--color-white);
4958
4973
  --color-content-secondary: var(--color-avo-neutral-300);
4959
4974
  --color-scheme: var(--color-black);
@@ -5884,31 +5899,26 @@ tag.tagify__tag {
5884
5899
  }
5885
5900
  [data-controller~="sidebar"] {
5886
5901
  --sidebar-width: calc(var(--spacing) * 64);
5887
- --sidebar-offset-size: 0rem;
5888
- --content-width: calc(100% - var(--spacing));
5902
+ --sidebar-offset-size: 0;
5903
+ --content-width: calc(100%);
5889
5904
  }
5890
5905
  @media (min-width: 64rem) {
5891
5906
  [data-controller~="sidebar"][data-sidebar-open-value="true"] {
5892
5907
  --sidebar-offset-size: var(--sidebar-width);
5893
5908
  }
5894
5909
  }
5895
- [data-controller~="sidebar"][data-sidebar-open-value="false"] {
5896
- .main-content {
5897
- margin-inline-start: calc(var(--spacing) * 0);
5898
- }
5899
- }
5900
5910
  .main {
5901
5911
  padding-top: var(--top-navbar-height);
5902
- padding-inline-start: calc(var(--sidebar-offset-size) - var(--spacing));
5912
+ padding-inline-start: var(--sidebar-offset-size);
5903
5913
  transition: padding 0.1s ease-in-out;
5904
5914
  }
5905
5915
  .main-content {
5906
- --main-content-start-radius: 0px;
5907
- --main-content-end-radius: 0px;
5916
+ --main-content-start-radius: 0;
5917
+ --main-content-end-radius: 0;
5918
+ --main-content-width: var(--content-width);
5908
5919
  position: relative;
5909
- margin-inline-start: calc(var(--spacing) * 1);
5910
5920
  display: flex;
5911
- width: var(--content-width);
5921
+ width: var(--main-content-width);
5912
5922
  flex-direction: column;
5913
5923
  border-start-start-radius: var(--main-content-start-radius);
5914
5924
  border-start-end-radius: var(--main-content-end-radius);
@@ -5927,10 +5937,33 @@ tag.tagify__tag {
5927
5937
  transition: margin 0.1s ease-in-out, width 0.1s ease-in-out;
5928
5938
  min-height: calc(100dvh - var(--top-navbar-height) - var(--spacing));
5929
5939
  @container style(--navbar-notch-enabled: true) {
5940
+ --main-content-start-radius: var(--main-content-radius);
5930
5941
  --main-content-end-radius: var(--main-content-radius);
5931
5942
  }
5932
5943
  @container style(--navbar-notch-enabled: true) and style(--top-navbar-start-notch-align-with-main-content: true) {
5933
5944
  --main-content-start-radius: var(--main-content-radius);
5945
+ --main-content-end-radius: var(--main-content-radius);
5946
+ }
5947
+ }
5948
+ @media (min-width: 64rem) {
5949
+ .sidebar-open .avo-sidebar {
5950
+ transform: translateX(0);
5951
+ }
5952
+ html[dir="rtl"] .sidebar-open .avo-sidebar {
5953
+ transform: translateX(0);
5954
+ }
5955
+ @container style(--navbar-notch-enabled: true) and style(--top-navbar-start-notch-align-with-main-content: false) {
5956
+ .sidebar-open .main-content {
5957
+ --main-content-start-radius: 0;
5958
+ }
5959
+ }
5960
+ }
5961
+ @media (width < 64rem) {
5962
+ .sidebar-mobile-open .avo-sidebar {
5963
+ transform: translateX(0);
5964
+ }
5965
+ html[dir="rtl"] .sidebar-mobile-open .avo-sidebar {
5966
+ transform: translateX(0);
5934
5967
  }
5935
5968
  }
5936
5969
  .main-content.focused, .main-content:focus-visible {
@@ -5941,7 +5974,10 @@ tag.tagify__tag {
5941
5974
  display: flex;
5942
5975
  flex: 1;
5943
5976
  flex-direction: column;
5944
- padding-inline: calc(var(--spacing) * 2);
5977
+ padding-inline: calc(var(--spacing) * 0);
5978
+ @media (width >= 48rem) {
5979
+ padding-inline: calc(var(--spacing) * 2);
5980
+ }
5945
5981
  }
5946
5982
  .container-large {
5947
5983
  @media (width >= 96rem) {
@@ -6152,25 +6188,6 @@ tag.tagify__tag {
6152
6188
  html[dir="rtl"] .avo-sidebar {
6153
6189
  transform: translateX(100%);
6154
6190
  }
6155
- @media (min-width: 64rem) {
6156
- .sidebar-open .avo-sidebar {
6157
- transform: translateX(0);
6158
- }
6159
- html[dir="rtl"] .sidebar-open .avo-sidebar {
6160
- transform: translateX(0);
6161
- }
6162
- .main:not(.sidebar-open) .main-content {
6163
- margin-inline-start: calc(var(--spacing) * 0);
6164
- }
6165
- }
6166
- @media (width < 64rem) {
6167
- .sidebar-mobile-open .avo-sidebar {
6168
- transform: translateX(0);
6169
- }
6170
- html[dir="rtl"] .sidebar-mobile-open .avo-sidebar {
6171
- transform: translateX(0);
6172
- }
6173
- }
6174
6191
  .button-spinner {
6175
6192
  width: 24px;
6176
6193
  height: 24px;
@@ -6964,7 +6981,7 @@ tag.tagify__tag {
6964
6981
  flex-direction: column;
6965
6982
  align-items: flex-start;
6966
6983
  align-self: stretch;
6967
- border-radius: var(--radius-xl);
6984
+ border-radius: var(--radius-card);
6968
6985
  border-style: var(--tw-border-style);
6969
6986
  border-width: 1px;
6970
6987
  border-color: var(--color-tertiary);
@@ -7043,7 +7060,7 @@ tag.tagify__tag {
7043
7060
  flex-direction: column;
7044
7061
  align-items: flex-start;
7045
7062
  align-self: stretch;
7046
- border-radius: var(--radius-lg);
7063
+ border-radius: var(--radius-card-wrapper);
7047
7064
  border-style: var(--tw-border-style);
7048
7065
  border-width: 1px;
7049
7066
  border-color: var(--color-tertiary);
@@ -7374,6 +7391,28 @@ tag.tagify__tag {
7374
7391
  border-color: var(--color-accent);
7375
7392
  margin-bottom: -1px;
7376
7393
  }
7394
+ .tab-group {
7395
+ position: relative;
7396
+ border-radius: var(--radius-2xl);
7397
+ border-style: var(--tw-border-style);
7398
+ border-width: 1px;
7399
+ --tw-border-style: dashed;
7400
+ border-style: dashed;
7401
+ border-color: var(--color-tertiary);
7402
+ &:hover {
7403
+ border-color: var(--color-quaternary);
7404
+ }
7405
+ --tab-group-modifier: 4;
7406
+ --tab-group-padding: calc(var(--tab-group-modifier) - (var(--tab-group-modifier)/2));
7407
+ width: calc(100% + calc(var(--spacing) * var(--tab-group-modifier)));
7408
+ margin-inline: calc(var(--spacing) * var(--tab-group-padding) * -1);
7409
+ padding: calc(var(--spacing) * var(--tab-group-padding));
7410
+ }
7411
+ @media (width > 48rem) {
7412
+ .tab-group {
7413
+ --tab-group-modifier: 8;
7414
+ }
7415
+ }
7377
7416
  }
7378
7417
  .badge {
7379
7418
  display: inline-flex;
@@ -7941,7 +7980,6 @@ tag.tagify__tag {
7941
7980
  .dropdown-menu {
7942
7981
  display: flex;
7943
7982
  width: 100%;
7944
- min-width: calc(var(--spacing) * 48);
7945
7983
  flex-direction: column;
7946
7984
  border-radius: var(--radius-lg);
7947
7985
  border-style: var(--tw-border-style);
@@ -8400,9 +8438,10 @@ tag.tagify__tag {
8400
8438
  display: flex;
8401
8439
  cursor: pointer;
8402
8440
  align-items: center;
8441
+ justify-content: center;
8403
8442
  border-radius: var(--radius-lg);
8404
8443
  color: var(--color-content-secondary);
8405
- padding-inline-end: var(--input-icon-offset);
8444
+ padding-inline: var(--input-icon-offset);
8406
8445
  outline-offset: var(--focus-outline-offset-inset);
8407
8446
  }
8408
8447
  .field-wrapper__input:has(.input-field__password-toggle) input {
@@ -8954,11 +8993,12 @@ tag.tagify__tag {
8954
8993
  }
8955
8994
  .breadcrumbs {
8956
8995
  position: sticky;
8996
+ top: var(--top-navbar-height);
8957
8997
  z-index: 40;
8958
8998
  margin-bottom: calc(var(--spacing) * 4);
8959
8999
  width: 100%;
8960
9000
  background-color: var(--color-main-content-background);
8961
- top: calc(var(--top-navbar-height));
9001
+ margin-top: calc(var(--spacing) * -1);
8962
9002
  }
8963
9003
  .breadcrumbs::after {
8964
9004
  content: "";
@@ -9009,6 +9049,12 @@ tag.tagify__tag {
9009
9049
  &:first-child {
9010
9050
  margin-inline-start: calc(var(--spacing) * -1);
9011
9051
  }
9052
+ &:first-child:has(.breadcrumb-element__icon) .breadcrumb-element__text {
9053
+ display: none;
9054
+ @media (width >= 48rem) {
9055
+ display: inline;
9056
+ }
9057
+ }
9012
9058
  &:focus-visible {
9013
9059
  outline-offset: var(--focus-outline-offset-inset);
9014
9060
  }
@@ -10066,12 +10112,12 @@ tag.tagify__tag {
10066
10112
  }
10067
10113
  .color-scheme-switcher__compact-trigger {
10068
10114
  display: inline-flex;
10069
- height: calc(var(--spacing) * 8);
10115
+ height: calc(var(--spacing) * 6);
10070
10116
  align-items: center;
10071
10117
  gap: calc(var(--spacing) * 1);
10072
10118
  border-radius: var(--radius-lg);
10073
- padding-inline-start: calc(var(--spacing) * 2);
10074
- padding-inline-end: calc(var(--spacing) * 1.5);
10119
+ padding-inline-start: calc(var(--spacing) * 1.5);
10120
+ padding-inline-end: calc(var(--spacing) * 1);
10075
10121
  transition-property: all;
10076
10122
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
10077
10123
  transition-duration: var(--tw-duration, var(--default-transition-duration));
@@ -10097,6 +10143,13 @@ tag.tagify__tag {
10097
10143
  color: var(--top-navbar-content-hover);
10098
10144
  }
10099
10145
  }
10146
+ @media (min-width: 64rem) {
10147
+ .color-scheme-switcher__compact-trigger {
10148
+ height: calc(var(--spacing) * 8);
10149
+ padding-inline-start: calc(var(--spacing) * 2);
10150
+ padding-inline-end: calc(var(--spacing) * 1.5);
10151
+ }
10152
+ }
10100
10153
  .color-scheme-switcher__chevron {
10101
10154
  width: calc(var(--spacing) * 3);
10102
10155
  height: calc(var(--spacing) * 3);
@@ -11165,8 +11218,9 @@ tag.tagify__tag {
11165
11218
  inset-inline-end: calc(var(--spacing) * 0);
11166
11219
  display: flex;
11167
11220
  align-items: center;
11221
+ justify-content: center;
11168
11222
  border-radius: var(--radius-lg);
11169
- padding-inline-end: calc(var(--spacing) * 2.5);
11223
+ padding-inline: calc(var(--spacing) * 2.5);
11170
11224
  color: var(--color-content-secondary);
11171
11225
  outline-offset: var(--focus-outline-offset-inset);
11172
11226
  }
@@ -11190,22 +11244,6 @@ tag.tagify__tag {
11190
11244
  text-align: start;
11191
11245
  white-space: normal;
11192
11246
  }
11193
- @layer components {
11194
- .tab-group {
11195
- position: relative;
11196
- border-radius: var(--radius-2xl);
11197
- border-style: var(--tw-border-style);
11198
- border-width: 1px;
11199
- --tw-border-style: dashed;
11200
- border-style: dashed;
11201
- border-color: var(--color-tertiary);
11202
- --tab-group-modifier: 8;
11203
- --tab-group-padding: calc(var(--tab-group-modifier) - (var(--tab-group-modifier)/2));
11204
- width: calc(100% + calc(var(--spacing) * var(--tab-group-modifier)));
11205
- margin-inline: calc(var(--spacing) * var(--tab-group-padding) * -1);
11206
- padding: calc(var(--spacing) * var(--tab-group-padding));
11207
- }
11208
- }
11209
11247
  .css-animate-dialog-slide-down[open], .css-animate-slide-down {
11210
11248
  opacity: 1;
11211
11249
  transform: translateY(0);
@@ -162,7 +162,6 @@
162
162
  @import "./css/components/hotkey.css";
163
163
  @import "./css/components/modal.css";
164
164
  @import "./css/components/filters.css";
165
- @import "./css/components/tab_group.css";
166
165
  @import "./css/css-animations.css";
167
166
  @import "./css/sidebar.css";
168
167
 
@@ -1,6 +1,7 @@
1
1
  .breadcrumbs {
2
- @apply sticky z-40 w-full bg-(--color-main-content-background) mb-4;
3
- top: calc(var(--top-navbar-height));
2
+ @apply sticky z-40 w-full bg-(--color-main-content-background) mb-4 top-(--top-navbar-height);
3
+ /* Vertical optical adjustment */
4
+ @apply -mt-1;
4
5
  }
5
6
 
6
7
  /* Soft fade strip just below the sticky breadcrumbs. Eases the seam between
@@ -36,6 +37,14 @@
36
37
  @apply -ms-1;
37
38
  }
38
39
 
40
+ /* The home crumb is the first element and is the only one carrying an icon by
41
+ default. On small screens collapse it to just the icon to save horizontal
42
+ space; the label returns at md. Scoping to :has(icon) means a custom first
43
+ crumb without an icon keeps its text instead of rendering empty. */
44
+ &:first-child:has(.breadcrumb-element__icon) .breadcrumb-element__text {
45
+ @apply hidden md:inline;
46
+ }
47
+
39
48
  &:focus-visible {
40
49
  outline-offset: var(--focus-outline-offset-inset);
41
50
  }
@@ -20,7 +20,7 @@
20
20
  }
21
21
 
22
22
  .color-scheme-switcher__compact-trigger {
23
- @apply inline-flex items-center gap-1 h-8 ps-2 pe-1.5 rounded-lg transition-all duration-150;
23
+ @apply inline-flex items-center gap-1 h-6 ps-1.5 pe-1 rounded-lg transition-all duration-150;
24
24
  @apply text-avo-neutral-300 bg-avo-neutral-800 border border-avo-neutral-700 hover:bg-avo-neutral-700 hover:text-avo-neutral-50;
25
25
  @apply cursor-pointer;
26
26
  background-color: var(--top-navbar-control-background);
@@ -33,6 +33,12 @@
33
33
  }
34
34
  }
35
35
 
36
+ @media (min-width: theme(--breakpoint-lg)) {
37
+ .color-scheme-switcher__compact-trigger {
38
+ @apply h-8 ps-2 pe-1.5;
39
+ }
40
+ }
41
+
36
42
  .color-scheme-switcher__chevron {
37
43
  @apply size-3 opacity-60;
38
44
  }
@@ -51,7 +51,7 @@
51
51
  }
52
52
 
53
53
  .filters-date-input__action {
54
- @apply absolute inset-y-0 end-0 flex items-center pe-2.5 text-content-secondary rounded-lg;
54
+ @apply absolute inset-y-0 end-0 flex items-center justify-center px-2.5 text-content-secondary rounded-lg;
55
55
 
56
56
  outline-offset: var(--focus-outline-offset-inset);
57
57
  }
@@ -150,9 +150,9 @@
150
150
  ========================================================================== */
151
151
 
152
152
  .input-field__password-toggle {
153
- @apply absolute text-content-secondary inset-y-0 end-0 flex items-center cursor-pointer rounded-lg;
153
+ @apply absolute text-content-secondary inset-y-0 end-0 flex items-center justify-center cursor-pointer rounded-lg;
154
154
 
155
- padding-inline-end: var(--input-icon-offset);
155
+ padding-inline: var(--input-icon-offset);
156
156
  outline-offset: var(--focus-outline-offset-inset);
157
157
  }
158
158
 
@@ -1,6 +1,12 @@
1
+ /* Card radii as shared design tokens. Consumed via Tailwind's `rounded-(--var)`
2
+ arbitrary-property syntax so the value can be reused and overridden anywhere
3
+ instead of being a one-off literal. */
4
+ @theme {
5
+ }
6
+
1
7
  /* Card Component - Based on Figma Design System */
2
8
  .card {
3
- @apply flex flex-col items-start self-stretch rounded-xl border border-tertiary bg-secondary;
9
+ @apply flex flex-col items-start self-stretch rounded-card border border-tertiary bg-secondary;
4
10
 
5
11
  /* Contain horizontal overflow so a wide inner scroller (e.g. .card__wrapper
6
12
  wrapping a wide table) can't bleed past the card and push the document
@@ -79,7 +85,7 @@
79
85
 
80
86
  /* Card body */
81
87
  .card__body {
82
- @apply flex flex-col items-start self-stretch w-full rounded-lg border border-tertiary bg-primary;
88
+ @apply flex flex-col items-start self-stretch w-full rounded-card-wrapper border border-tertiary bg-primary;
83
89
  }
84
90
 
85
91
  /* Card footer - full width so pagination can span edge to edge */
@@ -19,7 +19,7 @@
19
19
  }
20
20
 
21
21
  .dropdown-menu {
22
- @apply flex flex-col w-full rounded-lg border border-tertiary bg-primary min-w-48;
22
+ @apply flex flex-col w-full rounded-lg border border-tertiary bg-primary;
23
23
  }
24
24
 
25
25
  .dropdown-menu--scrollable {
@@ -155,4 +155,26 @@
155
155
  @apply border-b-2 border-accent;
156
156
  margin-bottom: -1px; /* Overlap with container border */
157
157
  }
158
+
159
+ /* Tab Group Component */
160
+ /* Dashed border wraps both the tabs list and the active tab's content.
161
+ The element extends 5px past each side of its container so the border
162
+ sits outside the panel padding without requiring the parent to know
163
+ about it. Uses width + negative margin-inline (RTL-safe) instead of
164
+ left/right. */
165
+ .tab-group {
166
+ @apply relative border border-dashed border-1 border-tertiary hover:border-quaternary rounded-2xl;
167
+ --tab-group-modifier: 4;
168
+ --tab-group-padding: calc(var(--tab-group-modifier) - (var(--tab-group-modifier)/2));
169
+
170
+ width: calc(100% + calc(var(--spacing) * var(--tab-group-modifier)));
171
+ margin-inline: calc(var(--spacing) * var(--tab-group-padding) * -1);
172
+ padding: calc(var(--spacing) * var(--tab-group-padding));
173
+ }
174
+
175
+ @media (width > theme(--breakpoint-md)) {
176
+ .tab-group {
177
+ --tab-group-modifier: 8;
178
+ }
179
+ }
158
180
  }
@@ -41,8 +41,9 @@
41
41
  mx-auto happens inside the area to the right of the sidebar, not the page. */
42
42
  [data-controller~="sidebar"] {
43
43
  --sidebar-width: --spacing(64);
44
- --sidebar-offset-size: 0rem;
45
- --content-width: calc(100% - var(--spacing));
44
+ --sidebar-offset-size: 0;
45
+
46
+ --content-width: calc(100%);
46
47
  }
47
48
 
48
49
  @media (min-width: theme(--breakpoint-lg)) {
@@ -51,35 +52,65 @@
51
52
  }
52
53
  }
53
54
 
54
- [data-controller~="sidebar"][data-sidebar-open-value="false"] {
55
- .main-content {
56
- @apply ms-0;
57
- }
58
- }
59
-
60
55
  .main {
61
56
  padding-top: var(--top-navbar-height);
62
- padding-inline-start: calc(var(--sidebar-offset-size) - var(--spacing));
57
+ padding-inline-start: var(--sidebar-offset-size);
63
58
  transition: padding 0.1s ease-in-out;
64
59
  }
65
60
 
66
61
  .main-content {
67
- --main-content-start-radius: 0px;
68
- --main-content-end-radius: 0px;
62
+ --main-content-start-radius: 0;
63
+ --main-content-end-radius: 0;
64
+ --main-content-width: var(--content-width);
69
65
 
70
- @apply relative w-(--content-width) flex flex-col bg-(--color-main-content-background) py-2 lg:py-4 px-2 lg:px-4 border-s border-(--color-main-content-border) ms-1 rounded-se-(--main-content-end-radius) rounded-ss-(--main-content-start-radius);
66
+ @apply relative w-(--main-content-width) flex flex-col bg-(--color-main-content-background) py-2 lg:py-4 px-2 lg:px-4 border-s border-(--color-main-content-border) rounded-se-(--main-content-end-radius) rounded-ss-(--main-content-start-radius);
71
67
 
72
68
  transition: margin 0.1s ease-in-out, width 0.1s ease-in-out;
73
69
  min-height: calc(100dvh - var(--top-navbar-height) - var(--spacing));
74
70
 
75
71
  @container style(--navbar-notch-enabled: true) {
72
+ --main-content-start-radius: var(--main-content-radius);
76
73
  --main-content-end-radius: var(--main-content-radius);
77
74
  }
78
75
 
79
76
  @container style(--navbar-notch-enabled: true) and style(--top-navbar-start-notch-align-with-main-content: true) {
80
77
  --main-content-start-radius: var(--main-content-radius);
78
+ --main-content-end-radius: var(--main-content-radius);
79
+ }
80
+
81
+ }
82
+
83
+ /* Desktop: show sidebar when sidebar-open class is present (lg+ only) */
84
+ @media (min-width: theme(--breakpoint-lg)) {
85
+ .sidebar-open .avo-sidebar {
86
+ transform: translateX(0);
87
+ }
88
+
89
+ html[dir="rtl"] .sidebar-open .avo-sidebar {
90
+ transform: translateX(0);
91
+ }
92
+
93
+ /* With the sidebar open the content panel butts up against it, so flatten the
94
+ start corner. When the sidebar is closed the panel floats free and keeps the
95
+ rounded start corner it inherits from the base block. The
96
+ align-with-main-content layout reads as one continuous strip, so it stays
97
+ rounded regardless of sidebar state (the `: false` style query excludes it). */
98
+ @container style(--navbar-notch-enabled: true) and style(--top-navbar-start-notch-align-with-main-content: false) {
99
+ .sidebar-open .main-content {
100
+ --main-content-start-radius: 0;
101
+ }
102
+ }
103
+ }
104
+
105
+ /* Mobile: show sidebar only when explicitly toggled open */
106
+ @media (width < theme(--breakpoint-lg)) {
107
+ .sidebar-mobile-open .avo-sidebar {
108
+ transform: translateX(0);
81
109
  }
82
110
 
111
+ html[dir="rtl"] .sidebar-mobile-open .avo-sidebar {
112
+ transform: translateX(0);
113
+ }
83
114
  }
84
115
 
85
116
  .main-content.focused,
@@ -89,7 +120,7 @@
89
120
  }
90
121
 
91
122
  .main-content__container {
92
- @apply flex flex-1 flex-col px-2;
123
+ @apply flex flex-1 flex-col px-0 md:px-2;
93
124
  }
94
125
 
95
126
  .container-large {
@@ -107,29 +138,6 @@
107
138
  .top-navbar {
108
139
  @apply z-400 fixed top-0 inset-x-0 w-full shrink-0 pointer-events-none;
109
140
 
110
- /* Top navbar theme contract.
111
- Override these variables on `.top-navbar` when the navbar needs its own
112
- palette. They are defined here so the customization point stays local to
113
- the navbar while popovers, dropdown panels, and the main content keep using
114
- their own surface tokens.
115
-
116
- Example:
117
- .top-navbar {
118
- --top-navbar-background: var(--color-primary);
119
- --top-navbar-content: var(--color-content-secondary);
120
- --top-navbar-content-hover: var(--color-content);
121
- --top-navbar-control-background: var(--color-secondary);
122
- --top-navbar-control-background-hover: var(--color-tertiary);
123
- --top-navbar-control-border: var(--color-tertiary);
124
- --top-navbar-control-content: var(--color-content);
125
- --top-navbar-control-muted: var(--color-content-secondary);
126
- --top-navbar-control-shortcut-background: var(--color-primary);
127
- --top-navbar-control-shortcut-border: var(--color-tertiary);
128
- --top-navbar-control-shortcut-content: var(--color-content-secondary);
129
- --top-navbar-active-background: var(--color-foreground);
130
- --top-navbar-active-content: var(--color-background);
131
- }
132
- */
133
141
  --top-navbar-background: var(--color-navbar-background);
134
142
  --top-navbar-content: var(--color-avo-neutral-300);
135
143
  --top-navbar-content-hover: var(--color-avo-neutral-50);
@@ -334,28 +342,3 @@ button[data-sidebar-toggle-icon] {
334
342
  html[dir="rtl"] .avo-sidebar {
335
343
  transform: translateX(100%);
336
344
  }
337
-
338
- /* Desktop: show sidebar when sidebar-open class is present (lg+ only) */
339
- @media (min-width: theme(--breakpoint-lg)) {
340
- .sidebar-open .avo-sidebar {
341
- transform: translateX(0);
342
- }
343
-
344
- html[dir="rtl"] .sidebar-open .avo-sidebar {
345
- transform: translateX(0);
346
- }
347
- .main:not(.sidebar-open) .main-content {
348
- @apply ms-0;
349
- }
350
- }
351
-
352
- /* Mobile: show sidebar only when explicitly toggled open */
353
- @media (width < theme(--breakpoint-lg)) {
354
- .sidebar-mobile-open .avo-sidebar {
355
- transform: translateX(0);
356
- }
357
-
358
- html[dir="rtl"] .sidebar-mobile-open .avo-sidebar {
359
- transform: translateX(0);
360
- }
361
- }
@@ -61,6 +61,7 @@
61
61
  --color-primary: var(--color-white);
62
62
  --color-secondary: var(--color-avo-neutral-100);
63
63
  --color-tertiary: var(--color-avo-neutral-200);
64
+ --color-quaternary: var(--color-avo-neutral-300);
64
65
  --color-content: var(--color-avo-neutral-950);
65
66
  --color-content-secondary: var(--color-avo-neutral-500);
66
67
 
@@ -108,6 +109,8 @@
108
109
  --border-color by default, so it resolves per-scheme automatically. */
109
110
  --color-main-content-border: var(--border-color);
110
111
 
112
+ --radius-card: var(--radius-xl);
113
+ --radius-card-wrapper: var(--radius-lg);
111
114
  }
112
115
 
113
116
  /* Navbar notch knobs live in a plain :root block, not in @theme:
@@ -167,6 +170,7 @@
167
170
  --color-primary: var(--color-avo-neutral-950);
168
171
  --color-secondary: var(--color-avo-neutral-800);
169
172
  --color-tertiary: var(--color-avo-neutral-700);
173
+ --color-quaternary: var(--color-avo-neutral-600);
170
174
  --color-content: var(--color-white);
171
175
  --color-content-secondary: var(--color-avo-neutral-300);
172
176
 
@@ -1,9 +1,7 @@
1
1
  <%= content_tag :div, class: @classes, data: @data do %>
2
- <div class="py-2 px-4 h-full w-full">
3
2
  <% if @field.as_html %>
4
3
  <%= sanitize @field.value %>
5
4
  <% else %>
6
- <div class="font-medium uppercase"><%= @field.value %></div>
5
+ <div class="uppercase"><%= @field.value %></div>
7
6
  <% end %>
8
- </div>
9
7
  <% end %>
@@ -7,7 +7,7 @@ class Avo::Fields::Common::HeadingComponent < Avo::BaseComponent
7
7
 
8
8
  def after_initialize
9
9
  @view = @field.resource.view
10
- @classes = "flex items-start py-1 leading-tight bg-secondary text-content-secondary text-xs #{@field.get_html(:classes, view: @view, element: :wrapper)}"
10
+ @classes = "flex items-start leading-tight bg-background text-content-secondary font-medium text-xs py-2 px-4 h-full w-full #{@field.get_html(:classes, view: @view, element: :wrapper)}"
11
11
  @data = {**stimulus_data_attributes, **@field.get_html(:data, view: @view, element: :wrapper)}
12
12
  add_stimulus_attributes_for(@field.resource, @data)
13
13
  end
@@ -36,16 +36,17 @@
36
36
  %>
37
37
 
38
38
  <%= content_tag :button,
39
- class: "absolute end-0 self-center me-2 uppercase font-semibold text-xs disabled:cursor-not-allowed disabled:opacity-50 text-content-secondary cursor-pointer rounded-md",
39
+ class: "absolute inset-y-0 end-0 flex items-center justify-center px-2.5 uppercase font-semibold text-xs disabled:cursor-not-allowed disabled:opacity-50 text-content-secondary cursor-pointer rounded-lg",
40
40
  id: :reset,
41
41
  type: :button,
42
42
  title: t("avo.reset").capitalize,
43
43
  disabled: disabled?,
44
+ style: "outline-offset: var(--focus-outline-offset-inset)",
44
45
  data: {
45
46
  action: "click->date-field#clear",
46
47
  tippy: :tooltip
47
48
  } do %>
48
- <%= helpers.svg "tabler/outline/x", class: "h-4" %>
49
+ <%= helpers.svg "tabler/outline/x", class: "size-4" %>
49
50
  <% end %>
50
51
  <% end %>
51
52
  <% end %>
@@ -37,16 +37,17 @@
37
37
  style: @field.get_html(:style, view: view, element: :input)
38
38
  %>
39
39
  <%= content_tag :button,
40
- class: "absolute end-0 self-center me-2 uppercase font-semibold text-xs disabled:cursor-not-allowed disabled:opacity-50 text-content-secondary cursor-pointer rounded-md",
40
+ class: "absolute inset-y-0 end-0 flex items-center justify-center px-2.5 uppercase font-semibold text-xs disabled:cursor-not-allowed disabled:opacity-50 text-content-secondary cursor-pointer rounded-lg",
41
41
  id: :reset,
42
42
  type: :button,
43
43
  title: t("avo.reset").capitalize,
44
44
  disabled: disabled?,
45
+ style: "outline-offset: var(--focus-outline-offset-inset)",
45
46
  data: {
46
47
  action: "click->date-field#clear",
47
48
  tippy: :tooltip
48
49
  } do %>
49
- <%= helpers.svg "tabler/outline/x", class: "h-4" %>
50
+ <%= helpers.svg "tabler/outline/x", class: "size-4" %>
50
51
  <% end %>
51
52
  <% end %>
52
53
  <% end %>
@@ -1,3 +1,3 @@
1
- <div class="<%= class_names("w-full",{'overflow-hidden rounded-t': @index == 0}) %>" data-field-id="<%= @field.id %>">
1
+ <%= content_tag :div, class: class_names("w-full", {"overflow-hidden rounded-t-card-wrapper": @index == 0}), data: {field_id: @field.id} do %>
2
2
  <%= render Avo::Fields::Common::HeadingComponent.new field: @field %>
3
- </div>
3
+ <% end %>
@@ -1,3 +1,3 @@
1
- <%= tag.div class: class_names(@field.width_class, "overflow-hidden rounded-t": @index == 0), data: {field_id: @field.id} do %>
1
+ <%= tag.div class: class_names(@field.width_class, "overflow-hidden rounded-t-card-wrapper": @index == 0), data: {field_id: @field.id, index: @index} do %>
2
2
  <%= render Avo::Fields::Common::HeadingComponent.new field: @field %>
3
3
  <% end %>
@@ -37,16 +37,17 @@
37
37
  style: @field.get_html(:style, view: view, element: :input)
38
38
  %>
39
39
  <%= content_tag :button,
40
- class: "absolute end-0 self-center me-2 uppercase font-semibold text-xs disabled:cursor-not-allowed disabled:opacity-50 text-content-secondary cursor-pointer rounded-md",
40
+ class: "absolute inset-y-0 end-0 flex items-center justify-center px-2.5 uppercase font-semibold text-xs disabled:cursor-not-allowed disabled:opacity-50 text-content-secondary cursor-pointer rounded-lg",
41
41
  id: :reset,
42
42
  type: :button,
43
43
  title: t("avo.reset").capitalize,
44
44
  disabled: disabled?,
45
+ style: "outline-offset: var(--focus-outline-offset-inset)",
45
46
  data: {
46
47
  action: "click->date-field#clear",
47
48
  tippy: :tooltip
48
49
  } do %>
49
- <%= helpers.svg "tabler/outline/x", class: "h-4" %>
50
+ <%= helpers.svg "tabler/outline/x", class: "size-4" %>
50
51
  <% end %>
51
52
  <% end %>
52
53
  <% end %>
@@ -62,11 +62,9 @@
62
62
  <% end %>
63
63
 
64
64
  <% header.with_controls do %>
65
- <div class="flex gap-3 flex-wrap">
66
- <% @resource.render_index_controls(item: singular_resource_name.downcase).each do |control| %>
67
- <%= render_control control %>
68
- <% end %>
69
- </div>
65
+ <% @resource.render_index_controls(item: singular_resource_name.downcase).each do |control| %>
66
+ <%= render_control control %>
67
+ <% end %>
70
68
  <% end %>
71
69
  <% end %>
72
70
  <% end %>
@@ -7,9 +7,10 @@
7
7
  <div class="top-navbar__start">
8
8
  <%# Mobile always needs a toggle to reach the overlay sidebar. Desktop toggle
9
9
  is optional and controlled by sidebar_toggle_visible. %>
10
- <%= a_button class: class_names('shrink-0', 'lg:hidden': !Avo.configuration.sidebar_toggle_visible),
10
+ <%= a_button class: class_names("shrink-0 -ms-1.5 lg:ms-0", "lg:hidden": !Avo.configuration.sidebar_toggle_visible),
11
11
  size: :sm,
12
12
  style: :text,
13
+ padding: :sm,
13
14
  data: {
14
15
  action: 'click->sidebar#toggleSidebarForViewport',
15
16
  sidebar_toggle_icon: true,
@@ -140,7 +140,7 @@ module Avo
140
140
  @license_key = nil
141
141
  @current_user = proc {}
142
142
  @authenticate = proc {}
143
- @explicit_authorization = false
143
+ @explicit_authorization = true
144
144
  @authorization_methods = {
145
145
  index: "index?",
146
146
  show: "show?",
@@ -119,11 +119,7 @@ module Avo
119
119
  resource = target_resource
120
120
  resource = Avo.resource_manager.get_resource_by_model_class model if model.present?
121
121
 
122
- query = resource.query_scope
123
-
124
- if attach_scope.present?
125
- query = Avo::ExecutionContext.new(target: attach_scope, query: query, parent: get_record).handle
126
- end
122
+ query = scoped_target_query(resource, get_record)
127
123
 
128
124
  query.all.limit(Avo.configuration.associations_lookup_list_limit).map do |record|
129
125
  [resource.new(record: record).record_title, record.to_param]
@@ -212,12 +208,18 @@ module Avo
212
208
  if valid_model_class.blank? || id_from_param.blank?
213
209
  record.send(:"#{polymorphic_as}_id=", nil)
214
210
  else
215
- record_id = target_resource(record:, polymorphic_model_class: value.safe_constantize).find_record(id_from_param).id
211
+ target = target_resource(record:, polymorphic_model_class: value.safe_constantize)
212
+ record_id = target.find_record(id_from_param, query: scoped_target_query(target, record, for_find: true)).id
216
213
 
217
214
  record.send(:"#{polymorphic_as}_id=", record_id)
218
215
  end
219
216
  else
220
- record_id = value.blank? ? value : target_resource(record:).find_record(value).send(reflection.association_primary_key)
217
+ target = target_resource(record:)
218
+ record_id = if value.blank?
219
+ value
220
+ else
221
+ target.find_record(value, query: scoped_target_query(target, record, for_find: true)).send(reflection.association_primary_key)
222
+ end
221
223
 
222
224
  record.send(:"#{key}=", record_id)
223
225
  end
@@ -325,6 +327,15 @@ module Avo
325
327
 
326
328
  private
327
329
 
330
+ def scoped_target_query(resource, parent_record, for_find: false)
331
+ resource_class = resource.is_a?(Class) ? resource : resource.class
332
+ query = for_find ? resource_class.find_scope : resource_class.query_scope
333
+
334
+ return query if attach_scope.blank?
335
+
336
+ Avo::ExecutionContext.new(target: attach_scope, query: query, parent: parent_record).handle
337
+ end
338
+
328
339
  def get_model_class(record)
329
340
  if record.nil?
330
341
  @resource.model_class
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "4.0.0.beta.43" unless const_defined?(:VERSION)
2
+ VERSION = "4.0.0.beta.45" unless const_defined?(:VERSION)
3
3
  end
@@ -37,7 +37,7 @@ Avo.configure do |config|
37
37
  # }
38
38
  # config.raise_error_on_missing_policy = false
39
39
  config.authorization_client = nil
40
- config.explicit_authorization = true
40
+ # config.explicit_authorization = true
41
41
 
42
42
  ## == Localization ==
43
43
  # config.locale = 'en-US'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avo
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.beta.43
4
+ version: 4.0.0.beta.45
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Marin
@@ -267,7 +267,6 @@ files:
267
267
  - app/assets/stylesheets/css/components/input.css
268
268
  - app/assets/stylesheets/css/components/media_library.css
269
269
  - app/assets/stylesheets/css/components/modal.css
270
- - app/assets/stylesheets/css/components/tab_group.css
271
270
  - app/assets/stylesheets/css/components/tooltip.css
272
271
  - app/assets/stylesheets/css/components/ui/badge.css
273
272
  - app/assets/stylesheets/css/components/ui/card.css
@@ -1,18 +0,0 @@
1
- /* Tab Group Component */
2
- @layer components {
3
- /* Dashed border wraps both the tabs list and the active tab's content.
4
- The element extends 5px past each side of its container so the border
5
- sits outside the panel padding without requiring the parent to know
6
- about it. Uses width + negative margin-inline (RTL-safe) instead of
7
- left/right. */
8
- .tab-group {
9
- @apply relative border border-dashed border-tertiary rounded-2xl;
10
- --tab-group-modifier: 8;
11
- --tab-group-padding: calc(var(--tab-group-modifier) - (var(--tab-group-modifier)/2));
12
-
13
- width: calc(100% + calc(var(--spacing) * var(--tab-group-modifier)));
14
- margin-inline: calc(var(--spacing) * var(--tab-group-padding) * -1);
15
- padding: calc(var(--spacing) * var(--tab-group-padding));
16
-
17
- }
18
- }