@wangs-ui/skills 1.3.0-alpha.2 → 1.3.0-alpha.21
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 +15 -11
- package/dist/bin.js +20 -15
- package/dist/index.js +2 -2
- package/dist/rules/wangs-ui/default-props-precedence.md +13 -0
- package/dist/rules/wangs-ui/forms-destructuring-lock.md +18 -0
- package/dist/rules/wangs-ui/no-raw-html.md +28 -0
- package/dist/rules/wangs-ui/no-redundant-wrappers.md +55 -0
- package/dist/rules/wangs-ui/react19-checklist-and-reference.md +37 -0
- package/dist/rules/wangs-ui/react19-compiler-render-patterns.md +12 -0
- package/dist/rules/wangs-ui/react19-naming-conventions.md +15 -0
- package/dist/rules/wangs-ui/react19-no-manual-memoization.md +27 -0
- package/dist/rules/wangs-ui/react19-primitives-typing.md +84 -0
- package/dist/rules/wangs-ui/react19-props-typing.md +24 -0
- package/dist/rules/wangs-ui/react19-purity-and-immutability.md +40 -0
- package/dist/rules/wangs-ui/react19-tooling-and-opt-out.md +77 -0
- package/dist/rules/wangs-ui/theme-variable-override-breaks-engine.md +19 -0
- package/dist/rules/wangs-ui/typescript-assertions-last-resort.md +12 -0
- package/dist/rules/wangs-ui/typescript-checklist-and-reference.md +33 -0
- package/dist/rules/wangs-ui/typescript-discriminated-unions.md +39 -0
- package/dist/rules/wangs-ui/typescript-explicit-return-types.md +21 -0
- package/dist/rules/wangs-ui/typescript-interface-vs-type.md +39 -0
- package/dist/rules/wangs-ui/typescript-literal-unions-vs-enums.md +21 -0
- package/dist/rules/wangs-ui/typescript-naming-conventions.md +23 -0
- package/dist/rules/wangs-ui/typescript-narrowing-over-casting.md +43 -0
- package/dist/rules/wangs-ui/typescript-readonly-by-default.md +23 -0
- package/dist/rules/wangs-ui/typescript-tsconfig-strictness.md +30 -0
- package/dist/rules/wangs-ui/typescript-zero-any.md +36 -0
- package/dist/skills/wangs-ui/craft-theme/SKILL.md +63 -0
- package/dist/skills/{create-form → wangs-ui/create-form}/SKILL.md +27 -16
- package/{skills → dist/skills/wangs-ui}/data-table/SKILL.md +24 -15
- package/{skills → dist/skills/wangs-ui}/dialog-modal/SKILL.md +18 -9
- package/{skills → dist/skills/wangs-ui}/i18n-usage/SKILL.md +19 -11
- package/dist/skills/wangs-ui/layout-navigation/SKILL.md +156 -0
- package/dist/skills/wangs-ui/responsive-design/SKILL.md +107 -0
- package/dist/skills/wangs-ui/universal-layout/SKILL.md +80 -0
- package/dist/skills/wangs-ui/wangs-ui-components/SKILL.md +104 -0
- package/dist/src-BFwMaU8I.js +663 -0
- package/package.json +3 -2
- package/rules/wangs-ui/default-props-precedence.md +13 -0
- package/rules/wangs-ui/forms-destructuring-lock.md +18 -0
- package/rules/wangs-ui/no-raw-html.md +28 -0
- package/rules/wangs-ui/no-redundant-wrappers.md +55 -0
- package/rules/wangs-ui/react19-checklist-and-reference.md +37 -0
- package/rules/wangs-ui/react19-compiler-render-patterns.md +12 -0
- package/rules/wangs-ui/react19-naming-conventions.md +15 -0
- package/rules/wangs-ui/react19-no-manual-memoization.md +27 -0
- package/rules/wangs-ui/react19-primitives-typing.md +84 -0
- package/rules/wangs-ui/react19-props-typing.md +24 -0
- package/rules/wangs-ui/react19-purity-and-immutability.md +40 -0
- package/rules/wangs-ui/react19-tooling-and-opt-out.md +77 -0
- package/rules/wangs-ui/theme-variable-override-breaks-engine.md +19 -0
- package/rules/wangs-ui/typescript-assertions-last-resort.md +12 -0
- package/rules/wangs-ui/typescript-checklist-and-reference.md +33 -0
- package/rules/wangs-ui/typescript-discriminated-unions.md +39 -0
- package/rules/wangs-ui/typescript-explicit-return-types.md +21 -0
- package/rules/wangs-ui/typescript-interface-vs-type.md +39 -0
- package/rules/wangs-ui/typescript-literal-unions-vs-enums.md +21 -0
- package/rules/wangs-ui/typescript-naming-conventions.md +23 -0
- package/rules/wangs-ui/typescript-narrowing-over-casting.md +43 -0
- package/rules/wangs-ui/typescript-readonly-by-default.md +23 -0
- package/rules/wangs-ui/typescript-tsconfig-strictness.md +30 -0
- package/rules/wangs-ui/typescript-zero-any.md +36 -0
- package/skills/wangs-ui/craft-theme/SKILL.md +63 -0
- package/skills/{create-form → wangs-ui/create-form}/SKILL.md +27 -16
- package/{dist/skills → skills/wangs-ui}/data-table/SKILL.md +24 -15
- package/{dist/skills → skills/wangs-ui}/dialog-modal/SKILL.md +18 -9
- package/{dist/skills → skills/wangs-ui}/i18n-usage/SKILL.md +19 -11
- package/skills/wangs-ui/layout-navigation/SKILL.md +156 -0
- package/skills/wangs-ui/responsive-design/SKILL.md +107 -0
- package/skills/wangs-ui/universal-layout/SKILL.md +80 -0
- package/skills/wangs-ui/wangs-ui-components/SKILL.md +104 -0
- package/dist/skills/layout-navigation/SKILL.md +0 -62
- package/dist/skills/react19-compiler-typescript/SKILL.md +0 -388
- package/dist/skills/typescript-strict-typing/SKILL.md +0 -317
- package/dist/skills/wangs-ui-components/SKILL.md +0 -108
- package/dist/src-DDi-O7tk.js +0 -246
- package/skills/layout-navigation/SKILL.md +0 -62
- package/skills/react19-compiler-typescript/SKILL.md +0 -388
- package/skills/typescript-strict-typing/SKILL.md +0 -317
- package/skills/wangs-ui-components/SKILL.md +0 -108
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
trigger: model_decision
|
|
3
|
+
description: "Apply when naming a TypeScript type, variable, or constant."
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
6
|
+
---
|
|
7
|
+
# Rule: TypeScript — Naming Conventions
|
|
8
|
+
|
|
9
|
+
| Kind | Convention | Example |
|
|
10
|
+
| ---------------------------------------------------------- | ------------------------------------------- | ----------------------------------- |
|
|
11
|
+
| Types, interfaces, classes, enums | `PascalCase` | `UserProfile`, `OrderStatus` |
|
|
12
|
+
| Interfaces | `PascalCase`, **no `I` prefix** | `User`, not `IUser` |
|
|
13
|
+
| Type aliases | `PascalCase` | `type ApiResponse<T> = ...` |
|
|
14
|
+
| Variables, functions, methods, properties | `camelCase` | `getUserById`, `isValid` |
|
|
15
|
+
| Booleans | `camelCase` with `is/has/should/can` prefix | `isLoading`, `hasPermission` |
|
|
16
|
+
| True constants (module-level, never reassigned, primitive) | `UPPER_SNAKE_CASE` | `MAX_RETRIES`, `DEFAULT_TIMEOUT_MS` |
|
|
17
|
+
| Enum members | `PascalCase` | `enum Status { Active, Archived }` |
|
|
18
|
+
| Generic type parameters (simple, single-purpose) | Single uppercase letter | `T`, `K`, `V`, `E` for errors |
|
|
19
|
+
| Generic type parameters (multiple / non-obvious) | Descriptive, prefixed with `T` | `TInput`, `TOutput`, `TContext` |
|
|
20
|
+
| Discriminated union tag field | Consistent across the codebase | `kind`, `type`, or `status` |
|
|
21
|
+
| Files with a single exported entity | Match the entity name | `UserProfile.ts`, `useAuth.ts` |
|
|
22
|
+
|
|
23
|
+
Naming should describe **intent**, not implementation — `fetchUser` not `getUserFromApiEndpoint`; `retryCount` not `numRetries2`.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
trigger: model_decision
|
|
3
|
+
description: "Apply when narrowing an `unknown` or union-typed value in TypeScript."
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
6
|
+
---
|
|
7
|
+
# Rule: TypeScript — `unknown` + Narrowing, Not Casting
|
|
8
|
+
|
|
9
|
+
Prefer proving a type through control flow over asserting it with `as`.
|
|
10
|
+
|
|
11
|
+
## Narrowing techniques, in order of preference:
|
|
12
|
+
|
|
13
|
+
1. **`typeof`** — primitives (`string`, `number`, `boolean`, `undefined`, `function`)
|
|
14
|
+
2. **`instanceof`** — class instances, `Error`, `Date`, custom classes
|
|
15
|
+
3. **`in`** — checking a property exists before accessing it on a union/unknown
|
|
16
|
+
4. **User-defined type guards** — `function isUser(x: unknown): x is User`
|
|
17
|
+
5. **Discriminated union tag checks** — `switch (value.kind) { ... }`
|
|
18
|
+
6. **Exhaustiveness checks** — a `never`-typed default branch so adding a new variant is a compile error until every switch/if-chain handles it
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
// ✅ Type guard
|
|
22
|
+
function isUser(value: unknown): value is User {
|
|
23
|
+
return typeof value === 'object' && value !== null && 'id' in value && 'email' in value;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ✅ Exhaustiveness check
|
|
27
|
+
function assertNever(x: never): never {
|
|
28
|
+
throw new Error(`Unhandled case: ${JSON.stringify(x)}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function area(shape: Shape): number {
|
|
32
|
+
switch (shape.kind) {
|
|
33
|
+
case 'circle':
|
|
34
|
+
return Math.PI * shape.radius ** 2;
|
|
35
|
+
case 'square':
|
|
36
|
+
return shape.side ** 2;
|
|
37
|
+
default:
|
|
38
|
+
return assertNever(shape); // compile error if a variant is missed
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Type assertions (`as X`) and the non-null assertion (`!`) bypass this entirely — treat them as a last resort, not a shortcut.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
trigger: model_decision
|
|
3
|
+
description: "Apply when declaring a TypeScript collection or object shape."
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
6
|
+
---
|
|
7
|
+
# Rule: TypeScript — Readonly by Default
|
|
8
|
+
|
|
9
|
+
Prefer immutable shapes unless mutation is intentional and localized.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
interface Point {
|
|
13
|
+
readonly x: number;
|
|
14
|
+
readonly y: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function config(values: readonly string[]) {
|
|
18
|
+
/* ... */
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const ROLES = ['admin', 'editor', 'viewer'] as const;
|
|
22
|
+
type UserRole = (typeof ROLES)[number];
|
|
23
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
trigger: model_decision
|
|
3
|
+
description: "Apply when configuring or reviewing tsconfig.json compiler strictness options."
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
6
|
+
---
|
|
7
|
+
# Rule: TypeScript — Baseline `tsconfig.json` Strictness
|
|
8
|
+
|
|
9
|
+
Treat these as the non-negotiable floor for any project this rule touches:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"compilerOptions": {
|
|
14
|
+
"strict": true,
|
|
15
|
+
"noImplicitAny": true,
|
|
16
|
+
"strictNullChecks": true,
|
|
17
|
+
"strictFunctionTypes": true,
|
|
18
|
+
"strictPropertyInitialization": true,
|
|
19
|
+
"noUncheckedIndexedAccess": true,
|
|
20
|
+
"exactOptionalPropertyTypes": true,
|
|
21
|
+
"noImplicitOverride": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"noUnusedLocals": true,
|
|
24
|
+
"noUnusedParameters": true,
|
|
25
|
+
"forceConsistentCasingInFileNames": true
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`strict: true` alone enables the core group (`noImplicitAny`, `strictNullChecks`, etc.), but `noUncheckedIndexedAccess` and `exactOptionalPropertyTypes` are commonly missed and close real gaps (array/object index access returning `T` instead of `T | undefined`; optional properties silently accepting `undefined` as an explicit value).
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
trigger: model_decision
|
|
3
|
+
description: "Apply when writing or reviewing any TypeScript type annotation."
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
6
|
+
---
|
|
7
|
+
# Rule: TypeScript — Never Use `any`
|
|
8
|
+
|
|
9
|
+
`any` is not "unknown type," it's "type checking off." It's contagious — once a value is `any`, everything it touches becomes unchecked too.
|
|
10
|
+
|
|
11
|
+
- Never write `any` for parameters, return types, variables, or generics.
|
|
12
|
+
- Use `unknown` for genuinely unknown external data (API responses, `JSON.parse`, catch clauses, third-party callbacks) and narrow it before use.
|
|
13
|
+
- Use generics (`<T>`) when a function needs to work across types but preserve the relationship between input and output.
|
|
14
|
+
- If a library ships untyped, write a minimal local type/interface for the surface area you actually use instead of reaching for `any`.
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
// ❌ Bad
|
|
18
|
+
function parseConfig(json: any) {
|
|
19
|
+
return json.settings.theme; // no safety, no autocomplete, silent runtime crash
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ✅ Good
|
|
23
|
+
function parseConfig(json: unknown): string {
|
|
24
|
+
if (
|
|
25
|
+
typeof json === 'object' &&
|
|
26
|
+
json !== null &&
|
|
27
|
+
'settings' in json &&
|
|
28
|
+
typeof (json as { settings: unknown }).settings === 'object'
|
|
29
|
+
) {
|
|
30
|
+
// still narrow further or validate with a schema library (zod, valibot, etc.)
|
|
31
|
+
}
|
|
32
|
+
throw new Error('Invalid config shape');
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The only acceptable `any` is a well-justified, isolated, and commented one (e.g. interfacing with a genuinely untyped legacy module) — never a default.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: craft-theme
|
|
3
|
+
description: Generate a brand-color theme (13-shade tonal palette + semantic tokens) for a Wangs UI app via the `wangs-ui-generate-palette` CLI — never hand-write hex shade ramps.
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
6
|
+
---
|
|
7
|
+
# Skill: Craft Theme
|
|
8
|
+
|
|
9
|
+
Use this skill whenever the user asks to create, customize, or rebrand the color theme of an app built on `@wangs-ui/react-core` / `@wangs-ui/foundation` — "make the app's theme orange", "use our brand color #ff6b35", "add a new palette called sunset", etc.
|
|
10
|
+
|
|
11
|
+
## The rule this skill exists to enforce
|
|
12
|
+
|
|
13
|
+
**Never hand-write a 13-shade tonal ramp, and never hand-pick which shade pairs with which as a text/foreground color.** Wangs UI's own design system shipped with exactly that mistake for a while: hand-tuned palette files drifted from what the perceptual (OKLCH) generator would produce, which caused white text to render at 2.54:1 contrast on one brand's primary color — invisible-adjacent, and only caught by a dedicated audit. The generator and the contrast math it's paired with exist specifically so this class of bug can't happen again. Always reach for the CLI below instead of writing hex values yourself.
|
|
14
|
+
|
|
15
|
+
## 1. Generate the palette
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm exec wangs-ui-generate-palette --name=<id> --primary=<#hex> [options] --out=<path>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
- `--name` (required): identifier for the palette, e.g. `sunset`. Used for the exported const name (`sunsetPalette`) and, unless `--out` is given, the output filename (`sunset.ts`).
|
|
22
|
+
- `--primary` (required): the brand/key hex color, e.g. `#ff6b35`.
|
|
23
|
+
- Optional per-family overrides — omit any of these to let the generator harmoniously auto-derive it from `--primary` (secondary: boosted-lightness variant of primary's hue; tertiary: +60° hue rotation; general: near-neutral variant of primary's hue) or fall back to the generator's calibrated defaults (success/danger/warning/info):
|
|
24
|
+
`--secondary=#hex --tertiary=#hex --general=#hex --success=#hex --danger=#hex --warning=#hex --info=#hex`
|
|
25
|
+
- `--out=<path>` (optional): where to write the file. Defaults to `./<name>.ts` in the current working directory — always pass an explicit `--out` pointing into the consumer app's own theme directory (e.g. `src/theme/sunset.ts`), don't rely on the default.
|
|
26
|
+
|
|
27
|
+
If `@wangs-ui/foundation` isn't already a dependency of the project you're working in, install it first (`pnpm add @wangs-ui/foundation` or the project's equivalent) — the CLI ships as its `bin`.
|
|
28
|
+
|
|
29
|
+
**The written file is chmod'd read-only (0o444) and headed with an AUTO-GENERATED / DO NOT EDIT BY HAND comment.** If a color needs to change, re-run the command (it clears the read-only bit, rewrites, and re-locks it) — never hand-edit a shade in the output, and never `chmod` it writable to bypass this. Note the read-only bit is a local filesystem attribute only; it is not preserved by git across clones, so it is a deterrent for the person/agent working in this checkout right now, not a hard guarantee for every future contributor.
|
|
30
|
+
|
|
31
|
+
## 2. Wire it into the app
|
|
32
|
+
|
|
33
|
+
The generated file exports a plain `Palette` object — pass it directly to `WangsUiProvider`'s `theme.palette` (or `theme.defaultPalette` for uncontrolled mode):
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { WangsUiProvider } from '@wangs-ui/react-core/api';
|
|
37
|
+
import preset from '@wangs-ui/react-presets/fixedasset'; // or whichever preset the app uses
|
|
38
|
+
import { sunsetPalette } from './theme/sunset';
|
|
39
|
+
|
|
40
|
+
const App = () => (
|
|
41
|
+
<WangsUiProvider configOptions={{ preset }} theme={{ palette: sunsetPalette, mode: 'light' }}>
|
|
42
|
+
<YourApp />
|
|
43
|
+
</WangsUiProvider>
|
|
44
|
+
);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`theme.palette` also accepts a built-in palette name (`'blue' | 'emerald' | 'crimson' | 'carbon' | 'gold'`) or a raw hex string — a generated `Palette` object is the right choice once you have brand-specific secondary/tertiary/status colors to preserve, not just a single key color.
|
|
48
|
+
|
|
49
|
+
## 3. Regenerating / evolving an existing custom palette
|
|
50
|
+
|
|
51
|
+
To change a color, re-run the same command with a new hex for the family that changed — **always pass every family you want to keep**, not just the one changing, since each run is a full regeneration from the anchors you give it:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pnpm exec wangs-ui-generate-palette --name=sunset --primary=#ff6b35 --tertiary=#2a9d8f --out=src/theme/sunset.ts
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 4. If you're extending Wangs UI itself (contributing a new official palette)
|
|
58
|
+
|
|
59
|
+
This is a different, rarer case than theming a consumer app — only relevant if you're working inside the `wangs-ui-react` monorepo itself and adding a 6th built-in palette alongside blue/emerald/crimson/carbon/gold:
|
|
60
|
+
|
|
61
|
+
1. Run the generator with `--out` pointing at `packages/foundation/theme/tokens/palettes/<name>.ts`.
|
|
62
|
+
2. Register it: add `'<name>'` to the `PaletteName` union and `paletteLoaders` map in `packages/foundation/theme/context/ThemeContext.tsx`, and re-export it from `packages/foundation/theme/tokens/palettes/index.ts`.
|
|
63
|
+
3. Run the contrast regression suite before considering it done: `pnpm exec vitest run --config packages/foundation/vitest.config.ts` — it checks every semantic token pairing (including the new palette) against WCAG AA across both light and dark mode. See `packages/foundation/theme/tokens/COLOR_TOKEN_CONTRACT.md` for the full rule set this is checked against.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: create-form
|
|
3
3
|
description: Form architecture, validation workflows, strongly-typed forms (useForm, useDialogForm, useWatchField), initialValues/reset lifecycle, and MCP discovery protocol for building forms and input controls with @wangs-ui/react-core.
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
4
6
|
---
|
|
5
|
-
|
|
6
7
|
# Skill: Form Architecture & Validation Workflows
|
|
7
8
|
|
|
8
9
|
Use this skill when building forms, data entry panels, modal forms, settings pages, or multipart forms in Wangs UI applications.
|
|
@@ -13,28 +14,36 @@ Use this skill when building forms, data entry panels, modal forms, settings pag
|
|
|
13
14
|
|
|
14
15
|
Do **NOT** hardcode or guess prop names, component options, preset variations, or Storybook patterns in this document. Always retrieve component definitions, active props, and live Storybook implementations directly via MCP:
|
|
15
16
|
|
|
16
|
-
### Component & Form
|
|
17
|
+
### Component & Form API Protocol:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
get_component_api({ "component": "form" })
|
|
21
|
+
get_component_api({ "component": "field" })
|
|
22
|
+
get_component_api({ "component": "dialogform" })
|
|
23
|
+
get_component_api({ "component": "input" })
|
|
24
|
+
get_component_api({ "component": "numberinput" })
|
|
25
|
+
get_component_api({ "component": "select" })
|
|
26
|
+
get_component_api({ "component": "multiselect" })
|
|
27
|
+
get_component_api({ "component": "datepicker" })
|
|
28
|
+
get_component_api({ "component": "fileupload" })
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Curated Form Documentation:
|
|
17
32
|
|
|
18
33
|
```json
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
get-documentation({ "id": "input" })
|
|
23
|
-
get-documentation({ "id": "numberinput" })
|
|
24
|
-
get-documentation({ "id": "select" })
|
|
25
|
-
get-documentation({ "id": "multiselect" })
|
|
26
|
-
get-documentation({ "id": "datepicker" })
|
|
27
|
-
get-documentation({ "id": "fileupload" })
|
|
34
|
+
get_documentation({ "id": "form" })
|
|
35
|
+
get_documentation({ "id": "dialogform" })
|
|
36
|
+
get_documentation({ "id": "field" })
|
|
28
37
|
```
|
|
29
38
|
|
|
30
39
|
### Live Storybook & Interactive Behavior Protocol:
|
|
31
40
|
|
|
32
41
|
```json
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
get_component_examples({ "component": "form", "variant": "Default" })
|
|
43
|
+
get_component_examples({ "component": "form", "variant": "AsyncInitialValues" })
|
|
44
|
+
get_component_examples({ "component": "form", "variant": "ConditionalFields" })
|
|
45
|
+
get_component_examples({ "component": "form", "variant": "CascadingOptions" })
|
|
46
|
+
get_component_examples({ "component": "dialogform", "variant": "Default" })
|
|
38
47
|
```
|
|
39
48
|
|
|
40
49
|
### Knowledge Graph & Symbol Usages:
|
|
@@ -74,6 +83,8 @@ query_graph({ "query": "useWatchField" })
|
|
|
74
83
|
- **Children Render Callback**: `Field` yields `{ fieldProps, fieldState }`.
|
|
75
84
|
- **`fieldProps`**: Pass directly to primitive inputs (`<Input {...fieldProps} />`). Contains `name`, `value`, `ref`, `onChange`.
|
|
76
85
|
- **`fieldState`**: Provides `invalid`, `error`, `isDirty`, `isPending`. Pass `invalid={fieldState.invalid}` to primitive components for accessibility and validation styling.
|
|
86
|
+
- **⚠️ Mandatory Destructuring (Never `(field) => ...`)**: `<Field>`'s callback render prop must destructure as `{({ fieldProps, fieldState })}`. Passing a single parameter instead (`{(field) => ...}`) produces `undefined` `value`/`onChange` and permanently locks the input.
|
|
87
|
+
- **Pass `fieldProps.onChange` directly**: `<Field>` is generic and `fieldProps.onChange` is already typed to the field's value type. Do not wrap it in unnecessary `e?.target?.value` extractions.
|
|
77
88
|
|
|
78
89
|
---
|
|
79
90
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: data-table
|
|
3
3
|
description: Architecture, workflows, and MCP discovery protocol for building DataTables with sorting, pagination, filtering, selection, and export.
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
4
6
|
---
|
|
5
|
-
|
|
6
7
|
# Skill: DataTable Architecture & Integration Workflows
|
|
7
8
|
|
|
8
9
|
Use this skill when implementing data grids, server-paginated tables, filterable listing views, or batch management interfaces with `@wangs-ui/react-core`.
|
|
@@ -13,24 +14,31 @@ Use this skill when implementing data grids, server-paginated tables, filterable
|
|
|
13
14
|
|
|
14
15
|
Do **NOT** guess table prop names or hardcode table structures. Query the MCP server dynamically to inspect exact TypeScript signatures, live story implementations, and companion controls:
|
|
15
16
|
|
|
16
|
-
### Inspect Component Contracts:
|
|
17
|
+
### Inspect Component Contracts (`component` parameter):
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
get_component_api({ "component": "datatable" })
|
|
21
|
+
get_component_api({ "component": "exportbutton" })
|
|
22
|
+
get_component_api({ "component": "filtercontainer" })
|
|
23
|
+
get_component_api({ "component": "bulkactionbutton" })
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Read Curated Documentation:
|
|
17
27
|
|
|
18
28
|
```json
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
get-documentation({ "id": "filtercontainer" })
|
|
22
|
-
get-documentation({ "id": "bulkactionbutton" })
|
|
29
|
+
get_documentation({ "id": "datatable" })
|
|
30
|
+
get_documentation({ "id": "exportbutton" })
|
|
23
31
|
```
|
|
24
32
|
|
|
25
33
|
### Inspect Live Story Implementations:
|
|
26
34
|
|
|
27
35
|
```json
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
get_component_examples({ "component": "datatable", "variant": "Basic" })
|
|
37
|
+
get_component_examples({ "component": "datatable", "variant": "CursorPagination" })
|
|
38
|
+
get_component_examples({ "component": "datatable", "variant": "Sortable" })
|
|
39
|
+
get_component_examples({ "component": "datatable", "variant": "MultipleSelection" })
|
|
40
|
+
get_component_examples({ "component": "datatable", "variant": "CustomColumn" })
|
|
41
|
+
get_component_examples({ "component": "exportbutton", "variant": "WithTable" })
|
|
34
42
|
```
|
|
35
43
|
|
|
36
44
|
### Inspect Knowledge Graph & Usages:
|
|
@@ -47,7 +55,7 @@ query_graph({ "query": "useDataTableFetch" })
|
|
|
47
55
|
The Wangs UI `DataTable` is built on a modular, headless-first architecture:
|
|
48
56
|
|
|
49
57
|
1. **Declarative Column Definitions (`TableColumn<T>[]`)**:
|
|
50
|
-
Columns are configured as typed array objects, not as JSX children. Check `
|
|
58
|
+
Columns are configured as typed array objects, not as JSX children. Check `get_component_api({ "component": "datatable" })` for column field types.
|
|
51
59
|
2. **Table Instance Hook (`useDataTable`)**:
|
|
52
60
|
Coordinates table state (sorting, pagination, selection, column ordering, pinning, visibility).
|
|
53
61
|
3. **Data Fetching Hook (`useDataTableFetch`)**:
|
|
@@ -62,7 +70,8 @@ The Wangs UI `DataTable` is built on a modular, headless-first architecture:
|
|
|
62
70
|
|
|
63
71
|
## 3. Mandatory Implementation Rules
|
|
64
72
|
|
|
65
|
-
1. **Query MCP for Current Code Patterns**: Always run `
|
|
73
|
+
1. **Query MCP for Current Code Patterns**: Always run `get_component_examples` for `datatable` before drafting code.
|
|
66
74
|
2. **Strict Subpath Imports**: Import via `@wangs-ui/react-core/primitive/datatable` and companion primitive paths.
|
|
67
75
|
3. **Always Translate Visible Copy**: All column header labels, empty state messages, and action button labels must be wrapped in `t('...')` from `@wangs-ui/react-i18n`.
|
|
68
|
-
4. **Stable Row Identity**: Always configure a unique key identifier for stable selection and row identity.
|
|
76
|
+
4. **Stable Row Identity**: Always configure a unique key identifier (`dataKey` / `rowId`) for stable selection and row identity.
|
|
77
|
+
5. **Zero Redundant Table Wrappers**: Never wrap `<DataTable />` in an isolated `<div>` or `<Box>` solely to set width or margin. Wangs UI DataTable manages its own container scroll and layout dimensions out of the box.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dialog-modal
|
|
3
3
|
description: Patterns, overlay selection criteria, and MCP discovery protocol for Dialog, Modal, and DialogForm components in Wangs UI.
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
4
6
|
---
|
|
5
|
-
|
|
6
7
|
# Skill: Dialog, Modal & Overlay Workflows
|
|
7
8
|
|
|
8
9
|
Use this skill when building interactive modals, create/edit dialog forms, destructive action confirmations, or slide-in overlay panels.
|
|
@@ -13,21 +14,29 @@ Use this skill when building interactive modals, create/edit dialog forms, destr
|
|
|
13
14
|
|
|
14
15
|
Do **NOT** guess overlay props, event names, or footer slots. Query the MCP server dynamically to inspect exact contracts and live story implementations:
|
|
15
16
|
|
|
16
|
-
### Inspect Overlay Contracts:
|
|
17
|
+
### Inspect Overlay Contracts (`component` parameter):
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
get_component_api({ "component": "dialog" })
|
|
21
|
+
get_component_api({ "component": "dialogform" })
|
|
22
|
+
get_component_api({ "component": "modal" })
|
|
23
|
+
get_component_api({ "component": "toast" })
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Read Curated Overlay Documentation:
|
|
17
27
|
|
|
18
28
|
```json
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
get-documentation({ "id": "toast" })
|
|
29
|
+
get_documentation({ "id": "dialog" })
|
|
30
|
+
get_documentation({ "id": "dialogform" })
|
|
31
|
+
get_documentation({ "id": "modal" })
|
|
23
32
|
```
|
|
24
33
|
|
|
25
34
|
### Inspect Live Story Implementations:
|
|
26
35
|
|
|
27
36
|
```json
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
get_component_examples({ "component": "dialog", "variant": "RichHeaderFooter" })
|
|
38
|
+
get_component_examples({ "component": "dialogform", "variant": "Default" })
|
|
39
|
+
get_component_examples({ "component": "modal", "variant": "Default" })
|
|
31
40
|
```
|
|
32
41
|
|
|
33
42
|
### Inspect Knowledge Graph & Usages:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: i18n-usage
|
|
3
3
|
description: Comprehensive guidelines for application internationalization, JIT translations (t), ICU formatting, and locale-aware formatting with @wangs-ui/react-i18n.
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
4
6
|
---
|
|
5
|
-
|
|
6
7
|
# Skill: Application Internationalization & Formatting Protocol
|
|
7
8
|
|
|
8
9
|
Use this skill when implementing multi-language interfaces, translating user-facing text, formatting dates, times, currencies, or numbers in React applications built with Wangs UI and `@wangs-ui/react-i18n`.
|
|
@@ -13,22 +14,29 @@ Use this skill when implementing multi-language interfaces, translating user-fac
|
|
|
13
14
|
|
|
14
15
|
Do **NOT** guess component localization contracts, language switcher variants, or datepicker props. Query the MCP server dynamically to inspect exact props and live story implementations:
|
|
15
16
|
|
|
16
|
-
### Inspect Localized Component Contracts:
|
|
17
|
+
### Inspect Localized Component Contracts (`component` parameter):
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
get_component_api({ "component": "languageswitcher" })
|
|
21
|
+
get_component_api({ "component": "currencyinput" })
|
|
22
|
+
get_component_api({ "component": "datepicker" })
|
|
23
|
+
get_component_api({ "component": "select" })
|
|
24
|
+
get_component_api({ "component": "datatable" })
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Read Curated Localization Documentation:
|
|
17
28
|
|
|
18
29
|
```json
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
get-documentation({ "id": "datepicker" })
|
|
22
|
-
get-documentation({ "id": "select" })
|
|
23
|
-
get-documentation({ "id": "datatable" })
|
|
30
|
+
get_documentation({ "id": "languageswitcher" })
|
|
31
|
+
get_documentation({ "id": "currencyinput" })
|
|
24
32
|
```
|
|
25
33
|
|
|
26
34
|
### Inspect Live Story Implementations:
|
|
27
35
|
|
|
28
36
|
```json
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
get_component_examples({ "component": "languageswitcher", "variant": "Default" })
|
|
38
|
+
get_component_examples({ "component": "currencyinput", "variant": "Default" })
|
|
39
|
+
get_component_examples({ "component": "datepicker", "variant": "Default" })
|
|
32
40
|
```
|
|
33
41
|
|
|
34
42
|
---
|
|
@@ -132,7 +140,7 @@ selectedCount === 0
|
|
|
132
140
|
Use standard supported HTML tags (`<a>`, `<b>`, `<i>`, `<u>`, `<s>`, `<br/>`, `<sub>`, `<sup>`, `<code>`, `<mark>`) for inline styling. Tags are automatically parsed into React elements without custom regex or string manipulation:
|
|
133
141
|
|
|
134
142
|
```tsx
|
|
135
|
-
import Link from '@wangs-ui/foundation/theme
|
|
143
|
+
import { Link } from '@wangs-ui/foundation/theme';
|
|
136
144
|
|
|
137
145
|
t('You have selected <b>{count} items</b>. Click <a>here</a> to review.', {
|
|
138
146
|
count: selectedCount,
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: layout-navigation
|
|
3
|
+
description: Architecture, navigation hierarchies, and MCP discovery protocol for AppLayout, Sidebar, Breadcrumb, and Tabs in Wangs UI.
|
|
4
|
+
metadata:
|
|
5
|
+
owner: wangs-ui
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Skill: Application Layout & Navigation Hierarchy
|
|
9
|
+
|
|
10
|
+
Use this skill when constructing application shells, multi-level sidebars, page headers, breadcrumbs, tabbed views, or feature routing with `@wangs-ui/react-core`, `@wangs-ui/foundation`, and `@wangs-ui/react-navigation`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. MCP Inspection Protocol (Mandatory Single Source of Truth)
|
|
15
|
+
|
|
16
|
+
Do **NOT** guess layout block slots, sidebar item interfaces, or breadcrumb props. Query the MCP server dynamically to inspect exact contracts and live story implementations:
|
|
17
|
+
|
|
18
|
+
### Inspect Layout & Navigation Contracts (`component` parameter):
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
get_component_api({ "component": "applayout" })
|
|
22
|
+
get_component_api({ "component": "sidebar" })
|
|
23
|
+
get_component_api({ "component": "tabletoolbar" })
|
|
24
|
+
get_component_api({ "component": "breadcrumb" })
|
|
25
|
+
get_component_api({ "component": "tabs" })
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Read Curated Layout Documentation (`id` parameter):
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
get_documentation({ "id": "applayout" })
|
|
33
|
+
get_documentation({ "id": "sidebar" })
|
|
34
|
+
get_documentation({ "id": "react-navigation" })
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Inspect Live Story Implementations:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
get_component_examples({ "component": "applayout", "variant": "TopNavbar" })
|
|
41
|
+
get_component_examples({ "component": "sidebar", "variant": "WithSubMenu" })
|
|
42
|
+
get_component_examples({ "component": "breadcrumb", "variant": "Default" })
|
|
43
|
+
get_component_examples({ "component": "tabs", "variant": "Default" })
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Inspect Knowledge Graph & Usages:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
query_graph({ "query": "AppLayout" })
|
|
50
|
+
query_graph({ "query": "Sidebar" })
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 2. Layout Architecture & Mental Model
|
|
56
|
+
|
|
57
|
+
1. **Top-Level App Shell (`AppLayout`)**:
|
|
58
|
+
- Subpath: `@wangs-ui/react-core/blocks/applayout`
|
|
59
|
+
- Outer responsive shell arranging navigation, navbar, sidebars, main viewport, and footer. Inspect slots and layout variants via `get_component_api({ "component": "applayout" })`.
|
|
60
|
+
2. **Hierarchical Menu (`Sidebar`)**:
|
|
61
|
+
- Subpath: `@wangs-ui/react-core/blocks/sidebar`
|
|
62
|
+
- Primary app navigation drawer/rail supporting nested menus, badges, and collapse states. Inspect items and events via `get_component_api({ "component": "sidebar" })`.
|
|
63
|
+
3. **Breadcrumb Trail (`Breadcrumb`)**:
|
|
64
|
+
- Subpath: `@wangs-ui/react-core/primitive/breadcrumb`
|
|
65
|
+
- Secondary hierarchy navigation displaying screen depth. Inspect item structure via `get_component_api({ "component": "breadcrumb" })`.
|
|
66
|
+
4. **Tabbed Sub-Views (`Tabs`)**:
|
|
67
|
+
- Subpath: `@wangs-ui/react-core/primitive/tabs`
|
|
68
|
+
- In-page view switcher for partitioning entity details into distinct panels. Inspect via `get_component_api({ "component": "tabs" })`.
|
|
69
|
+
5. **Universal Routing (`@wangs-ui/react-navigation`)**:
|
|
70
|
+
- Platform-agnostic route graph abstraction (`buildGraph`, `paramRoute`).
|
|
71
|
+
- Web router bridge: `@wangs-ui/react-navigation/web` (React Router).
|
|
72
|
+
- Native router bridge: `@wangs-ui/react-navigation/native` (React Navigation / Expo).
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 3. Structural Page Blueprint (Standard Pattern)
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import AppLayout from '@wangs-ui/react-core/blocks/applayout';
|
|
80
|
+
import Sidebar from '@wangs-ui/react-core/blocks/sidebar';
|
|
81
|
+
import Breadcrumb from '@wangs-ui/react-core/primitive/breadcrumb';
|
|
82
|
+
import { Container, Section, Stack, HStack } from '@wangs-ui/foundation/layout';
|
|
83
|
+
import { Text } from '@wangs-ui/foundation/theme';
|
|
84
|
+
import { useI18n } from '@wangs-ui/react-i18n';
|
|
85
|
+
import { HomeLine, Settings4Line } from '@wangs-ui/react-icons';
|
|
86
|
+
import { useState } from 'react';
|
|
87
|
+
|
|
88
|
+
export function ApplicationShell({ children }: { children: React.ReactNode }) {
|
|
89
|
+
const { t } = useI18n();
|
|
90
|
+
const [activeRoute, setActiveRoute] = useState('dashboard');
|
|
91
|
+
const [collapsed, setCollapsed] = useState(false);
|
|
92
|
+
|
|
93
|
+
const sidebarItems = [
|
|
94
|
+
{ value: 'dashboard', label: t('Dashboard'), icon: HomeLine, to: '/' },
|
|
95
|
+
{ value: 'settings', label: t('Settings'), icon: Settings4Line, to: '/settings' },
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<AppLayout
|
|
100
|
+
variant="full-sidebar"
|
|
101
|
+
sidebar={
|
|
102
|
+
<Sidebar
|
|
103
|
+
items={sidebarItems}
|
|
104
|
+
value={activeRoute}
|
|
105
|
+
onValueChange={setActiveRoute}
|
|
106
|
+
collapsed={collapsed}
|
|
107
|
+
onCollapsedChange={setCollapsed}
|
|
108
|
+
collapseMode="rail"
|
|
109
|
+
/>
|
|
110
|
+
}
|
|
111
|
+
>
|
|
112
|
+
<Container size="xl">
|
|
113
|
+
<Section space="md">
|
|
114
|
+
<Stack gap="4">
|
|
115
|
+
<Breadcrumb
|
|
116
|
+
items={[
|
|
117
|
+
{ label: t('Home'), href: '/' },
|
|
118
|
+
{ label: t('Dashboard') },
|
|
119
|
+
]}
|
|
120
|
+
/>
|
|
121
|
+
<Text variant="headlineLarge">{t('Overview')}</Text>
|
|
122
|
+
{children}
|
|
123
|
+
</Stack>
|
|
124
|
+
</Section>
|
|
125
|
+
</Container>
|
|
126
|
+
</AppLayout>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 4. Mandatory Implementation Rules
|
|
134
|
+
|
|
135
|
+
1. **Query MCP First**: Always inspect `applayout` and `sidebar` stories via MCP before assembling the layout.
|
|
136
|
+
2. **Strict Subpath Imports**:
|
|
137
|
+
- Blocks: `@wangs-ui/react-core/blocks/*` (`applayout`, `sidebar`, `tabletoolbar`)
|
|
138
|
+
- Primitives: `@wangs-ui/react-core/primitive/*` (`breadcrumb`, `tabs`)
|
|
139
|
+
- Layout Primitives: `@wangs-ui/foundation/layout` (`Container`, `Section`, `Stack`, `HStack`, `Box`, `Grid`)
|
|
140
|
+
- Typography: `@wangs-ui/foundation/theme` (`Text`)
|
|
141
|
+
3. **Standard Layout Containers & Spacing**:
|
|
142
|
+
- Use `Container` (max-width rhythm) and `Section` (vertical rhythm) for page boundaries.
|
|
143
|
+
- Use flat numeric Tailwind spacing (`gap="4"`, `p="6"`). Never use legacy named tokens like `p-3xl` or `gap-md`.
|
|
144
|
+
4. **Typography Scale**:
|
|
145
|
+
- Use `<Text variant="headlineLarge">` or `display*` / `title*` for page headers. Never use obsolete `.heading-*` helper classes or raw HTML heading tags without primitives.
|
|
146
|
+
5. **No Redundant Layout Wrappers**:
|
|
147
|
+
- Do NOT insert intermediate pass-through `<div>` or `<Box>` wrappers between `<Card>`/`<Tabs>` and tab contents.
|
|
148
|
+
- Render active tab content directly as a child of the container:
|
|
149
|
+
```tsx
|
|
150
|
+
// ✅ Good
|
|
151
|
+
<Card>
|
|
152
|
+
<Tabs items={tabItems} value={activeTab} onValueChange={setActiveTab} />
|
|
153
|
+
{activeTab === 'general' ? <GeneralTab /> : <SecurityTab />}
|
|
154
|
+
</Card>
|
|
155
|
+
```
|
|
156
|
+
6. **Translate Navigation Labels**: Wrap all sidebar item labels, breadcrumb text, and page headings in `t('...')` from `@wangs-ui/react-i18n`.
|