@godxjp/ui-mcp 0.19.1 → 0.20.0
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.
- package/README.md +2 -2
- package/dist/index.js +284 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ MCP-aware agent live access to:
|
|
|
7
7
|
- 80+ component catalog (props, types, defaults, examples)
|
|
8
8
|
- 14 shared prop-vocabulary types (`SizeProp`, `ColorProp`, `LoadingProp`, …)
|
|
9
9
|
- 48 design tokens across the primitive / semantic / component tiers
|
|
10
|
-
-
|
|
10
|
+
- 42 cardinal rules from `CLAUDE.md`
|
|
11
11
|
- 9 canonical copy-paste-ready patterns (sign-up, settings, data-table, …)
|
|
12
12
|
- 15 design skills, each tagged by **audience** — 12 taste-family (taste / soft / minimalist /
|
|
13
13
|
brutalist / gpt-tasteskill / redesign / output / brandkit / stitch / imagegen-mobile /
|
|
@@ -270,7 +270,7 @@ consumer/core guides are framework-native.
|
|
|
270
270
|
| `godx-ui://prop-vocabulary` | JSON | Shared vocab |
|
|
271
271
|
| `godx-ui://tokens` | JSON | All tokens |
|
|
272
272
|
| `godx-ui://tokens/{category}` | JSON | Tokens by category |
|
|
273
|
-
| `godx-ui://rules` | Markdown | All
|
|
273
|
+
| `godx-ui://rules` | Markdown | All 42 rules |
|
|
274
274
|
| `godx-ui://rules/{number}` | Markdown | One rule |
|
|
275
275
|
| `godx-ui://patterns` | JSON | Pattern index |
|
|
276
276
|
| `godx-ui://patterns/{name}` | Markdown | One pattern |
|
package/dist/index.js
CHANGED
|
@@ -712,9 +712,9 @@ function MyShell({ children }: { content: React.ReactNode }) {
|
|
|
712
712
|
props: [
|
|
713
713
|
{
|
|
714
714
|
name: "variant",
|
|
715
|
-
type: '"default" | "destructive" | "outline" | "secondary" | "ghost" | "link"',
|
|
715
|
+
type: '"default" | "destructive" | "outline" | "dashed" | "secondary" | "ghost" | "link"',
|
|
716
716
|
defaultValue: '"default"',
|
|
717
|
-
description: "Visual style."
|
|
717
|
+
description: "Visual style. `dashed` = outline with a dashed border (Ant-style add-row / placeholder action)."
|
|
718
718
|
},
|
|
719
719
|
{
|
|
720
720
|
name: "size",
|
|
@@ -722,6 +722,12 @@ function MyShell({ children }: { content: React.ReactNode }) {
|
|
|
722
722
|
defaultValue: '"default"',
|
|
723
723
|
description: "Size preset (height, padding, icon dims)."
|
|
724
724
|
},
|
|
725
|
+
{
|
|
726
|
+
name: "shape",
|
|
727
|
+
type: '"default" | "pill" | "sharp"',
|
|
728
|
+
defaultValue: '"default"',
|
|
729
|
+
description: "Corner radius from the tokens \u2014 `default` (control radius), `pill` (fully rounded, --radius-pill), `sharp` (square, --radius-sharp). Use the prop instead of a `rounded-*` className."
|
|
730
|
+
},
|
|
725
731
|
{
|
|
726
732
|
name: "asChild",
|
|
727
733
|
type: "boolean",
|
|
@@ -768,6 +774,98 @@ import { Trash2 } from "lucide-react";
|
|
|
768
774
|
storyPath: "general/Button.stories.tsx",
|
|
769
775
|
rules: [23]
|
|
770
776
|
},
|
|
777
|
+
{
|
|
778
|
+
name: "Text",
|
|
779
|
+
group: "general",
|
|
780
|
+
tagline: 'Typographic primitive \u2014 use INSTEAD of a hand-rolled `<span className="text-[13px] font-medium text-muted-foreground">`. Size is a type-scale step (never px); tone/weight are tokens.',
|
|
781
|
+
props: [
|
|
782
|
+
{
|
|
783
|
+
name: "size",
|
|
784
|
+
type: '"2xs" | "xs" | "sm" | "md" | "lg" | "xl"',
|
|
785
|
+
defaultValue: '"sm"',
|
|
786
|
+
description: "Golden-ratio type-scale step. NEVER an arbitrary px (`text-[13px]` is banned) \u2014 pick the nearest step."
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
name: "tone",
|
|
790
|
+
type: '"default" | "muted" | "primary" | "success" | "warning" | "destructive" | "info"',
|
|
791
|
+
defaultValue: '"default"',
|
|
792
|
+
description: "Semantic foreground colour. Replaces `text-muted-foreground` etc. on a raw span."
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
name: "weight",
|
|
796
|
+
type: '"regular" | "medium" | "semibold"',
|
|
797
|
+
defaultValue: '"regular"',
|
|
798
|
+
description: "Font weight (system 2-weight 400/500; semibold resolves to the 500 token)."
|
|
799
|
+
},
|
|
800
|
+
{ name: "align", type: '"start" | "center" | "end"', description: "Logical text alignment." },
|
|
801
|
+
{ name: "truncate", type: "boolean", description: "Single-line ellipsis." },
|
|
802
|
+
{ name: "tabular", type: "boolean", description: "Tabular figures for aligned numbers." },
|
|
803
|
+
{ name: "mono", type: "boolean", description: "Monospace family for codes / ids." },
|
|
804
|
+
{
|
|
805
|
+
name: "as",
|
|
806
|
+
type: '"span" | "p" | "div" | "label" | "strong" | "em" | "small"',
|
|
807
|
+
defaultValue: '"span"',
|
|
808
|
+
description: "Rendered element."
|
|
809
|
+
}
|
|
810
|
+
],
|
|
811
|
+
usage: [
|
|
812
|
+
"DO use `<Text>` for ALL body / inline / caption text instead of a styled `<span>`/`<p>`. Pick `size` from the scale; never write `text-[13px]`/`text-[11px]` or `font-semibold` by hand.",
|
|
813
|
+
'DO use `tone` for colour (`muted`/`primary`/semantic), `tabular` for numbers, `mono` for codes \u2014 not `className="text-muted-foreground font-mono tabular-nums"`.',
|
|
814
|
+
"For a heading, use `<Heading level>` instead of a large-size `<Text>`."
|
|
815
|
+
],
|
|
816
|
+
useCases: [
|
|
817
|
+
'A muted caption under a value: `<Text size="xs" tone="muted">2026\u5E745\u6708\u5EA6</Text>`.',
|
|
818
|
+
'A monospace id in a list row: `<Text size="xs" mono tone="muted">RC-204881</Text>`.',
|
|
819
|
+
'An emphasized inline figure: `<Text weight="medium" tabular>\xA51,240,000</Text>`.'
|
|
820
|
+
],
|
|
821
|
+
storyPath: "general/typography.tsx",
|
|
822
|
+
rules: [2, 23],
|
|
823
|
+
example: `import { Text } from "@godxjp/ui/general";
|
|
824
|
+
|
|
825
|
+
<Text size="xs" tone="muted">\u88DC\u52A9\u30C6\u30AD\u30B9\u30C8</Text>
|
|
826
|
+
<Text weight="medium" tabular>\xA51,240,000</Text>
|
|
827
|
+
<Text size="xs" mono tone="muted">RC-204881</Text>`
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
name: "Heading",
|
|
831
|
+
group: "general",
|
|
832
|
+
tagline: "Section heading sized from the --heading-h* tokens. `level` sets the size AND the semantic <h1..h4>.",
|
|
833
|
+
props: [
|
|
834
|
+
{
|
|
835
|
+
name: "level",
|
|
836
|
+
type: "1 | 2 | 3 | 4",
|
|
837
|
+
defaultValue: "2",
|
|
838
|
+
description: "Heading level \u2014 sizes from --heading-h{1..4} and renders the matching <h*>."
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
name: "as",
|
|
842
|
+
type: '"h1" | "h2" | "h3" | "h4" | "div"',
|
|
843
|
+
description: "Override the rendered element (e.g. a visual h2 that is a real <h1>)."
|
|
844
|
+
},
|
|
845
|
+
{
|
|
846
|
+
name: "tone",
|
|
847
|
+
type: '"default" | "muted" | "primary" | "success" | "warning" | "destructive" | "info"',
|
|
848
|
+
defaultValue: '"default"',
|
|
849
|
+
description: "Semantic foreground colour."
|
|
850
|
+
},
|
|
851
|
+
{ name: "align", type: '"start" | "center" | "end"', description: "Logical text alignment." },
|
|
852
|
+
{ name: "truncate", type: "boolean", description: "Single-line ellipsis." }
|
|
853
|
+
],
|
|
854
|
+
usage: [
|
|
855
|
+
'DO use `<Heading level>` for section titles instead of a raw `<h2 className="text-lg font-semibold">`. The level drives both the token size and the semantic element.',
|
|
856
|
+
"Inside a Card use `<CardTitle>`; use `<Heading>` for free-standing page/section headings not covered by a component slot."
|
|
857
|
+
],
|
|
858
|
+
useCases: [
|
|
859
|
+
"A section heading on a dashboard: `<Heading level={3}>\u4ECA\u6708\u306EKPI</Heading>`.",
|
|
860
|
+
'A visually-smaller heading that must stay an <h1> for a11y: `<Heading level={1} as="h1">\u2026</Heading>`.'
|
|
861
|
+
],
|
|
862
|
+
storyPath: "general/typography.tsx",
|
|
863
|
+
rules: [6, 23],
|
|
864
|
+
example: `import { Heading } from "@godxjp/ui/general";
|
|
865
|
+
|
|
866
|
+
<Heading level={2}>\u8ACB\u6C42\u66F8\u4E00\u89A7</Heading>
|
|
867
|
+
<Heading level={3} tone="muted">\u88DC\u8DB3\u30BB\u30AF\u30B7\u30E7\u30F3</Heading>`
|
|
868
|
+
},
|
|
771
869
|
// ─── data-display ───────────────────────────────────────────────────────
|
|
772
870
|
{
|
|
773
871
|
name: "DataTable",
|
|
@@ -1015,6 +1113,13 @@ export default function InvoiceList({
|
|
|
1015
1113
|
"Compose the compound parts as children: <DataGrid.Toolbar> (holds <DataGrid.BulkActions>, <DataGrid.Search>, <DataGrid.ViewOptions>, <DataGrid.DensityToggle>), then <DataGrid.Content> (auto-included if omitted) and <DataGrid.Pagination pageSizeOptions=[...]>.",
|
|
1016
1114
|
"Server mode (default): drive sorting/globalFilter/pagination from useQuery and pass rowCount. Client mode: set manualSorting/manualFiltering/manualPagination={false} and the grid handles it on the data array."
|
|
1017
1115
|
],
|
|
1116
|
+
useCases: [
|
|
1117
|
+
"Server-paginated \u4ED5\u8A33 (journal entry) or \u8ACB\u6C42 (invoice) admin list backed by an AJAX/useQuery endpoint: drive sorting + globalFilter + pagination from the query and pass rowCount \u2014 the grid never loads the whole table into the browser. (Prefer DataTable here if the screen must NOT pull @tanstack/react-table.)",
|
|
1118
|
+
"Member / employee directory with a user-toggled 'set view' column picker (DataGrid.ViewOptions) \u2014 let admins hide columns like \u5165\u793E\u65E5 or \u90E8\u7F72 they don't need, persisting the columnVisibility state per user.",
|
|
1119
|
+
"Bulk-operation worklist (e.g. approve/export selected \u7D4C\u8CBB\u7CBE\u7B97 rows): enableRowSelection + DataGrid.BulkActions to show a 'N\u4EF6\u9078\u629E\u4E2D' action bar with \u4E00\u62EC\u627F\u8A8D / CSV\u51FA\u529B buttons only when rows are checked.",
|
|
1120
|
+
"Dense reconciliation or ledger table where operators flip between compact and comfortable row height via DataGrid.DensityToggle to fit more rows on screen during data-entry-heavy sessions.",
|
|
1121
|
+
"Client-side grid for a fully-loaded small dataset (e.g. a fixed master list of \u52D8\u5B9A\u79D1\u76EE): set manualSorting/manualFiltering/manualPagination={false} so TanStack sorts, searches, and paginates in-browser without any server round-trip."
|
|
1122
|
+
],
|
|
1018
1123
|
related: ["DataTable", "Table", "DataState", "Select", "DropdownMenu"],
|
|
1019
1124
|
example: `import { DataGrid, type ColumnDef } from "@godxjp/ui/data-grid";
|
|
1020
1125
|
import { Flex } from "@godxjp/ui/layout";
|
|
@@ -1225,14 +1330,25 @@ import { ResponsiveGrid } from "@godxjp/ui/layout";
|
|
|
1225
1330
|
props: [
|
|
1226
1331
|
{
|
|
1227
1332
|
name: "variant",
|
|
1228
|
-
type: '"default" | "secondary" | "outline" | "
|
|
1333
|
+
type: '"default" | "secondary" | "outline" | "dashed"',
|
|
1229
1334
|
defaultValue: '"default"',
|
|
1230
|
-
description: "
|
|
1335
|
+
description: "STRUCTURAL emphasis only (fill/border style) \u2014 NOT colour. Use `tone` for semantic colour. `dashed` = dashed border."
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
name: "tone",
|
|
1339
|
+
type: '"default" | "success" | "warning" | "destructive" | "info" | "muted" | "neutral"',
|
|
1340
|
+
description: "SEMANTIC colour intent (ToneProp). This is the colour knob \u2014 success/warning/destructive/info/etc. Keep variant for structure, tone for meaning."
|
|
1341
|
+
},
|
|
1342
|
+
{
|
|
1343
|
+
name: "shape",
|
|
1344
|
+
type: '"default" | "pill" | "sharp"',
|
|
1345
|
+
defaultValue: '"default"',
|
|
1346
|
+
description: "Corner radius from the tokens \u2014 `default` (badge radius), `pill` (fully rounded), `sharp` (square). Use the prop instead of a `rounded-*` className."
|
|
1231
1347
|
},
|
|
1232
1348
|
{
|
|
1233
1349
|
name: "status",
|
|
1234
1350
|
type: "string",
|
|
1235
|
-
description: "Lifecycle key. Known keys auto-map to
|
|
1351
|
+
description: "Lifecycle key. Known keys auto-map to tone + icon + i18n label; unknown keys fall back to neutral."
|
|
1236
1352
|
},
|
|
1237
1353
|
{
|
|
1238
1354
|
name: "icon",
|
|
@@ -3316,7 +3432,7 @@ export function InvoicePeriodFilter() {
|
|
|
3316
3432
|
description: "Initial value for uncontrolled mode. Same shape as value."
|
|
3317
3433
|
},
|
|
3318
3434
|
{
|
|
3319
|
-
name: "
|
|
3435
|
+
name: "onValueChange",
|
|
3320
3436
|
type: "(value: string[] | string[][], selectedOptions?: TreeOptionProp[] | TreeOptionProp[][]) => void",
|
|
3321
3437
|
description: "Fires when selection changes. First arg is the selected path(s); second is the matching node objects. On clear, called with []."
|
|
3322
3438
|
},
|
|
@@ -3500,7 +3616,7 @@ function MultiRegionPicker() {
|
|
|
3500
3616
|
description: "Initial value for uncontrolled usage. Ignored once `value` is provided."
|
|
3501
3617
|
},
|
|
3502
3618
|
{
|
|
3503
|
-
name: "
|
|
3619
|
+
name: "onValueChange",
|
|
3504
3620
|
type: "(value: string | string[] | undefined) => void",
|
|
3505
3621
|
description: "Called on selection change. Returns `string` in single mode, `string[]` in multi/checkable mode, or `undefined` when cleared."
|
|
3506
3622
|
},
|
|
@@ -6024,18 +6140,35 @@ export default function PasswordBlock() {
|
|
|
6024
6140
|
group: "navigation",
|
|
6025
6141
|
tagline: "Context menu primitives with keyboard support and compound parts for command-style action surfaces.",
|
|
6026
6142
|
props: [
|
|
6027
|
-
{ name: "open", type: "boolean", description: "Controlled open state." },
|
|
6028
6143
|
{
|
|
6029
6144
|
name: "onOpenChange",
|
|
6030
6145
|
type: "(open: boolean) => void",
|
|
6031
6146
|
description: "Open-state callback."
|
|
6032
6147
|
},
|
|
6033
|
-
{
|
|
6148
|
+
{
|
|
6149
|
+
name: "modal",
|
|
6150
|
+
type: "boolean",
|
|
6151
|
+
defaultValue: "true",
|
|
6152
|
+
description: "Modal mode \u2014 locks scroll + outside interaction while open. Set false to keep the rest of the page interactive."
|
|
6153
|
+
},
|
|
6154
|
+
{
|
|
6155
|
+
name: "dir",
|
|
6156
|
+
type: '"ltr" | "rtl"',
|
|
6157
|
+
description: "Reading direction for arrow-key navigation (inherits from the document if omitted)."
|
|
6158
|
+
}
|
|
6159
|
+
],
|
|
6160
|
+
usage: [
|
|
6161
|
+
"DO trigger this on `onContextMenu` (right-click / long-press), NOT on left-click \u2014 for a button that opens a list of actions on left-click use `DropdownMenu` instead. The two are not interchangeable.",
|
|
6162
|
+
"DO wrap exactly the right-clickable surface in `<ContextMenuTrigger>` (a table row, a card, a file tile) \u2014 the menu anchors to the pointer position, so the trigger should be the whole interactive region the menu acts on.",
|
|
6163
|
+
"DON'T put primary, always-visible actions only behind a context menu \u2014 right-click is a discoverability dead-end on touch and for new users. Mirror critical actions in a visible `Button`/`DropdownMenu` and use ContextMenu as an accelerator.",
|
|
6164
|
+
'DO mark irreversible items with `variant="destructive"` (\u524A\u9664 / \u53D6\u308A\u6D88\u3057) and group them under a `<ContextMenuSeparator>`; use `<ContextMenuShortcut>` to show the keyboard accelerator, `<ContextMenuSub>`/`<ContextMenuSubTrigger>` for nested submenus, and `<ContextMenuCheckboxItem>`/`<ContextMenuRadioItem>` for stateful toggles.',
|
|
6165
|
+
"DON'T hand-roll a positioned `<div>` + `onContextMenu={e => e.preventDefault()}` \u2014 the primitive already gives you keyboard navigation, focus trapping, typeahead, and WAI-ARIA menu semantics for free."
|
|
6034
6166
|
],
|
|
6035
6167
|
useCases: [
|
|
6036
|
-
"Right-click action
|
|
6037
|
-
"Contextual
|
|
6038
|
-
"Nested action
|
|
6168
|
+
"Right-click actions on a DataTable/DataGrid row (\u8A73\u7D30 / \u8907\u88FD / \u524A\u9664) as a power-user accelerator alongside the visible row action button.",
|
|
6169
|
+
"Contextual menu on a file or document tile in an upload/asset manager (\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9 / \u540D\u524D\u5909\u66F4 / \u524A\u9664).",
|
|
6170
|
+
"Nested action menu with submenus and shortcuts (e.g. '\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8 \u25B8 CSV / PDF') on a report card.",
|
|
6171
|
+
"Stateful toggles on a board/kanban card via ContextMenuCheckboxItem (e.g. \u30D4\u30F3\u7559\u3081, \u5B8C\u4E86\u3068\u3057\u3066\u30DE\u30FC\u30AF)."
|
|
6039
6172
|
],
|
|
6040
6173
|
storyPath: "navigation/ContextMenu.stories.tsx",
|
|
6041
6174
|
rules: [3, 6],
|
|
@@ -6059,21 +6192,34 @@ export default function PasswordBlock() {
|
|
|
6059
6192
|
group: "navigation",
|
|
6060
6193
|
tagline: "Application menubar primitives (menus, sub-menus, and check/radio items).",
|
|
6061
6194
|
props: [
|
|
6195
|
+
{
|
|
6196
|
+
name: "value",
|
|
6197
|
+
type: "string",
|
|
6198
|
+
description: "Controlled value of the currently-open menu (pair with onValueChange)."
|
|
6199
|
+
},
|
|
6062
6200
|
{
|
|
6063
6201
|
name: "defaultValue",
|
|
6064
6202
|
type: "string",
|
|
6065
|
-
description: "Uncontrolled initial
|
|
6203
|
+
description: "Uncontrolled initial open menu."
|
|
6066
6204
|
},
|
|
6067
6205
|
{
|
|
6068
6206
|
name: "onValueChange",
|
|
6069
6207
|
type: "(value: string) => void",
|
|
6070
|
-
description: "
|
|
6208
|
+
description: "Fires with the id of the menu that opened (or '' when all close)."
|
|
6071
6209
|
}
|
|
6072
6210
|
],
|
|
6211
|
+
usage: [
|
|
6212
|
+
"DO reserve Menubar for a persistent, desktop-app-style command bar (\u30D5\u30A1\u30A4\u30EB / \u7DE8\u96C6 / \u8868\u793A \u2026) where multiple top-level menus sit side by side \u2014 moving the pointer across triggers opens the adjacent menu without an extra click.",
|
|
6213
|
+
"DON'T use Menubar for primary site/page navigation (links between pages) \u2014 that is `NavigationMenu`. Menubar items run *commands*; NavigationMenu items *navigate*.",
|
|
6214
|
+
"DON'T use Menubar when there is only one menu button \u2014 a single trigger that drops a list of actions is a `DropdownMenu`. Menubar earns its weight only with several coordinated menus.",
|
|
6215
|
+
"DO compose the full structure: `<Menubar>` \u203A `<MenubarMenu>` \u203A `<MenubarTrigger>` + `<MenubarContent>` with `<MenubarItem>`; use `<MenubarSeparator>` to group, `<MenubarShortcut>` for accelerators, `<MenubarSub>` for nested menus, and `<MenubarCheckboxItem>`/`<MenubarRadioItem>` for view toggles.",
|
|
6216
|
+
'DO mark destructive commands with `variant="destructive"` and give every item an `onSelect` handler \u2014 items are commands, so they should *do* something, not just close.'
|
|
6217
|
+
],
|
|
6073
6218
|
useCases: [
|
|
6074
|
-
"Top-bar
|
|
6075
|
-
"Workspace menus
|
|
6076
|
-
"Desktop-like
|
|
6219
|
+
"Top-bar command menu for a back-office editor (\u30D5\u30A1\u30A4\u30EB / \u7DE8\u96C6 / \u8868\u793A / \u30D8\u30EB\u30D7) with shortcuts and submenus.",
|
|
6220
|
+
"Workspace tool menus in an admin console where each menu groups a category of actions (\u30C7\u30FC\u30BF / \u30EC\u30DD\u30FC\u30C8 / \u8A2D\u5B9A).",
|
|
6221
|
+
"Desktop-like application shell (e.g. an internal POS or accounting workstation) that mirrors native menubar conventions.",
|
|
6222
|
+
"View-state toggles via MenubarCheckboxItem/MenubarRadioItem (e.g. \u8868\u793A \u203A \u30B0\u30EA\u30C3\u30C9\u7DDA\u3092\u8868\u793A, \u901A\u8CA8\u8868\u793A \u25B8 \xA5 / $)."
|
|
6077
6223
|
],
|
|
6078
6224
|
storyPath: "navigation/Menubar.stories.tsx",
|
|
6079
6225
|
rules: [3, 6],
|
|
@@ -6099,18 +6245,41 @@ export default function PasswordBlock() {
|
|
|
6099
6245
|
defaultValue: '"horizontal"',
|
|
6100
6246
|
description: "Main-axis arrangement for the nav menu."
|
|
6101
6247
|
},
|
|
6248
|
+
{
|
|
6249
|
+
name: "value",
|
|
6250
|
+
type: "string",
|
|
6251
|
+
description: "Controlled value of the currently-open item (pair with onValueChange)."
|
|
6252
|
+
},
|
|
6102
6253
|
{
|
|
6103
6254
|
name: "defaultValue",
|
|
6104
6255
|
type: "string",
|
|
6105
|
-
description: "Uncontrolled initial
|
|
6256
|
+
description: "Uncontrolled initial open item."
|
|
6106
6257
|
},
|
|
6107
6258
|
{
|
|
6108
6259
|
name: "onValueChange",
|
|
6109
6260
|
type: "(value: string) => void",
|
|
6110
|
-
description: "
|
|
6261
|
+
description: "Fires with the id of the item whose dropdown opened (or '' when all close)."
|
|
6262
|
+
},
|
|
6263
|
+
{
|
|
6264
|
+
name: "delayDuration",
|
|
6265
|
+
type: "number",
|
|
6266
|
+
defaultValue: "200",
|
|
6267
|
+
description: "Hover delay (ms) before a trigger's content opens."
|
|
6111
6268
|
}
|
|
6112
6269
|
],
|
|
6113
|
-
|
|
6270
|
+
usage: [
|
|
6271
|
+
"DO use NavigationMenu for primary *navigation* between pages/sections \u2014 items wrap `<NavigationMenuLink>` (an `<a>`), not command buttons. For command bars (\u30D5\u30A1\u30A4\u30EB/\u7DE8\u96C6 \u2026) use `Menubar`; for a single action drop-down use `DropdownMenu`.",
|
|
6272
|
+
"DO render real links inside `<NavigationMenuLink asChild>` so SPA routers work: `<NavigationMenuLink asChild><Link href={route('reports.index')}>\u30EC\u30DD\u30FC\u30C8</Link></NavigationMenuLink>` \u2014 never nest a raw `<a>` directly with its own onClick navigation.",
|
|
6273
|
+
"DO use `<NavigationMenuTrigger>` + `<NavigationMenuContent>` only when an item needs a rich dropdown panel (link groups, featured cards). Top-level items that go straight to a page should be a bare `<NavigationMenuLink>` with NO trigger.",
|
|
6274
|
+
"DON'T use it as the app's left sidebar \u2014 for a persistent vertical app sidebar use `Sidebar`/`AppShell`. Set `orientation=\"vertical\"` only for an in-content vertical link menu, not the global shell.",
|
|
6275
|
+
"DON'T hand-roll the hover/focus dropdown timing \u2014 the primitive manages open-on-hover with `delayDuration`, keyboard navigation, and the animated viewport for you."
|
|
6276
|
+
],
|
|
6277
|
+
useCases: [
|
|
6278
|
+
"Primary top navigation for an admin/portal app with dropdown panels grouping related pages (e.g. \u30EC\u30DD\u30FC\u30C8 \u25BE \u2192 \u58F2\u4E0A / \u7D4C\u8CBB / \u5165\u91D1).",
|
|
6279
|
+
"Sectioned marketing or docs navigation with featured link cards inside NavigationMenuContent.",
|
|
6280
|
+
"Nested link groups where one trigger reveals a multi-column panel of related destinations.",
|
|
6281
|
+
"Vertical in-content navigation (orientation='vertical') for a settings or documentation area \u2014 distinct from the global Sidebar shell."
|
|
6282
|
+
],
|
|
6114
6283
|
storyPath: "navigation/NavigationMenu.stories.tsx",
|
|
6115
6284
|
rules: [3, 6],
|
|
6116
6285
|
example: `import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger } from "@godxjp/ui/navigation";
|
|
@@ -6128,12 +6297,53 @@ export default function PasswordBlock() {
|
|
|
6128
6297
|
group: "layout",
|
|
6129
6298
|
tagline: "Resizable panel group/child/handle primitives from react-resizable-panels.",
|
|
6130
6299
|
props: [
|
|
6131
|
-
{
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6300
|
+
{
|
|
6301
|
+
name: "orientation",
|
|
6302
|
+
type: '"horizontal" | "vertical"',
|
|
6303
|
+
defaultValue: '"horizontal"',
|
|
6304
|
+
description: "ResizablePanelGroup prop \u2014 axis the panels are laid out / resized along (horizontal = side-by-side)."
|
|
6305
|
+
},
|
|
6306
|
+
{
|
|
6307
|
+
name: "id",
|
|
6308
|
+
type: "string",
|
|
6309
|
+
description: "ResizablePanel identifier \u2014 required for collapse/expand control and for layout persistence."
|
|
6310
|
+
},
|
|
6311
|
+
{
|
|
6312
|
+
name: "defaultSize",
|
|
6313
|
+
type: "number",
|
|
6314
|
+
description: "ResizablePanel initial size as a percentage (0\u2013100) of the group."
|
|
6315
|
+
},
|
|
6316
|
+
{
|
|
6317
|
+
name: "minSize",
|
|
6318
|
+
type: "number",
|
|
6319
|
+
description: "ResizablePanel minimum size (%) \u2014 drag can't shrink below this."
|
|
6320
|
+
},
|
|
6321
|
+
{ name: "maxSize", type: "number", description: "ResizablePanel maximum size (%)." },
|
|
6322
|
+
{
|
|
6323
|
+
name: "collapsible",
|
|
6324
|
+
type: "boolean",
|
|
6325
|
+
defaultValue: "false",
|
|
6326
|
+
description: "ResizablePanel \u2014 allow the panel to collapse to collapsedSize when dragged below minSize. Pair with onResize to react to collapse."
|
|
6327
|
+
},
|
|
6328
|
+
{
|
|
6329
|
+
name: "onResize",
|
|
6330
|
+
type: "(size: PanelSize, id, prevSize) => void",
|
|
6331
|
+
description: "ResizablePanel \u2014 fires while/after the panel is resized (e.g. to persist layout)."
|
|
6332
|
+
}
|
|
6333
|
+
],
|
|
6334
|
+
usage: [
|
|
6335
|
+
'DO put the layout on `<ResizablePanelGroup orientation="horizontal|vertical">`, the resizable regions in `<ResizablePanel>`, and a `<ResizableHandle>` BETWEEN every adjacent pair \u2014 a group of N panels needs N-1 handles or there is nothing to drag.',
|
|
6336
|
+
"DO size panels with `defaultSize`/`minSize`/`maxSize` as PERCENTAGES (the group totals 100), not pixels \u2014 don't fight this with a fixed `w-[280px]` className on the panel.",
|
|
6337
|
+
"DON'T reach for ResizablePanel when the split is fixed and never user-adjustable \u2014 use a plain `Flex`/`ResponsiveGrid`, or `SplitPane` for a simple two-pane layout. Resizable is for *user-draggable* boundaries only.",
|
|
6338
|
+
"DO give each panel a stable `id` and use `collapsible` + `collapsedSize` for a side panel the user can fully tuck away (e.g. a filters rail), reacting via `onResize`.",
|
|
6339
|
+
"DON'T hand-roll a draggable divider with mouse-move listeners \u2014 the primitive handles pointer + keyboard resizing, ARIA separator semantics, and min/max clamping. Always render `<ResizableHandle>`, never a bare styled `<div>`."
|
|
6340
|
+
],
|
|
6341
|
+
useCases: [
|
|
6342
|
+
"Master\u2013detail admin layout: a draggable list pane on the left and a detail/preview pane on the right (e.g. \u4ED5\u8A33\u4E00\u89A7 | \u4ED5\u8A33\u8A73\u7D30).",
|
|
6343
|
+
"Collapsible filters or navigation rail beside a data table that operators can widen for long labels or tuck away to maximize the table.",
|
|
6344
|
+
"Stacked vertical split (orientation='vertical') such as a results table over a live JSON/log preview in a data-import tool.",
|
|
6345
|
+
"Three-pane workbench (nav | content | inspector) where each boundary is independently draggable and layout is persisted via id + onResize."
|
|
6135
6346
|
],
|
|
6136
|
-
useCases: ["Split-pane layouts", "Resizable sidebars", "Code editors with adjustable zones"],
|
|
6137
6347
|
storyPath: "layout/ResizablePanel.stories.tsx",
|
|
6138
6348
|
rules: [3, 6],
|
|
6139
6349
|
example: `import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from "@godxjp/ui/layout";
|
|
@@ -6162,10 +6372,23 @@ export default function PasswordBlock() {
|
|
|
6162
6372
|
{
|
|
6163
6373
|
name: "setApi",
|
|
6164
6374
|
type: "(api: CarouselApi) => void",
|
|
6165
|
-
description: "Receive
|
|
6375
|
+
description: "Receive the Embla api for custom logic (autoplay, external prev/next). NOT needed for dots \u2014 CarouselDots reads the api from context itself."
|
|
6166
6376
|
}
|
|
6167
6377
|
],
|
|
6168
|
-
|
|
6378
|
+
usage: [
|
|
6379
|
+
"DO compose the full set: `<Carousel>` \u203A `<CarouselContent>` \u203A many `<CarouselItem>`, with `<CarouselPrevious>`/`<CarouselNext>` for arrows and `<CarouselDots>` for the indicator row. Don't render items outside `<CarouselContent>` \u2014 the track is the scroll container.",
|
|
6380
|
+
"DO use `<CarouselDots>` for the active-slide indicator instead of wiring `setApi` by hand \u2014 it reads `selectedIndex`/`scrollSnaps` from the Carousel context, renders one `aria-current` dot per snap, and auto-hides when there is \u22641 slide.",
|
|
6381
|
+
"DON'T use a Carousel where ALL items must be seen/compared at once or be keyboard-reachable in reading order (e.g. a list of selectable options, a data table, primary navigation) \u2014 hiding content behind a swipe is an anti-pattern there; use a Grid/`ResponsiveGrid`, `ScrollArea`, or `Tabs`.",
|
|
6382
|
+
"DON'T autoplay without a pause-on-hover/focus control and reduced-motion respect \u2014 pass the Embla autoplay plugin via `plugins` only for non-essential decorative content, never for content the user must read.",
|
|
6383
|
+
"DO set `opts={{ loop: true }}` for galleries that wrap, and rely on the built-in disabling: `CarouselPrevious`/`CarouselNext` auto-disable at the ends (via `canScrollPrev`/`canScrollNext`) \u2014 don't hide them, let them grey out.",
|
|
6384
|
+
"DO give each `<CarouselItem>` real, meaningful content; the component already injects an 'N of M' slide label for screen readers, so don't add a redundant one (a consumer `aria-label` on the item overrides the default)."
|
|
6385
|
+
],
|
|
6386
|
+
useCases: [
|
|
6387
|
+
"Feature / onboarding highlight cards on a dashboard or landing surface, with CarouselDots showing position.",
|
|
6388
|
+
"Image or document thumbnail gallery (e.g. uploaded receipts / \u7269\u4EF6\u5199\u771F) with looping and prev/next arrows.",
|
|
6389
|
+
"Horizontal stepping list of compact KPI or announcement cards that overflow the viewport width.",
|
|
6390
|
+
"Product/plan comparison cards on a marketing page where swiping between a few options is acceptable (not the primary action)."
|
|
6391
|
+
],
|
|
6169
6392
|
storyPath: "data-display/Carousel.stories.tsx",
|
|
6170
6393
|
rules: [3, 6],
|
|
6171
6394
|
example: `import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, CarouselDots } from "@godxjp/ui/data-display";
|
|
@@ -6197,10 +6420,28 @@ export default function PasswordBlock() {
|
|
|
6197
6420
|
type: "(value: string) => void",
|
|
6198
6421
|
description: "Validated value callback."
|
|
6199
6422
|
},
|
|
6200
|
-
{
|
|
6423
|
+
{
|
|
6424
|
+
name: "step",
|
|
6425
|
+
type: "number",
|
|
6426
|
+
defaultValue: "1",
|
|
6427
|
+
description: "Minute step (clamped 1\u201359). Snaps the committed minute to the nearest lower multiple and sets the ArrowUp/ArrowDown increment."
|
|
6428
|
+
},
|
|
6201
6429
|
{ name: "name", type: "string", description: "Form field name." }
|
|
6202
6430
|
],
|
|
6203
|
-
|
|
6431
|
+
usage: [
|
|
6432
|
+
"DO treat the value as a plain `HH:mm` string (24-hour, zero-padded) \u2014 TimeInput is calendar-free. For a date, or a date+time, use `DatePicker`/`Calendar`; for a richer dropdown time selector use `TimePicker`.",
|
|
6433
|
+
"DO drive it controlled with `value` + `onValueChange` (it follows the vocabulary \u2014 NOT `onChange`/`defaultValue` pairing for control). `onValueChange` fires only with a VALID, step-snapped `HH:mm`, so your state never holds a half-typed value.",
|
|
6434
|
+
"DON'T pass `value` without `onValueChange` \u2014 like every controlled @godxjp/ui input that freezes the field. Omit both for uncontrolled (use `defaultValue`).",
|
|
6435
|
+
"DO set `step` to your scheduling granularity (e.g. `15` or `30`) \u2014 the user can still type freely, but blur/Enter snaps the minute down to the nearest multiple, and ArrowUp/ArrowDown step by that amount (wrapping across midnight).",
|
|
6436
|
+
"DO let the built-in masking + validation work: digits auto-format to `HH:mm`, invalid input sets `aria-invalid` and is reverted on blur. Don't add your own regex/onChange masking on top.",
|
|
6437
|
+
"DON'T use it for a duration/elapsed time that can exceed 23:59 \u2014 it's a clock time-of-day input (00:00\u201323:59). Use a numeric Input for durations."
|
|
6438
|
+
],
|
|
6439
|
+
useCases: [
|
|
6440
|
+
"\u52E4\u6020 (attendance) start/end time fields \u2014 \u51FA\u52E4 / \u9000\u52E4 HH:mm entry with step={1} or a rounding step for shift schedules.",
|
|
6441
|
+
"Business-hours / reservation slot editor where times snap to a 15- or 30-minute grid (step={15}).",
|
|
6442
|
+
"A from\u2013to time range filter on a report or log screen (two TimeInputs) with no date component.",
|
|
6443
|
+
"Any calendar-free HH:mm-only form field (e.g. a recurring daily batch time, a \u7DE0\u3081\u6642\u523B)."
|
|
6444
|
+
],
|
|
6204
6445
|
storyPath: "data-entry/TimeInput.stories.tsx",
|
|
6205
6446
|
rules: [3, 6],
|
|
6206
6447
|
example: `import { TimeInput } from "@godxjp/ui/data-entry";
|
|
@@ -6671,6 +6912,11 @@ var CARDINAL_RULES = [
|
|
|
6671
6912
|
number: 41,
|
|
6672
6913
|
title: "Drawer & dialog footer layout",
|
|
6673
6914
|
body: 'Sheet/Dialog/AlertDialog footers are a pinned action bar (Ant Design Drawer footer): the footer sticks to the bottom, SheetFooter draws a full-bleed top border, and actions are RIGHT-aligned with the PRIMARY button rightmost (Cancel/secondary to its left). A destructive / clear / reset action goes far-LEFT \u2014 give that button `className="mr-auto"`. NEVER stack footer buttons full-width or center them.'
|
|
6915
|
+
},
|
|
6916
|
+
{
|
|
6917
|
+
number: 42,
|
|
6918
|
+
title: "Props & Tokens Before Customization",
|
|
6919
|
+
body: "Before reaching for a Tailwind class, inline `style`, or extra CSS, you MUST first check whether the component already supports the need via a PROP, a design TOKEN, or a layout/typography PRIMITIVE. godx-ui is meant to be enough on its own (Ant-Design-style): `className` is for genuine one-offs only \u2014 never to redo what an API already does. Specifically: (1) NEVER hand-roll typography \u2014 no `text-[13px]`/`text-[11px]` arbitrary px (bypasses the golden type scale), no `font-medium`/`font-semibold`/`text-muted-foreground` on a raw `<span>`; use `<Text size tone weight tabular mono>` / `<Heading level>`. (2) NEVER hand-roll a trivial flex/grid wrapper; use `<Flex>` / `<ResponsiveGrid>` / `<PageContainer>`. (3) NEVER set a control's radius/height/colour with a utility when a `shape`/`size`/`tone`/token exists. If a real need has NO prop/token/primitive, that is a library GAP \u2014 file it (draft_bug_report), don't paper over it with ad-hoc Tailwind."
|
|
6674
6920
|
}
|
|
6675
6921
|
];
|
|
6676
6922
|
function findRule(num) {
|
|
@@ -9633,7 +9879,10 @@ function lintJsx(jsx) {
|
|
|
9633
9879
|
check(/<input[\s>]/, "Use `<Input>` instead of raw `<input>` (rule 29).");
|
|
9634
9880
|
check(/<select[\s>]/, "Use `<Select>` instead of raw `<select>` (rule 29).");
|
|
9635
9881
|
check(/<textarea[\s>]/, "Use `<Textarea>` instead of raw `<textarea>` (rule 29).");
|
|
9636
|
-
check(
|
|
9882
|
+
check(
|
|
9883
|
+
/<(table|thead|tbody)[\s>]/,
|
|
9884
|
+
"Use `<DataTable>` instead of a hand-rolled `<table>` (rule 29)."
|
|
9885
|
+
);
|
|
9637
9886
|
check(
|
|
9638
9887
|
/bg-(red|blue|green|yellow|gray|slate|zinc|neutral|stone|orange|amber|lime|emerald|teal|cyan|sky|indigo|violet|purple|fuchsia|pink|rose)-\d{2,3}\b/,
|
|
9639
9888
|
"Use semantic token utilities (`bg-primary`/`bg-destructive`) not raw color scales (rule 2)."
|
|
@@ -9646,6 +9895,10 @@ function lintJsx(jsx) {
|
|
|
9646
9895
|
/size=["']default["']/,
|
|
9647
9896
|
'`size="default"` is not in the controlled vocabulary \u2014 use `size` \u2208 xs|sm|md|lg.'
|
|
9648
9897
|
);
|
|
9898
|
+
check(
|
|
9899
|
+
/\btext-\[[0-9.]+px\]/,
|
|
9900
|
+
"Arbitrary text size `text-[Npx]` bypasses the golden type scale \u2014 use `<Text size>` / `<Heading level>` (rule 42)."
|
|
9901
|
+
);
|
|
9649
9902
|
check(
|
|
9650
9903
|
/<Tag[\s\S]*?color=["']error["']/i,
|
|
9651
9904
|
'Tag `color="error"` \u2192 `"destructive"` (v5.0, PR #60).'
|
|
@@ -9844,7 +10097,7 @@ ${c.example}
|
|
|
9844
10097
|
// package.json
|
|
9845
10098
|
var package_default = {
|
|
9846
10099
|
name: "@godxjp/ui-mcp",
|
|
9847
|
-
version: "0.
|
|
10100
|
+
version: "0.20.0",
|
|
9848
10101
|
description: "Model Context Protocol server for @godxjp/ui \u2014 gives Claude Code / Codex CLI / Cursor / any MCP-aware agent live access to the component catalog, prop vocabulary, design tokens, 34 cardinal rules, copy-paste-ready patterns, 12 design / taste skills synthesised from Leonxlnx/taste-skill, 20+ anti-AI-tell patterns, and a 50-check redesign audit \u2014 token-efficient (list \u2192 drill-down).",
|
|
9849
10102
|
type: "module",
|
|
9850
10103
|
main: "./dist/index.js",
|