@cdx-ui/components 0.2.3 → 0.2.4
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/AGENTS.md +24 -0
- package/README.md +2 -0
- package/coverage.svg +1 -1
- package/docs/components/accordion/content.md +538 -0
- package/docs/components/alert/content.md +203 -0
- package/docs/components/alert-dialog/content.md +319 -0
- package/docs/components/avatar/content.md +368 -0
- package/docs/components/avatar/design.md +202 -0
- package/docs/components/badge/content.md +235 -0
- package/docs/components/bottom-sheet/content.md +351 -0
- package/docs/components/bottom-sheet/design.md +249 -0
- package/docs/components/breadcrumbs/content.md +169 -0
- package/docs/components/button/content.md +398 -0
- package/docs/components/button/design.md +258 -0
- package/docs/components/calendar/content.md +137 -0
- package/docs/components/card/content.md +283 -0
- package/docs/components/carousel/content.md +416 -0
- package/docs/components/checkbox/content.md +236 -0
- package/docs/components/checkbox/design.md +214 -0
- package/docs/components/chip/content.md +439 -0
- package/docs/components/chip/design.md +418 -0
- package/docs/components/color-area/content.md +86 -0
- package/docs/components/color-field/content.md +134 -0
- package/docs/components/color-picker/content.md +208 -0
- package/docs/components/color-slider/content.md +120 -0
- package/docs/components/color-swatch/content.md +64 -0
- package/docs/components/color-swatch-picker/content.md +126 -0
- package/docs/components/content.md +97 -0
- package/docs/components/currency-input/content.md +205 -0
- package/docs/components/data-grid/content.md +522 -0
- package/docs/components/date-field/content.md +147 -0
- package/docs/components/date-picker/content.md +360 -0
- package/docs/components/date-range-picker/content.md +301 -0
- package/docs/components/date-time-field/content.md +157 -0
- package/docs/components/date-time-list/content.md +105 -0
- package/docs/components/date-time-picker/content.md +272 -0
- package/docs/components/dialog/content.md +436 -0
- package/docs/components/dialog/design.md +192 -0
- package/docs/components/divider/content.md +112 -0
- package/docs/components/drawer/content.md +436 -0
- package/docs/components/field/content.md +277 -0
- package/docs/components/form/content.md +62 -0
- package/docs/components/full-screen-dialog/content.md +881 -0
- package/docs/components/heading/content.md +55 -0
- package/docs/components/icon/content.md +190 -0
- package/docs/components/icon-button/content.md +200 -0
- package/docs/components/icon-button/design.md +165 -0
- package/docs/components/image/content.md +104 -0
- package/docs/components/input/content.md +281 -0
- package/docs/components/input/design.md +389 -0
- package/docs/components/insurance-disclosure/content.md +103 -0
- package/docs/components/link/content.md +180 -0
- package/docs/components/link/design.md +160 -0
- package/docs/components/list-item/content.md +695 -0
- package/docs/components/menu/content.md +1247 -0
- package/docs/components/month-calendar/content.md +84 -0
- package/docs/components/month-picker/content.md +273 -0
- package/docs/components/otp-input/content.md +327 -0
- package/docs/components/progress-bar/content.md +87 -0
- package/docs/components/progress-circle/content.md +176 -0
- package/docs/components/progress-segmented/content.md +119 -0
- package/docs/components/quick-action-button/content.md +154 -0
- package/docs/components/quick-action-button/design.md +170 -0
- package/docs/components/radio/content.md +224 -0
- package/docs/components/range-calendar/content.md +123 -0
- package/docs/components/reorderable-list/content.md +309 -0
- package/docs/components/scoped-theme/content.md +47 -0
- package/docs/components/scroll-shadow/content.md +686 -0
- package/docs/components/select/content.md +400 -0
- package/docs/components/select/design.md +301 -0
- package/docs/components/skeleton/content.md +103 -0
- package/docs/components/slider/content.md +423 -0
- package/docs/components/stack/content.md +161 -0
- package/docs/components/switch/content.md +150 -0
- package/docs/components/switch/design.md +208 -0
- package/docs/components/table/content.md +548 -0
- package/docs/components/table-pagination/content.md +177 -0
- package/docs/components/tabs/content.md +292 -0
- package/docs/components/text/content.md +142 -0
- package/docs/components/textarea/content.md +222 -0
- package/docs/components/tile/content.md +703 -0
- package/docs/components/toast/content.md +456 -0
- package/docs/components/toggle-button/content.md +505 -0
- package/docs/components/tooltip/content.md +350 -0
- package/docs/components/virtualized-list/content.md +250 -0
- package/docs/foundations/content.md +9 -0
- package/docs/foundations/expressions/icons/content.md +19 -0
- package/docs/foundations/styles/tokens/all-tokens/content.md +192 -0
- package/docs/foundations/styles/tokens/what-are-tokens/content.md +33 -0
- package/docs/foundations/styles/tokens/what-are-tokens/design.md +33 -0
- package/docs/getting-started/content.md +4 -0
- package/docs/getting-started/designers/content.md +13 -0
- package/docs/getting-started/designers/design.md +13 -0
- package/docs/getting-started/developers/accessibility/content.md +31 -0
- package/docs/getting-started/developers/content.md +612 -0
- package/docs/getting-started/developers/styling/content.md +193 -0
- package/docs/llms.txt +193 -0
- package/docs/patterns/account-management/content.md +75 -0
- package/docs/patterns/authentication/content.md +52 -0
- package/docs/patterns/content.md +10 -0
- package/docs/patterns/dashboard/content.md +39 -0
- package/docs/patterns/empty-states/content.md +31 -0
- package/docs/patterns/forms/content.md +109 -0
- package/docs/patterns/onboarding/content.md +69 -0
- package/docs/patterns/payments/content.md +35 -0
- package/docs/patterns/settings/content.md +72 -0
- package/docs/resources/content.md +9 -0
- package/docs/resources/figma-libraries/content.md +42 -0
- package/docs/resources/release-notes/0.0.1-beta.118/content.md +27 -0
- package/docs/resources/release-notes/0.0.1-beta.122/content.md +21 -0
- package/docs/resources/release-notes/0.0.1-beta.124/content.md +16 -0
- package/docs/resources/release-notes/0.0.1-beta.126/content.md +10 -0
- package/docs/resources/release-notes/0.0.1-beta.127/content.md +14 -0
- package/docs/resources/release-notes/0.0.1-beta.128/content.md +9 -0
- package/docs/resources/release-notes/0.0.1-beta.129/content.md +18 -0
- package/docs/resources/release-notes/0.0.1-beta.130/content.md +18 -0
- package/docs/resources/release-notes/0.0.1-beta.133/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.134/content.md +17 -0
- package/docs/resources/release-notes/0.0.1-beta.136/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.137/content.md +10 -0
- package/docs/resources/release-notes/0.0.1-beta.138/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.139/content.md +13 -0
- package/docs/resources/release-notes/0.0.1-beta.140/content.md +26 -0
- package/docs/resources/release-notes/0.0.1-beta.141/content.md +63 -0
- package/docs/resources/release-notes/0.0.1-beta.142/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.143/content.md +12 -0
- package/docs/resources/release-notes/0.0.1-beta.144/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.145/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.147/content.md +10 -0
- package/docs/resources/release-notes/0.0.1-beta.149/content.md +10 -0
- package/docs/resources/release-notes/0.0.1-beta.150/content.md +13 -0
- package/docs/resources/release-notes/0.0.1-beta.152/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.154/content.md +15 -0
- package/docs/resources/release-notes/0.0.1-beta.156/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.158/content.md +9 -0
- package/docs/resources/release-notes/0.0.1-beta.159/content.md +11 -0
- package/docs/resources/release-notes/0.0.1-beta.160/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.161/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.163/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.164/content.md +9 -0
- package/docs/resources/release-notes/0.0.1-beta.166/content.md +17 -0
- package/docs/resources/release-notes/0.0.1-beta.167/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.168/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.169/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.171/content.md +16 -0
- package/docs/resources/release-notes/0.0.1-beta.172/content.md +24 -0
- package/docs/resources/release-notes/0.0.1-beta.173/content.md +15 -0
- package/docs/resources/release-notes/0.0.1-beta.174/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.176/content.md +32 -0
- package/docs/resources/release-notes/0.0.1-beta.179/content.md +11 -0
- package/docs/resources/release-notes/0.0.1-beta.182/content.md +13 -0
- package/docs/resources/release-notes/0.0.1-beta.185/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.187/content.md +27 -0
- package/docs/resources/release-notes/0.1.1/content.md +23 -0
- package/docs/resources/release-notes/0.1.2/content.md +7 -0
- package/docs/resources/release-notes/0.1.4/content.md +19 -0
- package/docs/resources/release-notes/0.1.5/content.md +7 -0
- package/docs/resources/release-notes/0.1.6/content.md +7 -0
- package/docs/resources/release-notes/0.2.0/content.md +31 -0
- package/docs/resources/release-notes/0.2.1/content.md +17 -0
- package/docs/resources/release-notes/0.2.2/content.md +11 -0
- package/docs/resources/release-notes/0.2.3/content.md +15 -0
- package/docs/resources/release-notes/content.md +64 -0
- package/lib/commonjs/components/DateTimeList/index.js +11 -26
- package/lib/commonjs/components/DateTimeList/index.js.map +1 -1
- package/lib/commonjs/components/DateTimeList/styles.js +2 -12
- package/lib/commonjs/components/DateTimeList/styles.js.map +1 -1
- package/lib/commonjs/components/ListItem/index.js.map +1 -1
- package/lib/commonjs/components/ListItem/styles.js +2 -1
- package/lib/commonjs/components/ListItem/styles.js.map +1 -1
- package/lib/commonjs/components/Menu/index.js +11 -5
- package/lib/commonjs/components/Menu/index.js.map +1 -1
- package/lib/commonjs/components/ScrollShadow/gradient.js +29 -0
- package/lib/commonjs/components/ScrollShadow/gradient.js.map +1 -0
- package/lib/commonjs/components/ScrollShadow/index.js +171 -44
- package/lib/commonjs/components/ScrollShadow/index.js.map +1 -1
- package/lib/commonjs/components/ScrollShadow/styles.js +58 -14
- package/lib/commonjs/components/ScrollShadow/styles.js.map +1 -1
- package/lib/commonjs/components/ScrollShadow/useComposedScrollHandler.js +63 -0
- package/lib/commonjs/components/ScrollShadow/useComposedScrollHandler.js.map +1 -0
- package/lib/commonjs/components/ScrollShadow/useScrollShadow.js +48 -8
- package/lib/commonjs/components/ScrollShadow/useScrollShadow.js.map +1 -1
- package/lib/commonjs/components/Tabs/index.js +16 -23
- package/lib/commonjs/components/Tabs/index.js.map +1 -1
- package/lib/commonjs/components/Tabs/styles.js +1 -10
- package/lib/commonjs/components/Tabs/styles.js.map +1 -1
- package/lib/commonjs/figma/ListItem.SectionHeader.figma.js +20 -5
- package/lib/commonjs/figma/ListItem.SectionHeader.figma.js.map +1 -1
- package/lib/module/components/DateTimeList/index.js +12 -27
- package/lib/module/components/DateTimeList/index.js.map +1 -1
- package/lib/module/components/DateTimeList/styles.js +1 -11
- package/lib/module/components/DateTimeList/styles.js.map +1 -1
- package/lib/module/components/ListItem/index.js.map +1 -1
- package/lib/module/components/ListItem/styles.js +2 -1
- package/lib/module/components/ListItem/styles.js.map +1 -1
- package/lib/module/components/Menu/index.js +11 -5
- package/lib/module/components/Menu/index.js.map +1 -1
- package/lib/module/components/ScrollShadow/gradient.js +24 -0
- package/lib/module/components/ScrollShadow/gradient.js.map +1 -0
- package/lib/module/components/ScrollShadow/index.js +170 -48
- package/lib/module/components/ScrollShadow/index.js.map +1 -1
- package/lib/module/components/ScrollShadow/styles.js +57 -13
- package/lib/module/components/ScrollShadow/styles.js.map +1 -1
- package/lib/module/components/ScrollShadow/useComposedScrollHandler.js +57 -0
- package/lib/module/components/ScrollShadow/useComposedScrollHandler.js.map +1 -0
- package/lib/module/components/ScrollShadow/useScrollShadow.js +46 -8
- package/lib/module/components/ScrollShadow/useScrollShadow.js.map +1 -1
- package/lib/module/components/Tabs/index.js +17 -24
- package/lib/module/components/Tabs/index.js.map +1 -1
- package/lib/module/components/Tabs/styles.js +0 -9
- package/lib/module/components/Tabs/styles.js.map +1 -1
- package/lib/module/figma/ListItem.SectionHeader.figma.js +20 -5
- package/lib/module/figma/ListItem.SectionHeader.figma.js.map +1 -1
- package/lib/typescript/components/DateTimeList/index.d.ts.map +1 -1
- package/lib/typescript/components/DateTimeList/styles.d.ts +1 -4
- package/lib/typescript/components/DateTimeList/styles.d.ts.map +1 -1
- package/lib/typescript/components/ListItem/index.d.ts +5 -4
- package/lib/typescript/components/ListItem/index.d.ts.map +1 -1
- package/lib/typescript/components/ListItem/styles.d.ts +1 -1
- package/lib/typescript/components/ListItem/styles.d.ts.map +1 -1
- package/lib/typescript/components/Menu/index.d.ts.map +1 -1
- package/lib/typescript/components/ScrollShadow/gradient.d.ts +7 -0
- package/lib/typescript/components/ScrollShadow/gradient.d.ts.map +1 -0
- package/lib/typescript/components/ScrollShadow/index.d.ts +57 -15
- package/lib/typescript/components/ScrollShadow/index.d.ts.map +1 -1
- package/lib/typescript/components/ScrollShadow/styles.d.ts +8 -2
- package/lib/typescript/components/ScrollShadow/styles.d.ts.map +1 -1
- package/lib/typescript/components/ScrollShadow/useComposedScrollHandler.d.ts +13 -0
- package/lib/typescript/components/ScrollShadow/useComposedScrollHandler.d.ts.map +1 -0
- package/lib/typescript/components/ScrollShadow/useScrollShadow.d.ts +15 -2
- package/lib/typescript/components/ScrollShadow/useScrollShadow.d.ts.map +1 -1
- package/lib/typescript/components/Tabs/index.d.ts.map +1 -1
- package/lib/typescript/components/Tabs/styles.d.ts +0 -7
- package/lib/typescript/components/Tabs/styles.d.ts.map +1 -1
- package/lib/typescript/figma/ListItem.SectionHeader.figma.d.ts.map +1 -1
- package/package.json +8 -6
- package/src/components/DateTimeList/index.tsx +13 -26
- package/src/components/DateTimeList/styles.ts +1 -10
- package/src/components/ListItem/index.tsx +5 -4
- package/src/components/ListItem/styles.ts +1 -0
- package/src/components/Menu/index.tsx +11 -8
- package/src/components/ScrollShadow/gradient.ts +48 -0
- package/src/components/ScrollShadow/index.tsx +300 -69
- package/src/components/ScrollShadow/styles.ts +45 -28
- package/src/components/ScrollShadow/useComposedScrollHandler.ts +58 -0
- package/src/components/ScrollShadow/useScrollShadow.ts +72 -10
- package/src/components/Tabs/index.tsx +25 -35
- package/src/components/Tabs/styles.ts +0 -9
|
@@ -0,0 +1,703 @@
|
|
|
1
|
+
# Tile (https://design.candescent.com/docs/components/tile)
|
|
2
|
+
|
|
3
|
+
Resources: [Figma](https://www.figma.com/design/0lEVMVlLj8ZS4fgItr3pmd/%E2%AD%90-Forge-DS--Components?node-id=8843-7101), [Storybook](https://victorious-wave-0daadf00f.6.azurestaticapps.net/?path=/story/surfaces-tile--default)
|
|
4
|
+
|
|
5
|
+
A compound component with sub-components for leading content, title, description, selection indicator, trailing content, and grouping. Selection state lives in `Tile.Group`; individual tiles are pressable.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Tile } from '@cdx-ui/components';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Shapes
|
|
12
|
+
|
|
13
|
+
`shape` sets how tiles look and how they sit together. Set it on `Tile.Group` so every child inherits it, or override per `Tile`.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { useState } from 'react';
|
|
17
|
+
import { Tile, View } from '@cdx-ui/components';
|
|
18
|
+
|
|
19
|
+
export default function TileShapesDemo() {
|
|
20
|
+
const [card, setCard] = useState('checking');
|
|
21
|
+
const [flat, setFlat] = useState('checking');
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<View className="w-full max-w-md gap-6">
|
|
25
|
+
<Tile.Group
|
|
26
|
+
type="single"
|
|
27
|
+
shape="card"
|
|
28
|
+
value={card}
|
|
29
|
+
onValueChange={setCard}
|
|
30
|
+
aria-label="Card shape"
|
|
31
|
+
>
|
|
32
|
+
<Tile value="checking">
|
|
33
|
+
<Tile.Content>
|
|
34
|
+
<Tile.Title>Card</Tile.Title>
|
|
35
|
+
<Tile.Description>Bordered and rounded, with gaps between tiles.</Tile.Description>
|
|
36
|
+
</Tile.Content>
|
|
37
|
+
<Tile.Indicator />
|
|
38
|
+
</Tile>
|
|
39
|
+
<Tile value="savings">
|
|
40
|
+
<Tile.Content>
|
|
41
|
+
<Tile.Title>Card</Tile.Title>
|
|
42
|
+
<Tile.Description>Each tile stands alone.</Tile.Description>
|
|
43
|
+
</Tile.Content>
|
|
44
|
+
<Tile.Indicator />
|
|
45
|
+
</Tile>
|
|
46
|
+
</Tile.Group>
|
|
47
|
+
<Tile.Group
|
|
48
|
+
type="single"
|
|
49
|
+
shape="flat"
|
|
50
|
+
spacing="none"
|
|
51
|
+
value={flat}
|
|
52
|
+
onValueChange={setFlat}
|
|
53
|
+
aria-label="Flat shape"
|
|
54
|
+
>
|
|
55
|
+
<Tile value="checking" showSeparator>
|
|
56
|
+
<Tile.Content>
|
|
57
|
+
<Tile.Title>Flat</Tile.Title>
|
|
58
|
+
<Tile.Description>Borderless rows that touch, split by separators.</Tile.Description>
|
|
59
|
+
</Tile.Content>
|
|
60
|
+
<Tile.Indicator />
|
|
61
|
+
</Tile>
|
|
62
|
+
<Tile value="savings">
|
|
63
|
+
<Tile.Content>
|
|
64
|
+
<Tile.Title>Flat</Tile.Title>
|
|
65
|
+
<Tile.Description>Suited to lists and cards.</Tile.Description>
|
|
66
|
+
</Tile.Content>
|
|
67
|
+
<Tile.Indicator />
|
|
68
|
+
</Tile>
|
|
69
|
+
</Tile.Group>
|
|
70
|
+
</View>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Card
|
|
76
|
+
|
|
77
|
+
The default. Each tile is a bordered, rounded surface with gaps between tiles. Use `type="single"` for radio semantics — one value at a time.
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
import { useState } from 'react';
|
|
81
|
+
import { Avatar, Tile } from '@cdx-ui/components';
|
|
82
|
+
import { Person } from '@cdx-ui/icons';
|
|
83
|
+
|
|
84
|
+
export default function TileCardDemo() {
|
|
85
|
+
const [selected, setSelected] = useState('checking');
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<Tile.Group
|
|
89
|
+
type="single"
|
|
90
|
+
shape="card"
|
|
91
|
+
value={selected}
|
|
92
|
+
onValueChange={setSelected}
|
|
93
|
+
aria-label="Choose an account"
|
|
94
|
+
className="w-full max-w-md"
|
|
95
|
+
>
|
|
96
|
+
<Tile value="checking">
|
|
97
|
+
<Tile.LeadingSlot>
|
|
98
|
+
<Avatar size="md">
|
|
99
|
+
<Avatar.Icon as={Person} />
|
|
100
|
+
</Avatar>
|
|
101
|
+
</Tile.LeadingSlot>
|
|
102
|
+
<Tile.Content>
|
|
103
|
+
<Tile.Title>Joint Checking · 6643</Tile.Title>
|
|
104
|
+
<Tile.Description>$11,308.34 available</Tile.Description>
|
|
105
|
+
</Tile.Content>
|
|
106
|
+
<Tile.Indicator />
|
|
107
|
+
</Tile>
|
|
108
|
+
<Tile value="savings">
|
|
109
|
+
<Tile.LeadingSlot>
|
|
110
|
+
<Avatar size="md">
|
|
111
|
+
<Avatar.Icon as={Person} />
|
|
112
|
+
</Avatar>
|
|
113
|
+
</Tile.LeadingSlot>
|
|
114
|
+
<Tile.Content>
|
|
115
|
+
<Tile.Title>High Yield Savings · 7891</Tile.Title>
|
|
116
|
+
<Tile.Description>$25,430.00 available</Tile.Description>
|
|
117
|
+
</Tile.Content>
|
|
118
|
+
<Tile.Indicator />
|
|
119
|
+
</Tile>
|
|
120
|
+
</Tile.Group>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Flat
|
|
126
|
+
|
|
127
|
+
Borderless rows with no radius. Pair with `spacing="none"` and `showSeparator` for tight lists, and see [In card](#in-card) and [List](#list) for common placements.
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import { useState } from 'react';
|
|
131
|
+
import { Tile } from '@cdx-ui/components';
|
|
132
|
+
|
|
133
|
+
export default function TileFlatDemo() {
|
|
134
|
+
const [selected, setSelected] = useState('checking');
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<Tile.Group
|
|
138
|
+
type="single"
|
|
139
|
+
shape="flat"
|
|
140
|
+
spacing="none"
|
|
141
|
+
value={selected}
|
|
142
|
+
onValueChange={setSelected}
|
|
143
|
+
aria-label="Choose an account"
|
|
144
|
+
className="w-full max-w-md"
|
|
145
|
+
>
|
|
146
|
+
<Tile value="checking" showSeparator>
|
|
147
|
+
<Tile.Content>
|
|
148
|
+
<Tile.Title>Joint Checking · 6643</Tile.Title>
|
|
149
|
+
<Tile.Description>$11,308.34 available</Tile.Description>
|
|
150
|
+
</Tile.Content>
|
|
151
|
+
<Tile.Indicator />
|
|
152
|
+
</Tile>
|
|
153
|
+
<Tile value="savings">
|
|
154
|
+
<Tile.Content>
|
|
155
|
+
<Tile.Title>High Yield Savings · 7891</Tile.Title>
|
|
156
|
+
<Tile.Description>$25,430.00 available</Tile.Description>
|
|
157
|
+
</Tile.Content>
|
|
158
|
+
<Tile.Indicator />
|
|
159
|
+
</Tile>
|
|
160
|
+
</Tile.Group>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Without indicator
|
|
166
|
+
|
|
167
|
+
Omit `Tile.Indicator` when the selected tile styling provides enough visual affordance for the interaction.
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
import { useState } from 'react';
|
|
171
|
+
import { Tile } from '@cdx-ui/components';
|
|
172
|
+
|
|
173
|
+
export default function TileWithoutIndicatorDemo() {
|
|
174
|
+
const [selected, setSelected] = useState('standard');
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<Tile.Group
|
|
178
|
+
type="single"
|
|
179
|
+
shape="card"
|
|
180
|
+
value={selected}
|
|
181
|
+
onValueChange={setSelected}
|
|
182
|
+
aria-label="Choose a delivery speed"
|
|
183
|
+
className="w-full max-w-md"
|
|
184
|
+
>
|
|
185
|
+
<Tile value="standard">
|
|
186
|
+
<Tile.Content>
|
|
187
|
+
<Tile.Title>Standard delivery</Tile.Title>
|
|
188
|
+
<Tile.Description>Arrives in 3–5 business days</Tile.Description>
|
|
189
|
+
</Tile.Content>
|
|
190
|
+
</Tile>
|
|
191
|
+
<Tile value="express">
|
|
192
|
+
<Tile.Content>
|
|
193
|
+
<Tile.Title>Express delivery</Tile.Title>
|
|
194
|
+
<Tile.Description>Arrives the next business day</Tile.Description>
|
|
195
|
+
</Tile.Content>
|
|
196
|
+
</Tile>
|
|
197
|
+
</Tile.Group>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Multiple
|
|
203
|
+
|
|
204
|
+
Use `type="multiple"` for checkbox semantics. Optional `max` caps how many tiles can be selected; unselected tiles disable when the cap is reached.
|
|
205
|
+
|
|
206
|
+
```tsx
|
|
207
|
+
import { useState } from 'react';
|
|
208
|
+
import { Tile } from '@cdx-ui/components';
|
|
209
|
+
|
|
210
|
+
const CATEGORY_OPTIONS = [
|
|
211
|
+
['dining', 'Dining out'],
|
|
212
|
+
['groceries', 'Groceries'],
|
|
213
|
+
['transport', 'Transportation'],
|
|
214
|
+
['travel', 'Travel'],
|
|
215
|
+
] as const;
|
|
216
|
+
|
|
217
|
+
export default function TileMultipleDemo() {
|
|
218
|
+
const [categories, setCategories] = useState<string[]>(['dining']);
|
|
219
|
+
|
|
220
|
+
return (
|
|
221
|
+
<Tile.Group
|
|
222
|
+
type="multiple"
|
|
223
|
+
shape="card"
|
|
224
|
+
max={3}
|
|
225
|
+
value={categories}
|
|
226
|
+
onValueChange={setCategories}
|
|
227
|
+
aria-label="Spending categories"
|
|
228
|
+
className="w-full max-w-md"
|
|
229
|
+
>
|
|
230
|
+
{CATEGORY_OPTIONS.map(([id, label]) => (
|
|
231
|
+
<Tile key={id} value={id}>
|
|
232
|
+
<Tile.Content>
|
|
233
|
+
<Tile.Title>{label}</Tile.Title>
|
|
234
|
+
</Tile.Content>
|
|
235
|
+
<Tile.Indicator />
|
|
236
|
+
</Tile>
|
|
237
|
+
))}
|
|
238
|
+
</Tile.Group>
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Horizontal
|
|
244
|
+
|
|
245
|
+
Set `direction="row"` for side-by-side segment-style choosers. Give each tile `className="flex-1"` so widths split evenly.
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { useState } from 'react';
|
|
249
|
+
import { Tile } from '@cdx-ui/components';
|
|
250
|
+
|
|
251
|
+
export default function TileHorizontalDemo() {
|
|
252
|
+
const [selected, setSelected] = useState('expense');
|
|
253
|
+
|
|
254
|
+
return (
|
|
255
|
+
<Tile.Group
|
|
256
|
+
type="single"
|
|
257
|
+
direction="row"
|
|
258
|
+
shape="card"
|
|
259
|
+
value={selected}
|
|
260
|
+
onValueChange={setSelected}
|
|
261
|
+
aria-label="Transaction type"
|
|
262
|
+
className="w-full max-w-md"
|
|
263
|
+
>
|
|
264
|
+
<Tile value="expense" className="flex-1">
|
|
265
|
+
<Tile.Content>
|
|
266
|
+
<Tile.Title>Expense</Tile.Title>
|
|
267
|
+
</Tile.Content>
|
|
268
|
+
<Tile.Indicator />
|
|
269
|
+
</Tile>
|
|
270
|
+
<Tile value="income" className="flex-1">
|
|
271
|
+
<Tile.Content>
|
|
272
|
+
<Tile.Title>Income</Tile.Title>
|
|
273
|
+
</Tile.Content>
|
|
274
|
+
<Tile.Indicator />
|
|
275
|
+
</Tile>
|
|
276
|
+
</Tile.Group>
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## In card
|
|
282
|
+
|
|
283
|
+
Use the [flat shape](#flat) for tight rows inside a `Card`. Use `Card.Content fullBleed` so tiles stretch edge-to-edge.
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
import { useState } from 'react';
|
|
287
|
+
import { Card, Tile } from '@cdx-ui/components';
|
|
288
|
+
|
|
289
|
+
export default function TileInCardDemo() {
|
|
290
|
+
const [selected, setSelected] = useState<string[]>([]);
|
|
291
|
+
|
|
292
|
+
return (
|
|
293
|
+
<Card className="w-full max-w-md">
|
|
294
|
+
<Card.Content fullBleed>
|
|
295
|
+
<Tile.Group
|
|
296
|
+
type="multiple"
|
|
297
|
+
spacing="none"
|
|
298
|
+
shape="flat"
|
|
299
|
+
value={selected}
|
|
300
|
+
onValueChange={setSelected}
|
|
301
|
+
aria-label="Statement preferences"
|
|
302
|
+
>
|
|
303
|
+
<Tile value="transactions" showSeparator>
|
|
304
|
+
<Tile.Content>
|
|
305
|
+
<Tile.Title>Transactions</Tile.Title>
|
|
306
|
+
</Tile.Content>
|
|
307
|
+
<Tile.Indicator />
|
|
308
|
+
</Tile>
|
|
309
|
+
<Tile value="running" showSeparator>
|
|
310
|
+
<Tile.Content>
|
|
311
|
+
<Tile.Title>Running balance</Tile.Title>
|
|
312
|
+
</Tile.Content>
|
|
313
|
+
<Tile.Indicator />
|
|
314
|
+
</Tile>
|
|
315
|
+
<Tile value="daily">
|
|
316
|
+
<Tile.Content>
|
|
317
|
+
<Tile.Title>Daily balances</Tile.Title>
|
|
318
|
+
</Tile.Content>
|
|
319
|
+
<Tile.Indicator />
|
|
320
|
+
</Tile>
|
|
321
|
+
</Tile.Group>
|
|
322
|
+
</Card.Content>
|
|
323
|
+
</Card>
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## List
|
|
329
|
+
|
|
330
|
+
Use the same [flat](#flat) rows without a `Card` for a plain list. Omit `showSeparator` on the last row.
|
|
331
|
+
|
|
332
|
+
```tsx
|
|
333
|
+
import { useState } from 'react';
|
|
334
|
+
import { Text, Tile } from '@cdx-ui/components';
|
|
335
|
+
|
|
336
|
+
const PAYMENT_OPTIONS = [
|
|
337
|
+
{ value: 'regular', title: 'Regular payment', description: 'Make your scheduled loan payment.' },
|
|
338
|
+
{
|
|
339
|
+
value: 'principal',
|
|
340
|
+
title: 'Principal only',
|
|
341
|
+
description: 'Apply your payment directly to the loan principal.',
|
|
342
|
+
},
|
|
343
|
+
{ value: 'interest', title: 'Interest only', description: 'Pay only the accrued interest.' },
|
|
344
|
+
{
|
|
345
|
+
value: 'escrow',
|
|
346
|
+
title: 'Escrow only',
|
|
347
|
+
description: 'Pay only the escrow portion of your loan.',
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
value: 'fees',
|
|
351
|
+
title: 'Fees only',
|
|
352
|
+
description: 'Pay outstanding fees only.',
|
|
353
|
+
amount: '$109.30',
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
value: 'payoff',
|
|
357
|
+
title: 'Pay off balance',
|
|
358
|
+
description: 'Pay the loan in full and keep the account open.',
|
|
359
|
+
},
|
|
360
|
+
];
|
|
361
|
+
|
|
362
|
+
export default function TileListDemo() {
|
|
363
|
+
const [selected, setSelected] = useState<string[]>(['fees']);
|
|
364
|
+
|
|
365
|
+
return (
|
|
366
|
+
<Tile.Group
|
|
367
|
+
type="multiple"
|
|
368
|
+
spacing="none"
|
|
369
|
+
shape="flat"
|
|
370
|
+
value={selected}
|
|
371
|
+
onValueChange={setSelected}
|
|
372
|
+
aria-label="Payment type"
|
|
373
|
+
className="w-full max-w-md"
|
|
374
|
+
>
|
|
375
|
+
{PAYMENT_OPTIONS.map((option, index) => (
|
|
376
|
+
<Tile
|
|
377
|
+
key={option.value}
|
|
378
|
+
value={option.value}
|
|
379
|
+
showSeparator={index < PAYMENT_OPTIONS.length - 1}
|
|
380
|
+
>
|
|
381
|
+
<Tile.Content>
|
|
382
|
+
<Tile.Title>{option.title}</Tile.Title>
|
|
383
|
+
<Tile.Description>{option.description}</Tile.Description>
|
|
384
|
+
</Tile.Content>
|
|
385
|
+
{option.amount ? (
|
|
386
|
+
<Tile.TrailingSlot>
|
|
387
|
+
<Text>{option.amount}</Text>
|
|
388
|
+
</Tile.TrailingSlot>
|
|
389
|
+
) : null}
|
|
390
|
+
<Tile.Indicator />
|
|
391
|
+
</Tile>
|
|
392
|
+
))}
|
|
393
|
+
</Tile.Group>
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
## Standalone
|
|
399
|
+
|
|
400
|
+
A `Tile` without a parent `Tile.Group` manages its own selection via `isSelected` / `defaultSelected` / `onSelectedChange`. Standalone tiles use checkbox semantics.
|
|
401
|
+
|
|
402
|
+
```tsx
|
|
403
|
+
import { useState } from 'react';
|
|
404
|
+
import { Tile } from '@cdx-ui/components';
|
|
405
|
+
|
|
406
|
+
export default function TileStandaloneDemo() {
|
|
407
|
+
const [agreed, setAgreed] = useState(false);
|
|
408
|
+
|
|
409
|
+
return (
|
|
410
|
+
<Tile
|
|
411
|
+
value="terms"
|
|
412
|
+
shape="card"
|
|
413
|
+
isSelected={agreed}
|
|
414
|
+
onSelectedChange={setAgreed}
|
|
415
|
+
className="w-full max-w-md"
|
|
416
|
+
>
|
|
417
|
+
<Tile.Content>
|
|
418
|
+
<Tile.Title>I agree to the terms and conditions</Tile.Title>
|
|
419
|
+
<Tile.Description>By selecting this, you accept our privacy policy.</Tile.Description>
|
|
420
|
+
</Tile.Content>
|
|
421
|
+
<Tile.Indicator indicatorType="checkbox" />
|
|
422
|
+
</Tile>
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## With trailing
|
|
428
|
+
|
|
429
|
+
`Tile.TrailingSlot` carries amounts, chips, or status text — separate from `Tile.Indicator`, which is reserved for the selection affordance.
|
|
430
|
+
|
|
431
|
+
```tsx
|
|
432
|
+
import { useState } from 'react';
|
|
433
|
+
import { Avatar, Text, Tile } from '@cdx-ui/components';
|
|
434
|
+
import { Person } from '@cdx-ui/icons';
|
|
435
|
+
|
|
436
|
+
export default function TileWithTrailingDemo() {
|
|
437
|
+
const [selected, setSelected] = useState<string[]>(['checking']);
|
|
438
|
+
|
|
439
|
+
return (
|
|
440
|
+
<Tile.Group
|
|
441
|
+
type="multiple"
|
|
442
|
+
shape="card"
|
|
443
|
+
value={selected}
|
|
444
|
+
onValueChange={setSelected}
|
|
445
|
+
aria-label="Accounts"
|
|
446
|
+
className="w-full max-w-md"
|
|
447
|
+
>
|
|
448
|
+
<Tile value="checking">
|
|
449
|
+
<Tile.LeadingSlot>
|
|
450
|
+
<Avatar size="md">
|
|
451
|
+
<Avatar.Icon as={Person} />
|
|
452
|
+
</Avatar>
|
|
453
|
+
</Tile.LeadingSlot>
|
|
454
|
+
<Tile.Content>
|
|
455
|
+
<Tile.Title>Joint Checking · 6643</Tile.Title>
|
|
456
|
+
<Tile.Description>Available balance</Tile.Description>
|
|
457
|
+
</Tile.Content>
|
|
458
|
+
<Tile.TrailingSlot>
|
|
459
|
+
<Text>$11,308.34</Text>
|
|
460
|
+
</Tile.TrailingSlot>
|
|
461
|
+
<Tile.Indicator />
|
|
462
|
+
</Tile>
|
|
463
|
+
<Tile value="savings">
|
|
464
|
+
<Tile.LeadingSlot>
|
|
465
|
+
<Avatar size="md">
|
|
466
|
+
<Avatar.Icon as={Person} />
|
|
467
|
+
</Avatar>
|
|
468
|
+
</Tile.LeadingSlot>
|
|
469
|
+
<Tile.Content>
|
|
470
|
+
<Tile.Title>High Yield Savings · 7891</Tile.Title>
|
|
471
|
+
<Tile.Description>Available balance</Tile.Description>
|
|
472
|
+
</Tile.Content>
|
|
473
|
+
<Tile.TrailingSlot>
|
|
474
|
+
<Text>$25,430.00</Text>
|
|
475
|
+
</Tile.TrailingSlot>
|
|
476
|
+
<Tile.Indicator />
|
|
477
|
+
</Tile>
|
|
478
|
+
</Tile.Group>
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
## Disabled
|
|
484
|
+
|
|
485
|
+
Set `disabled` on a single tile, or `isDisabled` on `Tile.Group` to cascade across the whole group.
|
|
486
|
+
|
|
487
|
+
```tsx
|
|
488
|
+
import { Avatar, Tile } from '@cdx-ui/components';
|
|
489
|
+
import { Person } from '@cdx-ui/icons';
|
|
490
|
+
|
|
491
|
+
export default function TileDisabledDemo() {
|
|
492
|
+
return (
|
|
493
|
+
<Tile.Group
|
|
494
|
+
type="multiple"
|
|
495
|
+
shape="card"
|
|
496
|
+
defaultValue={['open']}
|
|
497
|
+
aria-label="Accounts"
|
|
498
|
+
className="w-full max-w-md"
|
|
499
|
+
>
|
|
500
|
+
<Tile value="open">
|
|
501
|
+
<Tile.LeadingSlot>
|
|
502
|
+
<Avatar size="md">
|
|
503
|
+
<Avatar.Icon as={Person} />
|
|
504
|
+
</Avatar>
|
|
505
|
+
</Tile.LeadingSlot>
|
|
506
|
+
<Tile.Content>
|
|
507
|
+
<Tile.Title>Joint Checking · 6643</Tile.Title>
|
|
508
|
+
<Tile.Description>$11,308.34 available</Tile.Description>
|
|
509
|
+
</Tile.Content>
|
|
510
|
+
<Tile.Indicator />
|
|
511
|
+
</Tile>
|
|
512
|
+
<Tile value="closed" disabled>
|
|
513
|
+
<Tile.LeadingSlot>
|
|
514
|
+
<Avatar size="md">
|
|
515
|
+
<Avatar.Icon as={Person} />
|
|
516
|
+
</Avatar>
|
|
517
|
+
</Tile.LeadingSlot>
|
|
518
|
+
<Tile.Content>
|
|
519
|
+
<Tile.Title>Closed account</Tile.Title>
|
|
520
|
+
<Tile.Description>Press is no-op; opacity reduced</Tile.Description>
|
|
521
|
+
</Tile.Content>
|
|
522
|
+
<Tile.Indicator />
|
|
523
|
+
</Tile>
|
|
524
|
+
</Tile.Group>
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
## API
|
|
530
|
+
|
|
531
|
+
### Tile
|
|
532
|
+
|
|
533
|
+
Pressable root that toggles selection on press. Requires a unique `value`. Inside a `Tile.Group`, selection is owned by the group; standalone usage supports `isSelected` / `defaultSelected` / `onSelectedChange`.
|
|
534
|
+
|
|
535
|
+
| Prop | Type | Default | Description |
|
|
536
|
+
| --- | --- | --- | --- |
|
|
537
|
+
| `className?` | `string` | — | — |
|
|
538
|
+
| `children?` | `ReactNode \| ((state: PressableStateCallbackType) => React.ReactNode)` | — | Either children or a render prop that receives a boolean reflecting whether the component is currently pressed. |
|
|
539
|
+
| `shape?` | `'card' \| 'flat'` | `'card'` | Visual shape. Overrides the shape inherited from `Tile.Group`. `card` is a bordered surface; `flat` is a borderless row. |
|
|
540
|
+
| `showSeparator?` | `boolean` | `false` | Renders a bottom border. Omit it on the last row of a tight list. |
|
|
541
|
+
| `asChild?` | `boolean` | — | Merge tile props onto a single child instead of rendering the default Pressable. |
|
|
542
|
+
| `value` | `string` | — | Identifies this tile within `Tile.Group`. Must be unique within the group. Standalone tiles still require a value (useful for form submission, analytics, etc.). |
|
|
543
|
+
| `isSelected?` | `boolean` | — | Controlled selected state for **standalone** usage (no parent `Tile.Group`). Ignored when the tile is rendered inside a `Tile.Group` — selection is owned by the group. |
|
|
544
|
+
| `defaultSelected?` | `boolean` | — | Initial selected state for **standalone**, uncontrolled usage. |
|
|
545
|
+
| `onSelectedChange?` | `((isSelected: boolean) => void)` | — | Called when standalone selection state changes. Group context overrides this — when inside a `Tile.Group`, use the group's `onValueChange` instead. |
|
|
546
|
+
|
|
547
|
+
Inherits all [`PressableProps`](https://reactnative.dev/docs/pressable#props) (including `onPress`).
|
|
548
|
+
|
|
549
|
+
| Attribute | Values | Description |
|
|
550
|
+
| --------------- | -------------------------- | --------------- |
|
|
551
|
+
| `data-slot` | `tile` | Root pressable |
|
|
552
|
+
| `data-state` | `selected` \| `unselected` | Selection state |
|
|
553
|
+
| `data-disabled` | `true` \| `false` | Disabled state |
|
|
554
|
+
|
|
555
|
+
## Sub-components
|
|
556
|
+
|
|
557
|
+
### Tile.Group
|
|
558
|
+
|
|
559
|
+
Selection state container and layout. `type="single"` uses radio semantics and does not clear the current value when that tile is pressed again; `type="multiple"` (optional `max`) uses checkbox semantics. `direction` and `spacing` constrain layout to the three supported patterns. `shape` cascades to child tiles.
|
|
560
|
+
|
|
561
|
+
| Prop | Type | Default | Description |
|
|
562
|
+
| --- | --- | --- | --- |
|
|
563
|
+
| `className?` | `string` | — | — |
|
|
564
|
+
| `children?` | `ReactNode` | — | — |
|
|
565
|
+
| `direction?` | `'column' \| 'row' \| null` | — | — |
|
|
566
|
+
| `spacing?` | `'default' \| 'none' \| null` | — | — |
|
|
567
|
+
| `shape?` | `'flat' \| 'card' \| null` | — | — |
|
|
568
|
+
| `type?` | `'single' \| 'multiple'` | — | — |
|
|
569
|
+
| `value?` | `string \| string[]` | — | — |
|
|
570
|
+
| `defaultValue?` | `string \| string[]` | — | — |
|
|
571
|
+
| `onValueChange?` | `((value: string) => void) \| ((value: string[]) => void)` | — | — |
|
|
572
|
+
| `asChild?` | `boolean` | — | — |
|
|
573
|
+
| `isDisabled?` | `boolean` | — | — |
|
|
574
|
+
| `max?` | `number` | — | — |
|
|
575
|
+
|
|
576
|
+
Inherits all [`ViewProps`](https://reactnative.dev/docs/view#props). `Tile.Group` is a discriminated union on `type`; `max` applies only when `type="multiple"`.
|
|
577
|
+
|
|
578
|
+
| `direction` | `spacing` | Use case |
|
|
579
|
+
| ------------------ | ------------------- | --------------------------------- |
|
|
580
|
+
| `column` (default) | `default` (default) | Vertical stack with gaps |
|
|
581
|
+
| `column` | `none` | Tight vertical stack (rows touch) |
|
|
582
|
+
| `row` | `default` | Side-by-side horizontal layout |
|
|
583
|
+
|
|
584
|
+
### Tile.LeadingSlot
|
|
585
|
+
|
|
586
|
+
Optional leading adornment (Avatar, Icon). Decorative and `aria-hidden` by default — override for meaningful leading content.
|
|
587
|
+
|
|
588
|
+
| Prop | Type | Default | Description |
|
|
589
|
+
| --- | --- | --- | --- |
|
|
590
|
+
| `className?` | `string` | — | — |
|
|
591
|
+
| `children?` | `ReactNode` | — | — |
|
|
592
|
+
| `asChild?` | `boolean` | — | — |
|
|
593
|
+
|
|
594
|
+
Inherits all [`ViewProps`](https://reactnative.dev/docs/view#props).
|
|
595
|
+
|
|
596
|
+
### Tile.Content
|
|
597
|
+
|
|
598
|
+
Flex column for the text stack (`Tile.Title` and `Tile.Description`).
|
|
599
|
+
|
|
600
|
+
| Prop | Type | Default | Description |
|
|
601
|
+
| --- | --- | --- | --- |
|
|
602
|
+
| `className?` | `string` | — | — |
|
|
603
|
+
| `children?` | `ReactNode` | — | — |
|
|
604
|
+
| `asChild?` | `boolean` | — | — |
|
|
605
|
+
|
|
606
|
+
Inherits all [`ViewProps`](https://reactnative.dev/docs/view#props).
|
|
607
|
+
|
|
608
|
+
### Tile.Title
|
|
609
|
+
|
|
610
|
+
Primary label. Truncates to one line by default (`numberOfLines={1}`).
|
|
611
|
+
|
|
612
|
+
| Prop | Type | Default | Description |
|
|
613
|
+
| --- | --- | --- | --- |
|
|
614
|
+
| `className?` | `string` | — | — |
|
|
615
|
+
| `children?` | `ReactNode` | — | — |
|
|
616
|
+
| `asChild?` | `boolean` | — | — |
|
|
617
|
+
|
|
618
|
+
Inherits all [`TextProps`](https://reactnative.dev/docs/text#props).
|
|
619
|
+
|
|
620
|
+
### Tile.Description
|
|
621
|
+
|
|
622
|
+
Secondary text below the title. Wraps freely by default.
|
|
623
|
+
|
|
624
|
+
| Prop | Type | Default | Description |
|
|
625
|
+
| --- | --- | --- | --- |
|
|
626
|
+
| `className?` | `string` | — | — |
|
|
627
|
+
| `children?` | `ReactNode` | — | — |
|
|
628
|
+
| `asChild?` | `boolean` | — | — |
|
|
629
|
+
|
|
630
|
+
Inherits all [`TextProps`](https://reactnative.dev/docs/text#props).
|
|
631
|
+
|
|
632
|
+
### Tile.Indicator
|
|
633
|
+
|
|
634
|
+
Decorative selection affordance — radio for `type="single"`, checkbox for `type="multiple"`. Always `aria-hidden`; the tile root owns the press target and ARIA role. Use `indicatorType` to override (required for radio styling when standalone).
|
|
635
|
+
|
|
636
|
+
| Prop | Type | Default | Description |
|
|
637
|
+
| --- | --- | --- | --- |
|
|
638
|
+
| `className?` | `string` | — | — |
|
|
639
|
+
| `children?` | `ReactNode` | — | Replaces the default radio or checkbox visual when provided. |
|
|
640
|
+
| `asChild?` | `boolean` | — | — |
|
|
641
|
+
| `indicatorType?` | `'radio' \| 'checkbox'` | — | Explicit indicator visual. When inside a `Tile.Group`, auto-infers from `type` (`single` → radio, `multiple` → checkbox). For standalone tiles, defaults to `'checkbox'` to match the standalone `checkbox` ARIA role; override with `indicatorType="radio"` if a radio-style visual is needed. |
|
|
642
|
+
|
|
643
|
+
Inherits all [`ViewProps`](https://reactnative.dev/docs/view#props).
|
|
644
|
+
|
|
645
|
+
### Tile.TrailingSlot
|
|
646
|
+
|
|
647
|
+
Optional trailing content (amount, chip, status text) — distinct from `Tile.Indicator`.
|
|
648
|
+
|
|
649
|
+
| Prop | Type | Default | Description |
|
|
650
|
+
| --- | --- | --- | --- |
|
|
651
|
+
| `className?` | `string` | — | — |
|
|
652
|
+
| `children?` | `ReactNode` | — | — |
|
|
653
|
+
| `asChild?` | `boolean` | — | — |
|
|
654
|
+
|
|
655
|
+
Inherits all [`ViewProps`](https://reactnative.dev/docs/view#props).
|
|
656
|
+
|
|
657
|
+
## Anatomy
|
|
658
|
+
|
|
659
|
+
| `data-slot` | Element |
|
|
660
|
+
| ------------------ | -------------------- |
|
|
661
|
+
| `tile` | Root pressable |
|
|
662
|
+
| `tile-group` | Selection group |
|
|
663
|
+
| `tile-leading` | Leading adornment |
|
|
664
|
+
| `tile-content` | Text stack |
|
|
665
|
+
| `tile-title` | Primary label |
|
|
666
|
+
| `tile-description` | Secondary text |
|
|
667
|
+
| `tile-indicator` | Selection affordance |
|
|
668
|
+
| `tile-trailing` | Trailing content |
|
|
669
|
+
|
|
670
|
+
## Hook
|
|
671
|
+
|
|
672
|
+
### useTileContext
|
|
673
|
+
|
|
674
|
+
Reads this tile's selection state from a child, for example to swap a leading icon when the tile is selected. Call it inside a `Tile`; it throws otherwise.
|
|
675
|
+
|
|
676
|
+
```tsx
|
|
677
|
+
const { isSelected } = useTileContext();
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
| Return | Type | Description |
|
|
681
|
+
| --------------- | ------------------------ | -------------------------------------------------------------------------------------- |
|
|
682
|
+
| `value` | `string` | This tile's `value`. |
|
|
683
|
+
| `isSelected` | `boolean` | Whether the tile is selected. |
|
|
684
|
+
| `isDisabled` | `boolean` | Effective disabled state from the tile's `disabled` prop or group rules such as `max`. |
|
|
685
|
+
| `selectionType` | `'single' \| 'multiple'` | The group's `type`, or `'multiple'` when the tile is standalone. |
|
|
686
|
+
|
|
687
|
+
## Accessibility
|
|
688
|
+
|
|
689
|
+
| Attribute | Behavior |
|
|
690
|
+
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
691
|
+
| **Role** | `Tile.Group` is `radiogroup` for `single`, `group` for `multiple`. Each `Tile` is `radio` or `checkbox` accordingly. Standalone tiles are `checkbox`. |
|
|
692
|
+
| **`aria-checked`** | Reflects per-tile selection state. |
|
|
693
|
+
| **`aria-disabled`** | Set on disabled tiles and on unselected tiles when `max` is reached. |
|
|
694
|
+
| **Keyboard** | Focusable via Tab; activated with Enter or Space. Focus-visible ring on web. |
|
|
695
|
+
| **`Tile.LeadingSlot`** | `aria-hidden` by default — override for meaningful leading content. |
|
|
696
|
+
| **`Tile.Indicator`** | Always `aria-hidden`. The tile root is the accessible interactive element. |
|
|
697
|
+
|
|
698
|
+
## When to use
|
|
699
|
+
|
|
700
|
+
| Use `Tile` when… | Use `ListItem` when… |
|
|
701
|
+
| -------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
702
|
+
| The user is choosing one or many items | The row displays information, navigates, or triggers an action |
|
|
703
|
+
| The row should be a `radio` or `checkbox` with selection state | The row should not carry built-in selection state |
|