@zvoove/unity-ui 2.21.0 → 2.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/generate-skills.mjs +1242 -9
- package/dist/llms.txt +258 -0
- package/dist/theme.css +2 -0
- package/dist/unity-ui.cjs.js +1 -1
- package/dist/unity-ui.css +1 -1
- package/dist/unity-ui.es.js +2 -2
- package/package.json +10 -10
package/dist/llms.txt
CHANGED
|
@@ -1075,6 +1075,264 @@ useClickOutside(ref, () => setOpen(false), isOpen);
|
|
|
1075
1075
|
|
|
1076
1076
|
---
|
|
1077
1077
|
|
|
1078
|
+
## STYLING
|
|
1079
|
+
|
|
1080
|
+
When a UI element has no matching Unity UI component, use **Tailwind CSS v4** with the Unity UI design tokens. **Never use inline styles or arbitrary CSS values.**
|
|
1081
|
+
|
|
1082
|
+
### Setup
|
|
1083
|
+
|
|
1084
|
+
```bash
|
|
1085
|
+
npm install tailwindcss tailwind-variants tailwind-merge
|
|
1086
|
+
```
|
|
1087
|
+
|
|
1088
|
+
In your Tailwind CSS entry file:
|
|
1089
|
+
```css
|
|
1090
|
+
@import 'tailwindcss';
|
|
1091
|
+
@import '@zvoove/unity-ui/theme.css'; /* registers all design tokens as Tailwind utilities */
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
### Design Tokens as Tailwind Classes
|
|
1095
|
+
|
|
1096
|
+
All tokens from `theme.css` are available as Tailwind utilities. Use **semantic** tokens, not raw palette tokens.
|
|
1097
|
+
|
|
1098
|
+
**Colors (semantic — always prefer these)**
|
|
1099
|
+
| Token | Tailwind utility | Use for |
|
|
1100
|
+
|-------|-----------------|---------|
|
|
1101
|
+
| `--color-primary` | `bg-primary` / `text-primary` / `border-primary` | Primary brand color |
|
|
1102
|
+
| `--color-on-primary` | `text-on-primary` | Text on primary backgrounds |
|
|
1103
|
+
| `--color-surface` | `bg-surface` | Card/panel backgrounds |
|
|
1104
|
+
| `--color-surface-container` | `bg-surface-container` | Nested container backgrounds |
|
|
1105
|
+
| `--color-on-surface` | `text-on-surface` | Body text |
|
|
1106
|
+
| `--color-on-surface-variant` | `text-on-surface-variant` | Secondary/muted text |
|
|
1107
|
+
| `--color-outline` | `border-outline` | Default borders |
|
|
1108
|
+
| `--color-outline-variant` | `border-outline-variant` | Subtle dividers |
|
|
1109
|
+
| `--color-outline-variant-low` | `border-outline-variant-low` | Very subtle dividers/borders |
|
|
1110
|
+
| `--color-error` | `bg-error` / `text-error` | Error states |
|
|
1111
|
+
| `--color-background` | `bg-background` | Page background |
|
|
1112
|
+
|
|
1113
|
+
**Spacing** (for gap, padding, margin, width, height)
|
|
1114
|
+
`none`(0) • `xs2`(4px) • `xs`(8px) • `sm`(12px) • `md`(16px) • `lg`(20px) • `xl`(24px) • `xl2`(32px) • `xl3`(40px) • `xl4`(48px) • `xl5`(64px) • `xl6`(80px) • `xl7`(96px)
|
|
1115
|
+
|
|
1116
|
+
Examples: `p-md`, `gap-lg`, `mx-xl`, `w-xl4`
|
|
1117
|
+
|
|
1118
|
+
**Typography**
|
|
1119
|
+
`text-body-small` • `text-body-medium` • `text-body-large`
|
|
1120
|
+
`text-label-small` • `text-label-medium` • `text-label-large`
|
|
1121
|
+
`text-title-small` • `text-title-medium` • `text-title-large`
|
|
1122
|
+
`text-headline-small` • `text-headline-medium` • `text-headline-large`
|
|
1123
|
+
`text-display-small` • `text-display-medium` • `text-display-large`
|
|
1124
|
+
|
|
1125
|
+
**Border radius**: `rounded-none` • `rounded-xs` • `rounded-sm` • `rounded-md` • `rounded-lg` • `rounded-xl` • `rounded-full`
|
|
1126
|
+
|
|
1127
|
+
**Shadows**: `shadow-elevation1` • `shadow-elevation2` • `shadow-elevation3` • `shadow-elevation4` • `shadow-elevation5`
|
|
1128
|
+
Dark mode shadows: `dark:shadow-elevation1-dark` (replace `elevation1` with the level you need)
|
|
1129
|
+
|
|
1130
|
+
**Dark mode**: use `dark:` Tailwind prefix. Activated by `data-theme="dark"` on a parent element — not via `prefers-color-scheme`.
|
|
1131
|
+
|
|
1132
|
+
### tailwind-variants for Component Variants
|
|
1133
|
+
|
|
1134
|
+
Use `tailwind-variants` when a custom UI element has multiple visual variants.
|
|
1135
|
+
|
|
1136
|
+
Configure `tv` with Unity UI spacing tokens so class merging works correctly:
|
|
1137
|
+
```ts
|
|
1138
|
+
import { createTV } from 'tailwind-variants';
|
|
1139
|
+
|
|
1140
|
+
export const tv = createTV({
|
|
1141
|
+
twMergeConfig: {
|
|
1142
|
+
theme: {
|
|
1143
|
+
spacing: ['none', 'xs2', 'xs', 'sm', 'md', 'lg', 'xl', 'xl2', 'xl3', 'xl4', 'xl5', 'xl6', 'xl7'],
|
|
1144
|
+
borderRadius: ['none', 'xs', 'sm', 'md', 'lg', 'xl', 'full'],
|
|
1145
|
+
},
|
|
1146
|
+
},
|
|
1147
|
+
});
|
|
1148
|
+
```
|
|
1149
|
+
|
|
1150
|
+
Usage:
|
|
1151
|
+
```ts
|
|
1152
|
+
const badge = tv({
|
|
1153
|
+
base: ['inline-flex', 'items-center', 'rounded-full', 'px-sm', 'py-xs2', 'text-label-small'],
|
|
1154
|
+
variants: {
|
|
1155
|
+
tone: {
|
|
1156
|
+
primary: ['bg-primary-container', 'text-on-primary-container'],
|
|
1157
|
+
error: ['bg-error-container', 'text-on-error-container'],
|
|
1158
|
+
surface: ['bg-surface-container', 'text-on-surface'],
|
|
1159
|
+
},
|
|
1160
|
+
},
|
|
1161
|
+
defaultVariants: { tone: 'surface' },
|
|
1162
|
+
});
|
|
1163
|
+
|
|
1164
|
+
// Apply:
|
|
1165
|
+
<div className={badge({ tone: 'primary' })}>Label</div>
|
|
1166
|
+
```
|
|
1167
|
+
|
|
1168
|
+
### Class Merging
|
|
1169
|
+
|
|
1170
|
+
Use `tailwind-merge` for ad-hoc merging (e.g. accepting a `className` prop):
|
|
1171
|
+
```ts
|
|
1172
|
+
import { twMerge } from 'tailwind-merge';
|
|
1173
|
+
|
|
1174
|
+
const className = twMerge('p-md bg-surface', props.className);
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
### Rules
|
|
1178
|
+
|
|
1179
|
+
- NEVER use inline styles: `style={{ color: '#ff0000', padding: '13px' }}`
|
|
1180
|
+
- NEVER use arbitrary Tailwind values: `p-[13px]`, `text-[#ff0000]`, `bg-[rgba(0,0,0,0.5)]`
|
|
1181
|
+
- NEVER use generic Tailwind size utilities for spacing — use design tokens: `p-md` not `p-4`
|
|
1182
|
+
- NEVER use generic Tailwind text utilities for typography — use design tokens: `text-body-medium` not `text-sm`
|
|
1183
|
+
- ALWAYS use semantic color tokens (`bg-primary`, `text-on-surface`) not palette tokens (`bg-primary-40`)
|
|
1184
|
+
- Use `tv()` from `tailwind-variants` when a custom element has multiple visual variants
|
|
1185
|
+
- Use `dark:` prefix for dark mode — never hard-code colors per theme in two separate class sets
|
|
1186
|
+
|
|
1187
|
+
---
|
|
1188
|
+
|
|
1189
|
+
## CUSTOM COMPONENT
|
|
1190
|
+
|
|
1191
|
+
When you need UI that no existing Unity UI component covers, create a custom component that follows the same conventions so it stays consistent with the design system.
|
|
1192
|
+
|
|
1193
|
+
### File Structure
|
|
1194
|
+
|
|
1195
|
+
```
|
|
1196
|
+
src/components/MyComponent/
|
|
1197
|
+
MyComponent.tsx # Component implementation
|
|
1198
|
+
MyComponent.styled.ts # tailwind-variants styles
|
|
1199
|
+
MyComponent.types.ts # TypeScript props interface
|
|
1200
|
+
MyComponent.test.tsx # Vitest + RTL tests (optional but recommended)
|
|
1201
|
+
index.ts # Re-exports
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
### `MyComponent.types.ts`
|
|
1205
|
+
|
|
1206
|
+
```ts
|
|
1207
|
+
import { ReactNode } from 'react';
|
|
1208
|
+
|
|
1209
|
+
export interface MyComponentProps {
|
|
1210
|
+
/**
|
|
1211
|
+
* Content to render inside the component.
|
|
1212
|
+
*/
|
|
1213
|
+
children?: ReactNode;
|
|
1214
|
+
|
|
1215
|
+
/**
|
|
1216
|
+
* Visual variant.
|
|
1217
|
+
* @default 'primary'
|
|
1218
|
+
*/
|
|
1219
|
+
variant?: 'primary' | 'secondary';
|
|
1220
|
+
}
|
|
1221
|
+
```
|
|
1222
|
+
|
|
1223
|
+
Rules:
|
|
1224
|
+
- JSDoc on every prop; `@default` on every defaulted prop
|
|
1225
|
+
- Named export only
|
|
1226
|
+
|
|
1227
|
+
### `MyComponent.styled.ts`
|
|
1228
|
+
|
|
1229
|
+
```ts
|
|
1230
|
+
import { createTV } from 'tailwind-variants';
|
|
1231
|
+
|
|
1232
|
+
// Configure tv with Unity UI spacing/radius tokens for correct class merging
|
|
1233
|
+
const tv = createTV({
|
|
1234
|
+
twMergeConfig: {
|
|
1235
|
+
theme: {
|
|
1236
|
+
spacing: ['none', 'xs2', 'xs', 'sm', 'md', 'lg', 'xl', 'xl2', 'xl3', 'xl4', 'xl5', 'xl6', 'xl7'],
|
|
1237
|
+
borderRadius: ['none', 'xs', 'sm', 'md', 'lg', 'xl', 'full'],
|
|
1238
|
+
},
|
|
1239
|
+
},
|
|
1240
|
+
});
|
|
1241
|
+
|
|
1242
|
+
export const myComponentStyles = tv({
|
|
1243
|
+
base: ['text-body-medium', 'rounded-sm'],
|
|
1244
|
+
variants: {
|
|
1245
|
+
variant: {
|
|
1246
|
+
primary: ['bg-primary', 'text-on-primary'],
|
|
1247
|
+
secondary: ['bg-surface-container', 'text-on-surface'],
|
|
1248
|
+
},
|
|
1249
|
+
},
|
|
1250
|
+
defaultVariants: {
|
|
1251
|
+
variant: 'primary',
|
|
1252
|
+
},
|
|
1253
|
+
});
|
|
1254
|
+
```
|
|
1255
|
+
|
|
1256
|
+
Tip: define the configured `tv` once in a shared `lib/tv.ts` file in your project and import from there instead of re-configuring in every component.
|
|
1257
|
+
|
|
1258
|
+
### `MyComponent.tsx` — Simple
|
|
1259
|
+
|
|
1260
|
+
```tsx
|
|
1261
|
+
import { myComponentStyles } from './MyComponent.styled';
|
|
1262
|
+
import { MyComponentProps } from './MyComponent.types';
|
|
1263
|
+
|
|
1264
|
+
const MyComponent = ({
|
|
1265
|
+
children,
|
|
1266
|
+
variant = 'primary',
|
|
1267
|
+
}: MyComponentProps) => {
|
|
1268
|
+
return (
|
|
1269
|
+
<div className={myComponentStyles({ variant })}>
|
|
1270
|
+
{children}
|
|
1271
|
+
</div>
|
|
1272
|
+
);
|
|
1273
|
+
};
|
|
1274
|
+
|
|
1275
|
+
MyComponent.displayName = 'MyComponent';
|
|
1276
|
+
|
|
1277
|
+
export default MyComponent;
|
|
1278
|
+
```
|
|
1279
|
+
|
|
1280
|
+
### `MyComponent.tsx` — With `forwardRef`
|
|
1281
|
+
|
|
1282
|
+
Use when the root is a DOM element consumers may need a ref for:
|
|
1283
|
+
|
|
1284
|
+
```tsx
|
|
1285
|
+
import { forwardRef } from 'react';
|
|
1286
|
+
|
|
1287
|
+
import { myComponentStyles } from './MyComponent.styled';
|
|
1288
|
+
import { MyComponentProps } from './MyComponent.types';
|
|
1289
|
+
|
|
1290
|
+
const MyComponent = forwardRef<HTMLDivElement, MyComponentProps>(
|
|
1291
|
+
({ children, variant = 'primary', ...props }, ref) => {
|
|
1292
|
+
return (
|
|
1293
|
+
<div
|
|
1294
|
+
ref={ref}
|
|
1295
|
+
className={myComponentStyles({ variant })}
|
|
1296
|
+
{...props}
|
|
1297
|
+
>
|
|
1298
|
+
{children}
|
|
1299
|
+
</div>
|
|
1300
|
+
);
|
|
1301
|
+
}
|
|
1302
|
+
);
|
|
1303
|
+
|
|
1304
|
+
MyComponent.displayName = 'MyComponent';
|
|
1305
|
+
|
|
1306
|
+
export default MyComponent;
|
|
1307
|
+
```
|
|
1308
|
+
|
|
1309
|
+
### `index.ts`
|
|
1310
|
+
|
|
1311
|
+
```ts
|
|
1312
|
+
export { default as MyComponent } from './MyComponent';
|
|
1313
|
+
export type { MyComponentProps } from './MyComponent.types';
|
|
1314
|
+
```
|
|
1315
|
+
|
|
1316
|
+
### Using Unity UI Components Inside Custom Components
|
|
1317
|
+
|
|
1318
|
+
```tsx
|
|
1319
|
+
import { Icon, Stack, Typography } from '@zvoove/unity-ui';
|
|
1320
|
+
```
|
|
1321
|
+
|
|
1322
|
+
Always compose with existing Unity UI components rather than re-implementing their functionality.
|
|
1323
|
+
|
|
1324
|
+
### Rules
|
|
1325
|
+
|
|
1326
|
+
- Always set `ComponentName.displayName = 'ComponentName'`
|
|
1327
|
+
- Always JSDoc every prop with `@default` on defaulted props
|
|
1328
|
+
- Use `tv()` from `tailwind-variants` (configured with Unity UI tokens — see `unity-ui-styling` skill)
|
|
1329
|
+
- Use design tokens as Tailwind utilities — no arbitrary values, no inline styles
|
|
1330
|
+
- Use `forwardRef` when the root is a DOM element that callers may need to reference
|
|
1331
|
+
- Import Unity UI components from `@zvoove/unity-ui`
|
|
1332
|
+
- Never recreate what an existing Unity UI component already does
|
|
1333
|
+
|
|
1334
|
+
---
|
|
1335
|
+
|
|
1078
1336
|
## SPACING SCALE
|
|
1079
1337
|
|
|
1080
1338
|
Use these values for gap, padding, and margin props:
|
package/dist/theme.css
CHANGED
|
@@ -278,6 +278,7 @@
|
|
|
278
278
|
--color-on-surface-variant: var(--color-neutral-variant-40);
|
|
279
279
|
--color-outline: var(--color-neutral-variant-70);
|
|
280
280
|
--color-outline-variant: var(--color-neutral-variant-90);
|
|
281
|
+
--color-outline-variant-low: var(--color-neutral-variant-50);
|
|
281
282
|
--color-error: var(--color-error-40);
|
|
282
283
|
--color-error-hover: var(--color-error-50);
|
|
283
284
|
--color-on-error: var(--color-error-100);
|
|
@@ -498,6 +499,7 @@
|
|
|
498
499
|
--color-on-surface-variant: var(--color-neutral-70);
|
|
499
500
|
--color-outline: var(--color-neutral-50);
|
|
500
501
|
--color-outline-variant: var(--color-neutral-30);
|
|
502
|
+
--color-outline-variant-low: var(--color-neutral-variant-60);
|
|
501
503
|
--color-error: var(--color-error-80);
|
|
502
504
|
--color-error-hover: var(--color-error-70);
|
|
503
505
|
--color-on-error: var(--color-error-20);
|