nitro_kit 2.0.0.alpha.4 → 2.0.0.alpha.6

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/README.md +17 -2
  4. data/STYLE_GUIDE.md +2 -2
  5. data/app/assets/stylesheets/nitro_kit.css +298 -115
  6. data/app/components/nitro_kit/app_shell.rb +1 -1
  7. data/app/components/nitro_kit/dialog.rb +5 -3
  8. data/app/components/nitro_kit/dropzone.rb +18 -2
  9. data/app/components/nitro_kit/form_builder.rb +2 -0
  10. data/app/javascript/controllers/nk/dropzone_controller.js +20 -0
  11. data/docs/agent_guide.md +27 -0
  12. data/docs/component_contracts.md +53 -47
  13. data/docs/customization.md +3 -4
  14. data/docs/hotwire.md +2 -2
  15. data/docs/initialization_prompt.md +12 -6
  16. data/docs/migration_1_to_2.md +1 -1
  17. data/docs/patterns/application_foundation.md +20 -2
  18. data/docs/patterns/crud_resource.md +19 -4
  19. data/docs/patterns/destructive_action.md +31 -17
  20. data/docs/patterns/inset_workspace.md +178 -0
  21. data/docs/patterns/queryable_collection.md +104 -44
  22. data/docs/patterns/resource_form.md +16 -12
  23. data/docs/rails_integration.md +1 -1
  24. data/lib/nitro_kit/installation.rb +8 -0
  25. data/lib/nitro_kit/version.rb +1 -1
  26. data/plugins/nitro-kit/.codex-plugin/plugin.json +4 -4
  27. data/plugins/nitro-kit/skills/nitro-kit-hotwire/SKILL.md +18 -1
  28. data/plugins/nitro-kit/skills/nitro-kit-hotwire/agents/openai.yaml +1 -1
  29. data/plugins/nitro-kit/skills/nitro-kit-rails/SKILL.md +16 -1
  30. data/plugins/nitro-kit/skills/nitro-kit-rails/agents/openai.yaml +1 -1
  31. data/plugins/nitro-kit/skills/nitro-kit-ui/SKILL.md +28 -5
  32. data/plugins/nitro-kit/skills/nitro-kit-ui/agents/openai.yaml +1 -1
  33. data/src/stylesheets/nitro_kit/components/app_shell.css +1 -19
  34. data/src/stylesheets/nitro_kit/components/dialog.css +18 -1
  35. data/src/stylesheets/nitro_kit/components/dropzone.css +276 -72
  36. data/src/stylesheets/nitro_kit/components/pagination.css +1 -12
  37. data/src/stylesheets/nitro_kit/components/table.css +2 -1
  38. data/src/stylesheets/nitro_kit/components/toolbar.css +0 -10
  39. metadata +2 -1
@@ -1436,25 +1436,7 @@
1436
1436
 
1437
1437
  @layer nitro-kit.variant {
1438
1438
  :where(
1439
- [data-nk="app-shell"][data-layout="sidebar"]
1440
- > [data-slot="app-shell-header"]
1441
- > [data-slot="app-shell-topbar"]
1442
- ) {
1443
- display: none;
1444
- }
1445
-
1446
- :where(
1447
- [data-nk="app-shell"][data-layout="sidebar"]
1448
- > [data-slot="app-shell-main"]
1449
- ) {
1450
- grid-row: 1 / 3;
1451
- }
1452
-
1453
- :where(
1454
- [data-nk="app-shell"]:is(
1455
- [data-layout="sidebar"],
1456
- [data-layout="hybrid"]
1457
- ):not(
1439
+ [data-nk="app-shell"][data-layout="sidebar"]:not(
1458
1440
  :has(> [data-slot="app-shell-header"] > [data-slot="app-shell-brand"])
1459
1441
  )
1460
1442
  > [data-slot="app-shell-sidebar"]
@@ -3786,6 +3768,7 @@
3786
3768
  margin: auto;
3787
3769
  padding: calc(var(--nk-space) * 6);
3788
3770
  overflow: auto;
3771
+ text-align: start;
3789
3772
  color: var(--nk-color-foreground);
3790
3773
  background: var(--nk-color-surface);
3791
3774
  border: var(--nk-border-width) solid var(--nk-color-border);
@@ -3803,6 +3786,23 @@
3803
3786
  position: static;
3804
3787
  }
3805
3788
 
3789
+ :where(
3790
+ [data-nk="dialog"]
3791
+ > [data-slot="dialog-panel"]
3792
+ > [data-slot="dialog-header"]
3793
+ ) {
3794
+ display: flow-root;
3795
+ margin-block-end: calc(var(--nk-space) * 4);
3796
+ }
3797
+
3798
+ :where(
3799
+ [data-nk="dialog"]
3800
+ > [data-slot="dialog-panel"]
3801
+ > [data-slot="dialog-body"]
3802
+ ) {
3803
+ clear: both;
3804
+ }
3805
+
3806
3806
  :where([data-nk="dialog"] [data-slot="dialog-title"]) {
3807
3807
  font-size: var(--nk-title-surface-size);
3808
3808
  font-weight: var(--nk-title-surface-weight);
@@ -3812,7 +3812,6 @@
3812
3812
 
3813
3813
  :where([data-nk="dialog"] [data-slot="dialog-description"]) {
3814
3814
  margin-block-start: calc(var(--nk-space) * 2);
3815
- margin-block-end: calc(var(--nk-space) * 4);
3816
3815
  color: var(--nk-color-muted-foreground);
3817
3816
  font-size: var(--nk-text-sm);
3818
3817
  line-height: var(--nk-leading-relaxed);
@@ -4024,22 +4023,44 @@
4024
4023
  position: relative;
4025
4024
  display: grid;
4026
4025
  gap: calc(var(--nk-space) * 3);
4027
- min-inline-size: 16rem;
4028
- padding: calc(var(--nk-space) * 4);
4026
+ min-inline-size: 0;
4027
+ inline-size: 100%;
4029
4028
  color: var(--nk-color-foreground);
4030
- background: var(--nk-color-surface);
4031
- border: calc(var(--nk-border-width) * 2) dashed var(--nk-color-border);
4032
- border-radius: var(--nk-radius-lg);
4033
4029
  container: nk-dropzone / inline-size;
4034
4030
  }
4035
4031
 
4036
4032
  :where([data-nk="dropzone"] > [data-slot="dropzone-message"]) {
4037
4033
  display: grid;
4034
+ justify-items: center;
4035
+ align-content: center;
4038
4036
  gap: var(--nk-space);
4037
+ padding: calc(var(--nk-space) * 8) calc(var(--nk-space) * 4);
4038
+ background: var(--nk-color-muted);
4039
+ border: var(--nk-border-width) dashed var(--nk-color-border);
4040
+ border-color: color-mix(
4041
+ in srgb,
4042
+ var(--nk-color-foreground) 20%,
4043
+ transparent
4044
+ );
4045
+ border-radius: var(--nk-radius-lg);
4039
4046
  cursor: pointer;
4040
4047
  text-align: center;
4041
4048
  }
4042
4049
 
4050
+ :where([data-nk="dropzone"] [data-slot="dropzone-icon"]) {
4051
+ display: flex;
4052
+ margin-block-end: calc(var(--nk-space) * 2);
4053
+ color: var(--nk-color-muted-foreground);
4054
+ }
4055
+
4056
+ :where(
4057
+ [data-nk="dropzone"] [data-slot="dropzone-title"],
4058
+ [data-nk="dropzone"] [data-slot="dropzone-file-name"]
4059
+ ) {
4060
+ font-size: var(--nk-text-sm);
4061
+ font-weight: var(--nk-font-weight-medium);
4062
+ }
4063
+
4043
4064
  :where(
4044
4065
  [data-nk="dropzone"] [data-slot="dropzone-instruction"],
4045
4066
  [data-nk="dropzone"] [data-slot="dropzone-compact-instruction"],
@@ -4052,10 +4073,51 @@
4052
4073
  font-size: var(--nk-text-sm);
4053
4074
  }
4054
4075
 
4076
+ :where(
4077
+ [data-nk="dropzone"]
4078
+ [data-slot="dropzone-message"]
4079
+ > span:not([data-slot="dropzone-icon"])
4080
+ ) {
4081
+ color: var(--nk-color-muted-foreground);
4082
+ color: color-mix(
4083
+ in srgb,
4084
+ var(--nk-color-muted-foreground) 85%,
4085
+ var(--nk-color-foreground)
4086
+ );
4087
+ }
4088
+
4055
4089
  :where([data-nk="dropzone"] [data-slot="dropzone-compact-instruction"]) {
4056
4090
  display: none;
4057
4091
  }
4058
4092
 
4093
+ :where(
4094
+ [data-nk="dropzone"][data-layout="inline"]
4095
+ > [data-slot="dropzone-message"]
4096
+ ) {
4097
+ grid-template-columns: auto minmax(0, 1fr);
4098
+ justify-items: start;
4099
+ column-gap: calc(var(--nk-space) * 4);
4100
+ padding: calc(var(--nk-space) * 4);
4101
+ text-align: start;
4102
+ }
4103
+
4104
+ :where(
4105
+ [data-nk="dropzone"][data-layout="inline"] [data-slot="dropzone-icon"]
4106
+ ) {
4107
+ grid-column: 1;
4108
+ grid-row: 1 / span 3;
4109
+ align-self: center;
4110
+ margin: 0;
4111
+ }
4112
+
4113
+ :where(
4114
+ [data-nk="dropzone"][data-layout="inline"]
4115
+ [data-slot="dropzone-message"]
4116
+ > :not([data-slot="dropzone-icon"])
4117
+ ) {
4118
+ grid-column: 2;
4119
+ }
4120
+
4059
4121
  :where([data-nk="dropzone"] > [data-slot="dropzone-input"]) {
4060
4122
  inline-size: 100%;
4061
4123
  min-block-size: var(--nk-control-height-md);
@@ -4073,19 +4135,17 @@
4073
4135
  );
4074
4136
  margin-inline-end: calc(var(--nk-space) * 3);
4075
4137
  padding-inline: calc(var(--nk-space) * 3);
4076
- color: var(--nk-color-foreground);
4138
+ color: var(--nk-button-default-foreground);
4077
4139
  font-weight: var(--nk-font-weight-medium);
4078
- background: var(--nk-color-muted);
4140
+ background: var(--nk-button-default-background);
4079
4141
  border: 0;
4080
- border-inline-end: var(--nk-border-width) solid var(--nk-color-border);
4142
+ border-inline-end: var(--nk-border-width) solid
4143
+ var(--nk-button-default-border);
4081
4144
  }
4082
4145
 
4083
- /* The minimal presentation keeps the native input operable and in the
4084
- accessibility tree while the drop target is the only visible affordance.
4085
- The label already points at the input, so clicking anywhere in the message
4086
- still opens the file picker. */
4146
+ /* Keep the native input focusable; its label carries the visible focus ring. */
4087
4147
  :where(
4088
- [data-nk="dropzone"][data-presentation="minimal"]
4148
+ [data-nk="dropzone"]:not([data-presentation="input"])
4089
4149
  > [data-slot="dropzone-input"]
4090
4150
  ) {
4091
4151
  position: absolute;
@@ -4096,6 +4156,16 @@
4096
4156
  clip-path: inset(50%);
4097
4157
  }
4098
4158
 
4159
+ /* Selection is visible in the file rows. Keep the summary for screen readers. */
4160
+ :where([data-nk="dropzone"] > [data-slot="dropzone-status"]) {
4161
+ position: absolute;
4162
+ inline-size: 1px;
4163
+ block-size: 1px;
4164
+ overflow: hidden;
4165
+ white-space: nowrap;
4166
+ clip-path: inset(50%);
4167
+ }
4168
+
4099
4169
  :where([data-nk="dropzone"] > [data-slot="dropzone-preview-list"]) {
4100
4170
  display: grid;
4101
4171
  gap: calc(var(--nk-space) * 2);
@@ -4106,24 +4176,51 @@
4106
4176
  :where([data-nk="dropzone"] [data-slot="dropzone-preview"]) {
4107
4177
  display: grid;
4108
4178
  grid-template-columns: auto minmax(0, 1fr) auto;
4109
- gap: calc(var(--nk-space) * 2);
4179
+ column-gap: calc(var(--nk-space) * 3);
4180
+ row-gap: var(--nk-space);
4110
4181
  align-items: center;
4111
- padding: calc(var(--nk-space) * 2);
4112
- background: var(--nk-color-canvas);
4182
+ padding: calc(var(--nk-space) * 3);
4183
+ background: var(--nk-color-surface);
4113
4184
  border: var(--nk-border-width) solid var(--nk-color-border);
4114
4185
  border-radius: var(--nk-radius-lg);
4115
4186
  }
4116
4187
 
4188
+ :where(
4189
+ [data-nk="dropzone"] [data-slot="dropzone-preview-image"],
4190
+ [data-nk="dropzone"] [data-slot="dropzone-file-icon"]
4191
+ ) {
4192
+ grid-column: 1;
4193
+ grid-row: 1 / span 3;
4194
+ inline-size: calc(var(--nk-space) * 10);
4195
+ block-size: calc(var(--nk-space) * 10);
4196
+ border-radius: var(--nk-radius-sm);
4197
+ }
4198
+
4117
4199
  :where([data-nk="dropzone"] [data-slot="dropzone-preview-image"]) {
4118
- grid-row: span 2;
4119
- inline-size: calc(var(--nk-space) * 12);
4120
- block-size: calc(var(--nk-space) * 12);
4121
4200
  object-fit: cover;
4122
- border-radius: var(--nk-radius-sm);
4201
+ }
4202
+
4203
+ :where([data-nk="dropzone"] [data-slot="dropzone-file-icon"]) {
4204
+ display: grid;
4205
+ place-items: center;
4206
+ color: var(--nk-color-muted-foreground);
4207
+ background: var(--nk-color-muted);
4208
+ }
4209
+
4210
+ :where(
4211
+ [data-nk="dropzone"]
4212
+ [data-slot="dropzone-preview"]:has(
4213
+ [data-slot="dropzone-preview-image"]:not([hidden])
4214
+ )
4215
+ > [data-slot="dropzone-file-icon"]
4216
+ ) {
4217
+ display: none;
4123
4218
  }
4124
4219
 
4125
4220
  :where([data-nk="dropzone"] [data-slot="dropzone-file"]) {
4126
4221
  display: grid;
4222
+ grid-column: 2;
4223
+ grid-row: 1;
4127
4224
  min-inline-size: 0;
4128
4225
  }
4129
4226
 
@@ -4134,53 +4231,69 @@
4134
4231
  }
4135
4232
 
4136
4233
  :where([data-nk="dropzone"] [data-slot="dropzone-progress"]) {
4234
+ grid-column: 2;
4235
+ grid-row: 3;
4137
4236
  inline-size: 100%;
4138
- block-size: calc(var(--nk-space) * 2);
4237
+ block-size: var(--nk-space);
4139
4238
  accent-color: var(--nk-color-primary);
4140
4239
  }
4141
4240
 
4241
+ :where([data-nk="dropzone"] [data-slot="dropzone-file-status"]) {
4242
+ grid-column: 2;
4243
+ grid-row: 2;
4244
+ overflow-wrap: anywhere;
4245
+ }
4246
+
4142
4247
  :where([data-nk="dropzone"] [data-slot="dropzone-remove-control"]) {
4143
4248
  grid-column: -2 / -1;
4249
+ grid-row: 1 / span 3;
4144
4250
  justify-self: end;
4145
4251
  min-block-size: var(--nk-control-height-md);
4146
- padding-inline: calc(var(--nk-space) * 2);
4147
- color: var(--nk-color-foreground);
4148
- background: var(--nk-color-surface);
4149
- border: var(--nk-border-width) solid var(--nk-color-border);
4150
- border-radius: var(--nk-radius-sm);
4252
+ padding-inline: calc(var(--nk-space) * 3);
4253
+ font-size: var(--nk-text-sm);
4254
+ font-weight: var(--nk-font-weight-medium);
4255
+ color: var(--nk-button-default-foreground);
4256
+ background: var(--nk-button-default-background);
4257
+ border: var(--nk-border-width) solid var(--nk-button-default-border);
4258
+ border-radius: var(--nk-radius-md);
4259
+ cursor: pointer;
4151
4260
  }
4152
4261
  }
4153
4262
 
4154
4263
  @layer nitro-kit.state {
4155
- :where([data-nk="dropzone"][data-state="drag"]) {
4156
- background: var(--nk-color-muted);
4264
+ :where(
4265
+ [data-nk="dropzone"][data-state="drag"] > [data-slot="dropzone-message"]
4266
+ ) {
4267
+ background: var(--nk-color-surface-hover);
4157
4268
  border-color: var(--nk-color-primary);
4269
+ border-style: solid;
4158
4270
  }
4159
4271
 
4160
4272
  :where(
4161
- [data-nk="dropzone"][data-presentation="minimal"][data-state="idle"]
4162
- > [data-slot="dropzone-status"]
4273
+ [data-nk="dropzone"][data-state="uploading"]
4274
+ > [data-slot="dropzone-message"]
4163
4275
  ) {
4164
- text-align: center;
4165
- }
4166
-
4167
- :where([data-nk="dropzone"][data-state="uploading"]) {
4168
4276
  border-color: var(--nk-color-info);
4169
4277
  }
4170
4278
 
4171
- :where([data-nk="dropzone"][data-state="success"]) {
4172
- border-color: var(--nk-color-success);
4173
- }
4174
-
4175
- :where([data-nk="dropzone"][data-state="error"]) {
4279
+ :where(
4280
+ [data-nk="dropzone"][data-state="error"] > [data-slot="dropzone-message"],
4281
+ [data-nk="dropzone"] [data-slot="dropzone-preview"][data-state="error"]
4282
+ ) {
4176
4283
  border-color: var(--nk-color-destructive);
4177
4284
  }
4178
4285
 
4179
4286
  :where([data-nk="dropzone"][data-state="disabled"]) {
4180
- cursor: not-allowed;
4181
4287
  opacity: var(--nk-disabled-opacity);
4182
4288
  }
4183
4289
 
4290
+ :where(
4291
+ [data-nk="dropzone"][data-state="disabled"]
4292
+ > [data-slot="dropzone-message"]
4293
+ ) {
4294
+ cursor: not-allowed;
4295
+ }
4296
+
4184
4297
  :where(
4185
4298
  [data-nk="dropzone"] > [data-slot="dropzone-input"]:focus-visible,
4186
4299
  [data-nk="dropzone"] [data-slot="dropzone-remove-control"]:focus-visible
@@ -4189,24 +4302,35 @@
4189
4302
  outline-offset: var(--nk-focus-offset);
4190
4303
  }
4191
4304
 
4192
- /* The clipped input cannot carry a visible ring, so the drop target it
4193
- labels wears the focus treatment on its behalf. */
4194
4305
  :where(
4195
- [data-nk="dropzone"][data-presentation="minimal"]:has(
4306
+ [data-nk="dropzone"]:not([data-presentation="input"]):has(
4196
4307
  > [data-slot="dropzone-input"]:focus-visible
4197
4308
  )
4309
+ > [data-slot="dropzone-message"]
4198
4310
  ) {
4199
4311
  outline: var(--nk-focus-width) solid var(--nk-color-focus);
4200
4312
  outline-offset: var(--nk-focus-offset);
4201
4313
  }
4202
4314
 
4203
4315
  @media (hover: hover) {
4204
- :where([data-nk="dropzone"] [data-slot="dropzone-remove-control"]:hover) {
4316
+ :where(
4317
+ [data-nk="dropzone"]:not([data-state="disabled"])
4318
+ > [data-slot="dropzone-message"]:hover
4319
+ ) {
4205
4320
  background: var(--nk-color-surface-hover);
4206
4321
  }
4322
+
4323
+ :where([data-nk="dropzone"] [data-slot="dropzone-remove-control"]:hover) {
4324
+ background: var(--nk-button-default-hover-background);
4325
+ }
4207
4326
  }
4208
4327
 
4209
- :where([data-nk="dropzone"] > [data-slot="dropzone-error"]) {
4328
+ :where(
4329
+ [data-nk="dropzone"] > [data-slot="dropzone-error"],
4330
+ [data-nk="dropzone"]
4331
+ [data-slot="dropzone-preview"][data-state="error"]
4332
+ > [data-slot="dropzone-file-status"]
4333
+ ) {
4210
4334
  color: var(--nk-color-destructive-content);
4211
4335
  font-size: var(--nk-text-sm);
4212
4336
  }
@@ -4214,6 +4338,13 @@
4214
4338
 
4215
4339
  @container nk-dropzone (max-width: 24rem) {
4216
4340
  @layer nitro-kit.base {
4341
+ :where([data-nk="dropzone"] > [data-slot="dropzone-message"]) {
4342
+ padding: calc(var(--nk-space) * 5) calc(var(--nk-space) * 3);
4343
+ }
4344
+ :where([data-nk="dropzone"] [data-slot="dropzone-description"]) {
4345
+ text-wrap: pretty;
4346
+ }
4347
+
4217
4348
  :where([data-nk="dropzone"] [data-slot="dropzone-instruction"]) {
4218
4349
  display: none;
4219
4350
  }
@@ -4222,41 +4353,113 @@
4222
4353
  display: inline;
4223
4354
  }
4224
4355
 
4225
- :where([data-nk="dropzone"] > [data-slot="dropzone-input"]) {
4226
- position: absolute;
4227
- inline-size: 1px;
4228
- block-size: 1px;
4229
- overflow: hidden;
4230
- white-space: nowrap;
4231
- clip-path: inset(50%);
4356
+ :where([data-nk="dropzone"] [data-slot="dropzone-preview"]) {
4357
+ column-gap: calc(var(--nk-space) * 2);
4358
+ padding: calc(var(--nk-space) * 2);
4232
4359
  }
4360
+ }
4361
+ }
4233
4362
 
4234
- :where(
4235
- [data-nk="dropzone"][data-state="idle"] > [data-slot="dropzone-status"]
4236
- ) {
4237
- position: absolute;
4238
- inline-size: 1px;
4239
- block-size: 1px;
4240
- overflow: hidden;
4241
- white-space: nowrap;
4242
- clip-path: inset(50%);
4243
- }
4363
+ @layer nitro-kit.variant {
4364
+ :where(
4365
+ [data-nk="dropzone"][data-presentation="avatar"]
4366
+ > [data-slot="dropzone-message"]
4367
+ ) {
4368
+ position: relative;
4369
+ inline-size: calc(var(--nk-space) * 16 + var(--nk-space) * 4);
4370
+ block-size: calc(var(--nk-space) * 16 + var(--nk-space) * 4);
4371
+ padding: 0;
4372
+ border-style: solid;
4373
+ border-radius: 50%;
4374
+ }
4244
4375
 
4245
- :where([data-nk="dropzone"] [data-slot="dropzone-preview"]) {
4246
- grid-template-columns: minmax(0, 1fr) auto;
4247
- }
4376
+ :where(
4377
+ [data-nk="dropzone"][data-presentation="avatar"]
4378
+ [data-slot="dropzone-icon"]
4379
+ ) {
4380
+ margin: 0;
4381
+ }
4248
4382
 
4249
- :where([data-nk="dropzone"] [data-slot="dropzone-preview-image"]) {
4250
- display: none;
4251
- }
4383
+ :where([data-nk="dropzone"] [data-slot="dropzone-avatar-image"]) {
4384
+ position: absolute;
4385
+ inset: 0;
4386
+ inline-size: 100%;
4387
+ block-size: 100%;
4388
+ object-fit: cover;
4389
+ border-radius: inherit;
4252
4390
  }
4253
4391
 
4254
- @layer nitro-kit.state {
4392
+ :where(
4393
+ [data-nk="dropzone"]
4394
+ [data-slot="dropzone-message"]:has(
4395
+ [data-slot="dropzone-avatar-image"]:not([hidden])
4396
+ )
4397
+ > [data-slot="dropzone-icon"]
4398
+ ) {
4399
+ visibility: hidden;
4400
+ }
4401
+
4402
+ :where([data-nk="dropzone"] [data-slot="dropzone-upload-badge"]) {
4403
+ position: absolute;
4404
+ inset-inline-end: 0;
4405
+ inset-block-end: 0;
4406
+ display: grid;
4407
+ place-items: center;
4408
+ inline-size: calc(var(--nk-space) * 6);
4409
+ block-size: calc(var(--nk-space) * 6);
4410
+ color: var(--nk-color-foreground);
4411
+ background: var(--nk-color-muted);
4412
+ border: calc(var(--nk-border-width) * 2) solid var(--nk-color-canvas);
4413
+ border-radius: 50%;
4414
+ }
4415
+
4416
+ :where(
4417
+ [data-nk="dropzone"][data-presentation="compact"]
4418
+ > [data-slot="dropzone-message"]
4419
+ ) {
4420
+ display: inline-flex;
4421
+ justify-self: start;
4422
+ align-items: center;
4423
+ gap: calc(var(--nk-space) * 1.5);
4424
+ min-block-size: var(--nk-control-height-sm);
4425
+ max-inline-size: 100%;
4426
+ padding: calc(var(--nk-space) * 0.5) calc(var(--nk-space) * 2);
4427
+ background: var(--nk-button-default-background);
4428
+ color: var(--nk-button-default-foreground);
4429
+ border: var(--nk-border-width) solid var(--nk-button-default-border);
4430
+ border-radius: var(--nk-radius-md);
4431
+ text-align: start;
4432
+ }
4433
+
4434
+ /* Concise controls retain their full accessible label and constraints. */
4435
+ :where(
4436
+ [data-nk="dropzone"]:is(
4437
+ [data-presentation="avatar"],
4438
+ [data-presentation="compact"]
4439
+ )
4440
+ [data-slot="dropzone-message"]
4441
+ > span:not([data-slot="dropzone-icon"]):not(
4442
+ [data-slot="dropzone-upload-badge"]
4443
+ ),
4444
+ [data-nk="dropzone"][data-presentation="avatar"]
4445
+ [data-slot="dropzone-title"]
4446
+ ) {
4447
+ position: absolute;
4448
+ inline-size: 1px;
4449
+ block-size: 1px;
4450
+ overflow: hidden;
4451
+ white-space: nowrap;
4452
+ clip-path: inset(50%);
4453
+ }
4454
+ }
4455
+
4456
+ @media (pointer: coarse) {
4457
+ @layer nitro-kit.size {
4255
4458
  :where(
4256
- [data-nk="dropzone"]:has(> [data-slot="dropzone-input"]:focus-visible)
4459
+ [data-nk="dropzone"][data-presentation="compact"]
4460
+ > [data-slot="dropzone-message"]
4257
4461
  ) {
4258
- outline: var(--nk-focus-width) solid var(--nk-color-focus);
4259
- outline-offset: var(--nk-focus-offset);
4462
+ min-block-size: var(--nk-control-height-lg);
4260
4463
  }
4261
4464
  }
4262
4465
  }
@@ -5891,14 +6094,12 @@
5891
6094
  display: block;
5892
6095
  inline-size: fit-content;
5893
6096
  max-inline-size: 100%;
5894
- overflow-x: auto;
5895
6097
  font-size: var(--nk-text-sm);
5896
- scrollbar-width: thin;
5897
6098
  }
5898
6099
 
5899
6100
  :where([data-nk="pagination"] > [data-slot="pagination-list"]) {
5900
6101
  display: flex;
5901
- inline-size: max-content;
6102
+ flex-wrap: wrap;
5902
6103
  align-items: center;
5903
6104
  gap: var(--nk-space);
5904
6105
  list-style: none;
@@ -6006,15 +6207,6 @@
6006
6207
  }
6007
6208
  }
6008
6209
 
6009
- @layer nitro-kit.state {
6010
- @media (width < 48rem) {
6011
- :where([data-nk="pagination"] > [data-slot="pagination-list"]) {
6012
- inline-size: auto;
6013
- flex-wrap: wrap;
6014
- }
6015
- }
6016
- }
6017
-
6018
6210
  /* Source: src/stylesheets/nitro_kit/components/pagination_bar.css */
6019
6211
  @layer nitro-kit.base {
6020
6212
  :where([data-nk="pagination-bar"]) {
@@ -7290,7 +7482,7 @@
7290
7482
  @layer nitro-kit.base {
7291
7483
  :where([data-nk="table"]) {
7292
7484
  inline-size: 100%;
7293
- overflow-x: auto;
7485
+ overflow-x: scroll;
7294
7486
  color: var(--nk-color-foreground);
7295
7487
  scrollbar-width: thin;
7296
7488
  scrollbar-color: var(--nk-color-border) transparent;
@@ -7323,6 +7515,7 @@
7323
7515
  padding-inline: calc(var(--nk-space) * 2);
7324
7516
  text-align: start;
7325
7517
  vertical-align: middle;
7518
+ white-space: nowrap;
7326
7519
  }
7327
7520
 
7328
7521
  :where([data-nk="table"] [data-slot="table-header"]) {
@@ -7742,16 +7935,6 @@
7742
7935
  justify-content: flex-end;
7743
7936
  margin-inline-start: auto;
7744
7937
  }
7745
-
7746
- /* Nested scroll regions such as a clipped ButtonGroup keep a visible
7747
- scrollbar so cropped actions read as scrollable. */
7748
- :where(
7749
- [data-nk="toolbar"] > [data-slot="toolbar-leading"] > *,
7750
- [data-nk="toolbar"] > [data-slot="toolbar-trailing"] > *
7751
- ) {
7752
- scrollbar-width: thin;
7753
- scrollbar-color: var(--nk-color-border) transparent;
7754
- }
7755
7938
  }
7756
7939
 
7757
7940
  @layer nitro-kit.state {
@@ -4,7 +4,7 @@ module NitroKit
4
4
  class AppShell < Component
5
5
  alias_method :html_main, :main
6
6
 
7
- LAYOUTS = %i[sidebar topbar hybrid].freeze
7
+ LAYOUTS = %i[sidebar topbar].freeze
8
8
  REGIONS = %i[brand navigation topbar main].freeze
9
9
  REQUIRED_REGIONS = %i[navigation main].freeze
10
10
  private_constant :REQUIRED_REGIONS
@@ -214,9 +214,11 @@ module NitroKit
214
214
  )
215
215
  ) do
216
216
  render_close_button if @dismissible
217
- render_title
218
- render_description if @panel.description
219
- raw(safe(content))
217
+ header(**slot_attributes(:header)) do
218
+ render_title
219
+ render_description if @panel.description
220
+ end
221
+ div(**slot_attributes(:body)) { raw(safe(content)) }
220
222
  end
221
223
  end
222
224