@zvoove/unity-ui 2.22.1 → 2.23.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 +8 -76
- package/bin/cli.mjs +49 -0
- package/bin/commands/config.mjs +68 -0
- package/bin/commands/create.mjs +163 -0
- package/bin/commands/init.mjs +158 -0
- package/bin/commands/rules.mjs +100 -0
- package/bin/commands/skills.mjs +1883 -0
- package/bin/generate-skills.mjs +19 -1903
- package/bin/templates/component.tsx +15 -0
- package/bin/templates/doc.mdx +36 -0
- package/bin/templates/index.ts +2 -0
- package/bin/templates/stories.tsx +15 -0
- package/bin/templates/styled.ts +14 -0
- package/bin/templates/test.tsx +30 -0
- package/bin/templates/types.ts +13 -0
- package/dist/llms.txt +150 -43
- package/dist/theme.css +44 -0
- package/dist/unity-ui.cjs.js +1 -1
- package/dist/unity-ui.css +1 -1
- package/dist/unity-ui.d.ts +575 -24
- package/dist/unity-ui.es.js +762 -389
- package/package.json +9 -6
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { __STYLES__FUNCTION__Styles } from './__COMPONENT_NAME__.styled';
|
|
2
|
+
import { __COMPONENT_NAME__Props } from './__COMPONENT_NAME__.types';
|
|
3
|
+
|
|
4
|
+
const __COMPONENT_NAME__ = ({
|
|
5
|
+
children,
|
|
6
|
+
variant = 'primary',
|
|
7
|
+
}: __COMPONENT_NAME__Props) => {
|
|
8
|
+
return (
|
|
9
|
+
<div className={__STYLES__FUNCTION__Styles({ variant })}>{children}</div>
|
|
10
|
+
);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
__COMPONENT_NAME__.displayName = '__COMPONENT_NAME__';
|
|
14
|
+
|
|
15
|
+
export default __COMPONENT_NAME__;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Canvas, Controls, Meta } from '@storybook/addon-docs/blocks';
|
|
2
|
+
|
|
3
|
+
import { __COMPONENT_NAME__ } from '.';
|
|
4
|
+
import * as __COMPONENT_NAME__Stories from './__COMPONENT_NAME__.stories';
|
|
5
|
+
|
|
6
|
+
<Meta of={__COMPONENT_NAME__Stories} />
|
|
7
|
+
|
|
8
|
+
# **COMPONENT_NAME**
|
|
9
|
+
|
|
10
|
+
The `__COMPONENT_NAME__` component is a auto generated component using the `npm run create <componentName>` script.
|
|
11
|
+
|
|
12
|
+
<Canvas sourceState="none" of={__COMPONENT_NAME__Stories.Default} />
|
|
13
|
+
|
|
14
|
+
<Controls of={__COMPONENT_NAME__Stories.Default} />
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```jsx
|
|
19
|
+
import { __COMPONENT_NAME__ } from '@zvoove/unity-ui';
|
|
20
|
+
|
|
21
|
+
<__COMPONENT_NAME__ />;
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Variants
|
|
25
|
+
|
|
26
|
+
### Default
|
|
27
|
+
|
|
28
|
+
The default `__COMPONENT_NAME__` component has the following features:
|
|
29
|
+
|
|
30
|
+
<Canvas sourceState="none" of={__COMPONENT_NAME__Stories.Default} />
|
|
31
|
+
|
|
32
|
+
```jsx
|
|
33
|
+
import { __COMPONENT_NAME__ } from '@zvoove/unity-ui';
|
|
34
|
+
|
|
35
|
+
<__COMPONENT_NAME__ />;
|
|
36
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
import __COMPONENT_NAME__ from './__COMPONENT_NAME__';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof __COMPONENT_NAME__> = {
|
|
6
|
+
title: 'Components/__COMPONENT_NAME__',
|
|
7
|
+
component: __COMPONENT_NAME__,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof __COMPONENT_NAME__>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {
|
|
14
|
+
args: { children: 'Auto created component' },
|
|
15
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { tv } from '@libs';
|
|
2
|
+
|
|
3
|
+
export const __STYLES__FUNCTION__Styles = tv({
|
|
4
|
+
base: ['text-body-medium'],
|
|
5
|
+
variants: {
|
|
6
|
+
variant: {
|
|
7
|
+
primary: ['bg-primary', 'text-on-primary'],
|
|
8
|
+
secondary: ['bg-secondary', 'text-on-secondary'],
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
defaultVariants: {
|
|
12
|
+
variant: 'primary',
|
|
13
|
+
},
|
|
14
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
|
|
3
|
+
import __COMPONENT_NAME__ from './__COMPONENT_NAME__';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
|
|
6
|
+
describe('__COMPONENT_NAME__', () => {
|
|
7
|
+
it('renders children correctly', () => {
|
|
8
|
+
render(
|
|
9
|
+
<__COMPONENT_NAME__>
|
|
10
|
+
<div>Test Child</div>
|
|
11
|
+
</__COMPONENT_NAME__>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
expect(screen.getByText('Test Child')).toBeInTheDocument();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('applies the correct variant class', () => {
|
|
18
|
+
render(<__COMPONENT_NAME__ variant="secondary">Test</__COMPONENT_NAME__>);
|
|
19
|
+
const __COMPONENT_NAME__Element = screen.getByText('Test');
|
|
20
|
+
|
|
21
|
+
expect(__COMPONENT_NAME__Element).toHaveClass('bg-secondary'); // Assuming the class name matches the variant
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('uses the default variant when none is provided', () => {
|
|
25
|
+
render(<__COMPONENT_NAME__>Default Variant</__COMPONENT_NAME__>);
|
|
26
|
+
const __COMPONENT_NAME__Element = screen.getByText('Default Variant');
|
|
27
|
+
|
|
28
|
+
expect(__COMPONENT_NAME__Element).toHaveClass('bg-primary'); // Assuming 'primary' is the default class
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface __COMPONENT_NAME__Props {
|
|
4
|
+
/**
|
|
5
|
+
* The children of the __COMPONENT_NAME__.
|
|
6
|
+
*/
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The variant of the __COMPONENT_NAME__
|
|
11
|
+
*/
|
|
12
|
+
variant?: 'primary' | 'secondary';
|
|
13
|
+
}
|
package/dist/llms.txt
CHANGED
|
@@ -21,10 +21,7 @@ Import components:
|
|
|
21
21
|
import { Button, Card, TextField, Typography } from '@zvoove/unity-ui';
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
Font
|
|
25
|
-
```html
|
|
26
|
-
<link href="https://fonts.googleapis.com/css2?family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap" rel="stylesheet" />
|
|
27
|
-
```
|
|
24
|
+
Font: Source Sans 3 is bundled via `@font-face` in `theme.css` — no extra setup needed.
|
|
28
25
|
|
|
29
26
|
Dark mode: add `data-theme="dark"` to a parent element.
|
|
30
27
|
|
|
@@ -196,7 +193,10 @@ Horizontal separator line.
|
|
|
196
193
|
```tsx
|
|
197
194
|
import { Divider } from '@zvoove/unity-ui';
|
|
198
195
|
|
|
199
|
-
<Divider
|
|
196
|
+
<Divider
|
|
197
|
+
variant="fullWidth" // 'fullWidth' | 'inset' | 'middle'
|
|
198
|
+
color="outline-variant" // BackgroundColors — any design token name (default: 'outline-variant')
|
|
199
|
+
/>
|
|
200
200
|
```
|
|
201
201
|
|
|
202
202
|
### Expandable
|
|
@@ -548,15 +548,25 @@ import { SegmentGroup, SegmentButton } from '@zvoove/unity-ui';
|
|
|
548
548
|
### PopUpMenu
|
|
549
549
|
Context menu / dropdown menu.
|
|
550
550
|
```tsx
|
|
551
|
-
import { PopUpMenu } from '@zvoove/unity-ui';
|
|
551
|
+
import { PopUpMenu, type PopUpMenuItem } from '@zvoove/unity-ui';
|
|
552
|
+
|
|
553
|
+
const items: PopUpMenuItem[] = [
|
|
554
|
+
{ id: '1', label: 'Edit', icon: 'edit' },
|
|
555
|
+
{ id: '2', label: 'Delete', icon: 'delete' },
|
|
556
|
+
{ id: 'divider', label: '', isDivider: true, dividerProps: { variant: 'middle' } },
|
|
557
|
+
// Custom non-interactive content (e.g. user header)
|
|
558
|
+
{ id: 'header', label: '', customContent: <MyCustomHeader /> },
|
|
559
|
+
// Item that stays open on click (e.g. theme toggle)
|
|
560
|
+
{ id: 'theme', label: 'Dark Mode', icon: 'dark-mode', keepOpen: true, onClick: toggleTheme },
|
|
561
|
+
// Sub-menu items (opens nested menu on hover)
|
|
562
|
+
{ id: 'language', label: 'Sprache', icon: 'translate', subMenuItems: [
|
|
563
|
+
{ id: 'de', label: 'Deutsch' },
|
|
564
|
+
{ id: 'en', label: 'English' },
|
|
565
|
+
]},
|
|
566
|
+
];
|
|
552
567
|
|
|
553
568
|
<PopUpMenu
|
|
554
|
-
items={
|
|
555
|
-
{ id: '1', label: 'Edit', icon: 'Pencil' },
|
|
556
|
-
{ id: '2', label: 'Delete', icon: 'Trash', variant: 'error' },
|
|
557
|
-
{ id: 'divider', isDivider: true },
|
|
558
|
-
{ id: '3', label: 'Settings' },
|
|
559
|
-
]}
|
|
569
|
+
items={items} // PopUpMenuItem[] (required)
|
|
560
570
|
trigger="click" // 'hover' | 'click' | 'right-click' (default: 'click')
|
|
561
571
|
placement="bottom-left" // PopUpMenuPlacement (default: 'bottom-left')
|
|
562
572
|
selectable="none" // 'single' | 'multiple' | 'none' (default: 'none')
|
|
@@ -564,13 +574,20 @@ import { PopUpMenu } from '@zvoove/unity-ui';
|
|
|
564
574
|
onItemClick={handleClick} // (item, selectedItem?) => void
|
|
565
575
|
density="default" // 'default' | '-2' | '-4'
|
|
566
576
|
showSearch={false} // boolean
|
|
567
|
-
searchPlaceholder="
|
|
577
|
+
searchPlaceholder="Suchen" // string
|
|
568
578
|
disabled={false} // boolean
|
|
579
|
+
height, minHeight, maxHeight // ResponsiveType<number | string> — control popup size
|
|
569
580
|
>
|
|
570
|
-
<Button>
|
|
581
|
+
<Button>Aktionen</Button>
|
|
571
582
|
</PopUpMenu>
|
|
572
583
|
```
|
|
573
584
|
|
|
585
|
+
PopUpMenuItem special props:
|
|
586
|
+
- `customContent?: ReactNode` — non-interactive custom content (no hover effect)
|
|
587
|
+
- `keepOpen?: boolean` — don't close menu on click
|
|
588
|
+
- `subMenuItems?: PopUpMenuItem[]` — nested sub-menu on hover
|
|
589
|
+
- `dividerProps?: DividerProps` — pass props to Divider when `isDivider: true`
|
|
590
|
+
|
|
574
591
|
---
|
|
575
592
|
|
|
576
593
|
## DATA DISPLAY COMPONENTS
|
|
@@ -641,19 +658,22 @@ import { Chip } from '@zvoove/unity-ui';
|
|
|
641
658
|
```
|
|
642
659
|
|
|
643
660
|
### Avatar & AvatarGroup
|
|
644
|
-
User avatar display.
|
|
661
|
+
User avatar display. When `image` is provided and `type` is omitted, type is automatically inferred as `'image'`.
|
|
645
662
|
```tsx
|
|
646
663
|
import { Avatar, AvatarGroup } from '@zvoove/unity-ui';
|
|
647
664
|
|
|
648
665
|
<Avatar
|
|
649
666
|
size="large" // ResponsiveType<'small' | 'medium' | 'large'>
|
|
650
|
-
type="initials" // 'initials' | 'check' | 'avatar' | 'image'
|
|
651
|
-
name="
|
|
652
|
-
image="/path/to/photo.jpg" // string
|
|
667
|
+
type="initials" // 'initials' | 'check' | 'avatar' | 'image' | 'zvoove' — auto-inferred as 'image' when image prop is set
|
|
668
|
+
name="Max Mustermann" // string
|
|
669
|
+
image="/path/to/photo.jpg" // string — when set, type defaults to 'image'
|
|
653
670
|
initialsAmount={2} // 1 | 2
|
|
654
671
|
variant="round" // 'round' | 'square'
|
|
655
672
|
/>
|
|
656
673
|
|
|
674
|
+
// Image avatar — type is inferred, no need to set type="image"
|
|
675
|
+
<Avatar image="https://example.com/avatar.jpg" name="Max Mustermann" />
|
|
676
|
+
|
|
657
677
|
<AvatarGroup maxLength={3} total={10}>
|
|
658
678
|
<Avatar name="Alice" type="initials" />
|
|
659
679
|
<Avatar name="Bob" type="initials" />
|
|
@@ -754,7 +774,7 @@ import { Tabs } from '@zvoove/unity-ui';
|
|
|
754
774
|
```
|
|
755
775
|
|
|
756
776
|
### Breadcrumbs
|
|
757
|
-
Navigation breadcrumb trail.
|
|
777
|
+
Navigation breadcrumb trail. First item renders as an icon (customizable via `homeIcon`).
|
|
758
778
|
```tsx
|
|
759
779
|
import { Breadcrumbs } from '@zvoove/unity-ui';
|
|
760
780
|
|
|
@@ -764,28 +784,76 @@ import { Breadcrumbs } from '@zvoove/unity-ui';
|
|
|
764
784
|
{ label: 'Products', href: '/products' },
|
|
765
785
|
{ label: 'Details' },
|
|
766
786
|
]}
|
|
787
|
+
homeIcon="home" // CommonIconNames (default: 'home') — icon for the first breadcrumb
|
|
767
788
|
linkComponent={Link} // React.ElementType
|
|
768
789
|
/>
|
|
769
790
|
```
|
|
770
791
|
|
|
771
792
|
### SideNavigation
|
|
772
|
-
Collapsible sidebar navigation.
|
|
793
|
+
Collapsible sidebar navigation with user area and mid-sections.
|
|
773
794
|
```tsx
|
|
774
|
-
import { SideNavigation } from '@zvoove/unity-ui';
|
|
795
|
+
import { SideNavigation, type MidSection } from '@zvoove/unity-ui';
|
|
775
796
|
|
|
776
797
|
<SideNavigation
|
|
777
|
-
menuItems={[ //
|
|
778
|
-
{ id: 'home', label: '
|
|
779
|
-
{ id: 'users', label: '
|
|
798
|
+
menuItems={[ // ListMenuItem[] (required)
|
|
799
|
+
{ id: 'home', label: 'Startseite', icon: 'home', href: '/' },
|
|
800
|
+
{ id: 'users', label: 'Personal', icon: 'users', href: '/users' },
|
|
801
|
+
]}
|
|
802
|
+
utilityItems={[ // ListMenuItem[]
|
|
803
|
+
{ id: 'settings', label: 'Einstellungen', icon: 'settings', href: '/settings' },
|
|
780
804
|
]}
|
|
781
|
-
|
|
782
|
-
{
|
|
805
|
+
midSections={[ // MidSection[] — sections between menu and utility items
|
|
806
|
+
{
|
|
807
|
+
title: 'ANGEPINNT',
|
|
808
|
+
replaceWithIconOnClose: 'pin', // collapses to icon when closed, hover shows PopUpMenu
|
|
809
|
+
items: [{ id: 'p1', label: 'Pinned item', href: '#' }],
|
|
810
|
+
},
|
|
811
|
+
{
|
|
812
|
+
title: 'HEUTE',
|
|
813
|
+
hideOnMenuClosed: true, // fully hidden when menu closed
|
|
814
|
+
items: [{ id: 't1', label: 'Today item', href: '#' }],
|
|
815
|
+
},
|
|
783
816
|
]}
|
|
817
|
+
userArea={{ // UserAreaProps — user info at the bottom
|
|
818
|
+
name: 'Max Mustermann',
|
|
819
|
+
subtitle: 'Company Name',
|
|
820
|
+
avatar: { image: '/avatar.jpg' },
|
|
821
|
+
menuItems: [/* PopUpMenuItem[] */],
|
|
822
|
+
menuMaxHeight: '80dvh', // ResponsiveType<number | string> (default: '80dvh')
|
|
823
|
+
}}
|
|
824
|
+
logo={{ // { icon?: ReactNode; name?: ReactNode } — compact only, defaults to zvoove brand
|
|
825
|
+
icon: <MyIcon />, // shown when collapsed
|
|
826
|
+
name: <MyWordmark />, // shown when expanded (fades in/out)
|
|
827
|
+
}}
|
|
828
|
+
hideUserAreaInMobile={true} // boolean (default: true) — hides user area on mobile
|
|
784
829
|
activeItem="home" // string
|
|
830
|
+
variant="default" // 'default' | 'compact'
|
|
785
831
|
open={true} // boolean
|
|
786
832
|
onToggleOpen={handleToggle} // (open: boolean) => void
|
|
787
|
-
onItemClick={handleClick} // (item:
|
|
833
|
+
onItemClick={handleClick} // (item: ListMenuItem) => void
|
|
834
|
+
linkComponent={Link} // React.ElementType
|
|
835
|
+
/>
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
### ListMenu
|
|
839
|
+
Standalone vertical menu with icon + label items. Used internally by SideNavigation, available standalone.
|
|
840
|
+
```tsx
|
|
841
|
+
import { ListMenu, type ListMenuItem } from '@zvoove/unity-ui';
|
|
842
|
+
|
|
843
|
+
<ListMenu
|
|
844
|
+
items={[ // ListMenuItem[] (required) — icon is optional
|
|
845
|
+
{ id: 'home', label: 'Startseite', icon: 'home', href: '/' },
|
|
846
|
+
{ id: 'chat', label: 'Chat title', href: '#',
|
|
847
|
+
endContent: <Icon name="pin" size="xs" />, // extra content on the right
|
|
848
|
+
endContentVisibility: 'hover', // 'always' (default) | 'hover'
|
|
849
|
+
},
|
|
850
|
+
{ id: 'spacer', label: '', isSpacer: true }, // renders a 16px vertical spacer
|
|
851
|
+
]}
|
|
852
|
+
activeItem="home" // string
|
|
853
|
+
open={true} // boolean — shows/hides labels with animation
|
|
854
|
+
variant="default" // 'default' | 'compact'
|
|
788
855
|
linkComponent={Link} // React.ElementType
|
|
856
|
+
onItemClick={handleClick} // (item: ListMenuItem) => void
|
|
789
857
|
/>
|
|
790
858
|
```
|
|
791
859
|
|
|
@@ -1133,8 +1201,10 @@ Dark mode shadows: `dark:shadow-elevation1-dark` (replace `elevation1` with the
|
|
|
1133
1201
|
|
|
1134
1202
|
Use `tailwind-variants` when a custom UI element has multiple visual variants.
|
|
1135
1203
|
|
|
1136
|
-
Configure `tv`
|
|
1204
|
+
Configure `tv` once in a shared config file (e.g. `lib/tv.ts`) and import it everywhere — do **not** repeat `createTV` in each styled file:
|
|
1205
|
+
|
|
1137
1206
|
```ts
|
|
1207
|
+
// lib/tv.ts (create once, import everywhere)
|
|
1138
1208
|
import { createTV } from 'tailwind-variants';
|
|
1139
1209
|
|
|
1140
1210
|
export const tv = createTV({
|
|
@@ -1147,7 +1217,12 @@ export const tv = createTV({
|
|
|
1147
1217
|
});
|
|
1148
1218
|
```
|
|
1149
1219
|
|
|
1150
|
-
|
|
1220
|
+
Then in styled files:
|
|
1221
|
+
```ts
|
|
1222
|
+
import { tv } from '@/lib/tv'; // import from shared config, NOT from 'tailwind-variants'
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
Basic usage (single element):
|
|
1151
1226
|
```ts
|
|
1152
1227
|
const badge = tv({
|
|
1153
1228
|
base: ['inline-flex', 'items-center', 'rounded-full', 'px-sm', 'py-xs2', 'text-label-small'],
|
|
@@ -1165,6 +1240,39 @@ const badge = tv({
|
|
|
1165
1240
|
<div className={badge({ tone: 'primary' })}>Label</div>
|
|
1166
1241
|
```
|
|
1167
1242
|
|
|
1243
|
+
Slots (multi-element components — use when a component has distinct styled sub-parts):
|
|
1244
|
+
```ts
|
|
1245
|
+
const card = tv({
|
|
1246
|
+
slots: {
|
|
1247
|
+
base: ['rounded-md', 'bg-surface', 'shadow-elevation1'],
|
|
1248
|
+
header: ['px-md', 'py-sm', 'border-b', 'border-outline-variant'],
|
|
1249
|
+
body: ['p-md'],
|
|
1250
|
+
footer: ['px-md', 'py-sm', 'flex', 'justify-end', 'gap-sm'],
|
|
1251
|
+
},
|
|
1252
|
+
variants: {
|
|
1253
|
+
variant: {
|
|
1254
|
+
outlined: { base: ['border', 'border-outline-variant', 'shadow-none'] },
|
|
1255
|
+
elevated: { base: ['shadow-elevation2'] },
|
|
1256
|
+
},
|
|
1257
|
+
compact: {
|
|
1258
|
+
true: { body: ['p-sm'], header: ['px-sm', 'py-xs'] },
|
|
1259
|
+
},
|
|
1260
|
+
},
|
|
1261
|
+
defaultVariants: { variant: 'outlined' },
|
|
1262
|
+
});
|
|
1263
|
+
|
|
1264
|
+
// Apply — destructure slots from the result:
|
|
1265
|
+
const { base, header, body, footer } = card({ variant: 'elevated', compact: true });
|
|
1266
|
+
|
|
1267
|
+
<div className={base()}>
|
|
1268
|
+
<div className={header()}>Title</div>
|
|
1269
|
+
<div className={body()}>Content</div>
|
|
1270
|
+
<div className={footer()}>
|
|
1271
|
+
<Button>Save</Button>
|
|
1272
|
+
</div>
|
|
1273
|
+
</div>
|
|
1274
|
+
```
|
|
1275
|
+
|
|
1168
1276
|
### Class Merging
|
|
1169
1277
|
|
|
1170
1278
|
Use `tailwind-merge` for ad-hoc merging (e.g. accepting a `className` prop):
|
|
@@ -1227,17 +1335,7 @@ Rules:
|
|
|
1227
1335
|
### `MyComponent.styled.ts`
|
|
1228
1336
|
|
|
1229
1337
|
```ts
|
|
1230
|
-
import {
|
|
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
|
-
});
|
|
1338
|
+
import { tv } from '@/lib/tv'; // shared tv config — do NOT use createTV here
|
|
1241
1339
|
|
|
1242
1340
|
export const myComponentStyles = tv({
|
|
1243
1341
|
base: ['text-body-medium', 'rounded-sm'],
|
|
@@ -1253,8 +1351,6 @@ export const myComponentStyles = tv({
|
|
|
1253
1351
|
});
|
|
1254
1352
|
```
|
|
1255
1353
|
|
|
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
1354
|
### `MyComponent.tsx` — Simple
|
|
1259
1355
|
|
|
1260
1356
|
```tsx
|
|
@@ -1358,7 +1454,18 @@ Unity UI uses its own semantic icon names (not raw Phosphor icon names). Pass th
|
|
|
1358
1454
|
|
|
1359
1455
|
### Common Icons
|
|
1360
1456
|
|
|
1361
|
-
add, add-circle, add-file, agent, airplane, archive, arrow-back, arrow-bend, arrow-down, arrow-forward, arrow-left-right, arrow-up, article, attachment, automate, backspace, bank, bicycle, billing, binoculars, break, bus, calendar, calendar-blank, calendar-check, calendar-dot, calendar-x, camera, car, cart, cash-money, certificate, chat-bubble, chats, check, check-circle, checkbox, checkbox-empty, checkbox-indefinitely, checks, chevron-down, chevron-left, chevron-right, chevron-up, circle-notch, close, close-circle, clock-countdown, clock-person, cloud-download, cloud-upload, columns, copy, dark-mode, deactivate, delete, diagram-view, download, drag, edit, error, exclamation-mark, expand, expenses, face-id, file, filter, filters, first-page, folder, grid-view, hard-hat, help, hide, home, images, info, invoice, job, keyboard, knowledge, language, last-page, light-mode, list-view, location, location-pin, lock, menu, metadata, microphone, minus, more-horizontal, more-vertical, moped, navigation-arrow, note, notches, notifications, numpad, open-in-new-tab, order, organization, pause, phone, piggy-bank, plant, printer, privacy, qr-code, refresh, remark, save, search, send-message, settings, setup-time, shapes, show, sick, sidebar, sign-out, signature, skip-forward, smartphone, sparkle, star, start, stop, table, taxi, text-align-center, text-align-justify, text-align-left, text-align-right, text-t, time, time-sheet-download, time-sheet-upload, timer, train, translate, travel, unfold, upload, user, user-account, users, vacation, wallet, warning, wrench.
|
|
1457
|
+
add, add-circle, add-file, agent, airplane, archive, arrow-back, arrow-bend, arrow-down, arrow-forward, arrow-left-right, arrow-up, article, attachment, automate, backspace, bank, bicycle, billing, binoculars, break, bus, calendar, calendar-blank, calendar-check, calendar-dot, calendar-x, camera, car, cart, cash-money, certificate, chat-bubble, chat-dots, chat-slash, chats, check, check-circle, checkbox, checkbox-empty, checkbox-indefinitely, checks, chevron-down, chevron-left, chevron-right, chevron-up, circle-notch, close, close-circle, clock-countdown, clock-person, cloud-download, cloud-upload, columns, command, control, copy, currency-dollar, currency-dollar-circle, currency-gbp, dark-mode, deactivate, delete, diagram-view, download, drag, edit, error, exclamation-mark, expand, expenses, face-id, file, filter, filters, first-page, flag-de, flag-es, flag-fr, flag-gb, flag-nl, folder, folder-open, grid-view, hard-hat, head-circuit, help, hide, home, images, info, invoice, job, key-return, keyboard, knowledge, language, last-page, light-mode, list-view, location, location-pin, lock, lock-key, lock-key-open, menu, metadata, microphone, minus, more-horizontal, more-vertical, moped, navigation-arrow, note, notches, notifications, numpad, open-in-new-tab, option, order, organization, pause, phone, piggy-bank, pin, pin-simple, pin-simple-slash, pin-slash, plant, printer, privacy, qr-code, refresh, remark, robot, save, search, send-message, settings, setup-time, shapes, show, sick, sidebar, sign-out, signature, skip-forward, smartphone, sparkle, star, start, stop, table, taxi, text-align-center, text-align-justify, text-align-left, text-align-right, text-t, time, time-sheet-download, time-sheet-upload, timer, train, translate, travel, unfold, upload, user, user-account, users, vacation, wallet, warning, wrench.
|
|
1458
|
+
|
|
1459
|
+
### Flag Icons
|
|
1460
|
+
|
|
1461
|
+
Country flag SVGs — work in all components (ListMenu, PopUpMenu, Button, Chip, Select):
|
|
1462
|
+
|
|
1463
|
+
flag-de (Germany), flag-es (Spain), flag-fr (France), flag-gb (United Kingdom), flag-nl (Netherlands).
|
|
1464
|
+
|
|
1465
|
+
```tsx
|
|
1466
|
+
<Icon name="flag-de" size="sm" />
|
|
1467
|
+
<PopUpMenu items={[{ id: 'de', label: 'Deutsch', icon: 'flag-de' }]} />
|
|
1468
|
+
```
|
|
1362
1469
|
|
|
1363
1470
|
### File Type Icons
|
|
1364
1471
|
|
package/dist/theme.css
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
@import 'tailwindcss';
|
|
2
2
|
|
|
3
|
+
@font-face {
|
|
4
|
+
font-family: 'Source Sans 3';
|
|
5
|
+
font-style: normal;
|
|
6
|
+
font-weight: 300;
|
|
7
|
+
src: url('https://d1ciav5yxfbyc5.cloudfront.net/fonts/source-sans-3-variable.woff2')
|
|
8
|
+
format('woff2');
|
|
9
|
+
font-display: swap;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@font-face {
|
|
13
|
+
font-family: 'Source Sans 3';
|
|
14
|
+
font-style: normal;
|
|
15
|
+
font-weight: 400;
|
|
16
|
+
src: url('https://d1ciav5yxfbyc5.cloudfront.net/fonts/source-sans-3-variable.woff2')
|
|
17
|
+
format('woff2');
|
|
18
|
+
font-display: swap;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@font-face {
|
|
22
|
+
font-family: 'Source Sans 3';
|
|
23
|
+
font-style: normal;
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
src: url('https://d1ciav5yxfbyc5.cloudfront.net/fonts/source-sans-3-variable.woff2')
|
|
26
|
+
format('woff2');
|
|
27
|
+
font-display: swap;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@font-face {
|
|
31
|
+
font-family: 'Source Sans 3';
|
|
32
|
+
font-style: normal;
|
|
33
|
+
font-weight: 700;
|
|
34
|
+
src: url('https://d1ciav5yxfbyc5.cloudfront.net/fonts/source-sans-3-variable.woff2')
|
|
35
|
+
format('woff2');
|
|
36
|
+
font-display: swap;
|
|
37
|
+
}
|
|
38
|
+
|
|
3
39
|
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
|
|
4
40
|
@custom-variant child (& > *);
|
|
5
41
|
@theme {
|
|
@@ -276,8 +312,10 @@
|
|
|
276
312
|
--color-surface-container-highest: var(--color-neutral-variant-90);
|
|
277
313
|
--color-on-surface: var(--color-neutral-variant-10);
|
|
278
314
|
--color-on-surface-variant: var(--color-neutral-variant-40);
|
|
315
|
+
--color-on-surface-variant-lowest: var(--color-neutral-variant-70);
|
|
279
316
|
--color-outline: var(--color-neutral-variant-70);
|
|
280
317
|
--color-outline-variant: var(--color-neutral-variant-90);
|
|
318
|
+
--color-outline-low: var(--color-neutral-variant-95);
|
|
281
319
|
--color-outline-variant-low: var(--color-neutral-variant-50);
|
|
282
320
|
--color-error: var(--color-error-40);
|
|
283
321
|
--color-error-hover: var(--color-error-50);
|
|
@@ -497,8 +535,10 @@
|
|
|
497
535
|
--color-surface-container-highest: var(--color-neutral-35);
|
|
498
536
|
--color-on-surface: var(--color-neutral-90);
|
|
499
537
|
--color-on-surface-variant: var(--color-neutral-70);
|
|
538
|
+
--color-on-surface-variant-lowest: var(--color-neutral-50);
|
|
500
539
|
--color-outline: var(--color-neutral-50);
|
|
501
540
|
--color-outline-variant: var(--color-neutral-30);
|
|
541
|
+
--color-outline-low: var(--color-neutral-30);
|
|
502
542
|
--color-outline-variant-low: var(--color-neutral-variant-60);
|
|
503
543
|
--color-error: var(--color-error-80);
|
|
504
544
|
--color-error-hover: var(--color-error-70);
|
|
@@ -627,6 +667,10 @@
|
|
|
627
667
|
animation: circular-indeterminate 1.2s ease-in-out infinite;
|
|
628
668
|
}
|
|
629
669
|
|
|
670
|
+
.animate-circular-indeterminate-slow {
|
|
671
|
+
animation: circular-indeterminate 1.8s ease-in-out infinite;
|
|
672
|
+
}
|
|
673
|
+
|
|
630
674
|
.remove-margin-block-start {
|
|
631
675
|
margin-block-start: 0 !important;
|
|
632
676
|
}
|