From f3531c64f95240f71552ddad28578b4d434637f3 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Tue, 27 Oct 2026 00:06:06 +0700 Subject: [PATCH] Move the console onto ReUI PRO Install ReUI (MCP, skill, @reui registry, Tailwind v4, shadcn base-nova) and move the shared UI onto it: Button, Tag, Check, Input/Textarea, Segmented, Alert, Panel, Dialog, Tooltip, Menu and Select (Popover), Toast (sonner), the Table frame (DataGrid), the Dashboard KPI strip, the shnt Ops palette, Geist and the type scale. Design only: behaviour, texts and roles are unchanged. Tests that asserted the old DOM were updated; the tests now format numbers in English wherever they run. docs/reui-migration-plan.md records the plan and its decisions. Co-Authored-By: Claude Sonnet 5.5 --- .agents/skills/reui/SKILL.md | 83 + .agents/skills/reui/agents/openai.yaml | 4 + .agents/skills/reui/rules/adapting.md | 40 + .agents/skills/reui/rules/anti-patterns.md | 117 + .agents/skills/reui/rules/cli.md | 77 + .agents/skills/reui/rules/color.md | 74 + .agents/skills/reui/rules/components.md | 521 ++ .agents/skills/reui/rules/compose.md | 62 + .agents/skills/reui/rules/icons.md | 43 + .agents/skills/reui/rules/layout.md | 56 + .agents/skills/reui/rules/motion.md | 80 + .agents/skills/reui/rules/quality.md | 57 + .agents/skills/reui/rules/registry.md | 44 + .agents/skills/reui/rules/theming.md | 37 + .agents/skills/reui/rules/workflow.md | 66 + .agents/skills/reui/tools.md | 74 + .claude/skills/reui/SKILL.md | 83 + .claude/skills/reui/agents/openai.yaml | 4 + .claude/skills/reui/rules/adapting.md | 40 + .claude/skills/reui/rules/anti-patterns.md | 117 + .claude/skills/reui/rules/cli.md | 77 + .claude/skills/reui/rules/color.md | 74 + .claude/skills/reui/rules/components.md | 521 ++ .claude/skills/reui/rules/compose.md | 62 + .claude/skills/reui/rules/icons.md | 43 + .claude/skills/reui/rules/layout.md | 56 + .claude/skills/reui/rules/motion.md | 80 + .claude/skills/reui/rules/quality.md | 57 + .claude/skills/reui/rules/registry.md | 44 + .claude/skills/reui/rules/theming.md | 37 + .claude/skills/reui/rules/workflow.md | 66 + .claude/skills/reui/tools.md | 74 + .cursor/mcp.json | 10 + .cursor/rules/reui.mdc | 17 + .cursor/skills/reui/SKILL.md | 83 + .cursor/skills/reui/agents/openai.yaml | 4 + .cursor/skills/reui/rules/adapting.md | 40 + .cursor/skills/reui/rules/anti-patterns.md | 117 + .cursor/skills/reui/rules/cli.md | 77 + .cursor/skills/reui/rules/color.md | 74 + .cursor/skills/reui/rules/components.md | 521 ++ .cursor/skills/reui/rules/compose.md | 62 + .cursor/skills/reui/rules/icons.md | 43 + .cursor/skills/reui/rules/layout.md | 56 + .cursor/skills/reui/rules/motion.md | 80 + .cursor/skills/reui/rules/quality.md | 57 + .cursor/skills/reui/rules/registry.md | 44 + .cursor/skills/reui/rules/theming.md | 37 + .cursor/skills/reui/rules/workflow.md | 66 + .cursor/skills/reui/tools.md | 74 + .gemini/settings.json | 10 + .githooks/pre-commit | 15 + .github/FUNDING.yml | 4 + .github/ISSUE_TEMPLATE/bug.yml | 45 + .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature.yml | 20 + .github/actions/console-tarball/action.yml | 37 + .github/actions/init-image/action.yml | 154 + .github/actions/init-image/floating-tags.sh | 36 + .github/workflows/develop-image.yml | 85 + .github/workflows/release.yml | 200 + .gitignore | 6 + .mcp.json | 11 + .opencode/skills/reui/SKILL.md | 83 + .opencode/skills/reui/agents/openai.yaml | 4 + .opencode/skills/reui/rules/adapting.md | 40 + .opencode/skills/reui/rules/anti-patterns.md | 117 + .opencode/skills/reui/rules/cli.md | 77 + .opencode/skills/reui/rules/color.md | 74 + .opencode/skills/reui/rules/components.md | 521 ++ .opencode/skills/reui/rules/compose.md | 62 + .opencode/skills/reui/rules/icons.md | 43 + .opencode/skills/reui/rules/layout.md | 56 + .opencode/skills/reui/rules/motion.md | 80 + .opencode/skills/reui/rules/quality.md | 57 + .opencode/skills/reui/rules/registry.md | 44 + .opencode/skills/reui/rules/theming.md | 37 + .opencode/skills/reui/rules/workflow.md | 66 + .opencode/skills/reui/tools.md | 74 + .oxlintrc.json | 8 + AGENTS.md | 14 + CHANGELOG.md | 571 +++ CODE_OF_CONDUCT.md | 83 + CONTRIBUTING.md | 103 + CONVENTIONS.md | 863 ++++ LICENSE | 674 +++ PRODUCT.md | 70 + README.md | 480 ++ SECURITY.md | 105 + components.json | 30 + dev/README-parity.md | 51 + dev/README.md | 142 + dev/check-colour-tokens.mjs | 281 ++ dev/check-colour-tokens.test.mjs | 105 + dev/check-dashes.mjs | 111 + dev/check-dashes.test.mjs | 110 + dev/check-endpoints.mjs | 84 + dev/check-language.mjs | 379 ++ dev/check-language.test.mjs | 105 + dev/check-parity-actions.sh | 135 + dev/check-parity-controls.mjs | 429 ++ dev/check-parity-sort.mjs | 126 + dev/check-parity-sort.test.mjs | 65 + dev/check-parity.sh | 40 + dev/check-prefix.sh | 22 + dev/check-sort-fields.mjs | 96 + dev/check-word-breaks.mjs | 123 + dev/check-word-breaks.test.mjs | 28 + dev/compose.yaml | 57 + dev/css-dead.mjs | 315 ++ dev/css-duplicated.mjs | 90 + dev/dialog-inventory.sh | 24 + dev/installer-probe.sh | 1028 ++++ dev/installer-security.test.py | 153 + dev/master-switch-signal.test.mjs | 87 + dev/palette-distance.mjs | 351 ++ dev/parity-login.mjs | 43 + dev/raw.test.mjs | 88 + dev/relative-paths.test.mjs | 37 + dev/row-colours.mjs | 213 + dev/theme-contrast.mjs | 190 + dev/theme-contrast.test.mjs | 33 + dev/uniformity.js | 454 ++ dev/uniformity.test.mjs | 313 ++ dev/update-check-serve.mjs | 52 + docker/Dockerfile | 13 + docs/2026-09-07-installer-contract.md | 758 +++ docs/reui-migration-plan.md | 81 + docs/screenshots/apps.png | Bin 0 -> 134003 bytes docs/screenshots/blocking-lists.png | Bin 0 -> 116345 bytes docs/screenshots/blocking-overview-light.png | Bin 0 -> 119830 bytes docs/screenshots/blocking-overview.png | Bin 0 -> 127010 bytes docs/screenshots/blocking-rules.png | Bin 0 -> 87080 bytes docs/screenshots/cache.png | Bin 0 -> 81112 bytes docs/screenshots/dashboard.png | Bin 0 -> 217912 bytes docs/screenshots/login.png | Bin 0 -> 51029 bytes docs/screenshots/mobile.png | Bin 0 -> 62780 bytes docs/screenshots/query-logs.png | Bin 0 -> 135667 bytes docs/screenshots/settings.png | Bin 0 -> 157045 bytes docs/screenshots/zones.png | Bin 0 -> 78041 bytes docs/social-preview.png | Bin 0 -> 129288 bytes index.html | 13 + install.sh | 1594 +++++++ opencode.json | 13 + package-lock.json | 4189 +++++++++++++++++ package.json | 64 + public/favicon.ico | Bin 0 -> 8478 bytes public/fonts/OFL-Archivo.txt | 93 + public/fonts/OFL-IBMPlex.txt | 93 + public/fonts/README.md | 34 + public/fonts/archivo-latin.woff2 | Bin 0 -> 34928 bytes public/fonts/plex-mono-400-latin.woff2 | Bin 0 -> 14708 bytes public/fonts/plex-mono-600-latin.woff2 | Bin 0 -> 15620 bytes public/img/loader-small.gif | Bin 0 -> 5559 bytes public/img/loader.gif | Bin 0 -> 14752 bytes public/img/logo.png | Bin 0 -> 325 bytes public/img/logo25x25.png | Bin 0 -> 222 bytes public/img/oidc.png | Bin 0 -> 1918 bytes .../json/dnsclient-server-list-builtin.json | 204 + public/json/quick-block-lists-builtin.json | 204 + .../json/quick-forwarders-list-builtin.json | 430 ++ public/json/readme.txt | 12 + public/robots.txt | 2 + src/App.tsx | 10 + src/api/admin-cluster.test.ts | 176 + src/api/admin-cluster.ts | 228 + src/api/admin.test.ts | 255 + src/api/admin.ts | 417 ++ src/api/apps.test.ts | 179 + src/api/apps.ts | 189 + src/api/blocking.test.ts | 208 + src/api/blocking.ts | 158 + src/api/chart-labels.test.ts | 109 + src/api/chart-labels.ts | 56 + src/api/client.test.ts | 191 + src/api/client.ts | 175 + src/api/dashboard.metrics.test.ts | 54 + src/api/dashboard.test.ts | 76 + src/api/dashboard.ts | 194 + src/api/dhcp.test.ts | 171 + src/api/dhcp.ts | 256 + src/api/dnsclient.test.ts | 57 + src/api/dnsclient.ts | 72 + src/api/dnssec.test.ts | 216 + src/api/dnssec.ts | 373 ++ src/api/logs.test.ts | 150 + src/api/logs.ts | 255 + src/api/records.test.ts | 195 + src/api/records.ts | 379 ++ src/api/settings.test.ts | 141 + src/api/settings.ts | 376 ++ src/api/status.test.ts | 32 + src/api/status.ts | 22 + src/api/user.test.ts | 64 + src/api/user.ts | 135 + src/api/zonelists.test.ts | 165 + src/api/zonelists.ts | 219 + src/api/zones.test.ts | 219 + src/api/zones.ts | 513 ++ src/app/BlockingMark.module.css | 22 + src/app/BlockingMark.tsx | 26 + src/app/ChromeSlot.test.tsx | 70 + src/app/ChromeSlot.tsx | 54 + src/app/Shell.blocking.test.tsx | 103 + src/app/Shell.handoff.test.tsx | 194 + src/app/Shell.module.css | 174 + src/app/Shell.tsx | 665 +++ src/app/Versions.module.css | 127 + src/app/Versions.test.tsx | 265 ++ src/app/Versions.tsx | 272 ++ src/app/base.ts | 64 + src/app/console-update.test.ts | 162 + src/app/console-update.ts | 131 + src/app/footer.ts | 62 + src/app/handoff.ts | 82 + src/app/route.test.ts | 282 ++ src/app/route.ts | 127 + src/app/sections.test.ts | 19 + src/app/sections.ts | 54 + src/app/slug.ts | 15 + src/app/static-routes.ts | 35 + src/components/reui/alert.tsx | 92 + src/components/reui/badge.tsx | 102 + .../reui/cascader/cascader-async.tsx | 928 ++++ .../reui/cascader/cascader-columns.tsx | 272 ++ .../reui/cascader/cascader-context.tsx | 324 ++ .../reui/cascader/cascader-footer.tsx | 733 +++ .../reui/cascader/cascader-i18n.tsx | 92 + .../reui/cascader/cascader-item.tsx | 1080 +++++ src/components/reui/cascader/cascader-lib.tsx | 1012 ++++ src/components/reui/cascader/cascader-nav.tsx | 651 +++ .../reui/cascader/cascader-types.tsx | 220 + .../reui/cascader/cascader-virtual.tsx | 468 ++ src/components/reui/cascader/cascader.tsx | 3068 ++++++++++++ .../data-grid/data-grid-cell-selection.tsx | 2607 ++++++++++ .../data-grid/data-grid-column-filter.tsx | 192 + .../data-grid/data-grid-column-header.tsx | 506 ++ .../data-grid/data-grid-column-visibility.tsx | 68 + .../reui/data-grid/data-grid-i18n.tsx | 99 + .../reui/data-grid/data-grid-pagination.tsx | 306 ++ .../reui/data-grid/data-grid-scroll-area.tsx | 557 +++ .../data-grid/data-grid-table-dnd-rows.tsx | 820 ++++ .../reui/data-grid/data-grid-table-dnd.tsx | 555 +++ .../data-grid/data-grid-table-virtual.tsx | 1217 +++++ .../reui/data-grid/data-grid-table.tsx | 3100 ++++++++++++ src/components/reui/data-grid/data-grid.tsx | 1317 ++++++ .../reui/filters/filters-advanced.tsx | 2080 ++++++++ .../reui/filters/filters-builder.tsx | 305 ++ src/components/reui/filters/filters-chip.tsx | 1072 +++++ .../reui/filters/filters-context.tsx | 660 +++ src/components/reui/filters/filters-date.tsx | 213 + src/components/reui/filters/filters-dnd.tsx | 702 +++ src/components/reui/filters/filters-draft.tsx | 187 + .../reui/filters/filters-editors.tsx | 1339 ++++++ src/components/reui/filters/filters-i18n.tsx | 151 + src/components/reui/filters/filters-lib.tsx | 539 +++ .../reui/filters/filters-operators.tsx | 227 + src/components/reui/filters/filters-query.tsx | 701 +++ src/components/reui/filters/filters-types.tsx | 566 +++ src/components/reui/filters/filters.tsx | 1230 +++++ src/components/reui/frame.tsx | 180 + src/components/ui/alert-dialog.tsx | 185 + src/components/ui/avatar.tsx | 108 + src/components/ui/breadcrumb.tsx | 124 + src/components/ui/button-group.tsx | 87 + src/components/ui/button.tsx | 57 + src/components/ui/checkbox.tsx | 26 + src/components/ui/command.tsx | 194 + src/components/ui/dialog.tsx | 160 + src/components/ui/dropdown-menu.tsx | 267 ++ src/components/ui/field.tsx | 236 + src/components/ui/input-group.tsx | 158 + src/components/ui/input.tsx | 19 + src/components/ui/kbd.tsx | 26 + src/components/ui/label.tsx | 17 + src/components/ui/popover.tsx | 89 + src/components/ui/scroll-area.tsx | 55 + src/components/ui/select.tsx | 200 + src/components/ui/separator.tsx | 22 + src/components/ui/sheet.tsx | 136 + src/components/ui/sidebar.tsx | 723 +++ src/components/ui/skeleton.tsx | 13 + src/components/ui/sonner.tsx | 49 + src/components/ui/spinner.tsx | 10 + src/components/ui/switch.tsx | 29 + src/components/ui/table.tsx | 115 + src/components/ui/tabs.tsx | 79 + src/components/ui/textarea.tsx | 17 + src/components/ui/tooltip.tsx | 65 + src/hooks/use-mobile.ts | 19 + src/lib/allow-block.ts | 56 + src/lib/copy-text.test.ts | 52 + src/lib/copy-text.ts | 40 + src/lib/dates.test.ts | 67 + src/lib/dates.ts | 113 + src/lib/notice.test.ts | 27 + src/lib/notice.ts | 38 + src/lib/pagination.test.ts | 42 + src/lib/pagination.ts | 63 + src/lib/quick-lists.test.ts | 157 + src/lib/quick-lists.ts | 176 + src/lib/settings-signal.ts | 25 + src/lib/stored-per-page.test.ts | 18 + src/lib/stored-per-page.ts | 22 + src/lib/table-serialise.test.ts | 43 + src/lib/table-serialise.ts | 85 + src/lib/use-media.ts | 37 + src/lib/utils.ts | 6 + src/main.tsx | 33 + src/screens/Login.module.css | 75 + src/screens/Login.otp.test.tsx | 86 + src/screens/Login.status.test.tsx | 96 + src/screens/Login.test.tsx | 189 + src/screens/Login.tsx | 318 ++ src/screens/LoginCover.module.css | 101 + src/screens/LoginCover.test.tsx | 81 + src/screens/LoginCover.tsx | 69 + src/screens/StaleData.tsx | 48 + src/screens/about/About.module.css | 49 + src/screens/about/About.test.tsx | 113 + src/screens/about/About.tsx | 221 + src/screens/admin/Admin.module.css | 114 + src/screens/admin/Admin.test.tsx | 146 + src/screens/admin/Admin.tsx | 159 + src/screens/admin/Cluster.test.tsx | 604 +++ src/screens/admin/Cluster.tsx | 1656 +++++++ src/screens/admin/Groups.test.tsx | 186 + src/screens/admin/Groups.tsx | 426 ++ src/screens/admin/Ldap.test.tsx | 475 ++ src/screens/admin/Ldap.tsx | 653 +++ src/screens/admin/Permissions.test.tsx | 233 + src/screens/admin/Permissions.tsx | 603 +++ src/screens/admin/Sessions.test.tsx | 241 + src/screens/admin/Sessions.tsx | 386 ++ src/screens/admin/Sso.test.tsx | 412 ++ src/screens/admin/Sso.tsx | 648 +++ src/screens/admin/UserDetails.tsx | 371 ++ src/screens/admin/Users.test.tsx | 494 ++ src/screens/admin/Users.tsx | 588 +++ src/screens/admin/admin.fixture.ts | 220 + src/screens/admin/dates.ts | 2 + src/screens/admin/parts.tsx | 74 + src/screens/admin/table.test.ts | 66 + src/screens/admin/table.ts | 53 + src/screens/apps/AppCard.tsx | 125 + src/screens/apps/AppConfig.tsx | 94 + src/screens/apps/Apps.failure.test.tsx | 81 + src/screens/apps/Apps.module.css | 61 + src/screens/apps/Apps.test.tsx | 503 ++ src/screens/apps/Apps.tsx | 301 ++ src/screens/apps/InstallApp.tsx | 84 + src/screens/apps/StoreApps.tsx | 246 + src/screens/apps/UpdateApp.tsx | 80 + .../blocking/AddDomainBar.check.test.tsx | 171 + src/screens/blocking/AddDomainBar.test.tsx | 74 + src/screens/blocking/AddDomainBar.tsx | 207 + .../blocking/BlockLists.groups.test.tsx | 168 + src/screens/blocking/BlockLists.module.css | 135 + .../blocking/BlockLists.quick.test.tsx | 89 + src/screens/blocking/BlockLists.real.test.tsx | 75 + src/screens/blocking/BlockLists.test.tsx | 430 ++ src/screens/blocking/BlockLists.tsx | 829 ++++ src/screens/blocking/Blocking.module.css | 84 + src/screens/blocking/Blocking.test.tsx | 49 + src/screens/blocking/Blocking.tsx | 107 + src/screens/blocking/DomainCheck.module.css | 39 + src/screens/blocking/DomainCheck.tsx | 163 + src/screens/blocking/Locked.test.tsx | 26 + src/screens/blocking/Locked.tsx | 67 + src/screens/blocking/Overview.module.css | 84 + src/screens/blocking/Overview.real.test.tsx | 133 + src/screens/blocking/Overview.test.tsx | 378 ++ src/screens/blocking/Overview.tsx | 471 ++ src/screens/blocking/RecentBlocked.test.tsx | 216 + src/screens/blocking/RecentBlocked.tsx | 220 + src/screens/blocking/Rules.module.css | 25 + src/screens/blocking/Rules.real.test.tsx | 53 + src/screens/blocking/Rules.test.tsx | 473 ++ src/screens/blocking/Rules.tsx | 654 +++ src/screens/blocking/Rules.undo.test.tsx | 203 + src/screens/blocking/StatusPanel.test.tsx | 165 + src/screens/blocking/StatusPanel.tsx | 119 + src/screens/blocking/TopTable.test.tsx | 148 + src/screens/blocking/TopTable.tsx | 126 + src/screens/blocking/blocking-state.test.tsx | 106 + src/screens/blocking/blocking-state.ts | 144 + src/screens/blocking/check-domain.real.json | 684 +++ src/screens/blocking/check-domain.test.ts | 249 + src/screens/blocking/check-domain.ts | 339 ++ src/screens/blocking/extra-lists.json | 212 + src/screens/blocking/extra-lists.test.ts | 94 + src/screens/blocking/extra-lists.ts | 50 + src/screens/blocking/list-lines.test.ts | 327 ++ src/screens/blocking/list-lines.ts | 437 ++ src/screens/blocking/permissions.test.ts | 27 + src/screens/blocking/permissions.ts | 26 + src/screens/blocking/real-sample.json | 1830 +++++++ src/screens/blocking/rules-model.test.ts | 55 + src/screens/blocking/rules-model.ts | 71 + src/screens/blocking/undo.test.ts | 42 + src/screens/blocking/undo.ts | 98 + src/screens/dashboard/BlockingMenu.test.tsx | 114 + src/screens/dashboard/BlockingMenu.tsx | 169 + src/screens/dashboard/Breakdown.tsx | 196 + src/screens/dashboard/Chart.theme.test.tsx | 154 + src/screens/dashboard/Chart.tsx | 385 ++ .../dashboard/Dashboard.compare.test.tsx | 241 + .../dashboard/Dashboard.legend.test.tsx | 259 + src/screens/dashboard/Dashboard.module.css | 356 ++ .../dashboard/Dashboard.states.test.tsx | 223 + src/screens/dashboard/Dashboard.test.tsx | 340 ++ src/screens/dashboard/Dashboard.tops.test.tsx | 90 + src/screens/dashboard/Dashboard.tsx | 509 ++ src/screens/dashboard/Figures.tsx | 132 + src/screens/dashboard/Heatmap.module.css | 53 + src/screens/dashboard/Heatmap.test.tsx | 89 + src/screens/dashboard/Heatmap.tsx | 162 + src/screens/dashboard/Panels.tsx | 250 + src/screens/dashboard/Spark.module.css | 9 + src/screens/dashboard/Spark.test.tsx | 25 + src/screens/dashboard/Spark.tsx | 66 + src/screens/dashboard/TopRowMenu.test.tsx | 220 + src/screens/dashboard/TopRowMenu.tsx | 75 + src/screens/dashboard/TopStats.test.tsx | 150 + src/screens/dashboard/TopStats.tsx | 147 + src/screens/dashboard/compare.test.ts | 192 + src/screens/dashboard/compare.ts | 321 ++ src/screens/dashboard/custom-range.test.ts | 45 + src/screens/dashboard/custom-range.ts | 38 + src/screens/dashboard/heatmap.test.ts | 91 + src/screens/dashboard/heatmap.ts | 136 + src/screens/dashboard/jump.test.ts | 55 + src/screens/dashboard/jump.ts | 67 + src/screens/dashboard/legend-order.test.ts | 21 + src/screens/dashboard/legend-order.ts | 19 + src/screens/dashboard/live.test.ts | 196 + src/screens/dashboard/live.ts | 183 + src/screens/dashboard/metrics.ts | 46 + src/screens/dashboard/palette.test.ts | 43 + src/screens/dashboard/palette.ts | 76 + src/screens/dashboard/useLive.test.tsx | 185 + src/screens/dashboard/useLive.ts | 141 + src/screens/dhcp/Dhcp.failure.test.tsx | 97 + src/screens/dhcp/Dhcp.module.css | 49 + src/screens/dhcp/Dhcp.test.tsx | 468 ++ src/screens/dhcp/Dhcp.tsx | 102 + src/screens/dhcp/Leases.tsx | 338 ++ src/screens/dhcp/ScopeForm.tsx | 496 ++ src/screens/dhcp/Scopes.tsx | 358 ++ src/screens/dhcp/dates.ts | 2 + src/screens/dhcp/model.test.ts | 330 ++ src/screens/dhcp/model.ts | 368 ++ src/screens/dhcp/notices.ts | 4 + src/screens/dhcp/parts.tsx | 18 + src/screens/dnsclient/DnsClient.module.css | 46 + .../dnsclient/DnsClient.request.test.tsx | 106 + src/screens/dnsclient/DnsClient.test.tsx | 175 + src/screens/dnsclient/DnsClient.tsx | 257 + src/screens/lists/Cache.nav.test.tsx | 80 + src/screens/lists/CacheNav.tsx | 118 + src/screens/lists/Lists.embedded.test.tsx | 127 + src/screens/lists/Lists.loading.test.tsx | 57 + src/screens/lists/Lists.module.css | 360 ++ src/screens/lists/Lists.stale.test.tsx | 87 + src/screens/lists/Lists.test.tsx | 340 ++ src/screens/lists/Lists.tree.test.tsx | 218 + src/screens/lists/Lists.tsx | 730 +++ src/screens/lists/Path.tsx | 52 + src/screens/lists/Records.real.test.tsx | 146 + src/screens/lists/Records.tsx | 179 + src/screens/lists/Tree.tsx | 100 + src/screens/lists/real-sample.json | 504 ++ src/screens/lists/record.test.ts | 164 + src/screens/lists/record.ts | 207 + src/screens/logs/LogText.test.tsx | 128 + src/screens/logs/LogText.tsx | 160 + src/screens/logs/Logs.module.css | 323 ++ src/screens/logs/Logs.test.tsx | 754 +++ src/screens/logs/Logs.tsx | 100 + src/screens/logs/QueryLogs.filters.test.tsx | 213 + src/screens/logs/QueryLogs.jump.test.tsx | 75 + src/screens/logs/QueryLogs.menu.test.tsx | 270 ++ src/screens/logs/QueryLogs.tsx | 1023 ++++ src/screens/logs/ViewLogs.tsx | 367 ++ src/screens/logs/dates.ts | 20 + src/screens/modals/ChangePassword.tsx | 184 + src/screens/modals/ChangeTheme.test.tsx | 113 + src/screens/modals/ChangeTheme.tsx | 55 + src/screens/modals/Configure2FA.tsx | 225 + src/screens/modals/CreateApiToken.tsx | 140 + src/screens/modals/ForgotPassword.module.css | 4 + src/screens/modals/ForgotPassword.tsx | 71 + src/screens/modals/MyProfile.module.css | 12 + src/screens/modals/MyProfile.tsx | 296 ++ src/screens/modals/modals.test.tsx | 404 ++ src/screens/settings/Settings.module.css | 81 + src/screens/settings/Settings.test.tsx | 877 ++++ src/screens/settings/Settings.tsx | 655 +++ src/screens/settings/block.test.tsx | 89 + src/screens/settings/dialogs.tsx | 146 + src/screens/settings/master.test.tsx | 79 + src/screens/settings/model.test.ts | 384 ++ src/screens/settings/model.ts | 903 ++++ src/screens/settings/panes/Blocking.tsx | 308 ++ src/screens/settings/panes/Cache.tsx | 185 + src/screens/settings/panes/General.tsx | 541 +++ src/screens/settings/panes/Logging.tsx | 125 + .../settings/panes/OptionalProtocols.tsx | 372 ++ .../settings/panes/ProxyForwarders.tsx | 231 + src/screens/settings/panes/Recursion.tsx | 223 + src/screens/settings/panes/Tsig.tsx | 63 + src/screens/settings/panes/WebService.tsx | 233 + src/screens/settings/panes/types.ts | 10 + src/screens/settings/parts.tsx | 29 + src/screens/settings/pending.test.ts | 182 + src/screens/settings/pending.ts | 275 ++ src/screens/settings/redirect.test.ts | 73 + src/screens/settings/redirect.ts | 74 + src/screens/settings/settings.fixture.ts | 194 + src/screens/zones/DataCell.tsx | 144 + src/screens/zones/EditZoneFile.test.tsx | 309 ++ src/screens/zones/ZoneList.tsx | 801 ++++ src/screens/zones/ZoneRecords.tsx | 654 +++ src/screens/zones/Zones.loading.test.tsx | 48 + src/screens/zones/Zones.module.css | 112 + src/screens/zones/Zones.selection.test.tsx | 75 + src/screens/zones/Zones.stale.test.tsx | 163 + src/screens/zones/Zones.test.tsx | 455 ++ src/screens/zones/Zones.tsx | 355 ++ src/screens/zones/filter.test.ts | 103 + src/screens/zones/filter.ts | 89 + .../zones/modals/AddEditRecord.test.tsx | 179 + src/screens/zones/modals/AddEditRecord.tsx | 856 ++++ src/screens/zones/modals/AddZone.test.tsx | 89 + src/screens/zones/modals/AddZone.tsx | 482 ++ src/screens/zones/modals/CloneZone.tsx | 88 + src/screens/zones/modals/ConvertZone.tsx | 137 + src/screens/zones/modals/DnssecProperties.tsx | 823 ++++ src/screens/zones/modals/EditZoneFile.tsx | 161 + src/screens/zones/modals/ImportZone.tsx | 200 + src/screens/zones/modals/SignZone.tsx | 430 ++ src/screens/zones/modals/UnsignZone.tsx | 96 + src/screens/zones/modals/ViewDs.tsx | 150 + src/screens/zones/modals/ZoneOptions.tsx | 662 +++ src/screens/zones/modals/ZonePermissions.tsx | 246 + src/screens/zones/modals/add-zone.ts | 359 ++ .../zones/modals/dnssec-options.test.ts | 36 + src/screens/zones/modals/dnssec-options.ts | 79 + src/screens/zones/modals/help-texts.test.tsx | 248 + src/screens/zones/options.test.ts | 269 ++ src/screens/zones/options.ts | 604 +++ src/screens/zones/record-form.test.ts | 454 ++ src/screens/zones/record-form.ts | 967 ++++ src/screens/zones/record-view.test.ts | 261 + src/screens/zones/record-view.ts | 496 ++ src/screens/zones/references.ts | 13 + src/screens/zones/types.ts | 13 + src/screens/zones/zone-view.ts | 122 + src/session/SessionProvider.test.tsx | 636 +++ src/session/SessionProvider.tsx | 97 + src/session/boot.test.ts | 56 + src/session/boot.ts | 70 + src/test/dropdown.ts | 37 + src/test/quiet-hours.ts | 16 + src/test/real-blocking.ts | 68 + src/test/setup.ts | 99 + src/test/system-theme.ts | 37 + src/test/whole-text.ts | 17 + src/theme/ThemeProvider.test.tsx | 212 + src/theme/ThemeProvider.tsx | 62 + src/theme/base.css | 284 ++ src/theme/globals.css | 75 + src/theme/theme.ts | 129 + src/theme/tokens.css | 893 ++++ src/theme/useTheme.ts | 26 + src/ui/Alert.module.css | 113 + src/ui/Alert.test.tsx | 157 + src/ui/Alert.tsx | 93 + src/ui/Button.module.css | 111 + src/ui/Button.tsx | 41 + src/ui/Check.module.css | 45 + src/ui/Check.tsx | 62 + src/ui/ClusterNodeSelect.test.tsx | 101 + src/ui/ClusterNodeSelect.tsx | 101 + src/ui/Confirm.module.css | 36 + src/ui/Confirm.tsx | 124 + src/ui/Details.module.css | 36 + src/ui/Details.tsx | 24 + src/ui/Dialog.tsx | 92 + src/ui/DomainName.module.css | 2 + src/ui/DomainName.test.tsx | 49 + src/ui/DomainName.tsx | 45 + src/ui/EditableTable.module.css | 34 + src/ui/EditableTable.tsx | 35 + src/ui/Empty.module.css | 86 + src/ui/Empty.tsx | 107 + src/ui/External.module.css | 3 + src/ui/External.test.tsx | 29 + src/ui/External.tsx | 52 + src/ui/Field.tsx | 68 + src/ui/FooterLinks.module.css | 43 + src/ui/FooterLinks.tsx | 28 + src/ui/Form.module.css | 191 + src/ui/Form.tsx | 135 + src/ui/Icon.tsx | 284 ++ src/ui/IndexedForm.module.css | 68 + src/ui/IndexedForm.tsx | 49 + src/ui/Matrix.module.css | 189 + src/ui/Matrix.test.tsx | 149 + src/ui/Matrix.tsx | 197 + src/ui/Menu.module.css | 71 + src/ui/Menu.test.tsx | 166 + src/ui/Menu.tsx | 256 + src/ui/Notifier.test.tsx | 30 + src/ui/Notifier.tsx | 33 + src/ui/Pagination.module.css | 30 + src/ui/Pagination.tsx | 75 + src/ui/Panel.module.css | 70 + src/ui/Panel.tsx | 97 + src/ui/PanelForm.module.css | 218 + src/ui/PanelForm.tsx | 465 ++ src/ui/PermissionButton.tsx | 66 + src/ui/Raw.module.css | 71 + src/ui/Raw.test.tsx | 72 + src/ui/Raw.tsx | 110 + src/ui/RouteLink.test.tsx | 56 + src/ui/RouteLink.tsx | 27 + src/ui/SectionHeader.module.css | 113 + src/ui/SectionHeader.tsx | 107 + src/ui/SectionIndex.module.css | 175 + src/ui/SectionIndex.test.tsx | 200 + src/ui/SectionIndex.tsx | 109 + src/ui/Segmented.tsx | 56 + src/ui/Select.module.css | 146 + src/ui/Select.test.tsx | 264 ++ src/ui/Select.tsx | 467 ++ src/ui/SessionCells.module.css | 55 + src/ui/SessionCells.tsx | 60 + src/ui/SubTabs.module.css | 61 + src/ui/SubTabs.tsx | 84 + src/ui/Table.module.css | 471 ++ src/ui/Table.test.tsx | 269 ++ src/ui/Table.tsx | 435 ++ src/ui/Tag.module.css | 15 + src/ui/Tag.tsx | 57 + src/ui/Toast.test.tsx | 84 + src/ui/Toast.tsx | 241 + src/ui/Tooltip.test.tsx | 218 + src/ui/Tooltip.tsx | 113 + src/ui/UrlText.test.tsx | 39 + src/ui/UrlText.tsx | 36 + src/ui/count.module.css | 39 + src/ui/interaction.module.css | 23 + src/ui/kv.module.css | 35 + src/ui/label.module.css | 23 + src/ui/list.module.css | 37 + src/ui/record.module.css | 49 + src/ui/text.module.css | 113 + src/ui/tones.module.css | 23 + src/ui/tooltip-place.test.ts | 80 + src/ui/tooltip-place.ts | 108 + src/ui/useSectionInView.test.tsx | 57 + src/ui/useSectionInView.ts | 49 + src/vite-env.d.ts | 2 + tsconfig.app.json | 27 + tsconfig.json | 9 + tsconfig.node.json | 24 + update-check/README.md | 41 + update-check/functions/dns-query.ts | 30 + update-check/public/index.html | 19 + update-check/src/dns-message.test.ts | 71 + update-check/src/dns-message.ts | 97 + update-check/src/handler.test.ts | 195 + update-check/src/handler.ts | 122 + update-check/src/source.test.ts | 108 + update-check/src/source.ts | 67 + update-check/src/test-query.ts | 30 + update-check/tsconfig.json | 23 + vite.config.ts | 114 + vitest.config.ts | 19 + 680 files changed, 139836 insertions(+) create mode 100644 .agents/skills/reui/SKILL.md create mode 100644 .agents/skills/reui/agents/openai.yaml create mode 100644 .agents/skills/reui/rules/adapting.md create mode 100644 .agents/skills/reui/rules/anti-patterns.md create mode 100644 .agents/skills/reui/rules/cli.md create mode 100644 .agents/skills/reui/rules/color.md create mode 100644 .agents/skills/reui/rules/components.md create mode 100644 .agents/skills/reui/rules/compose.md create mode 100644 .agents/skills/reui/rules/icons.md create mode 100644 .agents/skills/reui/rules/layout.md create mode 100644 .agents/skills/reui/rules/motion.md create mode 100644 .agents/skills/reui/rules/quality.md create mode 100644 .agents/skills/reui/rules/registry.md create mode 100644 .agents/skills/reui/rules/theming.md create mode 100644 .agents/skills/reui/rules/workflow.md create mode 100644 .agents/skills/reui/tools.md create mode 100644 .claude/skills/reui/SKILL.md create mode 100644 .claude/skills/reui/agents/openai.yaml create mode 100644 .claude/skills/reui/rules/adapting.md create mode 100644 .claude/skills/reui/rules/anti-patterns.md create mode 100644 .claude/skills/reui/rules/cli.md create mode 100644 .claude/skills/reui/rules/color.md create mode 100644 .claude/skills/reui/rules/components.md create mode 100644 .claude/skills/reui/rules/compose.md create mode 100644 .claude/skills/reui/rules/icons.md create mode 100644 .claude/skills/reui/rules/layout.md create mode 100644 .claude/skills/reui/rules/motion.md create mode 100644 .claude/skills/reui/rules/quality.md create mode 100644 .claude/skills/reui/rules/registry.md create mode 100644 .claude/skills/reui/rules/theming.md create mode 100644 .claude/skills/reui/rules/workflow.md create mode 100644 .claude/skills/reui/tools.md create mode 100644 .cursor/mcp.json create mode 100644 .cursor/rules/reui.mdc create mode 100644 .cursor/skills/reui/SKILL.md create mode 100644 .cursor/skills/reui/agents/openai.yaml create mode 100644 .cursor/skills/reui/rules/adapting.md create mode 100644 .cursor/skills/reui/rules/anti-patterns.md create mode 100644 .cursor/skills/reui/rules/cli.md create mode 100644 .cursor/skills/reui/rules/color.md create mode 100644 .cursor/skills/reui/rules/components.md create mode 100644 .cursor/skills/reui/rules/compose.md create mode 100644 .cursor/skills/reui/rules/icons.md create mode 100644 .cursor/skills/reui/rules/layout.md create mode 100644 .cursor/skills/reui/rules/motion.md create mode 100644 .cursor/skills/reui/rules/quality.md create mode 100644 .cursor/skills/reui/rules/registry.md create mode 100644 .cursor/skills/reui/rules/theming.md create mode 100644 .cursor/skills/reui/rules/workflow.md create mode 100644 .cursor/skills/reui/tools.md create mode 100644 .gemini/settings.json create mode 100644 .githooks/pre-commit create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/bug.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature.yml create mode 100644 .github/actions/console-tarball/action.yml create mode 100644 .github/actions/init-image/action.yml create mode 100644 .github/actions/init-image/floating-tags.sh create mode 100644 .github/workflows/develop-image.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 .mcp.json create mode 100644 .opencode/skills/reui/SKILL.md create mode 100644 .opencode/skills/reui/agents/openai.yaml create mode 100644 .opencode/skills/reui/rules/adapting.md create mode 100644 .opencode/skills/reui/rules/anti-patterns.md create mode 100644 .opencode/skills/reui/rules/cli.md create mode 100644 .opencode/skills/reui/rules/color.md create mode 100644 .opencode/skills/reui/rules/components.md create mode 100644 .opencode/skills/reui/rules/compose.md create mode 100644 .opencode/skills/reui/rules/icons.md create mode 100644 .opencode/skills/reui/rules/layout.md create mode 100644 .opencode/skills/reui/rules/motion.md create mode 100644 .opencode/skills/reui/rules/quality.md create mode 100644 .opencode/skills/reui/rules/registry.md create mode 100644 .opencode/skills/reui/rules/theming.md create mode 100644 .opencode/skills/reui/rules/workflow.md create mode 100644 .opencode/skills/reui/tools.md create mode 100644 .oxlintrc.json create mode 100644 AGENTS.md create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 CONVENTIONS.md create mode 100644 LICENSE create mode 100644 PRODUCT.md create mode 100644 README.md create mode 100644 SECURITY.md create mode 100644 components.json create mode 100644 dev/README-parity.md create mode 100644 dev/README.md create mode 100644 dev/check-colour-tokens.mjs create mode 100644 dev/check-colour-tokens.test.mjs create mode 100644 dev/check-dashes.mjs create mode 100644 dev/check-dashes.test.mjs create mode 100644 dev/check-endpoints.mjs create mode 100644 dev/check-language.mjs create mode 100644 dev/check-language.test.mjs create mode 100644 dev/check-parity-actions.sh create mode 100644 dev/check-parity-controls.mjs create mode 100644 dev/check-parity-sort.mjs create mode 100644 dev/check-parity-sort.test.mjs create mode 100644 dev/check-parity.sh create mode 100644 dev/check-prefix.sh create mode 100644 dev/check-sort-fields.mjs create mode 100644 dev/check-word-breaks.mjs create mode 100644 dev/check-word-breaks.test.mjs create mode 100644 dev/compose.yaml create mode 100644 dev/css-dead.mjs create mode 100644 dev/css-duplicated.mjs create mode 100644 dev/dialog-inventory.sh create mode 100644 dev/installer-probe.sh create mode 100644 dev/installer-security.test.py create mode 100644 dev/master-switch-signal.test.mjs create mode 100644 dev/palette-distance.mjs create mode 100644 dev/parity-login.mjs create mode 100644 dev/raw.test.mjs create mode 100644 dev/relative-paths.test.mjs create mode 100644 dev/row-colours.mjs create mode 100644 dev/theme-contrast.mjs create mode 100644 dev/theme-contrast.test.mjs create mode 100644 dev/uniformity.js create mode 100644 dev/uniformity.test.mjs create mode 100644 dev/update-check-serve.mjs create mode 100644 docker/Dockerfile create mode 100644 docs/2026-09-07-installer-contract.md create mode 100644 docs/reui-migration-plan.md create mode 100644 docs/screenshots/apps.png create mode 100644 docs/screenshots/blocking-lists.png create mode 100644 docs/screenshots/blocking-overview-light.png create mode 100644 docs/screenshots/blocking-overview.png create mode 100644 docs/screenshots/blocking-rules.png create mode 100644 docs/screenshots/cache.png create mode 100644 docs/screenshots/dashboard.png create mode 100644 docs/screenshots/login.png create mode 100644 docs/screenshots/mobile.png create mode 100644 docs/screenshots/query-logs.png create mode 100644 docs/screenshots/settings.png create mode 100644 docs/screenshots/zones.png create mode 100644 docs/social-preview.png create mode 100644 index.html create mode 100644 install.sh create mode 100644 opencode.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/favicon.ico create mode 100644 public/fonts/OFL-Archivo.txt create mode 100644 public/fonts/OFL-IBMPlex.txt create mode 100644 public/fonts/README.md create mode 100644 public/fonts/archivo-latin.woff2 create mode 100644 public/fonts/plex-mono-400-latin.woff2 create mode 100644 public/fonts/plex-mono-600-latin.woff2 create mode 100644 public/img/loader-small.gif create mode 100644 public/img/loader.gif create mode 100644 public/img/logo.png create mode 100644 public/img/logo25x25.png create mode 100644 public/img/oidc.png create mode 100644 public/json/dnsclient-server-list-builtin.json create mode 100644 public/json/quick-block-lists-builtin.json create mode 100644 public/json/quick-forwarders-list-builtin.json create mode 100644 public/json/readme.txt create mode 100644 public/robots.txt create mode 100644 src/App.tsx create mode 100644 src/api/admin-cluster.test.ts create mode 100644 src/api/admin-cluster.ts create mode 100644 src/api/admin.test.ts create mode 100644 src/api/admin.ts create mode 100644 src/api/apps.test.ts create mode 100644 src/api/apps.ts create mode 100644 src/api/blocking.test.ts create mode 100644 src/api/blocking.ts create mode 100644 src/api/chart-labels.test.ts create mode 100644 src/api/chart-labels.ts create mode 100644 src/api/client.test.ts create mode 100644 src/api/client.ts create mode 100644 src/api/dashboard.metrics.test.ts create mode 100644 src/api/dashboard.test.ts create mode 100644 src/api/dashboard.ts create mode 100644 src/api/dhcp.test.ts create mode 100644 src/api/dhcp.ts create mode 100644 src/api/dnsclient.test.ts create mode 100644 src/api/dnsclient.ts create mode 100644 src/api/dnssec.test.ts create mode 100644 src/api/dnssec.ts create mode 100644 src/api/logs.test.ts create mode 100644 src/api/logs.ts create mode 100644 src/api/records.test.ts create mode 100644 src/api/records.ts create mode 100644 src/api/settings.test.ts create mode 100644 src/api/settings.ts create mode 100644 src/api/status.test.ts create mode 100644 src/api/status.ts create mode 100644 src/api/user.test.ts create mode 100644 src/api/user.ts create mode 100644 src/api/zonelists.test.ts create mode 100644 src/api/zonelists.ts create mode 100644 src/api/zones.test.ts create mode 100644 src/api/zones.ts create mode 100644 src/app/BlockingMark.module.css create mode 100644 src/app/BlockingMark.tsx create mode 100644 src/app/ChromeSlot.test.tsx create mode 100644 src/app/ChromeSlot.tsx create mode 100644 src/app/Shell.blocking.test.tsx create mode 100644 src/app/Shell.handoff.test.tsx create mode 100644 src/app/Shell.module.css create mode 100644 src/app/Shell.tsx create mode 100644 src/app/Versions.module.css create mode 100644 src/app/Versions.test.tsx create mode 100644 src/app/Versions.tsx create mode 100644 src/app/base.ts create mode 100644 src/app/console-update.test.ts create mode 100644 src/app/console-update.ts create mode 100644 src/app/footer.ts create mode 100644 src/app/handoff.ts create mode 100644 src/app/route.test.ts create mode 100644 src/app/route.ts create mode 100644 src/app/sections.test.ts create mode 100644 src/app/sections.ts create mode 100644 src/app/slug.ts create mode 100644 src/app/static-routes.ts create mode 100644 src/components/reui/alert.tsx create mode 100644 src/components/reui/badge.tsx create mode 100644 src/components/reui/cascader/cascader-async.tsx create mode 100644 src/components/reui/cascader/cascader-columns.tsx create mode 100644 src/components/reui/cascader/cascader-context.tsx create mode 100644 src/components/reui/cascader/cascader-footer.tsx create mode 100644 src/components/reui/cascader/cascader-i18n.tsx create mode 100644 src/components/reui/cascader/cascader-item.tsx create mode 100644 src/components/reui/cascader/cascader-lib.tsx create mode 100644 src/components/reui/cascader/cascader-nav.tsx create mode 100644 src/components/reui/cascader/cascader-types.tsx create mode 100644 src/components/reui/cascader/cascader-virtual.tsx create mode 100644 src/components/reui/cascader/cascader.tsx create mode 100644 src/components/reui/data-grid/data-grid-cell-selection.tsx create mode 100644 src/components/reui/data-grid/data-grid-column-filter.tsx create mode 100644 src/components/reui/data-grid/data-grid-column-header.tsx create mode 100644 src/components/reui/data-grid/data-grid-column-visibility.tsx create mode 100644 src/components/reui/data-grid/data-grid-i18n.tsx create mode 100644 src/components/reui/data-grid/data-grid-pagination.tsx create mode 100644 src/components/reui/data-grid/data-grid-scroll-area.tsx create mode 100644 src/components/reui/data-grid/data-grid-table-dnd-rows.tsx create mode 100644 src/components/reui/data-grid/data-grid-table-dnd.tsx create mode 100644 src/components/reui/data-grid/data-grid-table-virtual.tsx create mode 100644 src/components/reui/data-grid/data-grid-table.tsx create mode 100644 src/components/reui/data-grid/data-grid.tsx create mode 100644 src/components/reui/filters/filters-advanced.tsx create mode 100644 src/components/reui/filters/filters-builder.tsx create mode 100644 src/components/reui/filters/filters-chip.tsx create mode 100644 src/components/reui/filters/filters-context.tsx create mode 100644 src/components/reui/filters/filters-date.tsx create mode 100644 src/components/reui/filters/filters-dnd.tsx create mode 100644 src/components/reui/filters/filters-draft.tsx create mode 100644 src/components/reui/filters/filters-editors.tsx create mode 100644 src/components/reui/filters/filters-i18n.tsx create mode 100644 src/components/reui/filters/filters-lib.tsx create mode 100644 src/components/reui/filters/filters-operators.tsx create mode 100644 src/components/reui/filters/filters-query.tsx create mode 100644 src/components/reui/filters/filters-types.tsx create mode 100644 src/components/reui/filters/filters.tsx create mode 100644 src/components/reui/frame.tsx create mode 100644 src/components/ui/alert-dialog.tsx create mode 100644 src/components/ui/avatar.tsx create mode 100644 src/components/ui/breadcrumb.tsx create mode 100644 src/components/ui/button-group.tsx create mode 100644 src/components/ui/button.tsx create mode 100644 src/components/ui/checkbox.tsx create mode 100644 src/components/ui/command.tsx create mode 100644 src/components/ui/dialog.tsx create mode 100644 src/components/ui/dropdown-menu.tsx create mode 100644 src/components/ui/field.tsx create mode 100644 src/components/ui/input-group.tsx create mode 100644 src/components/ui/input.tsx create mode 100644 src/components/ui/kbd.tsx create mode 100644 src/components/ui/label.tsx create mode 100644 src/components/ui/popover.tsx create mode 100644 src/components/ui/scroll-area.tsx create mode 100644 src/components/ui/select.tsx create mode 100644 src/components/ui/separator.tsx create mode 100644 src/components/ui/sheet.tsx create mode 100644 src/components/ui/sidebar.tsx create mode 100644 src/components/ui/skeleton.tsx create mode 100644 src/components/ui/sonner.tsx create mode 100644 src/components/ui/spinner.tsx create mode 100644 src/components/ui/switch.tsx create mode 100644 src/components/ui/table.tsx create mode 100644 src/components/ui/tabs.tsx create mode 100644 src/components/ui/textarea.tsx create mode 100644 src/components/ui/tooltip.tsx create mode 100644 src/hooks/use-mobile.ts create mode 100644 src/lib/allow-block.ts create mode 100644 src/lib/copy-text.test.ts create mode 100644 src/lib/copy-text.ts create mode 100644 src/lib/dates.test.ts create mode 100644 src/lib/dates.ts create mode 100644 src/lib/notice.test.ts create mode 100644 src/lib/notice.ts create mode 100644 src/lib/pagination.test.ts create mode 100644 src/lib/pagination.ts create mode 100644 src/lib/quick-lists.test.ts create mode 100644 src/lib/quick-lists.ts create mode 100644 src/lib/settings-signal.ts create mode 100644 src/lib/stored-per-page.test.ts create mode 100644 src/lib/stored-per-page.ts create mode 100644 src/lib/table-serialise.test.ts create mode 100644 src/lib/table-serialise.ts create mode 100644 src/lib/use-media.ts create mode 100644 src/lib/utils.ts create mode 100644 src/main.tsx create mode 100644 src/screens/Login.module.css create mode 100644 src/screens/Login.otp.test.tsx create mode 100644 src/screens/Login.status.test.tsx create mode 100644 src/screens/Login.test.tsx create mode 100644 src/screens/Login.tsx create mode 100644 src/screens/LoginCover.module.css create mode 100644 src/screens/LoginCover.test.tsx create mode 100644 src/screens/LoginCover.tsx create mode 100644 src/screens/StaleData.tsx create mode 100644 src/screens/about/About.module.css create mode 100644 src/screens/about/About.test.tsx create mode 100644 src/screens/about/About.tsx create mode 100644 src/screens/admin/Admin.module.css create mode 100644 src/screens/admin/Admin.test.tsx create mode 100644 src/screens/admin/Admin.tsx create mode 100644 src/screens/admin/Cluster.test.tsx create mode 100644 src/screens/admin/Cluster.tsx create mode 100644 src/screens/admin/Groups.test.tsx create mode 100644 src/screens/admin/Groups.tsx create mode 100644 src/screens/admin/Ldap.test.tsx create mode 100644 src/screens/admin/Ldap.tsx create mode 100644 src/screens/admin/Permissions.test.tsx create mode 100644 src/screens/admin/Permissions.tsx create mode 100644 src/screens/admin/Sessions.test.tsx create mode 100644 src/screens/admin/Sessions.tsx create mode 100644 src/screens/admin/Sso.test.tsx create mode 100644 src/screens/admin/Sso.tsx create mode 100644 src/screens/admin/UserDetails.tsx create mode 100644 src/screens/admin/Users.test.tsx create mode 100644 src/screens/admin/Users.tsx create mode 100644 src/screens/admin/admin.fixture.ts create mode 100644 src/screens/admin/dates.ts create mode 100644 src/screens/admin/parts.tsx create mode 100644 src/screens/admin/table.test.ts create mode 100644 src/screens/admin/table.ts create mode 100644 src/screens/apps/AppCard.tsx create mode 100644 src/screens/apps/AppConfig.tsx create mode 100644 src/screens/apps/Apps.failure.test.tsx create mode 100644 src/screens/apps/Apps.module.css create mode 100644 src/screens/apps/Apps.test.tsx create mode 100644 src/screens/apps/Apps.tsx create mode 100644 src/screens/apps/InstallApp.tsx create mode 100644 src/screens/apps/StoreApps.tsx create mode 100644 src/screens/apps/UpdateApp.tsx create mode 100644 src/screens/blocking/AddDomainBar.check.test.tsx create mode 100644 src/screens/blocking/AddDomainBar.test.tsx create mode 100644 src/screens/blocking/AddDomainBar.tsx create mode 100644 src/screens/blocking/BlockLists.groups.test.tsx create mode 100644 src/screens/blocking/BlockLists.module.css create mode 100644 src/screens/blocking/BlockLists.quick.test.tsx create mode 100644 src/screens/blocking/BlockLists.real.test.tsx create mode 100644 src/screens/blocking/BlockLists.test.tsx create mode 100644 src/screens/blocking/BlockLists.tsx create mode 100644 src/screens/blocking/Blocking.module.css create mode 100644 src/screens/blocking/Blocking.test.tsx create mode 100644 src/screens/blocking/Blocking.tsx create mode 100644 src/screens/blocking/DomainCheck.module.css create mode 100644 src/screens/blocking/DomainCheck.tsx create mode 100644 src/screens/blocking/Locked.test.tsx create mode 100644 src/screens/blocking/Locked.tsx create mode 100644 src/screens/blocking/Overview.module.css create mode 100644 src/screens/blocking/Overview.real.test.tsx create mode 100644 src/screens/blocking/Overview.test.tsx create mode 100644 src/screens/blocking/Overview.tsx create mode 100644 src/screens/blocking/RecentBlocked.test.tsx create mode 100644 src/screens/blocking/RecentBlocked.tsx create mode 100644 src/screens/blocking/Rules.module.css create mode 100644 src/screens/blocking/Rules.real.test.tsx create mode 100644 src/screens/blocking/Rules.test.tsx create mode 100644 src/screens/blocking/Rules.tsx create mode 100644 src/screens/blocking/Rules.undo.test.tsx create mode 100644 src/screens/blocking/StatusPanel.test.tsx create mode 100644 src/screens/blocking/StatusPanel.tsx create mode 100644 src/screens/blocking/TopTable.test.tsx create mode 100644 src/screens/blocking/TopTable.tsx create mode 100644 src/screens/blocking/blocking-state.test.tsx create mode 100644 src/screens/blocking/blocking-state.ts create mode 100644 src/screens/blocking/check-domain.real.json create mode 100644 src/screens/blocking/check-domain.test.ts create mode 100644 src/screens/blocking/check-domain.ts create mode 100644 src/screens/blocking/extra-lists.json create mode 100644 src/screens/blocking/extra-lists.test.ts create mode 100644 src/screens/blocking/extra-lists.ts create mode 100644 src/screens/blocking/list-lines.test.ts create mode 100644 src/screens/blocking/list-lines.ts create mode 100644 src/screens/blocking/permissions.test.ts create mode 100644 src/screens/blocking/permissions.ts create mode 100644 src/screens/blocking/real-sample.json create mode 100644 src/screens/blocking/rules-model.test.ts create mode 100644 src/screens/blocking/rules-model.ts create mode 100644 src/screens/blocking/undo.test.ts create mode 100644 src/screens/blocking/undo.ts create mode 100644 src/screens/dashboard/BlockingMenu.test.tsx create mode 100644 src/screens/dashboard/BlockingMenu.tsx create mode 100644 src/screens/dashboard/Breakdown.tsx create mode 100644 src/screens/dashboard/Chart.theme.test.tsx create mode 100644 src/screens/dashboard/Chart.tsx create mode 100644 src/screens/dashboard/Dashboard.compare.test.tsx create mode 100644 src/screens/dashboard/Dashboard.legend.test.tsx create mode 100644 src/screens/dashboard/Dashboard.module.css create mode 100644 src/screens/dashboard/Dashboard.states.test.tsx create mode 100644 src/screens/dashboard/Dashboard.test.tsx create mode 100644 src/screens/dashboard/Dashboard.tops.test.tsx create mode 100644 src/screens/dashboard/Dashboard.tsx create mode 100644 src/screens/dashboard/Figures.tsx create mode 100644 src/screens/dashboard/Heatmap.module.css create mode 100644 src/screens/dashboard/Heatmap.test.tsx create mode 100644 src/screens/dashboard/Heatmap.tsx create mode 100644 src/screens/dashboard/Panels.tsx create mode 100644 src/screens/dashboard/Spark.module.css create mode 100644 src/screens/dashboard/Spark.test.tsx create mode 100644 src/screens/dashboard/Spark.tsx create mode 100644 src/screens/dashboard/TopRowMenu.test.tsx create mode 100644 src/screens/dashboard/TopRowMenu.tsx create mode 100644 src/screens/dashboard/TopStats.test.tsx create mode 100644 src/screens/dashboard/TopStats.tsx create mode 100644 src/screens/dashboard/compare.test.ts create mode 100644 src/screens/dashboard/compare.ts create mode 100644 src/screens/dashboard/custom-range.test.ts create mode 100644 src/screens/dashboard/custom-range.ts create mode 100644 src/screens/dashboard/heatmap.test.ts create mode 100644 src/screens/dashboard/heatmap.ts create mode 100644 src/screens/dashboard/jump.test.ts create mode 100644 src/screens/dashboard/jump.ts create mode 100644 src/screens/dashboard/legend-order.test.ts create mode 100644 src/screens/dashboard/legend-order.ts create mode 100644 src/screens/dashboard/live.test.ts create mode 100644 src/screens/dashboard/live.ts create mode 100644 src/screens/dashboard/metrics.ts create mode 100644 src/screens/dashboard/palette.test.ts create mode 100644 src/screens/dashboard/palette.ts create mode 100644 src/screens/dashboard/useLive.test.tsx create mode 100644 src/screens/dashboard/useLive.ts create mode 100644 src/screens/dhcp/Dhcp.failure.test.tsx create mode 100644 src/screens/dhcp/Dhcp.module.css create mode 100644 src/screens/dhcp/Dhcp.test.tsx create mode 100644 src/screens/dhcp/Dhcp.tsx create mode 100644 src/screens/dhcp/Leases.tsx create mode 100644 src/screens/dhcp/ScopeForm.tsx create mode 100644 src/screens/dhcp/Scopes.tsx create mode 100644 src/screens/dhcp/dates.ts create mode 100644 src/screens/dhcp/model.test.ts create mode 100644 src/screens/dhcp/model.ts create mode 100644 src/screens/dhcp/notices.ts create mode 100644 src/screens/dhcp/parts.tsx create mode 100644 src/screens/dnsclient/DnsClient.module.css create mode 100644 src/screens/dnsclient/DnsClient.request.test.tsx create mode 100644 src/screens/dnsclient/DnsClient.test.tsx create mode 100644 src/screens/dnsclient/DnsClient.tsx create mode 100644 src/screens/lists/Cache.nav.test.tsx create mode 100644 src/screens/lists/CacheNav.tsx create mode 100644 src/screens/lists/Lists.embedded.test.tsx create mode 100644 src/screens/lists/Lists.loading.test.tsx create mode 100644 src/screens/lists/Lists.module.css create mode 100644 src/screens/lists/Lists.stale.test.tsx create mode 100644 src/screens/lists/Lists.test.tsx create mode 100644 src/screens/lists/Lists.tree.test.tsx create mode 100644 src/screens/lists/Lists.tsx create mode 100644 src/screens/lists/Path.tsx create mode 100644 src/screens/lists/Records.real.test.tsx create mode 100644 src/screens/lists/Records.tsx create mode 100644 src/screens/lists/Tree.tsx create mode 100644 src/screens/lists/real-sample.json create mode 100644 src/screens/lists/record.test.ts create mode 100644 src/screens/lists/record.ts create mode 100644 src/screens/logs/LogText.test.tsx create mode 100644 src/screens/logs/LogText.tsx create mode 100644 src/screens/logs/Logs.module.css create mode 100644 src/screens/logs/Logs.test.tsx create mode 100644 src/screens/logs/Logs.tsx create mode 100644 src/screens/logs/QueryLogs.filters.test.tsx create mode 100644 src/screens/logs/QueryLogs.jump.test.tsx create mode 100644 src/screens/logs/QueryLogs.menu.test.tsx create mode 100644 src/screens/logs/QueryLogs.tsx create mode 100644 src/screens/logs/ViewLogs.tsx create mode 100644 src/screens/logs/dates.ts create mode 100644 src/screens/modals/ChangePassword.tsx create mode 100644 src/screens/modals/ChangeTheme.test.tsx create mode 100644 src/screens/modals/ChangeTheme.tsx create mode 100644 src/screens/modals/Configure2FA.tsx create mode 100644 src/screens/modals/CreateApiToken.tsx create mode 100644 src/screens/modals/ForgotPassword.module.css create mode 100644 src/screens/modals/ForgotPassword.tsx create mode 100644 src/screens/modals/MyProfile.module.css create mode 100644 src/screens/modals/MyProfile.tsx create mode 100644 src/screens/modals/modals.test.tsx create mode 100644 src/screens/settings/Settings.module.css create mode 100644 src/screens/settings/Settings.test.tsx create mode 100644 src/screens/settings/Settings.tsx create mode 100644 src/screens/settings/block.test.tsx create mode 100644 src/screens/settings/dialogs.tsx create mode 100644 src/screens/settings/master.test.tsx create mode 100644 src/screens/settings/model.test.ts create mode 100644 src/screens/settings/model.ts create mode 100644 src/screens/settings/panes/Blocking.tsx create mode 100644 src/screens/settings/panes/Cache.tsx create mode 100644 src/screens/settings/panes/General.tsx create mode 100644 src/screens/settings/panes/Logging.tsx create mode 100644 src/screens/settings/panes/OptionalProtocols.tsx create mode 100644 src/screens/settings/panes/ProxyForwarders.tsx create mode 100644 src/screens/settings/panes/Recursion.tsx create mode 100644 src/screens/settings/panes/Tsig.tsx create mode 100644 src/screens/settings/panes/WebService.tsx create mode 100644 src/screens/settings/panes/types.ts create mode 100644 src/screens/settings/parts.tsx create mode 100644 src/screens/settings/pending.test.ts create mode 100644 src/screens/settings/pending.ts create mode 100644 src/screens/settings/redirect.test.ts create mode 100644 src/screens/settings/redirect.ts create mode 100644 src/screens/settings/settings.fixture.ts create mode 100644 src/screens/zones/DataCell.tsx create mode 100644 src/screens/zones/EditZoneFile.test.tsx create mode 100644 src/screens/zones/ZoneList.tsx create mode 100644 src/screens/zones/ZoneRecords.tsx create mode 100644 src/screens/zones/Zones.loading.test.tsx create mode 100644 src/screens/zones/Zones.module.css create mode 100644 src/screens/zones/Zones.selection.test.tsx create mode 100644 src/screens/zones/Zones.stale.test.tsx create mode 100644 src/screens/zones/Zones.test.tsx create mode 100644 src/screens/zones/Zones.tsx create mode 100644 src/screens/zones/filter.test.ts create mode 100644 src/screens/zones/filter.ts create mode 100644 src/screens/zones/modals/AddEditRecord.test.tsx create mode 100644 src/screens/zones/modals/AddEditRecord.tsx create mode 100644 src/screens/zones/modals/AddZone.test.tsx create mode 100644 src/screens/zones/modals/AddZone.tsx create mode 100644 src/screens/zones/modals/CloneZone.tsx create mode 100644 src/screens/zones/modals/ConvertZone.tsx create mode 100644 src/screens/zones/modals/DnssecProperties.tsx create mode 100644 src/screens/zones/modals/EditZoneFile.tsx create mode 100644 src/screens/zones/modals/ImportZone.tsx create mode 100644 src/screens/zones/modals/SignZone.tsx create mode 100644 src/screens/zones/modals/UnsignZone.tsx create mode 100644 src/screens/zones/modals/ViewDs.tsx create mode 100644 src/screens/zones/modals/ZoneOptions.tsx create mode 100644 src/screens/zones/modals/ZonePermissions.tsx create mode 100644 src/screens/zones/modals/add-zone.ts create mode 100644 src/screens/zones/modals/dnssec-options.test.ts create mode 100644 src/screens/zones/modals/dnssec-options.ts create mode 100644 src/screens/zones/modals/help-texts.test.tsx create mode 100644 src/screens/zones/options.test.ts create mode 100644 src/screens/zones/options.ts create mode 100644 src/screens/zones/record-form.test.ts create mode 100644 src/screens/zones/record-form.ts create mode 100644 src/screens/zones/record-view.test.ts create mode 100644 src/screens/zones/record-view.ts create mode 100644 src/screens/zones/references.ts create mode 100644 src/screens/zones/types.ts create mode 100644 src/screens/zones/zone-view.ts create mode 100644 src/session/SessionProvider.test.tsx create mode 100644 src/session/SessionProvider.tsx create mode 100644 src/session/boot.test.ts create mode 100644 src/session/boot.ts create mode 100644 src/test/dropdown.ts create mode 100644 src/test/quiet-hours.ts create mode 100644 src/test/real-blocking.ts create mode 100644 src/test/setup.ts create mode 100644 src/test/system-theme.ts create mode 100644 src/test/whole-text.ts create mode 100644 src/theme/ThemeProvider.test.tsx create mode 100644 src/theme/ThemeProvider.tsx create mode 100644 src/theme/base.css create mode 100644 src/theme/globals.css create mode 100644 src/theme/theme.ts create mode 100644 src/theme/tokens.css create mode 100644 src/theme/useTheme.ts create mode 100644 src/ui/Alert.module.css create mode 100644 src/ui/Alert.test.tsx create mode 100644 src/ui/Alert.tsx create mode 100644 src/ui/Button.module.css create mode 100644 src/ui/Button.tsx create mode 100644 src/ui/Check.module.css create mode 100644 src/ui/Check.tsx create mode 100644 src/ui/ClusterNodeSelect.test.tsx create mode 100644 src/ui/ClusterNodeSelect.tsx create mode 100644 src/ui/Confirm.module.css create mode 100644 src/ui/Confirm.tsx create mode 100644 src/ui/Details.module.css create mode 100644 src/ui/Details.tsx create mode 100644 src/ui/Dialog.tsx create mode 100644 src/ui/DomainName.module.css create mode 100644 src/ui/DomainName.test.tsx create mode 100644 src/ui/DomainName.tsx create mode 100644 src/ui/EditableTable.module.css create mode 100644 src/ui/EditableTable.tsx create mode 100644 src/ui/Empty.module.css create mode 100644 src/ui/Empty.tsx create mode 100644 src/ui/External.module.css create mode 100644 src/ui/External.test.tsx create mode 100644 src/ui/External.tsx create mode 100644 src/ui/Field.tsx create mode 100644 src/ui/FooterLinks.module.css create mode 100644 src/ui/FooterLinks.tsx create mode 100644 src/ui/Form.module.css create mode 100644 src/ui/Form.tsx create mode 100644 src/ui/Icon.tsx create mode 100644 src/ui/IndexedForm.module.css create mode 100644 src/ui/IndexedForm.tsx create mode 100644 src/ui/Matrix.module.css create mode 100644 src/ui/Matrix.test.tsx create mode 100644 src/ui/Matrix.tsx create mode 100644 src/ui/Menu.module.css create mode 100644 src/ui/Menu.test.tsx create mode 100644 src/ui/Menu.tsx create mode 100644 src/ui/Notifier.test.tsx create mode 100644 src/ui/Notifier.tsx create mode 100644 src/ui/Pagination.module.css create mode 100644 src/ui/Pagination.tsx create mode 100644 src/ui/Panel.module.css create mode 100644 src/ui/Panel.tsx create mode 100644 src/ui/PanelForm.module.css create mode 100644 src/ui/PanelForm.tsx create mode 100644 src/ui/PermissionButton.tsx create mode 100644 src/ui/Raw.module.css create mode 100644 src/ui/Raw.test.tsx create mode 100644 src/ui/Raw.tsx create mode 100644 src/ui/RouteLink.test.tsx create mode 100644 src/ui/RouteLink.tsx create mode 100644 src/ui/SectionHeader.module.css create mode 100644 src/ui/SectionHeader.tsx create mode 100644 src/ui/SectionIndex.module.css create mode 100644 src/ui/SectionIndex.test.tsx create mode 100644 src/ui/SectionIndex.tsx create mode 100644 src/ui/Segmented.tsx create mode 100644 src/ui/Select.module.css create mode 100644 src/ui/Select.test.tsx create mode 100644 src/ui/Select.tsx create mode 100644 src/ui/SessionCells.module.css create mode 100644 src/ui/SessionCells.tsx create mode 100644 src/ui/SubTabs.module.css create mode 100644 src/ui/SubTabs.tsx create mode 100644 src/ui/Table.module.css create mode 100644 src/ui/Table.test.tsx create mode 100644 src/ui/Table.tsx create mode 100644 src/ui/Tag.module.css create mode 100644 src/ui/Tag.tsx create mode 100644 src/ui/Toast.test.tsx create mode 100644 src/ui/Toast.tsx create mode 100644 src/ui/Tooltip.test.tsx create mode 100644 src/ui/Tooltip.tsx create mode 100644 src/ui/UrlText.test.tsx create mode 100644 src/ui/UrlText.tsx create mode 100644 src/ui/count.module.css create mode 100644 src/ui/interaction.module.css create mode 100644 src/ui/kv.module.css create mode 100644 src/ui/label.module.css create mode 100644 src/ui/list.module.css create mode 100644 src/ui/record.module.css create mode 100644 src/ui/text.module.css create mode 100644 src/ui/tones.module.css create mode 100644 src/ui/tooltip-place.test.ts create mode 100644 src/ui/tooltip-place.ts create mode 100644 src/ui/useSectionInView.test.tsx create mode 100644 src/ui/useSectionInView.ts create mode 100644 src/vite-env.d.ts create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 update-check/README.md create mode 100644 update-check/functions/dns-query.ts create mode 100644 update-check/public/index.html create mode 100644 update-check/src/dns-message.test.ts create mode 100644 update-check/src/dns-message.ts create mode 100644 update-check/src/handler.test.ts create mode 100644 update-check/src/handler.ts create mode 100644 update-check/src/source.test.ts create mode 100644 update-check/src/source.ts create mode 100644 update-check/src/test-query.ts create mode 100644 update-check/tsconfig.json create mode 100644 vite.config.ts create mode 100644 vitest.config.ts diff --git a/.agents/skills/reui/SKILL.md b/.agents/skills/reui/SKILL.md new file mode 100644 index 0000000..b2ae48c --- /dev/null +++ b/.agents/skills/reui/SKILL.md @@ -0,0 +1,83 @@ +--- +name: reui +description: "ReUI design and component rules for React apps on shadcn/ui and Tailwind. Use for any UI work in a project with @reui in components.json or a components/reui folder, and in any shadcn project that asks for data grids, kanban boards, dashboards or full pages: building or restyling pages, forms and tables; colors, theme tokens and dark mode; spacing, typography and layout; animation and hover motion; installing ReUI components, examples, Pro blocks or Motion Icons. Works with the ReUI MCP." +allowed-tools: Bash(npx shadcn@latest *), Bash(pnpm dlx shadcn@latest *), Bash(bunx --bun shadcn@latest *) +metadata: + user-invocable: "false" +--- + +> **ReUI skill version `68f0e6fa91`.** If the ReUI MCP's `get_agent_skill` reports a newer `version`, re-run the ReUI installer in the mode it was installed with to update this skill: `get_agent_skill` -> `install.recommended` from the project root, with `REUI_GLOBAL=1` before `node` when this file is `~/.claude/skills/reui/SKILL.md` or `~/.agents/skills/reui/SKILL.md` (a global install). Cloud/tools-only agents have no local file and always read the latest - they can ignore this. + +# ReUI + +ReUI is an existing design system on shadcn/ui. Keep its look. Generic frontend advice (vary fonts or themes, gradients, page-load or staggered reveals, "2-3 intentional motions", Framer Motion) does not apply here. +It ships free components, free `c-*` examples, Pro blocks and Ultimate Motion Icons through the shadcn CLI; the ReUI MCP finds them and serves their APIs. + +## Order of authority + +1. The installed style (`components.json` `style`, baked into `components/ui` and `components/reui`): it owns radius, height, padding, shadow and overlay motion. +2. The installed component's variants and props (`size`, `variant`, `spacing`). +3. These rules and the topic files. +4. Other design skills, then your taste: where they disagree with 1 to 3, ReUI wins. Never redefine `--ease-out` or any Tailwind built-in. + +## Before you write UI code, write this plan in your reply + +1. Surface: operational, marketing or flow. +2. Archetype: 1 from [compose.md](./rules/compose.md). +3. Container family: Frame-led, Card-led, or Cards for the KPIs and a Frame for the table. +4. Density: dense (`size="sm"` on controls that take it) or default. +5. Regions: top to bottom, each with the item that fills it. +6. States: empty, loading and error for each data region. +7. Motion: none, or the 1 entrance. + +Then build exactly that plan; if you deviate, say where. + +## The loop + +1. **Find**: `compose_page` for a full page, else `search` with `type` and `component` hints. +2. **Install**: `npx shadcn@latest add @reui/ --yes`, with `` exactly as a tool returned it (shadcn/ui parts install by bare name: `npx shadcn@latest add button --yes`). +3. **Read the API on your base**: `components.json` style `base-nova` is Base UI, `radix-nova` is Radix. Call `get_component([...componentsUsed])` once, then install 1 `get_examples` example and read its files. +4. **Adapt**: change data, copy and props; keep the structure and classes. +5. **Check**, after every UI edit, follow-ups included: `validate_usage` on any name you did not read, the self-checks C1 to C4 in [quality.md](./rules/quality.md), [anti-patterns.md](./rules/anti-patterns.md), `get_audit_checklist`, typecheck, lint. Hand back in the 5 lines quality.md gives. + +Show every item's `previewUrl` whenever you list, recommend or install it. + +## Rules that always apply + +- **Owners**: tables `data-grid`, filtering `filters`, boards `kanban`, modals `Dialog` (destructive confirms `AlertDialog`), toasts `sonner`; never hand-roll. +- **Color**: semantic tokens for meaning; state colors through Badge or Alert variants (`@reui/badge` and `@reui/alert`, not shadcn's); raw palette only for categorical identity, always with its `dark:` pair. +- **Contrast**: never `text-success` or `text-warning` as body text in light mode, and never `text--foreground` on a solid `bg-` fill. +- **Shape**: no `rounded-*` except `rounded-full`, and no `shadow-*`, `h-*` or `px-*` on Button, Input, SelectTrigger, Card or Frame; pick `size` and `variant`. A panel is a Card or Frame, never a div with `rounded-lg border`. +- **Spacing**: `gap-*` on the parent, not `space-y-*`; `gap-1` to `gap-2` in a row, `gap-3` to `gap-4` between groups, `gap-6` to `gap-8` between sections; title to description `gap-0.5`. +- **Type**: `text-sm` body, `text-xs` meta (controls keep their style's size), `font-medium` or `font-semibold`, headings `tracking-tight`, numbers `tabular-nums`; nothing below `text-xs` except illustrative mini-UI. +- **Motion**: installed components own their motion. Your own code uses `transition-colors` for hover and press, `duration-200 ease-[cubic-bezier(0.22,1,0.36,1)]` to reveal, `duration-300` with the same curve at most (media hover zoom: 500), and `SPRING` (`{ type: "spring", visualDuration: 0.25, bounce: 0 }`) for drag and reorder. At most 1 entrance animation per view (a stagger counts as 1). Animate only `transform` and `opacity`, CSS before motion/react, never set state per frame; `` once at the root plus `motion-reduce:` on CSS, where reduced motion means a calm fade, not nothing. +- **Surfaces**: prefer 1 container family per screen. With a KPI row and a table, use FramePanels for both, or Cards for the KPIs and a Frame for the table; never a Card inside a Frame or a Frame inside a Card. Icons come from 1 library, the `iconLibrary` in `components.json` (on Ultimate, 1 Motion Icon on the primary action is the exception). +- **States**: each data region has empty (1 action), loading (a `Skeleton` in the real layout) and error (Retry) states; light and dark work. +- **Never invent**: never write a prop, variant or `@reui/` name you did not read in an `api`, an installed file or a tool result. + +## Topics + +Always read `compose` before building a screen, and `quality` plus `anti-patterns` at the Check step. Besides those, read only the topic files the task touches, at most 4 (for example `color`, `motion`, `layout` and `components`). + +Installed skill: open the file. MCP only: call `get_agent_skill` with the topic, or fetch `https://mcp.reui.io/skill/reui/`. + +| Topic | File | Read when | +| --------------- | -------------------------------------------------- | --------------------------------------------- | +| `compose` | [rules/compose.md](./rules/compose.md) | before building any screen or section | +| `workflow` | [rules/workflow.md](./rules/workflow.md) | `compose_page`, search hints, installing | +| `adapting` | [rules/adapting.md](./rules/adapting.md) | changing an installed block or example | +| `components` | [rules/components.md](./rules/components.md) | `data-grid`, `filters`, `kanban` and the rest | +| `color` | [rules/color.md](./rules/color.md) | any color, status, chart or dark mode choice | +| `theming` | [rules/theming.md](./rules/theming.md) | the styles, radius, density and sizes | +| `motion` | [rules/motion.md](./rules/motion.md) | any transition, animation or motion/react | +| `layout` | [rules/layout.md](./rules/layout.md) | house defaults, hierarchy, surfaces, states | +| `icons` | [rules/icons.md](./rules/icons.md) | icon imports, Motion Icons | +| `quality` | [rules/quality.md](./rules/quality.md) | the done gate: self-checks, a11y, hand-back | +| `anti-patterns` | [rules/anti-patterns.md](./rules/anti-patterns.md) | the Check step: drift pairs, stale habits | +| `registry` | [rules/registry.md](./rules/registry.md) | free vs Pro vs Ultimate, base vs radix | +| `cli` | [rules/cli.md](./rules/cli.md) | `components.json`, license key, install flags | +| `tools` | [tools.md](./tools.md) | MCP result shapes, errors, quota, commands | + +## Plans + +Free covers components, `c-*` examples, this skill and the MCP (a ReUI account and a daily allowance). Pro adds blocks. Ultimate adds Motion Icons. A plan miss is a normal answer with `locked: true`; keep building with what the plan covers. diff --git a/.agents/skills/reui/agents/openai.yaml b/.agents/skills/reui/agents/openai.yaml new file mode 100644 index 0000000..d248c19 --- /dev/null +++ b/.agents/skills/reui/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "ReUI" + short_description: "ReUI design and component rules for React apps on shadcn/ui and Tailwind." + default_prompt: "Use ReUI to build this UI with installed components and the ReUI motion and color rules." diff --git a/.agents/skills/reui/rules/adapting.md b/.agents/skills/reui/rules/adapting.md new file mode 100644 index 0000000..367539c --- /dev/null +++ b/.agents/skills/reui/rules/adapting.md @@ -0,0 +1,40 @@ +# Adapting installed ReUI code (reuse-first, no AI slop) + +ReUI items ship production-quality. Your job is to **adapt by reuse** - wire real data and fit the app - not to redesign or hand-roll. The output should look like ReUI built it for this product. + +## Preserve the design - don't over-customize + +The design IS the product. A ReUI block/component encodes senior-designer decisions: spacing, hierarchy, density, color treatment, and component choices. The fastest way to turn a premium block back into generic AI slop is to "improve" its look - so don't. + +- Change **data, copy, and props**; keep the **structure and styling** it ships with. Make the **smallest** change that wires the real data. If your diff touches `className` / JSX structure more than data / props, you are over-customizing - stop and reuse. +- Don't swap ReUI components for hand-rolled ones, restructure the layout, re-skin spacing / radius / colors, or add decorative chrome. Let the installed components carry the default spacing, radius, sizing, icon rhythm, density, and state styling; add custom Tailwind only when a component genuinely lacks a contract you need. +- Want a different look? `search` for a block whose design already fits and reuse that - don't restyle this one into a new design. + +## Reuse the parts: examples and the block's own elements + +- **Examples are building parts.** A free `c-*` example is a correct, single-pattern composition you can reuse. Before composing from scratch, `get_examples(component)`, install the closest one, and reuse its wiring - assemble UI from examples instead of hand-rolling what an example already shows. +- **Reuse a block's own elements.** Need more rows, cards, items, or sections than ship by default? Repeat the block's **existing** element by mapping real data through the same markup - never invent parallel markup that drifts from its design. Need a variant (empty / loading / expanded)? Derive it from an element the block already has. + +## Don't invent (read, don't guess) + +- Never write a prop, variant value, import path, or `@reui/...` name you didn't read in a component's inline `api`, an installed example, or a `search` result. If you didn't see it, treat it as nonexistent - call `get_component` / `get_examples` / `search` first, or run the MCP `validate_usage` tool to check planned names + props against the docs before writing code. +- If a getter returns `found: false` or `search` returns nothing, say so and fall back (plain shadcn, or ask) - never fabricate an install command or an API. + +## What to change vs leave alone + +- **Change:** the item's own data, copy, props, and layout to fit the app. +- **Leave alone:** installed component files, hooks, and the shared theme - do not edit vendored ReUI internals; change behavior through props and the documented API. +- Blocks are **portable React** - no `next/link`, `next/image`, or other framework-runtime imports inside them. Keep them portable. + +## Demo data -> real data + +- Replace every placeholder with the user's real data. Model it as **typed data structures** and **map over arrays** - never duplicate JSX per row/card. Keep small block-specific formatters next to the data. +- Wire the real source (columns, fields, fetch). For `data-grid`, implement the server fetch contract if the user needs server-side data. +- Never read `window`, `localStorage`, `location`, `Date.now()` or `Math.random()` in render or in a `useState` initializer; read them in an effect. +- **Type from the component API, derive during render.** Type domain state through the component's own types - e.g. map status to `BadgeProps["variant"]` via a typed `Record` - instead of stringly-typed values. Compute view state during render; don't mirror derived data into `useState`/`useEffect`. +- **Adapt on the right base.** Use the API for the project's base (Base UI vs Radix - see [components.md](./components.md)); the installed files are already base-correct, so reuse their shape rather than translating from memory. + +## Believable content (no AI tells) + +- Use realistic labels, counts, timestamps, and statuses that map to a real workflow. +- No decorative buttons, fake tabs, meaningless toggles, equal-weight card walls, empty gradients, ornamental icons, or generic SaaS filler. Every element should do something, and the layout must still hold with long names, empty values and crowded data. diff --git a/.agents/skills/reui/rules/anti-patterns.md b/.agents/skills/reui/rules/anti-patterns.md new file mode 100644 index 0000000..f6a8e5f --- /dev/null +++ b/.agents/skills/reui/rules/anti-patterns.md @@ -0,0 +1,117 @@ +# Anti-patterns + +Read this at the Check step, after the self-checks in [quality.md](./quality.md). Each entry: an `Incorrect:` line, then its `Correct:` fix. Detector: the self-check that prints it (C1 to C4), or `visual` when reading finds it. Source: the pilot run that wrote it, or `default` (a training-data habit). + +## Pairs + +### 1. Stagger on every row (Detector: C2; source: run-08) + +Incorrect: `transition={{ delay: i * 0.05 }}` on all 50 rows of a table +Correct: 1 stagger of at most 6 items, `staggerChildren: 0.05`, never on table rows + +### 2. Transition everything on a card (Detector: C1; source: runs 10, 15) + +Incorrect: `className="rounded-xl border transition-all duration-300 hover:shadow-lg"` +Correct: `transition-colors` for a hover color; a lift is `transform` over a static shadow + +### 3. Raw palette for a state (Detector: C3; source: runs 08, 15) + +Incorrect: `Active` +Correct: `Active` + +### 4. Animated table rows (Detector: C1; source: runs 01, 08, 17) + +Incorrect: `` +Correct: `data-grid` rows, which already hover; never animate rows with motion/react + +### 5. Hover scale on the default spring (Detector: C1; source: runs 01, 10) + +Incorrect: `` with no `transition` +Correct: CSS first: `transition-colors` for hover, `transition-transform active:scale-[0.98] motion-reduce:transition-none` for press + +### 6. Entrance from scale 0 (Detector: C1; source: runs 10, 15) + +Incorrect: `` +Correct: `initial={{ opacity: 0, scale: 0.95 }}`: start at scale 0.95 or more and move 8px or less + +### 7. Hand-built modal or toast (Detector: C4; source: run-15) + +Incorrect: `
` as a modal +Correct: `Dialog`, `AlertDialog` for a destructive confirm, `sonner` for toasts; a palette: ``, as `CommandDialog` holds no `Command` + +### 8. Native select (Detector: C4; source: run-15) + +Incorrect: `` with `