nitro_kit 2.0.0.alpha.2 → 2.0.0.alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -1
  3. data/README.md +23 -4
  4. data/STYLE_GUIDE.md +37 -5
  5. data/app/assets/stylesheets/nitro_kit.css +1714 -1358
  6. data/app/components/nitro_kit/accordion.rb +1 -7
  7. data/app/components/nitro_kit/app_navigation.rb +1 -2
  8. data/app/components/nitro_kit/app_shell.rb +1 -7
  9. data/app/components/nitro_kit/appearance_picker.rb +1 -11
  10. data/app/components/nitro_kit/avatar.rb +6 -1
  11. data/app/components/nitro_kit/avatar_stack.rb +3 -0
  12. data/app/components/nitro_kit/button_group.rb +2 -2
  13. data/app/components/nitro_kit/checkbox.rb +7 -4
  14. data/app/components/nitro_kit/checkbox_group.rb +0 -25
  15. data/app/components/nitro_kit/combobox.rb +3 -16
  16. data/app/components/nitro_kit/command_palette.rb +41 -59
  17. data/app/components/nitro_kit/component.rb +57 -5
  18. data/app/components/nitro_kit/danger_zone.rb +5 -1
  19. data/app/components/nitro_kit/data_section.rb +28 -4
  20. data/app/components/nitro_kit/details_table.rb +19 -8
  21. data/app/components/nitro_kit/dialog.rb +23 -19
  22. data/app/components/nitro_kit/dropdown.rb +1 -6
  23. data/app/components/nitro_kit/dropzone.rb +3 -14
  24. data/app/components/nitro_kit/empty_state.rb +21 -2
  25. data/app/components/nitro_kit/field.rb +35 -11
  26. data/app/components/nitro_kit/form_builder.rb +0 -1
  27. data/app/components/nitro_kit/progressive_image.rb +2 -2
  28. data/app/components/nitro_kit/radio_button.rb +7 -4
  29. data/app/components/nitro_kit/radio_button_group.rb +0 -25
  30. data/app/components/nitro_kit/select.rb +3 -3
  31. data/app/components/nitro_kit/settings_layout.rb +17 -4
  32. data/app/components/nitro_kit/{form_section.rb → settings_section.rb} +18 -11
  33. data/app/components/nitro_kit/sheet.rb +29 -20
  34. data/app/components/nitro_kit/stat_grid.rb +18 -2
  35. data/app/components/nitro_kit/table.rb +22 -3
  36. data/app/components/nitro_kit/tabs.rb +1 -13
  37. data/app/components/nitro_kit/toast.rb +4 -2
  38. data/app/components/nitro_kit/toolbar.rb +2 -0
  39. data/app/components/nitro_kit/tooltip.rb +7 -10
  40. data/app/javascript/controllers/nk/app_shell_controller.js +3 -3
  41. data/app/javascript/controllers/nk/appearance_controller.js +6 -0
  42. data/app/javascript/controllers/nk/combobox_controller.js +51 -1
  43. data/app/javascript/controllers/nk/command_palette_controller.js +21 -11
  44. data/app/javascript/controllers/nk/dialog_controller.js +54 -0
  45. data/app/javascript/controllers/nk/dropdown_controller.js +45 -0
  46. data/app/javascript/controllers/nk/dropzone_controller.js +2 -2
  47. data/app/javascript/controllers/nk/progressive_image_controller.js +11 -7
  48. data/app/javascript/controllers/nk/tabs_controller.js +8 -1
  49. data/app/javascript/controllers/nk/tooltip_controller.js +9 -0
  50. data/config/locales/en.yml +4 -1
  51. data/docs/agent_guide.md +31 -16
  52. data/docs/agent_native_spec.md +27 -10
  53. data/docs/browser_support.md +193 -0
  54. data/docs/component_contracts.md +88 -82
  55. data/docs/customization.md +27 -15
  56. data/docs/hotwire.md +15 -3
  57. data/docs/initialization_prompt.md +31 -6
  58. data/docs/migration_1_to_2.md +61 -19
  59. data/docs/patterns/application_foundation.md +6 -4
  60. data/docs/patterns/crud_resource.md +6 -3
  61. data/docs/patterns/destructive_action.md +25 -0
  62. data/docs/patterns/resource_form.md +1 -1
  63. data/docs/rails_conventions.md +4 -1
  64. data/docs/rails_integration.md +39 -11
  65. data/lib/generators/nitro_kit/upgrade_smoke_tests_generator.rb +12 -0
  66. data/lib/nitro_kit/installation.rb +9 -4
  67. data/lib/nitro_kit/migration_inventory.rb +268 -8
  68. data/lib/nitro_kit/upgrade_smoke_test.rb +10 -12
  69. data/lib/nitro_kit/version.rb +1 -1
  70. data/lib/rails/commands/nitro_kit/nitro_kit_command.rb +10 -3
  71. data/plugins/nitro-kit/skills/nitro-kit-hotwire/SKILL.md +4 -0
  72. data/plugins/nitro-kit/skills/nitro-kit-rails/SKILL.md +6 -1
  73. data/plugins/nitro-kit/skills/nitro-kit-ui/SKILL.md +18 -8
  74. data/src/stylesheets/nitro_kit/components/accordion.css +40 -40
  75. data/src/stylesheets/nitro_kit/components/alert.css +9 -9
  76. data/src/stylesheets/nitro_kit/components/app_navigation.css +19 -19
  77. data/src/stylesheets/nitro_kit/components/app_shell.css +196 -193
  78. data/src/stylesheets/nitro_kit/components/appearance_picker.css +41 -31
  79. data/src/stylesheets/nitro_kit/components/avatar.css +3 -3
  80. data/src/stylesheets/nitro_kit/components/avatar_stack.css +36 -19
  81. data/src/stylesheets/nitro_kit/components/button.css +83 -58
  82. data/src/stylesheets/nitro_kit/components/button_group.css +19 -14
  83. data/src/stylesheets/nitro_kit/components/card.css +11 -5
  84. data/src/stylesheets/nitro_kit/components/checkbox.css +40 -36
  85. data/src/stylesheets/nitro_kit/components/checkbox_group.css +13 -13
  86. data/src/stylesheets/nitro_kit/components/combobox.css +33 -23
  87. data/src/stylesheets/nitro_kit/components/command_palette.css +48 -47
  88. data/src/stylesheets/nitro_kit/components/control_group.css +52 -58
  89. data/src/stylesheets/nitro_kit/components/danger_zone.css +3 -3
  90. data/src/stylesheets/nitro_kit/components/data_section.css +1 -1
  91. data/src/stylesheets/nitro_kit/components/details_table.css +13 -13
  92. data/src/stylesheets/nitro_kit/components/dialog.css +6 -3
  93. data/src/stylesheets/nitro_kit/components/dropdown.css +29 -23
  94. data/src/stylesheets/nitro_kit/components/dropzone.css +71 -28
  95. data/src/stylesheets/nitro_kit/components/empty_state.css +6 -6
  96. data/src/stylesheets/nitro_kit/components/field.css +30 -26
  97. data/src/stylesheets/nitro_kit/components/field_group.css +13 -0
  98. data/src/stylesheets/nitro_kit/components/fieldset.css +6 -0
  99. data/src/stylesheets/nitro_kit/components/input.css +9 -2
  100. data/src/stylesheets/nitro_kit/components/layout.css +165 -165
  101. data/src/stylesheets/nitro_kit/components/page_header.css +3 -3
  102. data/src/stylesheets/nitro_kit/components/pagination.css +55 -46
  103. data/src/stylesheets/nitro_kit/components/pagination_bar.css +7 -7
  104. data/src/stylesheets/nitro_kit/components/palette.css +20 -20
  105. data/src/stylesheets/nitro_kit/components/progressive_image.css +44 -54
  106. data/src/stylesheets/nitro_kit/components/radio_button.css +36 -29
  107. data/src/stylesheets/nitro_kit/components/radio_button_group.css +43 -43
  108. data/src/stylesheets/nitro_kit/components/rich_text_area.css +15 -0
  109. data/src/stylesheets/nitro_kit/components/select.css +2 -9
  110. data/src/stylesheets/nitro_kit/components/settings_layout.css +21 -18
  111. data/src/stylesheets/nitro_kit/components/settings_section.css +84 -0
  112. data/src/stylesheets/nitro_kit/components/sheet.css +23 -3
  113. data/src/stylesheets/nitro_kit/components/stat_grid.css +10 -9
  114. data/src/stylesheets/nitro_kit/components/switch.css +37 -33
  115. data/src/stylesheets/nitro_kit/components/table.css +35 -31
  116. data/src/stylesheets/nitro_kit/components/tabs.css +43 -39
  117. data/src/stylesheets/nitro_kit/components/toast.css +20 -9
  118. data/src/stylesheets/nitro_kit/components/toolbar.css +14 -39
  119. data/src/stylesheets/nitro_kit/components/tooltip.css +34 -29
  120. data/src/stylesheets/nitro_kit/components/typeset.css +147 -1
  121. data/src/stylesheets/nitro_kit/reset.css +9 -9
  122. data/src/stylesheets/nitro_kit/tokens.css +8 -9
  123. metadata +4 -3
  124. data/src/stylesheets/nitro_kit/components/form_section.css +0 -71
@@ -7,17 +7,17 @@
7
7
  }
8
8
 
9
9
  :where(
10
- [data-nk="radio-button-group"] > [data-slot="radio-button-group-legend"]
11
- ) {
10
+ [data-nk="radio-button-group"] > [data-slot="radio-button-group-legend"]
11
+ ) {
12
12
  padding: 0;
13
13
  font-size: var(--nk-text-sm);
14
14
  font-weight: var(--nk-font-weight-semibold);
15
15
  }
16
16
 
17
17
  :where(
18
- [data-nk="radio-button-group"]
19
- > [data-slot="radio-button-group-description"]
20
- ) {
18
+ [data-nk="radio-button-group"]
19
+ > [data-slot="radio-button-group-description"]
20
+ ) {
21
21
  margin-block-start: var(--nk-space);
22
22
  color: var(--nk-color-muted-foreground);
23
23
  font-size: var(--nk-text-sm);
@@ -25,34 +25,34 @@
25
25
  }
26
26
 
27
27
  :where(
28
- [data-nk="radio-button-group"] > [data-slot="radio-button-group-choices"]
29
- ) {
28
+ [data-nk="radio-button-group"] > [data-slot="radio-button-group-choices"]
29
+ ) {
30
30
  display: grid;
31
31
  gap: var(--nk-space);
32
32
  margin-block-start: calc(var(--nk-space) * 2);
33
33
  }
34
34
 
35
35
  :where(
36
- [data-nk="radio-button-group"][data-presentation="list"][data-orientation="vertical"]
37
- > [data-slot="radio-button-group-choices"]
38
- ) {
36
+ [data-nk="radio-button-group"][data-presentation="list"][data-orientation="vertical"]
37
+ > [data-slot="radio-button-group-choices"]
38
+ ) {
39
39
  gap: 0;
40
40
  }
41
41
 
42
42
  :where(
43
- [data-nk="radio-button-group"][data-orientation="horizontal"]
44
- > [data-slot="radio-button-group-choices"]
45
- ) {
43
+ [data-nk="radio-button-group"][data-orientation="horizontal"]
44
+ > [data-slot="radio-button-group-choices"]
45
+ ) {
46
46
  display: flex;
47
47
  flex-wrap: wrap;
48
48
  gap: calc(var(--nk-space) * 4);
49
49
  }
50
50
 
51
51
  :where(
52
- [data-nk="radio-button-group"][data-presentation="cards"]
53
- > [data-slot="radio-button-group-choices"]
54
- > [data-slot="radio-button-group-choice"]
55
- ) {
52
+ [data-nk="radio-button-group"][data-presentation="cards"]
53
+ > [data-slot="radio-button-group-choices"]
54
+ > [data-slot="radio-button-group-choice"]
55
+ ) {
56
56
  inline-size: 100%;
57
57
  padding: calc(var(--nk-space) * 3);
58
58
  background: var(--nk-color-surface);
@@ -61,9 +61,9 @@
61
61
  }
62
62
 
63
63
  :where(
64
- [data-nk="radio-button-group"][data-presentation="segmented"]
65
- > [data-slot="radio-button-group-choices"]
66
- ) {
64
+ [data-nk="radio-button-group"][data-presentation="segmented"]
65
+ > [data-slot="radio-button-group-choices"]
66
+ ) {
67
67
  display: inline-flex;
68
68
  gap: 0;
69
69
  padding: var(--nk-space);
@@ -72,19 +72,19 @@
72
72
  }
73
73
 
74
74
  :where(
75
- [data-nk="radio-button-group"][data-presentation="segmented"]
76
- > [data-slot="radio-button-group-choices"]
77
- > [data-slot="radio-button-group-choice"]
78
- ) {
75
+ [data-nk="radio-button-group"][data-presentation="segmented"]
76
+ > [data-slot="radio-button-group-choices"]
77
+ > [data-slot="radio-button-group-choice"]
78
+ ) {
79
79
  min-inline-size: 0;
80
80
  padding-inline: calc(var(--nk-space) * 3);
81
81
  border-radius: calc(var(--nk-radius-md) - var(--nk-space));
82
82
  }
83
83
 
84
84
  :where(
85
- [data-nk="radio-button-group"][data-presentation="segmented"]
86
- [data-slot="radio-button-indicator"]
87
- ) {
85
+ [data-nk="radio-button-group"][data-presentation="segmented"]
86
+ [data-slot="radio-button-indicator"]
87
+ ) {
88
88
  display: none;
89
89
  }
90
90
 
@@ -94,9 +94,9 @@
94
94
  centred between the segment's own paddings and makes the entire segment
95
95
  clickable. */
96
96
  :where(
97
- [data-nk="radio-button-group"][data-presentation="segmented"]
98
- [data-slot="radio-button-label"]
99
- ) {
97
+ [data-nk="radio-button-group"][data-presentation="segmented"]
98
+ [data-slot="radio-button-label"]
99
+ ) {
100
100
  position: relative;
101
101
  display: flex;
102
102
  gap: 0;
@@ -106,9 +106,9 @@
106
106
  }
107
107
 
108
108
  :where(
109
- [data-nk="radio-button-group"][data-presentation="segmented"]
110
- [data-slot="radio-button-control"]
111
- ) {
109
+ [data-nk="radio-button-group"][data-presentation="segmented"]
110
+ [data-slot="radio-button-control"]
111
+ ) {
112
112
  position: absolute;
113
113
  inset: 0;
114
114
  inline-size: 100%;
@@ -118,13 +118,13 @@
118
118
 
119
119
  @layer nitro-kit.state {
120
120
  :where(
121
- [data-nk="radio-button-group"][data-presentation="cards"]
122
- > [data-slot="radio-button-group-choices"]
123
- > [data-slot="radio-button-group-choice"]:has(input:checked),
124
- [data-nk="radio-button-group"][data-presentation="segmented"]
125
- > [data-slot="radio-button-group-choices"]
126
- > [data-slot="radio-button-group-choice"]:has(input:checked)
127
- ) {
121
+ [data-nk="radio-button-group"][data-presentation="cards"]
122
+ > [data-slot="radio-button-group-choices"]
123
+ > [data-slot="radio-button-group-choice"]:has(input:checked),
124
+ [data-nk="radio-button-group"][data-presentation="segmented"]
125
+ > [data-slot="radio-button-group-choices"]
126
+ > [data-slot="radio-button-group-choice"]:has(input:checked)
127
+ ) {
128
128
  background: var(--nk-color-surface);
129
129
  border-color: var(--nk-color-primary);
130
130
  box-shadow: var(--nk-shadow-sm);
@@ -133,9 +133,9 @@
133
133
  /* The segmented indicator is hidden, so the focus ring belongs to the native
134
134
  radio that now covers the segment. */
135
135
  :where(
136
- [data-nk="radio-button-group"][data-presentation="segmented"]
137
- [data-slot="radio-button-control"]:focus-visible
138
- ) {
136
+ [data-nk="radio-button-group"][data-presentation="segmented"]
137
+ [data-slot="radio-button-control"]:focus-visible
138
+ ) {
139
139
  border-radius: calc(var(--nk-radius-md) - var(--nk-space));
140
140
  outline: var(--nk-focus-width) solid var(--nk-color-focus);
141
141
  outline-offset: calc(var(--nk-focus-offset) * -1);
@@ -5,8 +5,13 @@
5
5
  --lexxy-color-text-subtle: var(--nk-color-muted-foreground);
6
6
  --lexxy-color-link: var(--nk-color-primary);
7
7
  --lexxy-color-accent-dark: var(--nk-color-primary);
8
+ --lexxy-color-ink: var(--nk-color-foreground);
9
+ --lexxy-color-ink-medium: var(--nk-color-muted-foreground);
10
+ --lexxy-color-ink-inverted: var(--nk-color-primary-foreground);
8
11
  --lexxy-color-ink-lighter: var(--nk-color-border);
9
12
  --lexxy-color-ink-lightest: var(--nk-color-muted);
13
+ --lexxy-color-selected: var(--nk-color-muted);
14
+ --lexxy-color-selected-hover: var(--nk-color-border);
10
15
  --lexxy-radius: var(--nk-radius-md);
11
16
  display: block;
12
17
  inline-size: 100%;
@@ -19,3 +24,13 @@
19
24
  min-block-size: calc(var(--nk-space) * 24);
20
25
  }
21
26
  }
27
+
28
+ @layer nitro-kit.state {
29
+ :where(
30
+ [data-nk="rich-text-area"]
31
+ > [data-slot="rich-text-area-editor"]
32
+ > [aria-invalid="true"]
33
+ ) {
34
+ border-color: var(--nk-color-danger);
35
+ }
36
+ }
@@ -42,13 +42,6 @@
42
42
  padding: calc(var(--nk-space) * 2) calc(var(--nk-space) * 3);
43
43
  appearance: auto;
44
44
  }
45
-
46
- :where(
47
- [data-nk="select"]:has(> [data-slot="select-control"][multiple])
48
- > [data-slot="select-icon"]
49
- ) {
50
- display: none;
51
- }
52
45
  }
53
46
 
54
47
  @layer nitro-kit.state {
@@ -63,8 +56,8 @@
63
56
  }
64
57
 
65
58
  :where(
66
- [data-nk="select"] > [data-slot="select-control"][aria-invalid="true"]
67
- ) {
59
+ [data-nk="select"] > [data-slot="select-control"][aria-invalid="true"]
60
+ ) {
68
61
  border-color: var(--nk-color-danger);
69
62
  }
70
63
  }
@@ -8,9 +8,9 @@
8
8
  }
9
9
 
10
10
  :where(
11
- [data-nk="settings-layout"] > [data-slot="settings-layout-navigation"],
12
- [data-nk="settings-layout"] > [data-slot="settings-layout-content"]
13
- ) {
11
+ [data-nk="settings-layout"] > [data-slot="settings-layout-navigation"],
12
+ [data-nk="settings-layout"] > [data-slot="settings-layout-content"]
13
+ ) {
14
14
  min-width: 0;
15
15
  }
16
16
 
@@ -52,47 +52,50 @@
52
52
  /* Emphasis alone marks the current destination without adding a decorative
53
53
  edge or a filled block that would outweigh the content beside it. */
54
54
  :where(
55
- [data-nk="settings-layout"]
56
- [data-slot="settings-layout-item-link"][data-state="current"]
57
- ) {
55
+ [data-nk="settings-layout"]
56
+ [data-slot="settings-layout-item-link"][data-state="current"]
57
+ ) {
58
58
  color: var(--nk-color-foreground);
59
59
  font-weight: var(--nk-font-weight-semibold);
60
60
  }
61
61
 
62
62
  :where(
63
- [data-nk="settings-layout"]
64
- [data-slot="settings-layout-item-link"][data-state="current"]
65
- [data-slot="settings-layout-item-icon"]
66
- ) {
63
+ [data-nk="settings-layout"]
64
+ [data-slot="settings-layout-item-link"][data-state="current"]
65
+ [data-slot="settings-layout-item-icon"]
66
+ ) {
67
67
  color: var(--nk-color-foreground);
68
68
  }
69
69
 
70
70
  @media (hover: hover) {
71
71
  :where(
72
- [data-nk="settings-layout"] [data-slot="settings-layout-item-link"]:hover
73
- ) {
72
+ [data-nk="settings-layout"]
73
+ [data-slot="settings-layout-item-link"]:hover
74
+ ) {
74
75
  color: var(--nk-color-foreground);
75
76
  background: color-mix(in oklab, var(--nk-color-muted) 60%, transparent);
76
77
  }
77
78
  }
78
79
 
79
80
  :where(
80
- [data-nk="settings-layout"]
81
- [data-slot="settings-layout-item-link"]:focus-visible
82
- ) {
81
+ [data-nk="settings-layout"]
82
+ [data-slot="settings-layout-item-link"]:focus-visible
83
+ ) {
83
84
  outline: var(--nk-focus-width) solid var(--nk-color-focus);
84
85
  outline-offset: calc(var(--nk-focus-offset) * -1);
85
86
  }
86
87
 
87
88
  @media (prefers-reduced-motion: reduce) {
88
89
  :where(
89
- [data-nk="settings-layout"] [data-slot="settings-layout-item-link"]
90
- ) {
90
+ [data-nk="settings-layout"] [data-slot="settings-layout-item-link"]
91
+ ) {
91
92
  transition-duration: 0.01ms;
92
93
  }
93
94
  }
95
+ }
94
96
 
95
- @media (max-width: 48rem) {
97
+ @layer nitro-kit.compound {
98
+ @media (width < 48rem) {
96
99
  :where([data-nk="settings-layout"]) {
97
100
  grid-template-columns: minmax(0, 1fr);
98
101
  }
@@ -0,0 +1,84 @@
1
+ @layer nitro-kit.base {
2
+ :where([data-nk="settings-section"]) {
3
+ display: grid;
4
+ grid-template-columns: minmax(10rem, 14rem) minmax(0, 1fr);
5
+ column-gap: calc(var(--nk-space) * 8);
6
+ row-gap: calc(var(--nk-space) * 5);
7
+ align-items: start;
8
+ min-inline-size: 0;
9
+ color: var(--nk-color-foreground);
10
+ }
11
+
12
+ :where([data-nk="settings-section"] > [data-slot="settings-section-header"]) {
13
+ display: grid;
14
+ gap: calc(var(--nk-space) * 2);
15
+ }
16
+
17
+ :where([data-nk="settings-section"] [data-slot="settings-section-title"]) {
18
+ font-size: var(--nk-text-xl);
19
+ font-weight: var(--nk-font-weight-bold);
20
+ line-height: var(--nk-leading-tight);
21
+ text-wrap: balance;
22
+ }
23
+
24
+ :where(
25
+ [data-nk="settings-section"] [data-slot="settings-section-description"]
26
+ ) {
27
+ max-inline-size: var(--nk-content-lg);
28
+ color: var(--nk-color-muted-foreground);
29
+ font-size: var(--nk-text-sm);
30
+ line-height: var(--nk-leading-relaxed);
31
+ text-wrap: pretty;
32
+ }
33
+
34
+ :where([data-nk="settings-section"] > [data-slot="settings-section-form"]) {
35
+ display: grid;
36
+ grid-column: 2;
37
+ gap: calc(var(--nk-space) * 4);
38
+ inline-size: 100%;
39
+ max-inline-size: var(--nk-content-lg);
40
+ }
41
+
42
+ :where([data-nk="settings-section"] > [data-slot="settings-section-status"]) {
43
+ grid-column: 2;
44
+ inline-size: 100%;
45
+ max-inline-size: var(--nk-content-lg);
46
+ }
47
+
48
+ :where(
49
+ [data-nk="settings-section"] > [data-slot="settings-section-form"] > form
50
+ ) {
51
+ display: grid;
52
+ gap: calc(var(--nk-space) * 5);
53
+ }
54
+
55
+ :where(
56
+ [data-nk="settings-section"]
57
+ > [data-slot="settings-section-form"]
58
+ > form
59
+ > [data-nk="button"]
60
+ ) {
61
+ justify-self: start;
62
+ }
63
+
64
+ :where([data-nk="settings-section"] + [data-nk="settings-section"]) {
65
+ padding-block-start: calc(var(--nk-space) * 8);
66
+ border-block-start: var(--nk-border-width) solid var(--nk-color-border);
67
+ }
68
+ }
69
+
70
+ @layer nitro-kit.compound {
71
+ @media (width < 48rem) {
72
+ :where([data-nk="settings-section"]) {
73
+ grid-template-columns: minmax(0, 1fr);
74
+ row-gap: calc(var(--nk-space) * 4);
75
+ }
76
+
77
+ :where(
78
+ [data-nk="settings-section"] > [data-slot="settings-section-status"],
79
+ [data-nk="settings-section"] > [data-slot="settings-section-form"]
80
+ ) {
81
+ grid-column: 1;
82
+ }
83
+ }
84
+ }
@@ -53,7 +53,7 @@
53
53
  :where([data-nk="sheet"] [data-slot="sheet-title"]) {
54
54
  padding-inline-end: calc(var(--nk-space) * 10);
55
55
  font-size: var(--nk-text-lg);
56
- font-weight: var(--nk-font-weight-semibold);
56
+ font-weight: var(--nk-font-weight-bold);
57
57
  line-height: var(--nk-leading-tight);
58
58
  }
59
59
 
@@ -73,14 +73,34 @@
73
73
  animation: nk-sheet-enter var(--nk-duration-slow) var(--nk-ease);
74
74
  }
75
75
 
76
- :where([data-nk="sheet"][data-side="left"] > [data-slot="sheet-panel"][open]) {
76
+ :where(
77
+ [data-nk="sheet"][data-side="left"] > [data-slot="sheet-panel"][open]
78
+ ) {
77
79
  --_nk-sheet-from: -1rem;
78
80
  }
79
81
 
80
- :where([data-nk="sheet"][data-side="right"] > [data-slot="sheet-panel"][open]) {
82
+ :where(
83
+ [data-nk="sheet"][data-side="right"] > [data-slot="sheet-panel"][open]
84
+ ) {
81
85
  --_nk-sheet-from: 1rem;
82
86
  }
83
87
 
88
+ /* Sides are logical, but translateX is physical; RTL flips the slide so the
89
+ panel still enters from its own edge. */
90
+ :where(
91
+ [data-nk="sheet"][data-side="left"]:dir(rtl)
92
+ > [data-slot="sheet-panel"][open]
93
+ ) {
94
+ --_nk-sheet-from: 1rem;
95
+ }
96
+
97
+ :where(
98
+ [data-nk="sheet"][data-side="right"]:dir(rtl)
99
+ > [data-slot="sheet-panel"][open]
100
+ ) {
101
+ --_nk-sheet-from: -1rem;
102
+ }
103
+
84
104
  @keyframes nk-sheet-enter {
85
105
  from {
86
106
  opacity: 0;
@@ -1,22 +1,23 @@
1
1
  @layer nitro-kit.base {
2
2
  :where([data-nk="stat-grid"]) {
3
+ inline-size: 100%;
3
4
  color: var(--nk-color-foreground);
4
5
  }
5
6
 
6
7
  :where(
7
- [data-nk="stat-grid"]
8
- > [data-slot="stat-grid-grid"]
9
- > [data-slot="stat-grid-list"]
10
- ) {
8
+ [data-nk="stat-grid"]
9
+ > [data-slot="stat-grid-grid"]
10
+ > [data-slot="stat-grid-list"]
11
+ ) {
11
12
  display: contents;
12
13
  }
13
14
 
14
15
  :where(
15
- [data-nk="stat-grid"]
16
- > [data-slot="stat-grid-grid"]
17
- > [data-slot="stat-grid-list"]
18
- > [data-slot="stat-grid-stat"]
19
- ) {
16
+ [data-nk="stat-grid"]
17
+ > [data-slot="stat-grid-grid"]
18
+ > [data-slot="stat-grid-list"]
19
+ > [data-slot="stat-grid-stat"]
20
+ ) {
20
21
  display: grid;
21
22
  align-content: start;
22
23
  gap: calc(var(--nk-space) * 2);
@@ -14,9 +14,9 @@
14
14
  }
15
15
 
16
16
  :where(
17
- [data-nk="switch"] [data-slot="switch-control"],
18
- [data-nk="switch"] [data-slot="switch-track"]
19
- ) {
17
+ [data-nk="switch"] [data-slot="switch-control"],
18
+ [data-nk="switch"] [data-slot="switch-track"]
19
+ ) {
20
20
  grid-area: 1 / 1;
21
21
  }
22
22
 
@@ -46,9 +46,9 @@
46
46
  }
47
47
 
48
48
  :where(
49
- [data-nk="switch"][data-size="lg"] [data-slot="switch-control"],
50
- [data-nk="switch"][data-size="lg"] [data-slot="switch-track"]
51
- ) {
49
+ [data-nk="switch"][data-size="lg"] [data-slot="switch-control"],
50
+ [data-nk="switch"][data-size="lg"] [data-slot="switch-track"]
51
+ ) {
52
52
  inline-size: 3.25rem;
53
53
  block-size: 2rem;
54
54
  }
@@ -83,45 +83,45 @@
83
83
  }
84
84
 
85
85
  :where(
86
- [data-nk="switch"][data-size="lg"] > [data-slot="switch-description"]
87
- ) {
86
+ [data-nk="switch"][data-size="lg"] > [data-slot="switch-description"]
87
+ ) {
88
88
  padding-inline-start: calc(3.25rem + (var(--nk-space) * 3));
89
89
  }
90
90
  }
91
91
 
92
92
  @layer nitro-kit.state {
93
93
  :where(
94
- [data-nk="switch"]
95
- [data-slot="switch-control"]:checked
96
- + [data-slot="switch-track"]
97
- ) {
94
+ [data-nk="switch"]
95
+ [data-slot="switch-control"]:checked
96
+ + [data-slot="switch-track"]
97
+ ) {
98
98
  background: var(--nk-color-primary);
99
99
  border-color: var(--nk-color-primary);
100
100
  }
101
101
 
102
102
  :where(
103
- [data-nk="switch"]
104
- [data-slot="switch-control"]:checked
105
- + [data-slot="switch-track"]
106
- > [data-slot="switch-handle"]
107
- ) {
103
+ [data-nk="switch"]
104
+ [data-slot="switch-control"]:checked
105
+ + [data-slot="switch-track"]
106
+ > [data-slot="switch-handle"]
107
+ ) {
108
108
  transform: translateX(1rem);
109
109
  }
110
110
 
111
111
  :where(
112
- [data-nk="switch"][data-size="lg"]
113
- [data-slot="switch-control"]:checked
114
- + [data-slot="switch-track"]
115
- > [data-slot="switch-handle"]
116
- ) {
112
+ [data-nk="switch"][data-size="lg"]
113
+ [data-slot="switch-control"]:checked
114
+ + [data-slot="switch-track"]
115
+ > [data-slot="switch-handle"]
116
+ ) {
117
117
  transform: translateX(1.25rem);
118
118
  }
119
119
 
120
120
  :where(
121
- [data-nk="switch"]
122
- [data-slot="switch-control"]:focus-visible
123
- + [data-slot="switch-track"]
124
- ) {
121
+ [data-nk="switch"]
122
+ [data-slot="switch-control"]:focus-visible
123
+ + [data-slot="switch-track"]
124
+ ) {
125
125
  outline: var(--nk-focus-width) solid var(--nk-color-focus);
126
126
  outline-offset: var(--nk-focus-offset);
127
127
  }
@@ -131,11 +131,15 @@
131
131
  opacity: 0.6;
132
132
  }
133
133
 
134
+ /* The server error describes the submitted value. Once the user toggles the
135
+ control and it satisfies its own constraints the error is stale, so the
136
+ danger border stands down. `:user-valid` never matches before the user
137
+ touches the control, so an untouched invalid switch keeps its border. */
134
138
  :where(
135
- [data-nk="switch"]
136
- [data-slot="switch-control"][aria-invalid="true"]
137
- + [data-slot="switch-track"]
138
- ) {
139
+ [data-nk="switch"]
140
+ [data-slot="switch-control"][aria-invalid="true"]:not(:user-valid)
141
+ + [data-slot="switch-track"]
142
+ ) {
139
143
  border-color: var(--nk-color-danger);
140
144
  }
141
145
  }
@@ -143,9 +147,9 @@
143
147
  @media (prefers-reduced-motion: reduce) {
144
148
  @layer nitro-kit.base {
145
149
  :where(
146
- [data-nk="switch"] [data-slot="switch-track"],
147
- [data-nk="switch"] [data-slot="switch-handle"]
148
- ) {
150
+ [data-nk="switch"] [data-slot="switch-track"],
151
+ [data-nk="switch"] [data-slot="switch-handle"]
152
+ ) {
149
153
  transition-duration: 0.01ms;
150
154
  }
151
155
  }