nitro_kit 0.8.0 → 2.0.0.alpha.1
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.
- checksums.yaml +4 -4
- data/.agents/plugins/marketplace.json +20 -0
- data/CHANGELOG.md +151 -0
- data/LICENSE +28 -0
- data/README.md +21 -16
- data/STYLE_GUIDE.md +425 -0
- data/app/assets/stylesheets/nitro_kit-tailwind-v4.css +38 -0
- data/app/assets/stylesheets/nitro_kit.css +7225 -0
- data/app/components/nitro_kit/accordion.rb +125 -65
- data/app/components/nitro_kit/alert.rb +80 -43
- data/app/components/nitro_kit/app_navigation.rb +307 -0
- data/app/components/nitro_kit/app_shell.rb +227 -0
- data/app/components/nitro_kit/appearance_bootstrap.rb +146 -0
- data/app/components/nitro_kit/appearance_picker.rb +156 -0
- data/app/components/nitro_kit/auth_shell.rb +34 -0
- data/app/components/nitro_kit/avatar.rb +85 -29
- data/app/components/nitro_kit/avatar_stack.rb +155 -9
- data/app/components/nitro_kit/badge.rb +43 -81
- data/app/components/nitro_kit/button.rb +180 -103
- data/app/components/nitro_kit/button_group.rb +63 -11
- data/app/components/nitro_kit/button_to.rb +69 -0
- data/app/components/nitro_kit/card.rb +42 -45
- data/app/components/nitro_kit/checkbox.rb +115 -62
- data/app/components/nitro_kit/checkbox_group.rb +128 -22
- data/app/components/nitro_kit/choice.rb +55 -0
- data/app/components/nitro_kit/combobox.rb +292 -105
- data/app/components/nitro_kit/command_palette.rb +412 -0
- data/app/components/nitro_kit/component.rb +322 -46
- data/app/components/nitro_kit/container.rb +32 -0
- data/app/components/nitro_kit/control_group.rb +45 -0
- data/app/components/nitro_kit/danger_zone.rb +78 -0
- data/app/components/nitro_kit/data_section.rb +106 -0
- data/app/components/nitro_kit/details_table.rb +229 -0
- data/app/components/nitro_kit/dialog.rb +257 -83
- data/app/components/nitro_kit/dropdown.rb +336 -119
- data/app/components/nitro_kit/dropzone.rb +326 -0
- data/app/components/nitro_kit/empty_state.rb +99 -0
- data/app/components/nitro_kit/field.rb +461 -236
- data/app/components/nitro_kit/field_group.rb +15 -8
- data/app/components/nitro_kit/fieldset.rb +37 -39
- data/app/components/nitro_kit/flex.rb +49 -0
- data/app/components/nitro_kit/form_builder.rb +313 -72
- data/app/components/nitro_kit/form_section.rb +79 -0
- data/app/components/nitro_kit/grid.rb +34 -0
- data/app/components/nitro_kit/icon.rb +54 -25
- data/app/components/nitro_kit/input.rb +97 -10
- data/app/components/nitro_kit/label.rb +22 -6
- data/app/components/nitro_kit/layout_options.rb +7 -0
- data/app/components/nitro_kit/page_header.rb +76 -0
- data/app/components/nitro_kit/pagination.rb +355 -69
- data/app/components/nitro_kit/pagination_bar.rb +90 -0
- data/app/components/nitro_kit/progressive_image.rb +181 -0
- data/app/components/nitro_kit/radio_button.rb +77 -55
- data/app/components/nitro_kit/radio_button_group.rb +104 -36
- data/app/components/nitro_kit/responsive_value.rb +94 -0
- data/app/components/nitro_kit/rich_text_area.rb +31 -0
- data/app/components/nitro_kit/select.rb +129 -64
- data/app/components/nitro_kit/settings_layout.rb +152 -0
- data/app/components/nitro_kit/sheet.rb +202 -0
- data/app/components/nitro_kit/stat_grid.rb +75 -0
- data/app/components/nitro_kit/switch.rb +108 -51
- data/app/components/nitro_kit/table.rb +237 -45
- data/app/components/nitro_kit/tabs.rb +168 -63
- data/app/components/nitro_kit/textarea.rb +81 -10
- data/app/components/nitro_kit/toast.rb +211 -80
- data/app/components/nitro_kit/toolbar.rb +75 -0
- data/app/components/nitro_kit/tooltip.rb +235 -34
- data/app/components/nitro_kit/typeset.rb +28 -0
- data/app/javascript/controllers/nk/app_shell_controller.js +224 -0
- data/app/javascript/controllers/nk/appearance_controller.js +73 -0
- data/app/javascript/controllers/nk/avatar_controller.js +15 -0
- data/app/javascript/controllers/nk/button_controller.js +56 -0
- data/app/javascript/controllers/nk/checkable_controller.js +41 -0
- data/app/javascript/controllers/nk/combobox_controller.js +314 -82
- data/app/javascript/controllers/nk/command_palette_controller.js +249 -0
- data/app/javascript/controllers/nk/dialog_controller.js +14 -10
- data/app/javascript/controllers/nk/dropdown_controller.js +106 -58
- data/app/javascript/controllers/nk/dropzone/direct_upload.js +61 -0
- data/app/javascript/controllers/nk/dropzone/file_rules.js +77 -0
- data/app/javascript/controllers/nk/dropzone/form_submit_lock.js +30 -0
- data/app/javascript/controllers/nk/dropzone_controller.js +482 -0
- data/app/javascript/controllers/nk/overlay_position.js +37 -0
- data/app/javascript/controllers/nk/progressive_image_controller.js +116 -0
- data/app/javascript/controllers/nk/tabs_controller.js +135 -23
- data/app/javascript/controllers/nk/toast_controller.js +112 -45
- data/app/javascript/controllers/nk/tooltip_controller.js +12 -47
- data/config/importmap.rb +2 -0
- data/config/locales/en.yml +98 -0
- data/docs/agent_guide.md +139 -0
- data/docs/agent_native_spec.md +422 -0
- data/docs/component_contracts.md +263 -0
- data/docs/customization.md +595 -0
- data/docs/hotwire.md +94 -0
- data/docs/implementation_plan.md +279 -0
- data/docs/initialization_prompt.md +36 -0
- data/docs/migration_1_to_2.md +318 -0
- data/docs/new_app_strategy.md +24 -0
- data/docs/patterns/application_foundation.md +136 -0
- data/docs/patterns/crud_resource.md +144 -0
- data/docs/patterns/destructive_action.md +105 -0
- data/docs/patterns/flash_and_toast.md +57 -0
- data/docs/patterns/inline_edit.md +59 -0
- data/docs/patterns/queryable_collection.md +187 -0
- data/docs/patterns/resource_form.md +126 -0
- data/docs/rails_conventions.md +95 -0
- data/docs/rails_integration.md +514 -0
- data/lib/generators/nitro_kit/install_generator.rb +48 -0
- data/lib/generators/nitro_kit/upgrade_smoke_tests_generator.rb +67 -0
- data/lib/nitro_kit/engine.rb +20 -0
- data/lib/nitro_kit/installation.rb +671 -0
- data/lib/nitro_kit/migration_inventory.rb +345 -0
- data/lib/nitro_kit/upgrade_smoke_test.rb +403 -0
- data/lib/nitro_kit/version.rb +1 -1
- data/lib/nitro_kit.rb +5 -42
- data/lib/rails/commands/nitro_kit/nitro_kit_command.rb +42 -0
- data/lib/tasks/nitro_kit_tasks.rake +79 -4
- data/plugins/nitro-kit/.codex-plugin/plugin.json +28 -0
- data/plugins/nitro-kit/skills/nitro-kit-hotwire/SKILL.md +67 -0
- data/plugins/nitro-kit/skills/nitro-kit-hotwire/agents/openai.yaml +4 -0
- data/plugins/nitro-kit/skills/nitro-kit-rails/SKILL.md +60 -0
- data/plugins/nitro-kit/skills/nitro-kit-rails/agents/openai.yaml +4 -0
- data/plugins/nitro-kit/skills/nitro-kit-ui/SKILL.md +62 -0
- data/plugins/nitro-kit/skills/nitro-kit-ui/agents/openai.yaml +4 -0
- data/src/stylesheets/nitro_kit/components/accordion.css +119 -0
- data/src/stylesheets/nitro_kit/components/alert.css +82 -0
- data/src/stylesheets/nitro_kit/components/app_navigation.css +156 -0
- data/src/stylesheets/nitro_kit/components/app_shell.css +605 -0
- data/src/stylesheets/nitro_kit/components/appearance_picker.css +117 -0
- data/src/stylesheets/nitro_kit/components/auth_shell.css +8 -0
- data/src/stylesheets/nitro_kit/components/avatar.css +81 -0
- data/src/stylesheets/nitro_kit/components/avatar_stack.css +80 -0
- data/src/stylesheets/nitro_kit/components/badge.css +76 -0
- data/src/stylesheets/nitro_kit/components/button.css +283 -0
- data/src/stylesheets/nitro_kit/components/button_group.css +53 -0
- data/src/stylesheets/nitro_kit/components/button_to.css +6 -0
- data/src/stylesheets/nitro_kit/components/card.css +70 -0
- data/src/stylesheets/nitro_kit/components/checkbox.css +160 -0
- data/src/stylesheets/nitro_kit/components/checkbox_group.css +61 -0
- data/src/stylesheets/nitro_kit/components/combobox.css +148 -0
- data/src/stylesheets/nitro_kit/components/command_palette.css +255 -0
- data/src/stylesheets/nitro_kit/components/container.css +25 -0
- data/src/stylesheets/nitro_kit/components/control_group.css +149 -0
- data/src/stylesheets/nitro_kit/components/danger_zone.css +54 -0
- data/src/stylesheets/nitro_kit/components/data_section.css +40 -0
- data/src/stylesheets/nitro_kit/components/details_table.css +53 -0
- data/src/stylesheets/nitro_kit/components/dialog.css +80 -0
- data/src/stylesheets/nitro_kit/components/dropdown.css +152 -0
- data/src/stylesheets/nitro_kit/components/dropzone.css +189 -0
- data/src/stylesheets/nitro_kit/components/empty_state.css +53 -0
- data/src/stylesheets/nitro_kit/components/field.css +79 -0
- data/src/stylesheets/nitro_kit/components/field_group.css +6 -0
- data/src/stylesheets/nitro_kit/components/fieldset.css +28 -0
- data/src/stylesheets/nitro_kit/components/flex.css +455 -0
- data/src/stylesheets/nitro_kit/components/form_section.css +71 -0
- data/src/stylesheets/nitro_kit/components/grid.css +308 -0
- data/src/stylesheets/nitro_kit/components/icon.css +26 -0
- data/src/stylesheets/nitro_kit/components/input.css +80 -0
- data/src/stylesheets/nitro_kit/components/label.css +9 -0
- data/src/stylesheets/nitro_kit/components/layout.css +440 -0
- data/src/stylesheets/nitro_kit/components/page_header.css +62 -0
- data/src/stylesheets/nitro_kit/components/pagination.css +119 -0
- data/src/stylesheets/nitro_kit/components/pagination_bar.css +41 -0
- data/src/stylesheets/nitro_kit/components/palette.css +113 -0
- data/src/stylesheets/nitro_kit/components/progressive_image.css +139 -0
- data/src/stylesheets/nitro_kit/components/radio_button.css +127 -0
- data/src/stylesheets/nitro_kit/components/radio_button_group.css +143 -0
- data/src/stylesheets/nitro_kit/components/rich_text_area.css +21 -0
- data/src/stylesheets/nitro_kit/components/select.css +70 -0
- data/src/stylesheets/nitro_kit/components/settings_layout.css +100 -0
- data/src/stylesheets/nitro_kit/components/sheet.css +100 -0
- data/src/stylesheets/nitro_kit/components/stat_grid.css +51 -0
- data/src/stylesheets/nitro_kit/components/switch.css +152 -0
- data/src/stylesheets/nitro_kit/components/table.css +110 -0
- data/src/stylesheets/nitro_kit/components/tabs.css +138 -0
- data/src/stylesheets/nitro_kit/components/textarea.css +39 -0
- data/src/stylesheets/nitro_kit/components/toast.css +131 -0
- data/src/stylesheets/nitro_kit/components/toolbar.css +78 -0
- data/src/stylesheets/nitro_kit/components/tooltip.css +124 -0
- data/src/stylesheets/nitro_kit/components/typeset.css +191 -0
- data/src/stylesheets/nitro_kit/layers.css +7 -0
- data/src/stylesheets/nitro_kit/reset.css +192 -0
- data/src/stylesheets/nitro_kit/tokens.css +198 -0
- metadata +183 -50
- data/Rakefile +0 -8
- data/app/components/nitro_kit/datepicker.rb +0 -9
- data/app/helpers/nitro_kit/accordion_helper.rb +0 -9
- data/app/helpers/nitro_kit/alert_helper.rb +0 -11
- data/app/helpers/nitro_kit/avatar_helper.rb +0 -13
- data/app/helpers/nitro_kit/badge_helper.rb +0 -13
- data/app/helpers/nitro_kit/button_group_helper.rb +0 -9
- data/app/helpers/nitro_kit/button_helper.rb +0 -49
- data/app/helpers/nitro_kit/card_helper.rb +0 -9
- data/app/helpers/nitro_kit/checkbox_helper.rb +0 -50
- data/app/helpers/nitro_kit/combobox_helper.rb +0 -9
- data/app/helpers/nitro_kit/datepicker_helper.rb +0 -9
- data/app/helpers/nitro_kit/dialog_helper.rb +0 -9
- data/app/helpers/nitro_kit/dropdown_helper.rb +0 -9
- data/app/helpers/nitro_kit/field_group_helper.rb +0 -9
- data/app/helpers/nitro_kit/field_helper.rb +0 -9
- data/app/helpers/nitro_kit/fieldset_helper.rb +0 -9
- data/app/helpers/nitro_kit/form_helper.rb +0 -13
- data/app/helpers/nitro_kit/icon_helper.rb +0 -9
- data/app/helpers/nitro_kit/input_helper.rb +0 -37
- data/app/helpers/nitro_kit/label_helper.rb +0 -19
- data/app/helpers/nitro_kit/pagination_helper.rb +0 -42
- data/app/helpers/nitro_kit/radio_button_helper.rb +0 -23
- data/app/helpers/nitro_kit/select_helper.rb +0 -24
- data/app/helpers/nitro_kit/switch_helper.rb +0 -9
- data/app/helpers/nitro_kit/table_helper.rb +0 -9
- data/app/helpers/nitro_kit/tabs_helper.rb +0 -9
- data/app/helpers/nitro_kit/textarea_helper.rb +0 -9
- data/app/helpers/nitro_kit/toast_helper.rb +0 -25
- data/app/helpers/nitro_kit/tooltip_helper.rb +0 -9
- data/app/javascript/controllers/nk/accordion_controller.js +0 -18
- data/app/javascript/controllers/nk/datepicker_controller.js +0 -5
- data/app/javascript/controllers/nk/switch_controller.js +0 -32
- data/lib/generators/nitro_kit/component_generator.rb +0 -84
- data/lib/nitro_kit/schema_builder.rb +0 -121
- data/lib/nitro_kit/variants.rb +0 -21
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# Nitro Kit 2.0 implementation record
|
|
2
|
+
|
|
3
|
+
This document records the staged delivery program used for the agent-native pivot. `tk` is the source of truth for live status and dependency order; ticket IDs below connect durable design intent to executable work. Candidate lists in early stages are historical investigation prompts, not current public API. The settled contract lives in [`agent_native_spec.md`](agent_native_spec.md) and [`component_contracts.md`](component_contracts.md).
|
|
4
|
+
|
|
5
|
+
Nitro Kit 2.0 is allowed to break 1.x completely. Each stage should leave one simpler system behind rather than maintaining parallel APIs.
|
|
6
|
+
|
|
7
|
+
The original implementation program reached release-quality consolidation. Component migration, evidence-gathering flows, accepted layout/block extraction, the expanded gallery, 1.x removal, documentation, packaging, and browser verification are retained here as history; later contract revisions such as responsive Flex/Grid remain tracked in `tk` and the canonical contract documents.
|
|
8
|
+
|
|
9
|
+
## Definition of done
|
|
10
|
+
|
|
11
|
+
The 2.0 pivot is complete when:
|
|
12
|
+
|
|
13
|
+
- Every component is constructed directly from Phlex with explicit Ruby options.
|
|
14
|
+
- Nitro Kit owns the Ruby, markup contract, behavior, CSS, examples, and documentation.
|
|
15
|
+
- No Nitro-authored component, layout, block, flow, or gallery subject emits `class`, `style`, or an escape marker.
|
|
16
|
+
- Applications can theme the system through documented `--nk-*` variables and compose or subclass components.
|
|
17
|
+
- Rails forms, routes, assets, Turbo Frames, and Turbo Streams remain first-class.
|
|
18
|
+
- The gem does not expose `nk_*` view helpers, copied-component generators, a Tailwind runtime, or a template-buffer bridge.
|
|
19
|
+
- The complete catalog renders through explicit Rails routes in light/dark and narrow/wide states.
|
|
20
|
+
- Keyboard behavior and Turbo lifecycle behavior pass browser tests.
|
|
21
|
+
- The full Ruby, CSS, JavaScript formatting, package, and browser checks pass from a clean checkout.
|
|
22
|
+
|
|
23
|
+
## Delivery rules
|
|
24
|
+
|
|
25
|
+
Every migration ticket follows the same sequence:
|
|
26
|
+
|
|
27
|
+
1. Define the smallest explicit Ruby API and closed vocabularies.
|
|
28
|
+
2. Render native, self-describing HTML with `data-nk` and qualified `data-slot` identities.
|
|
29
|
+
3. Preserve Rails and accessibility semantics before visual styling.
|
|
30
|
+
4. Add static zero-specificity CSS driven by public theme tokens and private mechanics variables.
|
|
31
|
+
5. Add focused render, invalid-option, reserved-attribute, and integration tests.
|
|
32
|
+
6. Add representative and exhaustive gallery examples without classes or escape hatches.
|
|
33
|
+
7. Verify the family independently before allowing dependent flows to use it.
|
|
34
|
+
|
|
35
|
+
No compatibility layer should survive merely to keep a legacy example green. Replace the example and delete the obsolete API.
|
|
36
|
+
|
|
37
|
+
## Stage 0 — ownership and execution scaffold
|
|
38
|
+
|
|
39
|
+
Tickets: `nk-rzxf`, `nk-g3qu`
|
|
40
|
+
|
|
41
|
+
- Work on the dedicated `2.0-agent-native` branch.
|
|
42
|
+
- Keep the agent-native specification, component contracts, repository guidance, and this plan tracked with the gem.
|
|
43
|
+
- Track the entire program in the workspace-level `.tickets` database.
|
|
44
|
+
- Record implementation decisions and verification counts on each ticket before closing it.
|
|
45
|
+
|
|
46
|
+
Gate: an agent can explain who owns Ruby, markup, CSS, behavior, theming, composition, and the class escape hatch by reading the tracked docs.
|
|
47
|
+
|
|
48
|
+
## Stage 1 — kernel and distribution foundation
|
|
49
|
+
|
|
50
|
+
Tickets: `nk-6q5i`, `nk-fooc`, `nk-rx0j`
|
|
51
|
+
|
|
52
|
+
- Replace permissive attributes with explicit component options plus `html:`, `aria:`, and `data:` boundaries.
|
|
53
|
+
- Centralize identity, slot attachment, reserved attributes, validation, additive Stimulus data, and `desperately_need_a_class:`.
|
|
54
|
+
- Build deterministic layered CSS from split plain-CSS sources.
|
|
55
|
+
- Ship the built stylesheet, optional Tailwind adapter, importmap pins, and controllers from the gem without vendored third-party JavaScript.
|
|
56
|
+
- Prove the engine still boots when importmap-rails is absent.
|
|
57
|
+
|
|
58
|
+
Gate: a minimal Rails app can render and style a Nitro component without copying sources or configuring Tailwind or JavaScript pins.
|
|
59
|
+
|
|
60
|
+
## Stage 2 — representative vertical slice
|
|
61
|
+
|
|
62
|
+
Ticket: `nk-g3x1`
|
|
63
|
+
|
|
64
|
+
Migrate Button/Icon, Card, Input/Field/FormBuilder, Table, and Dialog all the way through Ruby, HTML, CSS, behavior, Rails integration, tests, and gallery routes.
|
|
65
|
+
|
|
66
|
+
Use this slice to settle:
|
|
67
|
+
|
|
68
|
+
- Direct compound-component methods and nested slot ownership.
|
|
69
|
+
- Native attribute boundaries and error messages.
|
|
70
|
+
- Intrinsic versus stretch sizing.
|
|
71
|
+
- Rails form names, IDs, values, errors, multipart behavior, and checkbox semantics.
|
|
72
|
+
- Native dialog behavior, stable ARIA relationships, and Stimulus cleanup.
|
|
73
|
+
- The explicit gallery catalog and route contract.
|
|
74
|
+
|
|
75
|
+
Gate: the slice is classless, invalid options fail immediately, focused tests pass, and its examples render through real Rails routes with Nitro CSS alone.
|
|
76
|
+
|
|
77
|
+
## Stage 3 — complete atom migration
|
|
78
|
+
|
|
79
|
+
Tickets: `nk-t17c`, `nk-b18t`, `nk-7lkw`, `nk-4r36`, `nk-i4xu`, `nk-19gd`
|
|
80
|
+
|
|
81
|
+
### Display
|
|
82
|
+
|
|
83
|
+
Migrate Alert, Avatar, AvatarStack, Badge, and Icon. Cover semantic intents, long content, image/fallback behavior, overflow, sizes, labeled/decorative icons, and nested combinations.
|
|
84
|
+
|
|
85
|
+
### Actions and navigation
|
|
86
|
+
|
|
87
|
+
Migrate ButtonGroup and Pagination. Preserve native links/buttons, current-page semantics, disabled previous/next controls, ellipses, compact ranges, and stable labels.
|
|
88
|
+
|
|
89
|
+
### Forms
|
|
90
|
+
|
|
91
|
+
Migrate Label, Textarea, Select, Checkbox, CheckboxGroup, RadioButton, RadioButtonGroup, Switch, FieldGroup, Fieldset, and all FormBuilder methods. Cover:
|
|
92
|
+
|
|
93
|
+
- Bound and unbound forms.
|
|
94
|
+
- Required, disabled, readonly, checked, indeterminate, invalid, prompt, and empty states.
|
|
95
|
+
- Array and nested parameter names.
|
|
96
|
+
- Active Model values and errors.
|
|
97
|
+
- Multipart uploads and native file-input constraints.
|
|
98
|
+
- Accessible descriptions, legends, labels, and error relationships.
|
|
99
|
+
|
|
100
|
+
### Structured content
|
|
101
|
+
|
|
102
|
+
Migrate Accordion and Tabs alongside the Card and Table slice. Require deterministic IDs and keys, direct compound APIs, semantic table structure, and keyboard-visible state.
|
|
103
|
+
|
|
104
|
+
### Interaction
|
|
105
|
+
|
|
106
|
+
Migrate Dropdown, Tooltip, Combobox, and Toast alongside Dialog. Require closed placement/state APIs, visible ARIA/data state, keyboard behavior, native controls where possible, and complete disconnect cleanup.
|
|
107
|
+
|
|
108
|
+
Gate: every shipped atom has a classless direct-Phlex API, static CSS, focused tests, exhaustive examples, and no dependency on a legacy helper.
|
|
109
|
+
|
|
110
|
+
## Stage 4 — Rails and Hotwire proof
|
|
111
|
+
|
|
112
|
+
Ticket: `nk-19gd`
|
|
113
|
+
|
|
114
|
+
- Exercise `form_with` directly from Phlex using `NitroKit::FormBuilder`.
|
|
115
|
+
- Prove route helpers, DOM ID helpers, CSRF behavior, model errors, submit paths, and multipart forms.
|
|
116
|
+
- Render Turbo Frames and Turbo Streams from direct-Phlex pages.
|
|
117
|
+
- Add one small validation submit path that demonstrates the real request/response loop.
|
|
118
|
+
- Document the supported Rails boundary and show examples without introducing Nitro view helpers.
|
|
119
|
+
|
|
120
|
+
Gate: Rails supplies framework semantics while Phlex remains the only general UI composition language.
|
|
121
|
+
|
|
122
|
+
## Stage 5 — gallery infrastructure and exhaustive combinations
|
|
123
|
+
|
|
124
|
+
Tickets: `nk-q4mj`, `nk-put2`, `nk-jp63`, `nk-5028`, `nk-t23x`, `nk-rtwj`, `nk-8mh8`, `nk-t66i`, `nk-vnwu`
|
|
125
|
+
|
|
126
|
+
- Keep one explicit catalog of component, block, and flow entries.
|
|
127
|
+
- Render the shell, pages, sections, examples, samples, and notes in Phlex.
|
|
128
|
+
- Pair every preview with highlighted, copyable Ruby extracted from the exact rendering block or concrete flow method.
|
|
129
|
+
- Generate route contract tests from the catalog.
|
|
130
|
+
- Assert every subject has stable Nitro identities and no `class`, `style`, or escape markers.
|
|
131
|
+
- Add meaningful Cartesian coverage without mechanically showing nonsense combinations.
|
|
132
|
+
|
|
133
|
+
Required pressure cases:
|
|
134
|
+
|
|
135
|
+
- All closed variants and sizes.
|
|
136
|
+
- Default, hover/focus-capable, disabled, readonly, invalid, empty, loading-like, open, and selected states where meaningful.
|
|
137
|
+
- Short, long, wrapped, numeric, missing-image, and high-item-count content.
|
|
138
|
+
- Nested atoms and compound slots.
|
|
139
|
+
- Light and dark themes.
|
|
140
|
+
- Narrow and wide viewports.
|
|
141
|
+
- Forms, tables, overlays, and navigation used together rather than only in isolation.
|
|
142
|
+
|
|
143
|
+
Gate: every catalog entry succeeds through an explicit route and the gallery itself requires no Tailwind or ERB templates.
|
|
144
|
+
|
|
145
|
+
## Stage 6 — atom-only product flows
|
|
146
|
+
|
|
147
|
+
Tickets: `nk-31ne`, `nk-7d05`, `nk-q37g`, `nk-tcig`, `nk-32vc`
|
|
148
|
+
|
|
149
|
+
Build realistic screens before inventing layout abstractions:
|
|
150
|
+
|
|
151
|
+
- Authentication, registration, password reset, and verification.
|
|
152
|
+
- Onboarding progress, validation, resume, and completion.
|
|
153
|
+
- Dashboard overview, statistics, recent records, and activity.
|
|
154
|
+
- Profile, preferences, account, and destructive settings.
|
|
155
|
+
- Billing plans, payment methods, invoices, and upgrade states.
|
|
156
|
+
- Users search, filters, pagination, empty state, and detail.
|
|
157
|
+
- Team members, invitations, roles, and removal confirmation.
|
|
158
|
+
- API credential empty, create, reveal-once, list, and revoke states.
|
|
159
|
+
|
|
160
|
+
Use deterministic PORO data and explicit state slugs. Record repeated layout and responsibility friction in `notes/block_candidates.md`; do not abstract a one-off screen.
|
|
161
|
+
|
|
162
|
+
Gate: all required product states exist using atoms and plain Phlex composition, and repeated structures are backed by concrete evidence.
|
|
163
|
+
|
|
164
|
+
## Stage 7 — evidence-driven layouts and blocks
|
|
165
|
+
|
|
166
|
+
Tickets: `nk-okls`, `nk-bjv5`, `nk-b8eg`
|
|
167
|
+
|
|
168
|
+
Extract the smallest vocabulary that removes proven repetition. The evidence pass accepted:
|
|
169
|
+
|
|
170
|
+
- Layouts: VStack, HStack, the three-column Grid, and Container.
|
|
171
|
+
- Shell: AuthShell.
|
|
172
|
+
- Sections and blocks: SettingsLayout, Toolbar, PaginationBar, PageHeader, StatGrid, DataSection, FormSection, DangerZone, and EmptyState.
|
|
173
|
+
|
|
174
|
+
This list records the first extraction decision. It has since been superseded: `VStack` and `HStack` were removed in favor of unified responsive `Flex`, and the fixed three-column Grid became a responsive 1–12-column `Grid`. See the canonical specification and component contracts for the current API.
|
|
175
|
+
|
|
176
|
+
At that stage, the evidence pass deferred Spacer, Split, Frame, AppShell, MarketingShell, AuthenticationPanel, and ProgressSteps because their responsibilities were not stable across enough domains. A later application-layout mandate supplied enough evidence to accept AppShell; the other deferred candidates remain outside 2.0. The settled contracts, rather than this historical stage record, live in [`agent_native_spec.md`](agent_native_spec.md) and [`component_contracts.md`](component_contracts.md).
|
|
177
|
+
|
|
178
|
+
Each abstraction must:
|
|
179
|
+
|
|
180
|
+
- Have one clear responsibility.
|
|
181
|
+
- Use closed layout options.
|
|
182
|
+
- Own only structure that actually repeats.
|
|
183
|
+
- Accept atoms/content through direct Ruby composition.
|
|
184
|
+
- Emit classless self-describing markup.
|
|
185
|
+
- Include examples showing reuse in at least two flows.
|
|
186
|
+
|
|
187
|
+
Then rewrite the atom-only flows with blocks and compare the result. Delete abstractions that do not make application code meaningfully clearer.
|
|
188
|
+
|
|
189
|
+
Gate: flow code describes product intent, while layouts and blocks remain a small coherent vocabulary rather than a second page framework.
|
|
190
|
+
|
|
191
|
+
## Stage 8 — expanded application gallery
|
|
192
|
+
|
|
193
|
+
Tickets: `nk-pmcn`, `nk-q1tc`, `nk-oi4y`, `nk-gn4s`, `nk-ky42`
|
|
194
|
+
|
|
195
|
+
Extend the block-based gallery across:
|
|
196
|
+
|
|
197
|
+
- Data detail, activity, audit, uploads, and integrations.
|
|
198
|
+
- Billing, authentication, onboarding, team, and API states.
|
|
199
|
+
- System error, permission, empty, loading-like, and marketing states.
|
|
200
|
+
- Changelog, support, and help experiences.
|
|
201
|
+
|
|
202
|
+
Prefer depth of state over disconnected decorative pages. Each flow should show success, empty/error, destructive/confirmation, and constrained-width behavior where applicable.
|
|
203
|
+
|
|
204
|
+
Gate: the gallery demonstrates that the vocabulary can build a credible Rails product, not only isolated controls.
|
|
205
|
+
|
|
206
|
+
## Stage 9 — remove the old system
|
|
207
|
+
|
|
208
|
+
Ticket: `nk-u534`
|
|
209
|
+
|
|
210
|
+
- Delete all `nk_*` view helpers and automatic variant aliases.
|
|
211
|
+
- Delete copied-component generators, schemas, manifests, and installation paths.
|
|
212
|
+
- Delete the Action View/template capture bridge and legacy builder path.
|
|
213
|
+
- Remove Tailwind Merge and consumer Tailwind dependencies.
|
|
214
|
+
- Remove legacy ERB test pages, Tailwind assets, and obsolete tests.
|
|
215
|
+
- Audit packaged gem files and runtime dependencies.
|
|
216
|
+
|
|
217
|
+
Gate: repository-wide searches find no public legacy invocation, copied-source promise, internal component class string, or required Tailwind runtime.
|
|
218
|
+
|
|
219
|
+
## Stage 10 — browser behavior and lifecycle verification
|
|
220
|
+
|
|
221
|
+
Tickets: `nk-352j`, `nk-6ivz`, `nk-gxwn`, `nk-lij5`, `nk-tkds`
|
|
222
|
+
|
|
223
|
+
- Enumerate every catalog URL and state in a real browser.
|
|
224
|
+
- Exercise keyboard order, arrows, Escape, Enter/Space, tab trapping/return, and focus visibility.
|
|
225
|
+
- Exercise open/close, select, filter, validation, submit, and destructive confirmation paths.
|
|
226
|
+
- Navigate through Turbo Drive, Frames, Streams, and morph refreshes; look for duplicate controllers and leaked listeners/positioners/timers.
|
|
227
|
+
- Review representative pages at narrow/wide sizes and light/dark themes.
|
|
228
|
+
- Check for horizontal overflow, clipped overlays, unstable layout, unreadable content, and broken focus state.
|
|
229
|
+
|
|
230
|
+
Gate: browser coverage proves both route completeness and interaction lifecycle behavior.
|
|
231
|
+
|
|
232
|
+
## Stage 11 — release-quality consolidation
|
|
233
|
+
|
|
234
|
+
Tickets: `nk-g3qu`, `nk-obb7`
|
|
235
|
+
|
|
236
|
+
- Reconcile actual component APIs with `docs/component_contracts.md` and `STYLE_GUIDE.md`.
|
|
237
|
+
- Document Rails integration, theming tokens, composition, subclass caveats, and the escape hatch.
|
|
238
|
+
- Run a data-structure review for duplicated collections, scattered state, and invalid intermediate states.
|
|
239
|
+
- Run a simplification pass and remove compatibility branches, duplicate validation, dead CSS, dead JavaScript, and unused dependencies.
|
|
240
|
+
- Audit all CSS selectors for zero specificity and owner scoping.
|
|
241
|
+
- Audit all controllers for disconnect cleanup and Turbo safety.
|
|
242
|
+
- Run the complete test, lint, format, CSS build/check, package, route, and browser suites.
|
|
243
|
+
|
|
244
|
+
Gate: every child of `nk-rzxf` is closed with evidence and the repository contains one coherent 2.0 architecture.
|
|
245
|
+
|
|
246
|
+
## Stage 12 — deterministic agent installation
|
|
247
|
+
|
|
248
|
+
Ticket: `2an-5ayl`
|
|
249
|
+
|
|
250
|
+
- Ship concise Nitro Kit Rails, Hotwire, and UI skills that resolve the
|
|
251
|
+
installed gem before acting.
|
|
252
|
+
- Add a setup-only generator that installs the skills for Codex and Claude and
|
|
253
|
+
maintains a bounded `AGENTS.md` section without copying component source.
|
|
254
|
+
- Add diagnostics for the resolved version, agent guidance, Hotwire wiring,
|
|
255
|
+
Phlex Kit inclusion, stylesheet loading, and Nitro Kit 1.x shadows.
|
|
256
|
+
- Print or copy an initialization prompt without launching an agent.
|
|
257
|
+
- Make guided and Pro eval profiles run the real installer and name Nitro Kit
|
|
258
|
+
2.x explicitly; retain cold profiles for diagnostic comparisons.
|
|
259
|
+
|
|
260
|
+
Gate: installation is idempotent, preserves application-owned instructions,
|
|
261
|
+
routes agents to version-matched doctrine, and is exercised by the eval
|
|
262
|
+
harness.
|
|
263
|
+
|
|
264
|
+
## Verification matrix
|
|
265
|
+
|
|
266
|
+
| Surface | Required verification |
|
|
267
|
+
| ------------- | ------------------------------------------------------------------------------------------------- |
|
|
268
|
+
| Ruby API | Focused construction/render tests; invalid vocabulary; missing content; reserved attributes |
|
|
269
|
+
| Markup | Native semantics; stable IDs; ARIA relationships; `data-nk`; qualified `data-slot`; visible state |
|
|
270
|
+
| CSS | Deterministic build/check; zero-specificity owner-scoped selectors; token audit; light/dark |
|
|
271
|
+
| Rails | Real `form_with`; Active Model; routes/DOM IDs; multipart; validation submit; Frame/Stream |
|
|
272
|
+
| JavaScript | Keyboard behavior; open/close/select; disconnect cleanup; Turbo navigation and morph |
|
|
273
|
+
| Gallery | Catalog routes; exact escaped source; copy behavior; no class/style/escape; narrow/wide |
|
|
274
|
+
| Packaging | Engine boot with optional integrations absent; gem contents and dependencies audited |
|
|
275
|
+
| Documentation | Specification, contracts, style guide, Rails boundary, theming, examples, repository commands |
|
|
276
|
+
|
|
277
|
+
## Execution and handoff
|
|
278
|
+
|
|
279
|
+
Use `tk ready` to select dependency-safe work. Preparatory parallel work is permitted only when the orchestrator explicitly assigns non-overlapping ownership. Every handoff names changed files, behavior decisions, focused test counts, and known failures. The orchestrator independently reviews and reproduces meaningful checks before closing a feature ticket.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Initialize Nitro Kit 2 in this Rails application
|
|
2
|
+
|
|
3
|
+
Finish the application-specific Nitro Kit 2 setup. Do not use Nitro Kit 1.x
|
|
4
|
+
APIs or examples.
|
|
5
|
+
|
|
6
|
+
1. Run `bundle show nitro_kit` and confirm the resolved version begins with
|
|
7
|
+
`2.`.
|
|
8
|
+
2. Read `docs/agent_guide.md` from that installed gem, then read the locally
|
|
9
|
+
installed `nitro-kit-rails`, `nitro-kit-hotwire`, and `nitro-kit-ui` skills.
|
|
10
|
+
3. Inspect the application before editing. Preserve established application
|
|
11
|
+
conventions unless they conflict with the requested Nitro Kit 2 setup.
|
|
12
|
+
4. Ensure an application base Phlex component includes `NitroKit` once and
|
|
13
|
+
product components inherit from it.
|
|
14
|
+
5. Re-run `bin/rails generate nitro_kit:install`. Ensure its application layout
|
|
15
|
+
setup has one appearance bootstrap before every stylesheet, then optional
|
|
16
|
+
third-party base styles, the optional Tailwind adapter, `nitro_kit`, compiled
|
|
17
|
+
Tailwind, and application token overrides in that order. Add flash toast
|
|
18
|
+
rendering when the application uses it.
|
|
19
|
+
6. Ensure Turbo and Stimulus are wired and the normal Stimulus loader can
|
|
20
|
+
discover the gem-owned `nk--*` controllers. Never copy Nitro components,
|
|
21
|
+
helpers, or controllers into the application.
|
|
22
|
+
7. Remove confirmed Nitro Kit 1.x shadows such as application-owned
|
|
23
|
+
`NitroKit` components, `nk_*` helpers, or `controllers/nk` only when this
|
|
24
|
+
task is authorized to migrate the application.
|
|
25
|
+
8. Use ordinary Rails routes, models, forms, and server-rendered HTML. Follow
|
|
26
|
+
the installed Rails and Hotwire guidance for new work. During a migration,
|
|
27
|
+
replace an existing control only when Nitro Kit 2 has a genuine semantic
|
|
28
|
+
and behavioral equivalent. Otherwise preserve it as application-owned
|
|
29
|
+
Rails and semantic HTML; never downgrade specialized behavior or retain
|
|
30
|
+
copied Nitro Kit 1.x source as the fallback.
|
|
31
|
+
9. Run `bin/rails nitro_kit:doctor`, fix actionable failures, and run the
|
|
32
|
+
application's relevant tests.
|
|
33
|
+
|
|
34
|
+
Report what you changed, any existing convention you deliberately preserved,
|
|
35
|
+
any unsupported control recorded as a Nitro Kit coverage gap, and any warning
|
|
36
|
+
that still needs a product decision.
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
# Migrating a Nitro Kit 1.x application
|
|
2
|
+
|
|
3
|
+
Treat a 1.x migration as a product-flow review, not a helper rename. Nitro Kit
|
|
4
|
+
2 deliberately removed copied components, `nk_*` helpers, application-owned
|
|
5
|
+
`controllers/nk`, and unrestricted utility-class customization.
|
|
6
|
+
|
|
7
|
+
## Install the 2.0 alpha before migrating
|
|
8
|
+
|
|
9
|
+
Add the 2.0 alpha prerelease to the application's Gemfile:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem "nitro_kit", "2.0.0.alpha.1"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Bundler records the exact released version in `Gemfile.lock`; commit `Gemfile`
|
|
16
|
+
and `Gemfile.lock` together. Before upgrading during the migration, review the
|
|
17
|
+
changelog, run `bundle update nitro_kit`, rerun the installer and doctor, and
|
|
18
|
+
exercise the converted flows before committing the updated lockfile.
|
|
19
|
+
Production applications should use the released gem and a committed lockfile
|
|
20
|
+
rather than a moving Git branch.
|
|
21
|
+
|
|
22
|
+
## Inventory behavior before editing
|
|
23
|
+
|
|
24
|
+
1. List every `nk_*` helper, `NitroKit::*` component, copied Nitro source file,
|
|
25
|
+
and `controllers/nk` controller.
|
|
26
|
+
2. Group usage by user flow: authentication, settings, collection browsing,
|
|
27
|
+
mobile navigation, editing, destructive actions, notifications, and
|
|
28
|
+
copy/share controls.
|
|
29
|
+
3. Record behavior that must survive: native element, submitted method and
|
|
30
|
+
parameters, Turbo target, accessible name and description, focus behavior,
|
|
31
|
+
narrow-screen presentation, empty/error state, and visual density.
|
|
32
|
+
4. Capture representative wide and narrow screenshots before conversion.
|
|
33
|
+
|
|
34
|
+
If the Nitro Kit MCP catalog is connected, search it by workflow after this
|
|
35
|
+
inventory — for example `mobile transcript navigation`, `settings form`, or
|
|
36
|
+
`empty query results`. Do not search only for an old component name. MCP can
|
|
37
|
+
deliver complete compositions; the installed gem remains the authority for
|
|
38
|
+
the free component contract.
|
|
39
|
+
|
|
40
|
+
## Select semantics before atoms
|
|
41
|
+
|
|
42
|
+
Map each flow to the highest-level matching 2.x component first:
|
|
43
|
+
|
|
44
|
+
| Existing need | Begin with |
|
|
45
|
+
| --------------------------------------- | --------------------------------------- |
|
|
46
|
+
| Sign-in or recovery card | `AuthShell` |
|
|
47
|
+
| Application navigation | `AppShell`, `AppNavigation` |
|
|
48
|
+
| Mobile contextual navigation or details | `Sheet` |
|
|
49
|
+
| Settings screen | `SettingsLayout`, `FormSection` |
|
|
50
|
+
| Empty collection card | `EmptyState` |
|
|
51
|
+
| Data collection | `DataSection`, `Table`, `PaginationBar` |
|
|
52
|
+
| Destructive settings | `DangerZone`, `Dialog`, `ButtonTo` |
|
|
53
|
+
| Joined copy or filter controls | `ControlGroup` |
|
|
54
|
+
|
|
55
|
+
Only then replace remaining atoms. Common direct mappings include:
|
|
56
|
+
|
|
57
|
+
- `nk_button_link_to` → `NitroKit::Button.new(..., href:)`
|
|
58
|
+
- `nk_button_to` → `NitroKit::ButtonTo.new(..., href:, method:)`
|
|
59
|
+
- `nk_form_with` → Rails `form_with(..., builder: NitroKit::FormBuilder)`
|
|
60
|
+
- block-wrapped tooltips → a linked Button trigger or Tooltip `as: :custom`
|
|
61
|
+
- copied mobile Sidebar → `Sheet`, not a plain disclosure
|
|
62
|
+
|
|
63
|
+
Do not preserve a Card merely because 1.x used one. Empty states,
|
|
64
|
+
authentication shells, settings regions, and data sections have stronger
|
|
65
|
+
semantics and more useful responsive behavior.
|
|
66
|
+
|
|
67
|
+
## Move ERB collections and yielded content into compound declarations
|
|
68
|
+
|
|
69
|
+
The ERB below is representative application-owned migration input, not a
|
|
70
|
+
Nitro Kit 2 API. Nitro Kit 2 has no ERB component bridge. Move the collection
|
|
71
|
+
to the Phlex component, then declare entries only inside their owning compound
|
|
72
|
+
region. Content formerly yielded by a partial belongs directly inside the
|
|
73
|
+
matching `panel` or `content` block.
|
|
74
|
+
|
|
75
|
+
### AppNavigation
|
|
76
|
+
|
|
77
|
+
ERB source — the call site owns the destination collection and the partial
|
|
78
|
+
iterates it:
|
|
79
|
+
|
|
80
|
+
```erb
|
|
81
|
+
<% destinations = [["Home", root_path], ["Projects", projects_path]] %>
|
|
82
|
+
<%= render "app_navigation", label: "Primary", destinations: destinations %>
|
|
83
|
+
|
|
84
|
+
<%# _app_navigation.html.erb %>
|
|
85
|
+
<nav aria-label="<%= label %>">
|
|
86
|
+
<ul>
|
|
87
|
+
<% destinations.each do |text, href| %>
|
|
88
|
+
<li><%= link_to text, href %></li>
|
|
89
|
+
<% end %>
|
|
90
|
+
</ul>
|
|
91
|
+
</nav>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Phlex destination — declare the collection before `AppNavigation`; consume it
|
|
95
|
+
inside the required `body` collection region:
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
destinations = [["Home", root_path], ["Projects", projects_path]]
|
|
99
|
+
|
|
100
|
+
render NitroKit::AppNavigation.new(label: "Primary") do |navigation|
|
|
101
|
+
navigation.body do
|
|
102
|
+
destinations.each_with_index do |(text, href), index|
|
|
103
|
+
navigation.item(text, href:, current: index.zero?)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The executable minimal version is on the
|
|
110
|
+
[`AppNavigation` gallery page](/gallery/components/app-navigation#example-app-navigation-minimal).
|
|
111
|
+
|
|
112
|
+
### Dialog
|
|
113
|
+
|
|
114
|
+
ERB source — the call-site block is yielded inside the partial's panel:
|
|
115
|
+
|
|
116
|
+
```erb
|
|
117
|
+
<%= render "dialog", id: "transcript-details", title: "Transcript details" do %>
|
|
118
|
+
<p>The transcript was recorded at 09:42 UTC.</p>
|
|
119
|
+
<% end %>
|
|
120
|
+
|
|
121
|
+
<%# _dialog.html.erb %>
|
|
122
|
+
<button command="show-modal" commandfor="<%= id %>-panel">Details</button>
|
|
123
|
+
<dialog id="<%= id %>-panel">
|
|
124
|
+
<h2><%= title %></h2>
|
|
125
|
+
<%= yield %>
|
|
126
|
+
</dialog>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Phlex destination — trigger and panel declarations live inside `Dialog`; the
|
|
130
|
+
former yielded content lives inside `panel`:
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
render NitroKit::Dialog.new(id: "transcript-details") do |dialog|
|
|
134
|
+
dialog.trigger("Details")
|
|
135
|
+
dialog.panel(title: "Transcript details") do
|
|
136
|
+
p { "The transcript was recorded at 09:42 UTC." }
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Placement belongs to the parent. In the conversion that exposed this rule, a
|
|
142
|
+
`Flex` containing **Redact** and **Permalink** was followed by a `Dialog`
|
|
143
|
+
sibling, so the Dialog trigger started a second line. Put the Dialog root
|
|
144
|
+
inside the same no-wrap action cluster:
|
|
145
|
+
|
|
146
|
+
```ruby
|
|
147
|
+
Flex(dir: :row, gap: 1, align: :center, wrap: :nowrap) do
|
|
148
|
+
Button("Redact", size: :sm, variant: :destructive)
|
|
149
|
+
Button("Permalink", href: transcript_path(transcript), size: :sm)
|
|
150
|
+
|
|
151
|
+
Dialog(id: dom_id(transcript, :details)) do |dialog|
|
|
152
|
+
dialog.trigger("Details", size: :sm)
|
|
153
|
+
dialog.panel(title: "Transcript details") do
|
|
154
|
+
render UI::TranscriptDetails.new(transcript)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The gallery runs this structure at narrow widths in
|
|
161
|
+
[`Narrow transcript actions`](/gallery/components/dialog#example-dialog-narrow-action-cluster).
|
|
162
|
+
|
|
163
|
+
### Sheet
|
|
164
|
+
|
|
165
|
+
ERB source — the partial yields contextual content into its side panel:
|
|
166
|
+
|
|
167
|
+
```erb
|
|
168
|
+
<%= render "sheet", id: "transcript-prompts", title: "Prompts" do %>
|
|
169
|
+
<%= render "prompts", prompts: @prompts %>
|
|
170
|
+
<% end %>
|
|
171
|
+
|
|
172
|
+
<%# _sheet.html.erb %>
|
|
173
|
+
<button command="show-modal" commandfor="<%= id %>-panel">Prompts</button>
|
|
174
|
+
<dialog id="<%= id %>-panel">
|
|
175
|
+
<h2><%= title %></h2>
|
|
176
|
+
<%= yield %>
|
|
177
|
+
</dialog>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Phlex destination — declare the collection before `Sheet`; render it only
|
|
181
|
+
inside the `panel` content slot:
|
|
182
|
+
|
|
183
|
+
```ruby
|
|
184
|
+
prompts = transcript.prompts.map { |prompt| [prompt.title, prompt_path(prompt)] }
|
|
185
|
+
|
|
186
|
+
render NitroKit::Sheet.new(id: "transcript-prompts", side: :left) do |sheet|
|
|
187
|
+
sheet.trigger("Prompts", icon: :list)
|
|
188
|
+
sheet.panel(title: "Transcript prompts") do
|
|
189
|
+
render NitroKit::AppNavigation.new(label: "Transcript prompts") do |navigation|
|
|
190
|
+
navigation.body do
|
|
191
|
+
prompts.each do |text, href|
|
|
192
|
+
navigation.item(text, href:)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
See the executable
|
|
201
|
+
[`Sheet` collection example](/gallery/components/sheet#example-sheet-constructions).
|
|
202
|
+
|
|
203
|
+
### SettingsLayout
|
|
204
|
+
|
|
205
|
+
ERB source — the call site supplies both the navigation collection and yielded
|
|
206
|
+
settings content:
|
|
207
|
+
|
|
208
|
+
```erb
|
|
209
|
+
<% sections = [["Profile", profile_settings_path], ["Security", security_settings_path]] %>
|
|
210
|
+
<%= render "settings_layout", sections: sections do %>
|
|
211
|
+
<%= render "profile_form" %>
|
|
212
|
+
<% end %>
|
|
213
|
+
|
|
214
|
+
<%# _settings_layout.html.erb %>
|
|
215
|
+
<nav aria-label="Settings">
|
|
216
|
+
<% sections.each do |text, href| %>
|
|
217
|
+
<%= link_to text, href %>
|
|
218
|
+
<% end %>
|
|
219
|
+
</nav>
|
|
220
|
+
<main><%= yield %></main>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Phlex destination — navigation entries stay inside `navigation`; the former
|
|
224
|
+
yield lives inside the one `content` region:
|
|
225
|
+
|
|
226
|
+
```ruby
|
|
227
|
+
sections = [["Profile", profile_settings_path], ["Security", security_settings_path]]
|
|
228
|
+
|
|
229
|
+
render NitroKit::SettingsLayout.new do |layout|
|
|
230
|
+
layout.navigation(label: "Settings") do
|
|
231
|
+
sections.each_with_index do |(text, href), index|
|
|
232
|
+
layout.item(text, href:, current: index.zero?)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
layout.content { render UI::ProfileForm.new(profile) }
|
|
236
|
+
end
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
See the executable
|
|
240
|
+
[`SettingsLayout` minimal example](/gallery/components/settings-layout#example-settings-layout-cardinality-states).
|
|
241
|
+
|
|
242
|
+
## Preserve unsupported behavior honestly
|
|
243
|
+
|
|
244
|
+
When no equivalent exists, keep semantic Rails or HTML under the application
|
|
245
|
+
namespace and report the missing capability. Do not retain copied 1.x source,
|
|
246
|
+
downgrade a specialized control, or hide the gap behind a generic component.
|
|
247
|
+
|
|
248
|
+
Tooltip custom triggers are the explicit composition path for an existing
|
|
249
|
+
focusable control. Forward every yielded boundary to that actual control:
|
|
250
|
+
|
|
251
|
+
```ruby
|
|
252
|
+
render NitroKit::Tooltip.new(id: "revoke-help", content: "Revokes access immediately") do |tooltip|
|
|
253
|
+
tooltip.trigger(as: :custom) do |attributes|
|
|
254
|
+
render NitroKit::ButtonTo.new(
|
|
255
|
+
"Revoke",
|
|
256
|
+
href: token_path(token),
|
|
257
|
+
method: :delete,
|
|
258
|
+
variant: :destructive,
|
|
259
|
+
button_html: attributes.html,
|
|
260
|
+
button_aria: attributes.aria,
|
|
261
|
+
button_data: attributes.data
|
|
262
|
+
)
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Verify fidelity
|
|
268
|
+
|
|
269
|
+
Install and run Nitro Kit's focused host-integration acceptance flow:
|
|
270
|
+
|
|
271
|
+
```sh
|
|
272
|
+
bin/rails generate nitro_kit:upgrade_smoke_tests
|
|
273
|
+
bin/rails test test/integration/nitro_kit_upgrade_smoke_test.rb
|
|
274
|
+
bin/rails test test/system/nitro_kit_upgrade_smoke_test.rb
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
The generator does not overwrite existing tests. It generates only files
|
|
278
|
+
supported by the host's Rails Minitest and system-test setup and prints setup
|
|
279
|
+
guidance for skipped files. The tests use the currently bundled gem and cover
|
|
280
|
+
the shared upgrade boundary — browser-submitted Turbo validation and mutation,
|
|
281
|
+
Dialog and Sheet, layout-owned Rails flash, Turbo Frame identity, redirects,
|
|
282
|
+
and post-mutation Phlex rendering. Their collision-checked route exists only
|
|
283
|
+
during each test and is restored afterward; they add no production route or
|
|
284
|
+
component source. Keep application-specific migration tests for inventoried
|
|
285
|
+
product behavior alongside them.
|
|
286
|
+
|
|
287
|
+
The endpoint deliberately inherits `ApplicationController` callbacks. If the
|
|
288
|
+
application requires authentication or current-account state, fill in the
|
|
289
|
+
generated `prepare_nitro_kit_upgrade_smoke_test` methods with the same sign-in
|
|
290
|
+
and account-selection helpers used by ordinary integration and system tests.
|
|
291
|
+
Extend those application-owned classes rather than changing gem test support
|
|
292
|
+
or skipping host callbacks.
|
|
293
|
+
|
|
294
|
+
Run focused request and component tests, then compare the converted flows in a
|
|
295
|
+
browser at wide and narrow widths. Exercise keyboard focus, dialogs and sheets,
|
|
296
|
+
Turbo submissions, errors, empty states, light/dark appearance, and dense
|
|
297
|
+
metadata. A green request suite does not prove that a tooltip, off-canvas
|
|
298
|
+
panel, interactive Card treatment, or responsive composition survived.
|
|
299
|
+
|
|
300
|
+
Finish by deleting copied components, helpers, and controllers; run
|
|
301
|
+
`bin/rails nitro_kit:doctor`; and record every remaining application-owned
|
|
302
|
+
fallback as either intentional product UI or a Nitro Kit coverage gap.
|
|
303
|
+
|
|
304
|
+
Doctor inventories only concrete Nitro Kit 1.x conventions: `nk_*` helpers,
|
|
305
|
+
generated files under `app/components/nitro_kit`, controllers under
|
|
306
|
+
`app/javascript/controllers/nk`, the old Floating UI and combobox packages,
|
|
307
|
+
and `tailwind_merge`. Every finding includes a file and replacement. Its
|
|
308
|
+
disposition is:
|
|
309
|
+
|
|
310
|
+
- `migrated` — no remaining occurrence in that category.
|
|
311
|
+
- `unresolved` — a known 1.x integration still needs its documented 2.x
|
|
312
|
+
replacement or removal.
|
|
313
|
+
- `application-owned` — custom or unsupported behavior must be preserved under
|
|
314
|
+
an application namespace, not as a Nitro shadow.
|
|
315
|
+
|
|
316
|
+
The inventory deliberately does not guess from generic component, JavaScript,
|
|
317
|
+
or dependency names. Review application-owned product behavior separately and
|
|
318
|
+
keep its migration record with the application.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# New application strategy
|
|
2
|
+
|
|
3
|
+
Recommend a Rails application template for new applications, not a return to Nitro Kit's old component-copying generator.
|
|
4
|
+
|
|
5
|
+
Rails application templates are designed to configure a new app during `rails new`, can add gems, and can run generators after Bundler finishes. That gives Nitro Kit an eventual one-command entry point:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
rails new my_app -m https://nitrokit.dev/template.rb
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The template should remain thin while the conventions settle. Its first
|
|
12
|
+
version should add Nitro Kit and invoke `nitro_kit:install`. The generator owns
|
|
13
|
+
the project-local skills and `AGENTS.md`; the template may add an application
|
|
14
|
+
layout that renders the stylesheet, appearance bootstrap, and flash toasts. It
|
|
15
|
+
must not copy Nitro components or their controllers.
|
|
16
|
+
|
|
17
|
+
Existing applications install the gem directly and run the setup generator.
|
|
18
|
+
Agent discovery, version-matched skill routing, diagnostics, and initialization
|
|
19
|
+
handoff are meaningful application-owned setup; component source remains
|
|
20
|
+
gem-owned.
|
|
21
|
+
|
|
22
|
+
An optional `nitro_kit:application` generator can later create an application-owned base: layout, `UI` namespace, shell choice, root screen, and authentication hooks. Keep that separate from installing the UI gem so teams can adopt Nitro Kit without adopting an application architecture.
|
|
23
|
+
|
|
24
|
+
Promote the template into a versioned starter application only when Nitro Kit deliberately owns opinions beyond UI and interaction conventions, such as authentication, accounts, teams, billing, jobs, mail, and deployment. Until then, the application template is easier to inspect, test, and evolve and does not impose the maintenance cost of a forked starter repository.
|