nitro_kit 2.0.0.alpha.3 → 2.0.0.alpha.4

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +179 -0
  3. data/README.md +22 -26
  4. data/STYLE_GUIDE.md +10 -0
  5. data/app/assets/stylesheets/nitro_kit-tailwind-v4.css +3 -3
  6. data/app/assets/stylesheets/nitro_kit.css +1220 -572
  7. data/app/components/nitro_kit/accordion.rb +1 -19
  8. data/app/components/nitro_kit/alert.rb +1 -11
  9. data/app/components/nitro_kit/app_navigation.rb +44 -9
  10. data/app/components/nitro_kit/appearance_picker.rb +10 -1
  11. data/app/components/nitro_kit/badge.rb +13 -4
  12. data/app/components/nitro_kit/combobox.rb +1 -17
  13. data/app/components/nitro_kit/command_palette.rb +1 -0
  14. data/app/components/nitro_kit/dropzone.rb +1 -1
  15. data/app/components/nitro_kit/form_builder.rb +1 -1
  16. data/app/components/nitro_kit/select.rb +1 -14
  17. data/app/components/nitro_kit/tabs.rb +1 -0
  18. data/app/javascript/controllers/nk/command_palette_controller.js +4 -0
  19. data/app/javascript/controllers/nk/tabs_controller.js +13 -1
  20. data/docs/agent_guide.md +63 -138
  21. data/docs/agent_native_spec.md +72 -400
  22. data/docs/browser_support.md +77 -188
  23. data/docs/component_contracts.md +56 -36
  24. data/docs/customization.md +675 -89
  25. data/docs/hotwire.md +61 -99
  26. data/docs/initialization_prompt.md +27 -57
  27. data/docs/migration_1_to_2.md +34 -18
  28. data/docs/patterns/application_foundation.md +45 -121
  29. data/docs/patterns/crud_resource.md +44 -129
  30. data/docs/patterns/destructive_action.md +45 -102
  31. data/docs/patterns/flash_and_toast.md +18 -36
  32. data/docs/patterns/inline_edit.md +21 -44
  33. data/docs/patterns/queryable_collection.md +65 -161
  34. data/docs/patterns/resource_form.md +33 -81
  35. data/docs/rails_conventions.md +38 -78
  36. data/docs/rails_integration.md +96 -474
  37. data/lib/nitro_kit/installation.rb +11 -3
  38. data/lib/nitro_kit/migration_inventory.rb +15 -8
  39. data/lib/nitro_kit/version.rb +1 -1
  40. data/plugins/nitro-kit/skills/nitro-kit-rails/SKILL.md +7 -0
  41. data/plugins/nitro-kit/skills/nitro-kit-ui/SKILL.md +15 -8
  42. data/src/stylesheets/nitro_kit/components/accordion.css +4 -4
  43. data/src/stylesheets/nitro_kit/components/alert.css +20 -29
  44. data/src/stylesheets/nitro_kit/components/app_navigation.css +74 -2
  45. data/src/stylesheets/nitro_kit/components/app_shell.css +3 -3
  46. data/src/stylesheets/nitro_kit/components/appearance_picker.css +20 -8
  47. data/src/stylesheets/nitro_kit/components/auth_shell.css +2 -2
  48. data/src/stylesheets/nitro_kit/components/avatar.css +12 -8
  49. data/src/stylesheets/nitro_kit/components/avatar_stack.css +12 -10
  50. data/src/stylesheets/nitro_kit/components/badge.css +13 -9
  51. data/src/stylesheets/nitro_kit/components/button.css +42 -25
  52. data/src/stylesheets/nitro_kit/components/card.css +2 -2
  53. data/src/stylesheets/nitro_kit/components/checkbox.css +29 -46
  54. data/src/stylesheets/nitro_kit/components/checkbox_group.css +3 -3
  55. data/src/stylesheets/nitro_kit/components/combobox.css +6 -6
  56. data/src/stylesheets/nitro_kit/components/command_palette.css +62 -4
  57. data/src/stylesheets/nitro_kit/components/container.css +6 -6
  58. data/src/stylesheets/nitro_kit/components/control_group.css +9 -9
  59. data/src/stylesheets/nitro_kit/components/danger_zone.css +6 -6
  60. data/src/stylesheets/nitro_kit/components/data_section.css +4 -4
  61. data/src/stylesheets/nitro_kit/components/details_table.css +7 -5
  62. data/src/stylesheets/nitro_kit/components/dialog.css +3 -3
  63. data/src/stylesheets/nitro_kit/components/dropdown.css +7 -7
  64. data/src/stylesheets/nitro_kit/components/dropzone.css +7 -7
  65. data/src/stylesheets/nitro_kit/components/empty_state.css +4 -4
  66. data/src/stylesheets/nitro_kit/components/field.css +2 -2
  67. data/src/stylesheets/nitro_kit/components/fieldset.css +2 -2
  68. data/src/stylesheets/nitro_kit/components/flex.css +1 -1
  69. data/src/stylesheets/nitro_kit/components/grid.css +1 -1
  70. data/src/stylesheets/nitro_kit/components/icon.css +5 -5
  71. data/src/stylesheets/nitro_kit/components/input.css +33 -6
  72. data/src/stylesheets/nitro_kit/components/page_header.css +4 -4
  73. data/src/stylesheets/nitro_kit/components/pagination.css +3 -3
  74. data/src/stylesheets/nitro_kit/components/pagination_bar.css +2 -2
  75. data/src/stylesheets/nitro_kit/components/palette.css +140 -72
  76. data/src/stylesheets/nitro_kit/components/progressive_image.css +1 -1
  77. data/src/stylesheets/nitro_kit/components/radio_button.css +28 -33
  78. data/src/stylesheets/nitro_kit/components/radio_button_group.css +6 -6
  79. data/src/stylesheets/nitro_kit/components/rich_text_area.css +2 -2
  80. data/src/stylesheets/nitro_kit/components/select.css +24 -8
  81. data/src/stylesheets/nitro_kit/components/settings_layout.css +5 -5
  82. data/src/stylesheets/nitro_kit/components/settings_section.css +2 -2
  83. data/src/stylesheets/nitro_kit/components/sheet.css +10 -10
  84. data/src/stylesheets/nitro_kit/components/stat_grid.css +1 -1
  85. data/src/stylesheets/nitro_kit/components/switch.css +34 -40
  86. data/src/stylesheets/nitro_kit/components/table.css +8 -4
  87. data/src/stylesheets/nitro_kit/components/tabs.css +5 -1
  88. data/src/stylesheets/nitro_kit/components/textarea.css +20 -5
  89. data/src/stylesheets/nitro_kit/components/toast.css +11 -58
  90. data/src/stylesheets/nitro_kit/components/toolbar.css +2 -2
  91. data/src/stylesheets/nitro_kit/components/tooltip.css +4 -0
  92. data/src/stylesheets/nitro_kit/components/typeset.css +4 -4
  93. data/src/stylesheets/nitro_kit/reset.css +6 -6
  94. data/src/stylesheets/nitro_kit/tokens.css +497 -74
  95. metadata +1 -2
  96. data/docs/new_app_strategy.md +0 -22
@@ -1,11 +1,11 @@
1
1
  @layer nitro-kit.base {
2
2
  :where([data-nk="button"]) {
3
3
  --_nk-button-height: var(--nk-control-height-md);
4
- --_nk-button-padding: calc(var(--nk-space) * 4);
4
+ --_nk-button-padding: var(--nk-control-padding-inline);
5
5
  --_nk-button-icon-padding: calc(var(--nk-space) * 3);
6
6
  --_nk-button-radius: var(--nk-button-radius, var(--nk-radius-lg));
7
7
  --_nk-button-font-size: var(--nk-text-sm);
8
- --_nk-button-line-height: 1.25rem;
8
+ --_nk-button-line-height: var(--nk-leading-normal);
9
9
  --_nk-button-background: var(--nk-button-default-background);
10
10
  --_nk-button-hover-background: var(--nk-button-default-hover-background);
11
11
  --_nk-button-foreground: var(--nk-button-default-foreground);
@@ -19,7 +19,7 @@
19
19
  ),
20
20
  var(--nk-button-default-border)
21
21
  );
22
- --_nk-button-shadow: 0 1px 2px 0 oklch(0 0 0 / 0.05);
22
+ --_nk-button-shadow: var(--nk-shadow-xs);
23
23
 
24
24
  position: relative;
25
25
  display: inline-flex;
@@ -104,6 +104,21 @@
104
104
  inline-size: var(--_nk-button-height);
105
105
  padding-inline: 0;
106
106
  }
107
+
108
+ /* Touch guidance wants a 44px minimum target. The rendered button keeps
109
+ its size; an invisible extension expands the tappable area to the large
110
+ control step on coarse pointers. */
111
+ @media (pointer: coarse) {
112
+ :where([data-nk="button"])::after {
113
+ position: absolute;
114
+ inset-block-start: 50%;
115
+ inset-inline-start: 50%;
116
+ inline-size: max(100%, var(--nk-control-height-lg));
117
+ block-size: max(100%, var(--nk-control-height-lg));
118
+ content: "";
119
+ translate: -50% -50%;
120
+ }
121
+ }
107
122
  }
108
123
 
109
124
  @layer nitro-kit.variant {
@@ -111,27 +126,31 @@
111
126
  --_nk-button-background: var(--nk-color-primary);
112
127
  --_nk-button-hover-background: var(--nk-color-primary-hover);
113
128
  --_nk-button-foreground: var(--nk-color-primary-foreground);
114
- --_nk-button-border: light-dark(oklch(0 0 0 / 0.1), transparent);
129
+ --_nk-button-border: light-dark(
130
+ color-mix(in oklab, var(--nk-black) 10%, transparent),
131
+ transparent
132
+ );
115
133
  --_nk-button-border-bottom: var(--_nk-button-border);
116
- --_nk-button-shadow: inset 0 1px oklch(1 0 0 / 0.2);
134
+ --_nk-button-shadow: inset 0 1px
135
+ color-mix(in oklab, var(--nk-white) 20%, transparent);
117
136
  }
118
137
 
119
138
  :where([data-nk="button"][data-variant="destructive"]) {
120
- --_nk-button-background: var(--nk-color-danger);
121
- --_nk-button-hover-background: var(--nk-color-danger-hover);
122
- --_nk-button-foreground: var(--nk-color-danger-foreground);
139
+ --_nk-button-background: var(--nk-color-destructive);
140
+ --_nk-button-hover-background: var(--nk-color-destructive-hover);
141
+ --_nk-button-foreground: var(--nk-color-destructive-foreground);
123
142
  --_nk-button-border-width: 0;
124
143
  --_nk-button-border: transparent;
125
144
  --_nk-button-border-bottom: transparent;
126
- --_nk-button-shadow: inset 0 1px var(--nk-color-danger),
127
- inset 0 2px oklch(1 0 0 / 0.15);
145
+ --_nk-button-shadow: inset 0 1px var(--nk-color-destructive),
146
+ inset 0 2px color-mix(in oklab, var(--nk-white) 15%, transparent);
128
147
  }
129
148
 
130
149
  :where([data-nk="button"][data-variant="ghost"]) {
131
150
  --_nk-button-background: transparent;
132
151
  --_nk-button-hover-background: light-dark(
133
- oklch(0.274 0.006 286.033 / 0.05),
134
- oklch(1 0 0 / 0.15)
152
+ color-mix(in oklab, var(--nk-zinc-800) 5%, transparent),
153
+ color-mix(in oklab, var(--nk-white) 15%, transparent)
135
154
  );
136
155
  --_nk-button-foreground: var(--nk-color-foreground);
137
156
  --_nk-button-border-width: 0;
@@ -174,22 +193,21 @@
174
193
  --_nk-button-icon-padding: var(--nk-space);
175
194
  --_nk-button-radius: var(--nk-button-radius, var(--nk-radius-md));
176
195
  --_nk-button-font-size: var(--nk-text-xs);
177
- --_nk-button-line-height: 1rem;
178
- --_nk-button-avatar-size: 1rem;
196
+ --_nk-button-avatar-size: calc(var(--nk-space) * 4);
179
197
  --_nk-button-avatar-font-size: calc(var(--nk-text-xs) * 0.75);
180
198
  }
181
199
 
182
200
  :where([data-nk="button"][data-size="sm"]) {
183
- --_nk-button-height: calc(var(--nk-space) * 8);
201
+ --_nk-button-height: var(--nk-control-height-sm);
184
202
  --_nk-button-padding: calc(var(--nk-space) * 3);
185
203
  --_nk-button-icon-padding: calc(var(--nk-space) * 2);
186
204
  --_nk-button-radius: var(--nk-button-radius, var(--nk-radius-md));
187
- --_nk-button-avatar-size: 1.25rem;
205
+ --_nk-button-avatar-size: calc(var(--nk-space) * 5);
188
206
  --_nk-button-avatar-font-size: calc(var(--nk-text-xs) * 0.875);
189
207
  }
190
208
 
191
209
  :where([data-nk="button"][data-size="md"]) {
192
- --_nk-button-avatar-size: 1.5rem;
210
+ --_nk-button-avatar-size: calc(var(--nk-space) * 6);
193
211
  --_nk-button-avatar-font-size: calc(var(--nk-text-xs) * 0.875);
194
212
  }
195
213
 
@@ -197,7 +215,7 @@
197
215
  --_nk-button-height: var(--nk-control-height-lg);
198
216
  --_nk-button-padding: calc(var(--nk-space) * 5);
199
217
  --_nk-button-icon-padding: calc(var(--nk-space) * 4);
200
- --_nk-button-avatar-size: 1.75rem;
218
+ --_nk-button-avatar-size: calc(var(--nk-space) * 7);
201
219
  --_nk-button-avatar-font-size: var(--nk-text-xs);
202
220
  }
203
221
 
@@ -207,8 +225,7 @@
207
225
  --_nk-button-icon-padding: calc(var(--nk-space) * 7);
208
226
  --_nk-button-radius: var(--nk-button-radius, var(--nk-radius-xl));
209
227
  --_nk-button-font-size: var(--nk-text-base);
210
- --_nk-button-line-height: 1.5rem;
211
- --_nk-button-avatar-size: 2rem;
228
+ --_nk-button-avatar-size: calc(var(--nk-space) * 8);
212
229
  --_nk-button-avatar-font-size: var(--nk-text-xs);
213
230
  gap: calc(var(--nk-space) * 4);
214
231
  }
@@ -232,7 +249,7 @@
232
249
  ) {
233
250
  pointer-events: none;
234
251
  cursor: default;
235
- opacity: 0.75;
252
+ opacity: var(--nk-disabled-opacity);
236
253
  }
237
254
 
238
255
  /* Dark surfaces need more than reduced opacity to read a saturated
@@ -247,7 +264,7 @@
247
264
  ) {
248
265
  --_nk-button-background: color-mix(
249
266
  in oklab,
250
- var(--nk-color-danger) 40%,
267
+ var(--nk-color-destructive) 40%,
251
268
  var(--nk-color-surface)
252
269
  );
253
270
  }
@@ -262,7 +279,7 @@
262
279
  ) {
263
280
  --_nk-button-background: color-mix(
264
281
  in oklab,
265
- var(--nk-color-danger) 40%,
282
+ var(--nk-color-destructive) 40%,
266
283
  var(--nk-color-surface)
267
284
  );
268
285
  }
@@ -298,8 +315,8 @@
298
315
 
299
316
  @layer nitro-kit.compound {
300
317
  :where([data-nk="button"] > [data-slot="button-label"] > [data-nk="avatar"]) {
301
- width: min(var(--_nk-avatar-size), var(--_nk-button-avatar-size));
302
- height: min(var(--_nk-avatar-size), var(--_nk-button-avatar-size));
318
+ inline-size: min(var(--_nk-avatar-size), var(--_nk-button-avatar-size));
319
+ block-size: min(var(--_nk-avatar-size), var(--_nk-button-avatar-size));
303
320
  font-size: min(
304
321
  var(--_nk-avatar-font-size),
305
322
  var(--_nk-button-avatar-font-size)
@@ -15,8 +15,8 @@
15
15
  }
16
16
 
17
17
  :where([data-nk="card"] > [data-slot="card-title"]) {
18
- font-size: var(--nk-text-lg);
19
- font-weight: var(--nk-font-weight-bold);
18
+ font-size: var(--nk-title-surface-size);
19
+ font-weight: var(--nk-title-surface-weight);
20
20
  line-height: var(--nk-leading-tight);
21
21
  text-wrap: balance;
22
22
  }
@@ -1,39 +1,36 @@
1
1
  @layer nitro-kit.base {
2
+ /* Every box dimension derives from one choice size, so the two sizes are one
3
+ rule apart and the glyph keeps its proportions at either. The check stroke
4
+ is two border widths and its optical nudge is one, at every size. */
2
5
  :where([data-nk="checkbox"]) {
6
+ --_nk-choice-size: var(--nk-choice-size-md);
7
+
3
8
  display: inline-grid;
4
9
  min-inline-size: var(--nk-control-height-md);
5
10
  min-block-size: var(--nk-control-height-md);
6
11
  color: var(--nk-color-foreground);
7
12
  }
8
13
 
14
+ :where([data-nk="checkbox"][data-size="lg"]) {
15
+ --_nk-choice-size: var(--nk-choice-size-lg);
16
+ }
17
+
9
18
  :where([data-nk="checkbox"] > [data-slot="checkbox-label"]) {
10
19
  display: grid;
11
- grid-template-columns: 1.125rem minmax(0, 1fr);
20
+ grid-template-columns: var(--_nk-choice-size) minmax(0, 1fr);
12
21
  gap: calc(var(--nk-space) * 2);
13
22
  align-items: center;
14
23
  min-block-size: var(--nk-control-height-md);
15
24
  cursor: pointer;
16
25
  }
17
26
 
18
- :where([data-nk="checkbox"][data-size="lg"] > [data-slot="checkbox-label"]) {
19
- grid-template-columns: 1.5rem minmax(0, 1fr);
20
- }
21
-
22
27
  :where(
23
28
  [data-nk="checkbox"] [data-slot="checkbox-control"],
24
29
  [data-nk="checkbox"] [data-slot="checkbox-indicator"]
25
30
  ) {
26
31
  grid-area: 1 / 1;
27
- inline-size: 1.125rem;
28
- block-size: 1.125rem;
29
- }
30
-
31
- :where(
32
- [data-nk="checkbox"][data-size="lg"] [data-slot="checkbox-control"],
33
- [data-nk="checkbox"][data-size="lg"] [data-slot="checkbox-indicator"]
34
- ) {
35
- inline-size: 1.5rem;
36
- block-size: 1.5rem;
32
+ inline-size: var(--_nk-choice-size);
33
+ block-size: var(--_nk-choice-size);
37
34
  }
38
35
 
39
36
  :where([data-nk="checkbox"] [data-slot="checkbox-control"]) {
@@ -58,20 +55,13 @@
58
55
  }
59
56
 
60
57
  :where([data-nk="checkbox"] [data-slot="checkbox-indicator"])::after {
61
- inline-size: 0.5rem;
62
- block-size: 0.3rem;
58
+ inline-size: calc(var(--_nk-choice-size) * 0.44);
59
+ block-size: calc(var(--_nk-choice-size) * 0.27);
63
60
  content: "";
64
- border-block-end: 0.125rem solid currentcolor;
65
- border-inline-start: 0.125rem solid currentcolor;
61
+ border-block-end: calc(var(--nk-border-width) * 2) solid currentcolor;
62
+ border-inline-start: calc(var(--nk-border-width) * 2) solid currentcolor;
66
63
  opacity: 0;
67
- transform: translateY(-0.0625rem) rotate(-45deg);
68
- }
69
-
70
- :where(
71
- [data-nk="checkbox"][data-size="lg"] [data-slot="checkbox-indicator"]
72
- )::after {
73
- inline-size: 0.625rem;
74
- block-size: 0.375rem;
64
+ transform: translateY(calc(var(--nk-border-width) * -1)) rotate(-45deg);
75
65
  }
76
66
 
77
67
  :where([data-nk="checkbox"] [data-slot="checkbox-label-text"]) {
@@ -82,17 +72,11 @@
82
72
  :where([data-nk="checkbox"] > [data-slot="checkbox-description"]) {
83
73
  display: block;
84
74
  margin-block-start: var(--nk-space);
85
- padding-inline-start: calc(1.125rem + (var(--nk-space) * 2));
75
+ padding-inline-start: calc(var(--_nk-choice-size) + (var(--nk-space) * 2));
86
76
  color: var(--nk-color-muted-foreground);
87
77
  font-size: var(--nk-text-sm);
88
78
  text-wrap: pretty;
89
79
  }
90
-
91
- :where(
92
- [data-nk="checkbox"][data-size="lg"] > [data-slot="checkbox-description"]
93
- ) {
94
- padding-inline-start: calc(1.5rem + (var(--nk-space) * 2));
95
- }
96
80
  }
97
81
 
98
82
  @layer nitro-kit.state {
@@ -119,21 +103,14 @@
119
103
  [data-nk="checkbox"][data-state="indeterminate"]
120
104
  [data-slot="checkbox-indicator"]
121
105
  )::after {
122
- inline-size: 0.55rem;
106
+ inline-size: calc(var(--_nk-choice-size) * 0.49);
123
107
  block-size: 0;
124
- border-block-end: 0.125rem solid currentcolor;
108
+ border-block-end: calc(var(--nk-border-width) * 2) solid currentcolor;
125
109
  border-inline-start: 0;
126
110
  opacity: 1;
127
111
  transform: none;
128
112
  }
129
113
 
130
- :where(
131
- [data-nk="checkbox"][data-size="lg"][data-state="indeterminate"]
132
- [data-slot="checkbox-indicator"]
133
- )::after {
134
- inline-size: 0.7rem;
135
- }
136
-
137
114
  :where(
138
115
  [data-nk="checkbox"]
139
116
  [data-slot="checkbox-control"]:focus-visible
@@ -145,12 +122,12 @@
145
122
 
146
123
  :where([data-nk="checkbox"][data-disabled="true"]) {
147
124
  cursor: not-allowed;
148
- opacity: 0.6;
125
+ opacity: var(--nk-disabled-opacity);
149
126
  }
150
127
 
151
128
  /* A server-rendered error describes the value that was submitted. Once the
152
129
  user has interacted with the control and it satisfies its own constraints,
153
- that error is stale, so the danger border stands down and the native
130
+ that error is stale, so the destructive border stands down and the native
154
131
  checked treatment takes over again. `:user-valid` never matches before the
155
132
  user touches the control, so an untouched invalid checkbox keeps its
156
133
  border. */
@@ -159,6 +136,12 @@
159
136
  [data-slot="checkbox-control"][aria-invalid="true"]:not(:user-valid)
160
137
  + [data-slot="checkbox-indicator"]
161
138
  ) {
162
- border-color: var(--nk-color-danger);
139
+ border-color: var(--nk-color-destructive);
140
+ }
141
+
142
+ @media (prefers-reduced-motion: reduce) {
143
+ :where([data-nk="checkbox"] [data-slot="checkbox-indicator"]) {
144
+ transition-duration: 0.01ms;
145
+ }
163
146
  }
164
147
  }
@@ -8,8 +8,8 @@
8
8
 
9
9
  :where([data-nk="checkbox-group"] > [data-slot="checkbox-group-legend"]) {
10
10
  padding: 0;
11
- font-size: var(--nk-text-sm);
12
- font-weight: var(--nk-font-weight-semibold);
11
+ font-size: var(--nk-title-compact-size);
12
+ font-weight: var(--nk-title-compact-weight);
13
13
  }
14
14
 
15
15
  :where(
@@ -45,7 +45,7 @@
45
45
  padding: calc(var(--nk-space) * 3);
46
46
  background: var(--nk-color-surface);
47
47
  border: var(--nk-border-width) solid var(--nk-color-border);
48
- border-radius: var(--nk-radius-md);
48
+ border-radius: var(--nk-radius-lg);
49
49
  }
50
50
  }
51
51
 
@@ -29,8 +29,8 @@
29
29
 
30
30
  :where([data-nk="combobox"] > [data-slot="combobox-status"]) {
31
31
  position: absolute;
32
- width: 1px;
33
- height: 1px;
32
+ inline-size: 1px;
33
+ block-size: 1px;
34
34
  padding: 0;
35
35
  margin: -1px;
36
36
  overflow: hidden;
@@ -44,7 +44,7 @@
44
44
  position: fixed;
45
45
  z-index: 50;
46
46
  inline-size: max(var(--_nk-combobox-width, 12rem), 12rem);
47
- max-inline-size: min(28rem, calc(100vw - (var(--nk-space) * 8)));
47
+ max-inline-size: min(28rem, calc(100% - (var(--nk-space) * 8)));
48
48
  max-block-size: 15rem;
49
49
  margin-block: var(--nk-space);
50
50
  padding: var(--nk-space);
@@ -69,7 +69,7 @@
69
69
  font-size: var(--nk-text-sm);
70
70
  line-height: var(--nk-leading-normal);
71
71
  cursor: pointer;
72
- border-radius: var(--nk-radius-md);
72
+ border-radius: calc(var(--nk-radius-lg) - var(--nk-space));
73
73
  transition:
74
74
  color var(--nk-duration-normal) var(--nk-ease),
75
75
  background-color var(--nk-duration-normal) var(--nk-ease);
@@ -130,7 +130,7 @@
130
130
  [data-nk="combobox"] [data-slot="combobox-option"][aria-disabled="true"]
131
131
  ) {
132
132
  cursor: not-allowed;
133
- opacity: 0.6;
133
+ opacity: var(--nk-disabled-opacity);
134
134
  }
135
135
 
136
136
  :where(
@@ -142,7 +142,7 @@
142
142
  @keyframes nk-combobox-enter {
143
143
  from {
144
144
  opacity: 0;
145
- transform: translateY(-0.25rem);
145
+ transform: translateY(calc(var(--nk-space) * -1));
146
146
  }
147
147
  to {
148
148
  opacity: 1;
@@ -3,12 +3,17 @@
3
3
  inline-size: 100%;
4
4
  }
5
5
 
6
+ /* The trigger reads as the search input it opens: Input's plain border,
7
+ radius, and surface instead of Button's raised treatment. */
6
8
  :where([data-nk="command-palette"] > [data-slot="command-palette-trigger"]) {
7
9
  justify-content: start;
8
10
  inline-size: 100%;
9
11
  color: var(--nk-color-muted-foreground);
10
12
  font-weight: var(--nk-font-weight-normal);
11
13
  background: var(--nk-color-surface);
14
+ border-color: var(--nk-color-border);
15
+ border-block-end-color: var(--nk-color-border);
16
+ border-radius: var(--nk-radius-lg);
12
17
  box-shadow: none;
13
18
  }
14
19
 
@@ -32,6 +37,17 @@
32
37
  white-space: nowrap;
33
38
  }
34
39
 
40
+ /* The chip floats at the trigger's end with the same inset on its top,
41
+ end, and bottom sides, so the trigger's text padding stands down. */
42
+ :where(
43
+ [data-nk="command-palette"]
44
+ > [data-slot="command-palette-trigger"]:has(
45
+ [data-slot="command-palette-shortcut"]
46
+ )
47
+ ) {
48
+ padding-inline-end: calc(var(--nk-space) * 2 - var(--nk-border-width));
49
+ }
50
+
35
51
  :where([data-nk="command-palette"] [data-slot="command-palette-shortcut"]) {
36
52
  flex: 0 0 auto;
37
53
  margin-inline-start: auto;
@@ -46,6 +62,16 @@
46
62
  border-radius: var(--nk-radius-sm);
47
63
  }
48
64
 
65
+ /* The panel hugs its results and stops growing at the cap; past it, the
66
+ shrinkable list scrolls. The flex display applies only while open, so
67
+ the closed dialog keeps the user-agent's display: none. */
68
+ :where(
69
+ [data-nk="command-palette"] > [data-slot="command-palette-panel"][open]
70
+ ) {
71
+ display: flex;
72
+ flex-direction: column;
73
+ }
74
+
49
75
  :where([data-nk="command-palette"] > [data-slot="command-palette-panel"]) {
50
76
  inline-size: min(calc(100% - (var(--nk-space) * 8)), var(--nk-content-md));
51
77
  max-block-size: min(36rem, calc(100dvh - (var(--nk-space) * 8)));
@@ -59,6 +85,16 @@
59
85
  box-shadow: var(--nk-shadow-lg);
60
86
  }
61
87
 
88
+ /* The modal palette anchors near the viewport top, so hugging grows and
89
+ shrinks downward and the top edge never jumps while filtering. The
90
+ non-enhanced fallback keeps the centered default. */
91
+ :where(
92
+ [data-nk="command-palette"] > [data-slot="command-palette-panel"]:modal
93
+ ) {
94
+ margin-block: 12dvh auto;
95
+ max-block-size: min(36rem, calc(88dvh - var(--nk-space) * 4));
96
+ }
97
+
62
98
  :where(
63
99
  [data-nk="command-palette"] > [data-slot="command-palette-panel"]
64
100
  )::backdrop {
@@ -70,8 +106,8 @@
70
106
  [data-nk="command-palette"] [data-slot="command-palette-status"]
71
107
  ) {
72
108
  position: absolute;
73
- width: 1px;
74
- height: 1px;
109
+ inline-size: 1px;
110
+ block-size: 1px;
75
111
  padding: 0;
76
112
  margin: -1px;
77
113
  overflow: hidden;
@@ -83,6 +119,7 @@
83
119
 
84
120
  :where([data-nk="command-palette"] [data-slot="command-palette-search"]) {
85
121
  display: flex;
122
+ flex: 0 0 auto;
86
123
  gap: calc(var(--nk-space) * 2);
87
124
  align-items: center;
88
125
  padding: calc(var(--nk-space) * 2);
@@ -146,8 +183,10 @@
146
183
 
147
184
  :where([data-nk="command-palette"] [data-slot="command-palette-results"]) {
148
185
  display: grid;
186
+ flex: 0 1 auto;
149
187
  gap: var(--nk-space);
150
188
  max-block-size: 26rem;
189
+ min-block-size: 0;
151
190
  padding: calc(var(--nk-space) * 2);
152
191
  overflow-y: auto;
153
192
  overscroll-behavior: contain;
@@ -171,7 +210,7 @@
171
210
  font-size: var(--nk-text-sm);
172
211
  line-height: var(--nk-leading-normal);
173
212
  text-decoration: none;
174
- border-radius: var(--nk-radius-md);
213
+ border-radius: calc(var(--nk-radius-xl) - var(--nk-space) * 2);
175
214
  transition:
176
215
  color var(--nk-duration-normal) var(--nk-ease),
177
216
  background-color var(--nk-duration-normal) var(--nk-ease);
@@ -196,6 +235,25 @@
196
235
  }
197
236
  }
198
237
 
238
+ @layer nitro-kit.compound {
239
+ /* The search strip is the field: the icon sits inside it and the nested
240
+ Input drops its own chrome, so the row reads as one input bounded by
241
+ the hairline below. The caret is the focus indicator, matching every
242
+ command palette — a ring on a borderless strip would show permanently,
243
+ because text inputs are always focus-visible. */
244
+ :where([data-nk="command-palette"] [data-slot="command-palette-input"]) {
245
+ background: transparent;
246
+ border-color: transparent;
247
+ }
248
+
249
+ :where(
250
+ [data-nk="command-palette"]
251
+ [data-slot="command-palette-input"]:focus-visible
252
+ ) {
253
+ outline: none;
254
+ }
255
+ }
256
+
199
257
  @layer nitro-kit.state {
200
258
  @media (hover: hover) {
201
259
  :where(
@@ -234,7 +292,7 @@
234
292
  @keyframes nk-command-palette-enter {
235
293
  from {
236
294
  opacity: 0;
237
- transform: translateY(-0.5rem) scale(0.98);
295
+ transform: translateY(calc(var(--nk-space) * -2)) scale(0.98);
238
296
  }
239
297
  to {
240
298
  opacity: 1;
@@ -1,25 +1,25 @@
1
1
  @layer nitro-kit.base {
2
2
  :where([data-nk="container"]) {
3
- width: 100%;
4
- min-width: 0;
3
+ inline-size: 100%;
4
+ min-inline-size: 0;
5
5
  margin-inline: auto;
6
6
  }
7
7
  }
8
8
 
9
9
  @layer nitro-kit.size {
10
10
  :where([data-nk="container"][data-size="sm"]) {
11
- max-width: var(--nk-content-sm);
11
+ max-inline-size: var(--nk-content-sm);
12
12
  }
13
13
 
14
14
  :where([data-nk="container"][data-size="md"]) {
15
- max-width: var(--nk-content-md);
15
+ max-inline-size: var(--nk-content-md);
16
16
  }
17
17
 
18
18
  :where([data-nk="container"][data-size="lg"]) {
19
- max-width: var(--nk-content-lg);
19
+ max-inline-size: var(--nk-content-lg);
20
20
  }
21
21
 
22
22
  :where([data-nk="container"][data-size="xl"]) {
23
- max-width: var(--nk-content-xl);
23
+ max-inline-size: var(--nk-content-xl);
24
24
  }
25
25
  }
@@ -52,7 +52,7 @@
52
52
  }
53
53
 
54
54
  :where([data-nk="control-group"] > [data-nk="select"] > select) {
55
- height: 100%;
55
+ block-size: 100%;
56
56
  border-radius: 0;
57
57
  }
58
58
 
@@ -73,8 +73,8 @@
73
73
  span[data-slot="control-group-addon"]
74
74
  ):first-child
75
75
  ) {
76
- border-start-start-radius: var(--nk-radius-md);
77
- border-end-start-radius: var(--nk-radius-md);
76
+ border-start-start-radius: var(--nk-radius-lg);
77
+ border-end-start-radius: var(--nk-radius-lg);
78
78
  }
79
79
 
80
80
  :where(
@@ -85,8 +85,8 @@
85
85
  span[data-slot="control-group-addon"]
86
86
  ):last-child
87
87
  ) {
88
- border-start-end-radius: var(--nk-radius-md);
89
- border-end-end-radius: var(--nk-radius-md);
88
+ border-start-end-radius: var(--nk-radius-lg);
89
+ border-end-end-radius: var(--nk-radius-lg);
90
90
  }
91
91
 
92
92
  :where(
@@ -132,12 +132,12 @@
132
132
  }
133
133
 
134
134
  :where([data-nk="control-group"] > [data-nk="select"]:first-child > select) {
135
- border-start-start-radius: var(--nk-radius-md);
136
- border-end-start-radius: var(--nk-radius-md);
135
+ border-start-start-radius: var(--nk-radius-lg);
136
+ border-end-start-radius: var(--nk-radius-lg);
137
137
  }
138
138
 
139
139
  :where([data-nk="control-group"] > [data-nk="select"]:last-child > select) {
140
- border-start-end-radius: var(--nk-radius-md);
141
- border-end-end-radius: var(--nk-radius-md);
140
+ border-start-end-radius: var(--nk-radius-lg);
141
+ border-end-end-radius: var(--nk-radius-lg);
142
142
  }
143
143
  }
@@ -5,14 +5,14 @@
5
5
  align-items: end;
6
6
  gap: calc(var(--nk-space) * 5);
7
7
  padding: calc(var(--nk-space) * 6);
8
- color: var(--nk-color-danger-content);
8
+ color: var(--nk-color-destructive-content);
9
9
  background: color-mix(
10
10
  in oklab,
11
- var(--nk-color-danger) 8%,
11
+ var(--nk-color-destructive) 8%,
12
12
  var(--nk-color-surface)
13
13
  );
14
14
  border: var(--nk-border-width) solid
15
- color-mix(in oklab, var(--nk-color-danger) 50%, transparent);
15
+ color-mix(in oklab, var(--nk-color-destructive) 50%, transparent);
16
16
  border-radius: var(--nk-radius-lg);
17
17
  }
18
18
 
@@ -23,14 +23,14 @@
23
23
  }
24
24
 
25
25
  :where([data-nk="danger-zone"] [data-slot="danger-zone-title"]) {
26
- font-size: var(--nk-text-xl);
27
- font-weight: var(--nk-font-weight-bold);
26
+ font-size: var(--nk-title-section-size);
27
+ font-weight: var(--nk-title-section-weight);
28
28
  line-height: var(--nk-leading-tight);
29
29
  text-wrap: balance;
30
30
  }
31
31
 
32
32
  :where([data-nk="danger-zone"] [data-slot="danger-zone-description"]) {
33
- max-width: var(--nk-content-lg);
33
+ max-inline-size: var(--nk-content-lg);
34
34
  font-size: var(--nk-text-sm);
35
35
  line-height: var(--nk-leading-relaxed);
36
36
  text-wrap: pretty;
@@ -19,14 +19,14 @@
19
19
  }
20
20
 
21
21
  :where([data-nk="data-section"] [data-slot="data-section-title"]) {
22
- font-size: var(--nk-text-xl);
23
- font-weight: var(--nk-font-weight-bold);
22
+ font-size: var(--nk-title-section-size);
23
+ font-weight: var(--nk-title-section-weight);
24
24
  line-height: var(--nk-leading-tight);
25
25
  text-wrap: balance;
26
26
  }
27
27
 
28
28
  :where([data-nk="data-section"] [data-slot="data-section-description"]) {
29
- max-width: var(--nk-content-lg);
29
+ max-inline-size: var(--nk-content-lg);
30
30
  color: var(--nk-color-muted-foreground);
31
31
  font-size: var(--nk-text-sm);
32
32
  line-height: var(--nk-leading-relaxed);
@@ -35,6 +35,6 @@
35
35
 
36
36
  :where([data-nk="data-section"] > [data-slot="data-section-table"]),
37
37
  :where([data-nk="data-section"] > [data-slot="data-section-empty-state"]) {
38
- width: 100%;
38
+ inline-size: 100%;
39
39
  }
40
40
  }