@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.
@@ -1,12 +1,14 @@
1
1
  ---
2
2
  name: unity-find-component
3
3
  description: >
4
- Load before choosing or creating Unity UI. Use it to map a UI need to an
5
- existing @payfit/unity-components export, then fall back to React Aria plus
6
- uy: classes only when Unity has no fit.
7
- type: core
8
- library: '@payfit/unity-components'
9
- library_version: '2.x'
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
- ## Quick Reference
22
-
23
- All exports come from a single entry: `@payfit/unity-components`. There are
24
- no sub-paths for runtime components; the only sub-paths are
25
- `@payfit/unity-components/integrations/tanstack-router` (router-aware
26
- navigation) and `@payfit/unity-components/i18n/<locale>.json` (message
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 and scheduled for removal after the rebrand. Do not
245
- author new code with `useUnityForm`. See `unity-tanstack-form`.
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)"; maintainer interview
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); maintainer interview
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
- - `unity-setup-feature-plugin` required before any Unity import will work
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
- type: core
8
- library: '@payfit/unity-components, @payfit/unity-themes'
9
- library_version: '2.x'
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
- ### Flex for 1D, Grid for 2D
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
- `Flex` is for one-dimensional rows/columns; `Grid` is for the 12-column (or 6-column)
56
- two-dimensional layout. Each exposes layout props; everything else goes via
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: maintainer interview; themes/dist/css/unity.css (@theme block enumerates valid tokens)
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: maintainer interview; themes/src/utils/tailwind-variants.ts
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
- type: lifecycle
8
- library: '@payfit/unity-components'
9
- library_version: '2.x'
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
- RHF `useUnityForm` + `*Field` wrappers in the same package index are
76
- deprecated and will be removed after the rebrand do not pause on the
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; maintainer interview (Unity enforces)
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; maintainer interview
154
+ Source: AGENTS.md migration awareness
155
155
 
156
156
  ### MEDIUM Port Midnight transition utility instead of using uy: classes
157
157