@payfit/unity-components 2.55.14 → 2.55.15
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/package.json +9 -9
- package/skills/unity-data-table/SKILL.md +24 -240
- package/skills/unity-data-table/references/patterns.md +237 -0
- package/skills/unity-find-component/SKILL.md +20 -105
- package/skills/unity-find-component/references/component-catalog.md +94 -0
- package/skills/unity-layout-and-styling/SKILL.md +14 -141
- package/skills/unity-layout-and-styling/references/patterns.md +139 -0
- package/skills/unity-migrate-from-midnight/SKILL.md +9 -9
- package/skills/unity-navigation/SKILL.md +12 -116
- package/skills/unity-navigation/references/patterns.md +115 -0
- package/skills/unity-overlays/SKILL.md +11 -132
- package/skills/unity-overlays/references/patterns.md +131 -0
- package/skills/unity-setup-feature-plugin/SKILL.md +4 -3
- package/skills/unity-tanstack-form/SKILL.md +15 -102
- package/skills/unity-tanstack-form/references/patterns.md +102 -0
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: unity-find-component
|
|
3
3
|
description: >
|
|
4
|
-
Load
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
Load when selecting a Unity component is unclear or before creating a custom
|
|
5
|
+
UI primitive that may already exist in @payfit/unity-components. Use it to
|
|
6
|
+
find the existing component, then fall back to React Aria plus uy: classes
|
|
7
|
+
only when Unity has no fit.
|
|
8
|
+
metadata:
|
|
9
|
+
type: core
|
|
10
|
+
library: '@payfit/unity-components'
|
|
11
|
+
library_version: '2.x'
|
|
10
12
|
sources:
|
|
11
13
|
- 'PayFit/hr-apps:libs/shared/unity/components/src/index.ts'
|
|
12
14
|
- 'PayFit/hr-apps:libs/shared/unity/icons/src/components/icon/parts/IconSprite.tsx'
|
|
@@ -18,100 +20,12 @@ sources:
|
|
|
18
20
|
Routing skill for selecting a Unity component before writing UI code. Walk
|
|
19
21
|
the catalog, then the decision tree, then the commonly-confused pairs.
|
|
20
22
|
|
|
21
|
-
##
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
bundles). Names below are grouped by purpose.
|
|
28
|
-
|
|
29
|
-
### Layout
|
|
30
|
-
|
|
31
|
-
`Flex`, `FlexItem`, `Grid`, `GridItem`, `Card`, `CardTitle`,
|
|
32
|
-
`CardContent`, `SelectableCard...`, `NavigationCard`, `NavigationCardGroup`,
|
|
33
|
-
`Page`, `PageHeader`, `PageHeading`, `AppLayout`, `AppMenu`,
|
|
34
|
-
`FunnelLayout`, `FunnelPage`, `FunnelBody`, `FunnelSidebar`, `FunnelTopBar`,
|
|
35
|
-
`FunnelPageHeader`, `FunnelPageContent`, `FunnelPageFooter`,
|
|
36
|
-
`FunnelPageActions`, `FunnelBackButton`.
|
|
37
|
-
|
|
38
|
-
### Navigation
|
|
39
|
-
|
|
40
|
-
Router-agnostic (base entry): `RawLink`, `RawNavItem`, `RawBreadcrumbLink`,
|
|
41
|
-
`RawPaginationLink`, `RawPaginationPrevious`, `RawPaginationNext`, `RawTab`,
|
|
42
|
-
`Nav`, `NavGroup`, `Breadcrumbs`, `Breadcrumb`, `Pagination`,
|
|
43
|
-
`PaginationContent`, `PaginationItem`, `PaginationEllipsis`, `Tabs`,
|
|
44
|
-
`TabList`, `TabPanel`, `SkipLinks`, `TaskMenu`, `RawTask`, `RawSubTask`,
|
|
45
|
-
`TaskGroup`, `ListView`, `RawListViewItem`, `ListViewSection`,
|
|
46
|
-
`ListViewItemLabel`, `ListViewItemText`.
|
|
47
|
-
|
|
48
|
-
Router-aware (from
|
|
49
|
-
`@payfit/unity-components/integrations/tanstack-router`): `Link`,
|
|
50
|
-
`NavItem`, `BreadcrumbLink`, `PaginationLink`, `Tab`.
|
|
51
|
-
|
|
52
|
-
### Form fields (Tanstack Form — current)
|
|
53
|
-
|
|
54
|
-
Bound via `form.AppField` then `field.<Name>`: `TextField`, `SelectField`,
|
|
55
|
-
`NumberField`, `CheckboxField`, `CheckboxGroupField`, `DatePickerField`,
|
|
56
|
-
`DateRangePickerField`, `MultiSelectField`, `RadioButtonGroupField`,
|
|
57
|
-
`SelectableButtonGroupField`, `SelectableCardCheckboxGroupField`,
|
|
58
|
-
`SelectableCardRadioGroupField`, `ToggleSwitchField`,
|
|
59
|
-
`ToggleSwitchGroupField`, `PasswordField`.
|
|
60
|
-
|
|
61
|
-
### Form primitives (no form state)
|
|
62
|
-
|
|
63
|
-
`Input`, `NumberInput`, `Select`, `SelectButton`, `SelectOption`,
|
|
64
|
-
`SelectOptionGroup`, `SelectOptionHelper`, `MultiSelect`,
|
|
65
|
-
`MultiSelectOption`, `MultiSelectOptGroup`, `Checkbox`, `CheckboxStandalone`,
|
|
66
|
-
`CheckboxGroup`, `RadioButtonGroup`, `RadioButton`, `RadioButtonHelper`,
|
|
67
|
-
`TextArea`, `ToggleSwitch`, `ToggleSwitchGroup`, `SegmentedButtonGroup`,
|
|
68
|
-
`ToggleButton`, `SelectableButtonGroup`, `SelectableButton`, `Search`,
|
|
69
|
-
`PhoneNumberInput`, `DatePicker`, `DateCalendar`, `DateRangePicker`,
|
|
70
|
-
`DateRangeCalendar`, `Autocomplete`, `AutocompleteItem`,
|
|
71
|
-
`AutocompleteItemGroup`, `Fieldset`, `FieldGroup`, `Label`, `FormField`,
|
|
72
|
-
`FormControl`, `FormLabel`, `FormHelperText`, `FormFeedbackText`.
|
|
73
|
-
|
|
74
|
-
### Buttons and actions
|
|
75
|
-
|
|
76
|
-
`Button`, `IconButton`, `CircularIconButton`, `RawLinkButton`, `Actionable`,
|
|
77
|
-
`ActionBar`, `ActionBarRoot`, `ActionBarButton`, `ActionBarIconButton`,
|
|
78
|
-
`FloatingActionBar`, `Anchor`.
|
|
79
|
-
|
|
80
|
-
### Overlays
|
|
81
|
-
|
|
82
|
-
Modal: `Dialog`, `DialogContent`, `DialogTitle`, `DialogActions`,
|
|
83
|
-
`DialogButton`, `PromoDialog`, `PromoDialogHero`, `PromoDialogTitle`,
|
|
84
|
-
`PromoDialogSubtitle`, `PromoDialogContent`, `PromoDialogActions`,
|
|
85
|
-
`SidePanel`, `SidePanelHeader`, `SidePanelContent`, `SidePanelFooter`,
|
|
86
|
-
`BottomSheet`, `BottomSheetHeader`, `BottomSheetContent`,
|
|
87
|
-
`BottomSheetFooter`.
|
|
88
|
-
|
|
89
|
-
Non-modal: `Tooltip`, `DefinitionTooltip`, `Popover`, `Menu`, `MenuTrigger`,
|
|
90
|
-
`MenuContent`, `MenuHeader`, `RawMenuItem`, `MenuSeparator`.
|
|
91
|
-
|
|
92
|
-
### Content and data
|
|
93
|
-
|
|
94
|
-
`Text`, `Icon`, `Pill`, `Badge`, `Alert`, `AlertTitle`, `AlertContent`,
|
|
95
|
-
`AlertActions`, `Avatar`, `AvatarFallback`, `AvatarIcon`, `AvatarImage`,
|
|
96
|
-
`AvatarPair`, `DataTable`, `DataTableRoot`, `DataTableBulkActions`,
|
|
97
|
-
`Table`, `TableBody`, `TableHeader`, `TableColumnHeader`, `TableRow`,
|
|
98
|
-
`TableCell`, `TableEmptyState`, `TablePagination`, `Filter`,
|
|
99
|
-
`FilterToolbar`, `Carousel`, `CarouselHeader`, `CarouselContent`,
|
|
100
|
-
`CarouselSlide`, `CarouselNav`, `Collapsible`, `CollapsibleTitle`,
|
|
101
|
-
`CollapsibleContent`, `Timeline`, `TimelineStep`, `TimelineStepHeader`,
|
|
102
|
-
`TimelineStepDescription`.
|
|
103
|
-
|
|
104
|
-
### Status and loading
|
|
105
|
-
|
|
106
|
-
`Spinner`, `ProgressBar`, `FullPageLoader`, `EmptyState`, `EmptyStateIcon`,
|
|
107
|
-
`EmptyStateContent`, `EmptyStateActions`, `EmptyStateGetStarted`,
|
|
108
|
-
`EmptyStateWaitingForData`, `EmptyStateGoodJob`,
|
|
109
|
-
`EmptyStateUpgradeRequired`, `EmptyStateNoSearchResults`,
|
|
110
|
-
`EmptyStateUseDesktop`, `ErrorState`, `ToastManager`, `toast`.
|
|
111
|
-
|
|
112
|
-
### Semantic and brand
|
|
113
|
-
|
|
114
|
-
`PayFitBrand`, `PayFitPreprod`.
|
|
23
|
+
## Component Catalog
|
|
24
|
+
|
|
25
|
+
Inspect the current exports in `src/index.ts`, then use the decision tree below.
|
|
26
|
+
For a categorized catalog of commonly used exports, read
|
|
27
|
+
[references/component-catalog.md](references/component-catalog.md) only when
|
|
28
|
+
component discovery requires it.
|
|
115
29
|
|
|
116
30
|
## Decision Tree
|
|
117
31
|
|
|
@@ -241,8 +155,8 @@ const icon: UnityIcon = 'MagnifyingGlassOutlined'
|
|
|
241
155
|
Tanstack Form (`useTanstackUnityForm`) is the only supported form system.
|
|
242
156
|
The React Hook Form path — `useUnityForm` plus the legacy `TextField` /
|
|
243
157
|
`SelectField` / `NumberField` etc. RHF wrappers exported from the same
|
|
244
|
-
index — is deprecated
|
|
245
|
-
|
|
158
|
+
index — is deprecated. Do not author new code with `useUnityForm`. See
|
|
159
|
+
`unity-tanstack-form`.
|
|
246
160
|
|
|
247
161
|
## Common Mistakes
|
|
248
162
|
|
|
@@ -308,7 +222,7 @@ import { Button, Dialog } from '@payfit/unity-components'
|
|
|
308
222
|
Midnight is deprecated; new screens that import it cannot match the Unity
|
|
309
223
|
theme tokens and will require a migration pass later anyway.
|
|
310
224
|
|
|
311
|
-
Source: AGENTS.md "Do NOT use (deprecated)"
|
|
225
|
+
Source: AGENTS.md "Do NOT use (deprecated)"
|
|
312
226
|
|
|
313
227
|
### MEDIUM Combine Input + FormField when \*Field exists
|
|
314
228
|
|
|
@@ -359,11 +273,12 @@ The `UnityIcon` literal union encodes the exact sprite ids; lowercase or
|
|
|
359
273
|
kebab-case strings have no matching `<symbol id>` in the injected sprite,
|
|
360
274
|
so `<use href="#search">` resolves to nothing and the SVG renders empty.
|
|
361
275
|
|
|
362
|
-
Source: libs/shared/unity/icons/src/components/icon/parts/IconSprite.tsx; generated/index.ts (UnityIcon type)
|
|
276
|
+
Source: libs/shared/unity/icons/src/components/icon/parts/IconSprite.tsx; generated/index.ts (UnityIcon type)
|
|
363
277
|
|
|
364
278
|
## See also
|
|
365
279
|
|
|
366
|
-
-
|
|
280
|
+
- For projects not yet configured for Unity, use the repository's
|
|
281
|
+
`@payfit/nx-tools:setup-unity` generator
|
|
367
282
|
- `unity-migrate-from-midnight` — when Level 3 fallback hits a Midnight
|
|
368
283
|
screen, follow this skill to replace it
|
|
369
284
|
- `unity-tanstack-form` — the only supported form authoring path
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Unity component catalog
|
|
2
|
+
|
|
3
|
+
All exports come from a single entry: `@payfit/unity-components`. There are
|
|
4
|
+
no sub-paths for runtime components; the only sub-paths are
|
|
5
|
+
`@payfit/unity-components/integrations/tanstack-router` (router-aware
|
|
6
|
+
navigation) and `@payfit/unity-components/i18n/<locale>.json` (message
|
|
7
|
+
bundles). Names below are grouped by purpose.
|
|
8
|
+
|
|
9
|
+
### Layout
|
|
10
|
+
|
|
11
|
+
`Flex`, `FlexItem`, `Grid`, `GridItem`, `Card`, `CardTitle`,
|
|
12
|
+
`CardContent`, `SelectableCard...`, `NavigationCard`, `NavigationCardGroup`,
|
|
13
|
+
`Page`, `PageHeader`, `PageHeading`, `AppLayout`, `AppMenu`,
|
|
14
|
+
`FunnelLayout`, `FunnelPage`, `FunnelBody`, `FunnelSidebar`, `FunnelTopBar`,
|
|
15
|
+
`FunnelPageHeader`, `FunnelPageContent`, `FunnelPageFooter`,
|
|
16
|
+
`FunnelPageActions`, `FunnelBackButton`.
|
|
17
|
+
|
|
18
|
+
### Navigation
|
|
19
|
+
|
|
20
|
+
Router-agnostic (base entry): `RawLink`, `RawNavItem`, `RawBreadcrumbLink`,
|
|
21
|
+
`RawPaginationLink`, `RawPaginationPrevious`, `RawPaginationNext`, `RawTab`,
|
|
22
|
+
`Nav`, `NavGroup`, `Breadcrumbs`, `Breadcrumb`, `Pagination`,
|
|
23
|
+
`PaginationContent`, `PaginationItem`, `PaginationEllipsis`, `Tabs`,
|
|
24
|
+
`TabList`, `TabPanel`, `SkipLinks`, `TaskMenu`, `RawTask`, `RawSubTask`,
|
|
25
|
+
`TaskGroup`, `ListView`, `RawListViewItem`, `ListViewSection`,
|
|
26
|
+
`ListViewItemLabel`, `ListViewItemText`.
|
|
27
|
+
|
|
28
|
+
Router-aware (from
|
|
29
|
+
`@payfit/unity-components/integrations/tanstack-router`): `Link`,
|
|
30
|
+
`NavItem`, `BreadcrumbLink`, `PaginationLink`, `Tab`.
|
|
31
|
+
|
|
32
|
+
### Form fields (Tanstack Form — current)
|
|
33
|
+
|
|
34
|
+
Bound via `form.AppField` then `field.<Name>`: `TextField`, `SelectField`,
|
|
35
|
+
`NumberField`, `CheckboxField`, `CheckboxGroupField`, `DatePickerField`,
|
|
36
|
+
`DateRangePickerField`, `MultiSelectField`, `RadioButtonGroupField`,
|
|
37
|
+
`SelectableButtonGroupField`, `SelectableCardCheckboxGroupField`,
|
|
38
|
+
`SelectableCardRadioGroupField`, `ToggleSwitchField`,
|
|
39
|
+
`ToggleSwitchGroupField`, `PasswordField`.
|
|
40
|
+
|
|
41
|
+
### Form primitives (no form state)
|
|
42
|
+
|
|
43
|
+
`Input`, `NumberInput`, `Select`, `SelectButton`, `SelectOption`,
|
|
44
|
+
`SelectOptionGroup`, `SelectOptionHelper`, `MultiSelect`,
|
|
45
|
+
`MultiSelectOption`, `MultiSelectOptGroup`, `Checkbox`, `CheckboxStandalone`,
|
|
46
|
+
`CheckboxGroup`, `RadioButtonGroup`, `RadioButton`, `RadioButtonHelper`,
|
|
47
|
+
`TextArea`, `ToggleSwitch`, `ToggleSwitchGroup`, `SegmentedButtonGroup`,
|
|
48
|
+
`ToggleButton`, `SelectableButtonGroup`, `SelectableButton`, `Search`,
|
|
49
|
+
`PhoneNumberInput`, `DatePicker`, `DateCalendar`, `DateRangePicker`,
|
|
50
|
+
`DateRangeCalendar`, `Autocomplete`, `AutocompleteItem`,
|
|
51
|
+
`AutocompleteItemGroup`, `Fieldset`, `FieldGroup`, `Label`, `FormField`,
|
|
52
|
+
`FormControl`, `FormLabel`, `FormHelperText`, `FormFeedbackText`.
|
|
53
|
+
|
|
54
|
+
### Buttons and actions
|
|
55
|
+
|
|
56
|
+
`Button`, `IconButton`, `CircularIconButton`, `RawLinkButton`, `Actionable`,
|
|
57
|
+
`ActionBar`, `ActionBarRoot`, `ActionBarButton`, `ActionBarIconButton`,
|
|
58
|
+
`FloatingActionBar`, `Anchor`.
|
|
59
|
+
|
|
60
|
+
### Overlays
|
|
61
|
+
|
|
62
|
+
Modal: `Dialog`, `DialogContent`, `DialogTitle`, `DialogActions`,
|
|
63
|
+
`DialogButton`, `PromoDialog`, `PromoDialogHero`, `PromoDialogTitle`,
|
|
64
|
+
`PromoDialogSubtitle`, `PromoDialogContent`, `PromoDialogActions`,
|
|
65
|
+
`SidePanel`, `SidePanelHeader`, `SidePanelContent`, `SidePanelFooter`,
|
|
66
|
+
`BottomSheet`, `BottomSheetHeader`, `BottomSheetContent`,
|
|
67
|
+
`BottomSheetFooter`.
|
|
68
|
+
|
|
69
|
+
Non-modal: `Tooltip`, `DefinitionTooltip`, `Popover`, `Menu`, `MenuTrigger`,
|
|
70
|
+
`MenuContent`, `MenuHeader`, `RawMenuItem`, `MenuSeparator`.
|
|
71
|
+
|
|
72
|
+
### Content and data
|
|
73
|
+
|
|
74
|
+
`Text`, `Icon`, `Pill`, `Badge`, `Alert`, `AlertTitle`, `AlertContent`,
|
|
75
|
+
`AlertActions`, `Avatar`, `AvatarFallback`, `AvatarIcon`, `AvatarImage`,
|
|
76
|
+
`AvatarPair`, `DataTable`, `DataTableRoot`, `DataTableBulkActions`,
|
|
77
|
+
`Table`, `TableBody`, `TableHeader`, `TableColumnHeader`, `TableRow`,
|
|
78
|
+
`TableCell`, `TableEmptyState`, `TablePagination`, `Filter`,
|
|
79
|
+
`FilterToolbar`, `Carousel`, `CarouselHeader`, `CarouselContent`,
|
|
80
|
+
`CarouselSlide`, `CarouselNav`, `Collapsible`, `CollapsibleTitle`,
|
|
81
|
+
`CollapsibleContent`, `Timeline`, `TimelineStep`, `TimelineStepHeader`,
|
|
82
|
+
`TimelineStepDescription`.
|
|
83
|
+
|
|
84
|
+
### Status and loading
|
|
85
|
+
|
|
86
|
+
`Spinner`, `ProgressBar`, `FullPageLoader`, `EmptyState`, `EmptyStateIcon`,
|
|
87
|
+
`EmptyStateContent`, `EmptyStateActions`, `EmptyStateGetStarted`,
|
|
88
|
+
`EmptyStateWaitingForData`, `EmptyStateGoodJob`,
|
|
89
|
+
`EmptyStateUpgradeRequired`, `EmptyStateNoSearchResults`,
|
|
90
|
+
`EmptyStateUseDesktop`, `ErrorState`, `ToastManager`, `toast`.
|
|
91
|
+
|
|
92
|
+
### Semantic and brand
|
|
93
|
+
|
|
94
|
+
`PayFitBrand`, `PayFitPreprod`.
|
|
@@ -4,9 +4,10 @@ description: >
|
|
|
4
4
|
Load when composing Unity layouts or styling with uy: Tailwind utilities.
|
|
5
5
|
Use it for Flex/Grid/Text choices, class merging/variants, and validating
|
|
6
6
|
Unity token names before adding styles.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
metadata:
|
|
8
|
+
type: core
|
|
9
|
+
library: '@payfit/unity-components, @payfit/unity-themes'
|
|
10
|
+
library_version: '2.x'
|
|
10
11
|
sources:
|
|
11
12
|
- 'PayFit/hr-apps:libs/shared/unity/components/src/components/flex/Flex.tsx'
|
|
12
13
|
- 'PayFit/hr-apps:libs/shared/unity/components/src/components/grid/Grid.tsx'
|
|
@@ -50,143 +51,15 @@ export function PayslipSummary() {
|
|
|
50
51
|
|
|
51
52
|
## Core Patterns
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
- Use `Flex` for one-dimensional layout and `Grid` for two-dimensional layout.
|
|
55
|
+
- Express responsiveness and interaction states with `uy:` variants.
|
|
56
|
+
- Use `uyTv` for typed component variants, `uyMerge` when merging external
|
|
57
|
+
classes, and `cn` for simple conditional strings.
|
|
58
|
+
- Use `Text` variants for typography and prefer exposed `data-*` states over
|
|
59
|
+
raw hover selectors when components provide them.
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
`className` with `uy:` utilities.
|
|
58
|
-
|
|
59
|
-
```tsx
|
|
60
|
-
import { Flex, FlexItem, Grid, GridItem } from '@payfit/unity-components'
|
|
61
|
-
|
|
62
|
-
// Flex props: asElement, inline, direction, isReversed, wrap,
|
|
63
|
-
// gap, gapX, gapY, justify, align, alignContent, className
|
|
64
|
-
<Flex direction="row" gap="200" justify="between" align="center">
|
|
65
|
-
<FlexItem grow="1">Left</FlexItem>
|
|
66
|
-
<FlexItem>Right</FlexItem>
|
|
67
|
-
</Flex>
|
|
68
|
-
|
|
69
|
-
// Grid props: asElement, inline, cols (6 | 12), rows, areas, flow,
|
|
70
|
-
// justifyItems, alignItems, className
|
|
71
|
-
// GridItem positions via colSpan/colStart/colEnd OR area (mutually exclusive)
|
|
72
|
-
<Grid cols={12} className="uy:gap-200">
|
|
73
|
-
<GridItem colSpan={8}>Main</GridItem>
|
|
74
|
-
<GridItem colSpan={4}>Aside</GridItem>
|
|
75
|
-
</Grid>
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Responsive classes via uy:md:
|
|
79
|
-
|
|
80
|
-
There is no responsive prop-object API. Responsive behavior is driven by
|
|
81
|
-
TailwindCSS v4 modifiers on `className`.
|
|
82
|
-
|
|
83
|
-
```tsx
|
|
84
|
-
<Flex gap="100" className="uy:md:gap-200 uy:lg:gap-300">
|
|
85
|
-
<span>Item</span>
|
|
86
|
-
</Flex>
|
|
87
|
-
|
|
88
|
-
<Grid cols={12} className="uy:grid-cols-1 uy:md:grid-cols-2 uy:lg:grid-cols-3" />
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### Variants with uyTv
|
|
92
|
-
|
|
93
|
-
`uyTv` from `@payfit/unity-themes` is the pre-configured tailwind-variants
|
|
94
|
-
factory. It applies the Unity `twMergeConfig` so variant collisions resolve
|
|
95
|
-
against Unity tokens. Export the variant function and derive its typed props
|
|
96
|
-
with `VariantProps`.
|
|
97
|
-
|
|
98
|
-
```tsx
|
|
99
|
-
import type { VariantProps } from '@payfit/unity-themes'
|
|
100
|
-
|
|
101
|
-
import { uyTv } from '@payfit/unity-themes'
|
|
102
|
-
|
|
103
|
-
export const callout = uyTv({
|
|
104
|
-
base: 'uy:inline-flex uy:items-center uy:gap-100 uy:rounded-100 uy:px-200 uy:py-100',
|
|
105
|
-
variants: {
|
|
106
|
-
intent: {
|
|
107
|
-
info: 'uy:bg-surface-primary-default uy:text-content-inverted-default',
|
|
108
|
-
danger: 'uy:bg-surface-danger-default uy:text-content-inverted-default',
|
|
109
|
-
neutral: 'uy:bg-surface-neutral-default uy:text-content-neutral-default',
|
|
110
|
-
},
|
|
111
|
-
size: {
|
|
112
|
-
sm: 'uy:typography-body-small',
|
|
113
|
-
md: 'uy:typography-body',
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
defaultVariants: { intent: 'info', size: 'md' },
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
export type CalloutVariantProps = VariantProps<typeof callout>
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### Class merging with uyMerge
|
|
123
|
-
|
|
124
|
-
`uyMerge` is `tailwind-merge` configured with Unity's class groups. Use it
|
|
125
|
-
whenever an external `className` may collide with internal classes.
|
|
126
|
-
|
|
127
|
-
```tsx
|
|
128
|
-
import { uyMerge } from '@payfit/unity-themes'
|
|
129
|
-
|
|
130
|
-
uyMerge('uy:p-100', 'uy:p-200') // → 'uy:p-200'
|
|
131
|
-
uyMerge('uy:bg-surface-primary-default', 'uy:bg-surface-danger-default')
|
|
132
|
-
// → 'uy:bg-surface-danger-default'
|
|
133
|
-
uyMerge('uy:p-100', 'uy:px-200', 'uy:py-300') // p, px, py don't collide
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Conditional classes with cn / classNames / clsx
|
|
137
|
-
|
|
138
|
-
`cn`, `classNames`, and `clsx` are aliases for the same Unity-configured helper
|
|
139
|
-
in `@payfit/unity-themes`. Use them for ad-hoc conditional strings — not for
|
|
140
|
-
component-scoped variant APIs.
|
|
141
|
-
|
|
142
|
-
```tsx
|
|
143
|
-
import { cn } from '@payfit/unity-themes'
|
|
144
|
-
|
|
145
|
-
function Row({
|
|
146
|
-
isActive,
|
|
147
|
-
className,
|
|
148
|
-
}: {
|
|
149
|
-
isActive: boolean
|
|
150
|
-
className?: string
|
|
151
|
-
}) {
|
|
152
|
-
return (
|
|
153
|
-
<div
|
|
154
|
-
className={cn(
|
|
155
|
-
'uy:flex uy:items-center uy:px-200 uy:py-100',
|
|
156
|
-
isActive && 'uy:bg-surface-primary-default',
|
|
157
|
-
className,
|
|
158
|
-
)}
|
|
159
|
-
/>
|
|
160
|
-
)
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### Typography with `<Text>`
|
|
165
|
-
|
|
166
|
-
Use `<Text variant=...>` instead of a `<div>` + typography class. `Text`
|
|
167
|
-
picks a semantic element from the variant (e.g. `variant="h1"` → `<h1>`),
|
|
168
|
-
applies the typography variant, and exposes `color`, `isTruncated`,
|
|
169
|
-
`lineClamp`, and `maxWidthCh`.
|
|
170
|
-
|
|
171
|
-
```tsx
|
|
172
|
-
import { Text } from '@payfit/unity-components'
|
|
173
|
-
|
|
174
|
-
<Text variant="h1" color="content.primary">Title</Text>
|
|
175
|
-
<Text variant="body" color="content.neutral">Description</Text>
|
|
176
|
-
// Override the semantic element when needed:
|
|
177
|
-
<Text variant="h1" asElement="h2">Visual h1, semantic h2</Text>
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Data-attribute pseudo-states
|
|
181
|
-
|
|
182
|
-
Several Unity components expose internal state via `data-hovered`,
|
|
183
|
-
`data-pressed`, `data-focus-visible`, etc. Target the component-owned state
|
|
184
|
-
attribute rather than the native CSS pseudo-state.
|
|
185
|
-
|
|
186
|
-
```tsx
|
|
187
|
-
import { ListViewItem } from '@payfit/unity-components'
|
|
188
|
-
;<ListViewItem className="uy:data-[hovered=true]:bg-surface-primary-hover" />
|
|
189
|
-
```
|
|
61
|
+
Read [references/patterns.md](references/patterns.md) for implementation
|
|
62
|
+
examples.
|
|
190
63
|
|
|
191
64
|
## Common Mistakes
|
|
192
65
|
|
|
@@ -327,7 +200,7 @@ Correct:
|
|
|
327
200
|
|
|
328
201
|
Agents generate names that match standard Tailwind conventions but are not in the Unity token set; the class is absent from the compiled stylesheet, the element silently renders with no style.
|
|
329
202
|
|
|
330
|
-
Source:
|
|
203
|
+
Source: themes/dist/css/unity.css (@theme block enumerates valid tokens)
|
|
331
204
|
|
|
332
205
|
### MEDIUM Reach for cn() to compose variant classes when uyTv fits
|
|
333
206
|
|
|
@@ -382,7 +255,7 @@ function Pill(props: PillProps) {
|
|
|
382
255
|
|
|
383
256
|
cn() / classNames / clsx are for ad-hoc conditional class strings; component-scoped variant APIs with multiple axes (size × color × intent) belong in `uyTv`, which gives a typed `VariantProps` signature and pre-applied conflict resolution.
|
|
384
257
|
|
|
385
|
-
Source:
|
|
258
|
+
Source: themes/src/utils/tailwind-variants.ts
|
|
386
259
|
|
|
387
260
|
## See also
|
|
388
261
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Unity layout and styling patterns
|
|
2
|
+
|
|
3
|
+
### Flex for 1D, Grid for 2D
|
|
4
|
+
|
|
5
|
+
`Flex` is for one-dimensional rows/columns; `Grid` is for the 12-column (or 6-column)
|
|
6
|
+
two-dimensional layout. Each exposes layout props; everything else goes via
|
|
7
|
+
`className` with `uy:` utilities.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Flex, FlexItem, Grid, GridItem } from '@payfit/unity-components'
|
|
11
|
+
|
|
12
|
+
// Flex props: asElement, inline, direction, isReversed, wrap,
|
|
13
|
+
// gap, gapX, gapY, justify, align, alignContent, className
|
|
14
|
+
<Flex direction="row" gap="200" justify="between" align="center">
|
|
15
|
+
<FlexItem grow="1">Left</FlexItem>
|
|
16
|
+
<FlexItem>Right</FlexItem>
|
|
17
|
+
</Flex>
|
|
18
|
+
|
|
19
|
+
// Grid props: asElement, inline, cols (6 | 12), rows, areas, flow,
|
|
20
|
+
// justifyItems, alignItems, className
|
|
21
|
+
// GridItem positions via colSpan/colStart/colEnd OR area (mutually exclusive)
|
|
22
|
+
<Grid cols={12} className="uy:gap-200">
|
|
23
|
+
<GridItem colSpan={8}>Main</GridItem>
|
|
24
|
+
<GridItem colSpan={4}>Aside</GridItem>
|
|
25
|
+
</Grid>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Responsive classes via uy:md:
|
|
29
|
+
|
|
30
|
+
There is no responsive prop-object API. Responsive behavior is driven by
|
|
31
|
+
TailwindCSS v4 modifiers on `className`.
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<Flex gap="100" className="uy:md:gap-200 uy:lg:gap-300">
|
|
35
|
+
<span>Item</span>
|
|
36
|
+
</Flex>
|
|
37
|
+
|
|
38
|
+
<Grid cols={12} className="uy:grid-cols-1 uy:md:grid-cols-2 uy:lg:grid-cols-3" />
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Variants with uyTv
|
|
42
|
+
|
|
43
|
+
`uyTv` from `@payfit/unity-themes` is the pre-configured tailwind-variants
|
|
44
|
+
factory. It applies the Unity `twMergeConfig` so variant collisions resolve
|
|
45
|
+
against Unity tokens. Export the variant function and derive its typed props
|
|
46
|
+
with `VariantProps`.
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import type { VariantProps } from '@payfit/unity-themes'
|
|
50
|
+
|
|
51
|
+
import { uyTv } from '@payfit/unity-themes'
|
|
52
|
+
|
|
53
|
+
export const callout = uyTv({
|
|
54
|
+
base: 'uy:inline-flex uy:items-center uy:gap-100 uy:rounded-100 uy:px-200 uy:py-100',
|
|
55
|
+
variants: {
|
|
56
|
+
intent: {
|
|
57
|
+
info: 'uy:bg-surface-primary-default uy:text-content-inverted-default',
|
|
58
|
+
danger: 'uy:bg-surface-danger-default uy:text-content-inverted-default',
|
|
59
|
+
neutral: 'uy:bg-surface-neutral-default uy:text-content-neutral-default',
|
|
60
|
+
},
|
|
61
|
+
size: {
|
|
62
|
+
sm: 'uy:typography-body-small',
|
|
63
|
+
md: 'uy:typography-body',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
defaultVariants: { intent: 'info', size: 'md' },
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
export type CalloutVariantProps = VariantProps<typeof callout>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Class merging with uyMerge
|
|
73
|
+
|
|
74
|
+
`uyMerge` is `tailwind-merge` configured with Unity's class groups. Use it
|
|
75
|
+
whenever an external `className` may collide with internal classes.
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { uyMerge } from '@payfit/unity-themes'
|
|
79
|
+
|
|
80
|
+
uyMerge('uy:p-100', 'uy:p-200') // → 'uy:p-200'
|
|
81
|
+
uyMerge('uy:bg-surface-primary-default', 'uy:bg-surface-danger-default')
|
|
82
|
+
// → 'uy:bg-surface-danger-default'
|
|
83
|
+
uyMerge('uy:p-100', 'uy:px-200', 'uy:py-300') // p, px, py don't collide
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Conditional classes with cn / classNames / clsx
|
|
87
|
+
|
|
88
|
+
`cn`, `classNames`, and `clsx` are aliases for the same Unity-configured helper
|
|
89
|
+
in `@payfit/unity-themes`. Use them for ad-hoc conditional strings — not for
|
|
90
|
+
component-scoped variant APIs.
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { cn } from '@payfit/unity-themes'
|
|
94
|
+
|
|
95
|
+
function Row({
|
|
96
|
+
isActive,
|
|
97
|
+
className,
|
|
98
|
+
}: {
|
|
99
|
+
isActive: boolean
|
|
100
|
+
className?: string
|
|
101
|
+
}) {
|
|
102
|
+
return (
|
|
103
|
+
<div
|
|
104
|
+
className={cn(
|
|
105
|
+
'uy:flex uy:items-center uy:px-200 uy:py-100',
|
|
106
|
+
isActive && 'uy:bg-surface-primary-default',
|
|
107
|
+
className,
|
|
108
|
+
)}
|
|
109
|
+
/>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Typography with `<Text>`
|
|
115
|
+
|
|
116
|
+
Use `<Text variant=...>` instead of a `<div>` + typography class. `Text`
|
|
117
|
+
picks a semantic element from the variant (e.g. `variant="h1"` → `<h1>`),
|
|
118
|
+
applies the typography variant, and exposes `color`, `isTruncated`,
|
|
119
|
+
`lineClamp`, and `maxWidthCh`.
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
import { Text } from '@payfit/unity-components'
|
|
123
|
+
|
|
124
|
+
<Text variant="h1" color="content.primary">Title</Text>
|
|
125
|
+
<Text variant="body" color="content.neutral">Description</Text>
|
|
126
|
+
// Override the semantic element when needed:
|
|
127
|
+
<Text variant="h1" asElement="h2">Visual h1, semantic h2</Text>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Data-attribute pseudo-states
|
|
131
|
+
|
|
132
|
+
Several Unity components expose internal state via `data-hovered`,
|
|
133
|
+
`data-pressed`, `data-focus-visible`, etc. Target the component-owned state
|
|
134
|
+
attribute rather than the native CSS pseudo-state.
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import { ListViewItem } from '@payfit/unity-components'
|
|
138
|
+
;<ListViewItem className="uy:data-[hovered=true]:bg-surface-primary-hover" />
|
|
139
|
+
```
|
|
@@ -4,9 +4,10 @@ description: >
|
|
|
4
4
|
Load when replacing @payfit/midnight UI with Unity. Use it to choose Unity
|
|
5
5
|
equivalents, avoid obsolete Midnight patterns, and route unclear component
|
|
6
6
|
mappings to unity-find-component.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
metadata:
|
|
8
|
+
type: lifecycle
|
|
9
|
+
library: '@payfit/unity-components'
|
|
10
|
+
library_version: '2.x'
|
|
10
11
|
sources:
|
|
11
12
|
- 'PayFit/hr-apps:libs/shared/unity/components/src/components/tooltip/Tooltip.tsx'
|
|
12
13
|
- 'PayFit/hr-apps:libs/shared/unity/components/src/components/button/Button.tsx'
|
|
@@ -71,10 +72,9 @@ Unity enforces several WCAG rules that Midnight allowed:
|
|
|
71
72
|
|
|
72
73
|
Midnight-era screens commonly use React Hook Form. When porting, replace
|
|
73
74
|
the form with `useTanstackUnityForm` and the Tanstack-bound `*Field`
|
|
74
|
-
components (`TextField`, `SelectField`, `NumberField`, etc.). The legacy
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
RHF intermediate step. See `unity-tanstack-form`.
|
|
75
|
+
components (`TextField`, `SelectField`, `NumberField`, etc.). The legacy RHF
|
|
76
|
+
`useUnityForm` + `*Field` wrappers in the same package index are deprecated.
|
|
77
|
+
Do not pause on the RHF intermediate step. See `unity-tanstack-form`.
|
|
78
78
|
|
|
79
79
|
## Common Mistakes
|
|
80
80
|
|
|
@@ -106,7 +106,7 @@ rule that disabled controls must not have tooltips because they are not
|
|
|
106
106
|
keyboard-focusable, so the tooltip is unreachable — Unity's `Tooltip`
|
|
107
107
|
component rejects this pairing at the library level.
|
|
108
108
|
|
|
109
|
-
Source: libs/shared/unity/components/src/components/tooltip/Tooltip.tsx
|
|
109
|
+
Source: libs/shared/unity/components/src/components/tooltip/Tooltip.tsx
|
|
110
110
|
|
|
111
111
|
### HIGH Assume Midnight props map 1:1 to Unity
|
|
112
112
|
|
|
@@ -151,7 +151,7 @@ Midnight and Unity ship divergent theme tokens — colors, spacing, and
|
|
|
151
151
|
typography differ — so a mixed screen renders with mismatched scales and
|
|
152
152
|
the visual regression lands silently because both stylesheets are valid.
|
|
153
153
|
|
|
154
|
-
Source: AGENTS.md migration awareness
|
|
154
|
+
Source: AGENTS.md migration awareness
|
|
155
155
|
|
|
156
156
|
### MEDIUM Port Midnight transition utility instead of using uy: classes
|
|
157
157
|
|