@urbint/cl 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules +313 -0
- package/.rnstorybook/index.ts +11 -0
- package/.rnstorybook/main.ts +8 -0
- package/.rnstorybook/preview.tsx +14 -0
- package/.rnstorybook/storybook.requires.ts +49 -0
- package/.storybook/main.ts +16 -0
- package/.storybook/preview.ts +32 -0
- package/.storybook/vitest.setup.ts +7 -0
- package/App.tsx +422 -0
- package/README.md +229 -0
- package/app.json +33 -0
- package/assets/adaptive-icon.png +0 -0
- package/assets/favicon.png +0 -0
- package/assets/icon.png +0 -0
- package/assets/splash-icon.png +0 -0
- package/babel.config.js +16 -0
- package/docs/components/CodeBlock.tsx +80 -0
- package/docs/components/PropTable.tsx +93 -0
- package/docs/components/Sidebar.tsx +199 -0
- package/docs/components/index.ts +8 -0
- package/docs/data/colorTokens.ts +70 -0
- package/docs/data/componentData.tsx +1685 -0
- package/docs/data/index.ts +7 -0
- package/docs/index.ts +19 -0
- package/docs/navigation.ts +94 -0
- package/docs/pages/ColorsPage.tsx +226 -0
- package/docs/pages/ComponentPage.tsx +235 -0
- package/docs/pages/InstallationPage.tsx +232 -0
- package/docs/pages/IntroductionPage.tsx +163 -0
- package/docs/pages/ThemingPage.tsx +251 -0
- package/docs/pages/index.ts +10 -0
- package/docs/theme.ts +64 -0
- package/docs/types.ts +54 -0
- package/index.ts +8 -0
- package/llms.txt +1893 -0
- package/mcp-config.example.json +10 -0
- package/mcp-server/README.md +192 -0
- package/mcp-server/package-lock.json +1707 -0
- package/mcp-server/package.json +38 -0
- package/mcp-server/src/index.ts +1136 -0
- package/mcp-server/src/registry/components.ts +1446 -0
- package/mcp-server/src/registry/index.ts +3 -0
- package/mcp-server/src/registry/tokens.ts +256 -0
- package/mcp-server/tsconfig.json +19 -0
- package/package.json +92 -0
- package/src/components/Accordion/Accordion.stories.tsx +226 -0
- package/src/components/Accordion/Accordion.tsx +255 -0
- package/src/components/Accordion/index.ts +12 -0
- package/src/components/ActionSheet/ActionSheet.stories.tsx +393 -0
- package/src/components/ActionSheet/ActionSheet.tsx +258 -0
- package/src/components/ActionSheet/index.ts +2 -0
- package/src/components/Alert/Alert.stories.tsx +165 -0
- package/src/components/Alert/Alert.tsx +164 -0
- package/src/components/Alert/index.ts +2 -0
- package/src/components/AlertDialog/AlertDialog.stories.tsx +330 -0
- package/src/components/AlertDialog/AlertDialog.tsx +234 -0
- package/src/components/AlertDialog/index.ts +2 -0
- package/src/components/Avatar/Avatar.stories.tsx +154 -0
- package/src/components/Avatar/Avatar.tsx +219 -0
- package/src/components/Avatar/index.ts +2 -0
- package/src/components/Badge/Badge.stories.tsx +146 -0
- package/src/components/Badge/Badge.tsx +125 -0
- package/src/components/Badge/index.ts +2 -0
- package/src/components/Box/Box.stories.tsx +192 -0
- package/src/components/Box/Box.tsx +184 -0
- package/src/components/Box/index.ts +2 -0
- package/src/components/Button/Button.stories.tsx +157 -0
- package/src/components/Button/Button.tsx +180 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/Card/Card.stories.tsx +145 -0
- package/src/components/Card/Card.tsx +169 -0
- package/src/components/Card/index.ts +11 -0
- package/src/components/Center/Center.stories.tsx +215 -0
- package/src/components/Center/Center.tsx +29 -0
- package/src/components/Center/index.ts +2 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +94 -0
- package/src/components/Checkbox/Checkbox.tsx +242 -0
- package/src/components/Checkbox/index.ts +2 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +623 -0
- package/src/components/DatePicker/DatePicker.tsx +1228 -0
- package/src/components/DatePicker/index.ts +8 -0
- package/src/components/Divider/Divider.stories.tsx +224 -0
- package/src/components/Divider/Divider.tsx +73 -0
- package/src/components/Divider/index.ts +2 -0
- package/src/components/Drawer/Drawer.stories.tsx +414 -0
- package/src/components/Drawer/Drawer.tsx +342 -0
- package/src/components/Drawer/index.ts +11 -0
- package/src/components/Fab/Fab.stories.tsx +360 -0
- package/src/components/Fab/Fab.tsx +185 -0
- package/src/components/Fab/index.ts +2 -0
- package/src/components/FormControl/FormControl.stories.tsx +276 -0
- package/src/components/FormControl/FormControl.tsx +185 -0
- package/src/components/FormControl/index.ts +12 -0
- package/src/components/Grid/Grid.stories.tsx +244 -0
- package/src/components/Grid/Grid.tsx +93 -0
- package/src/components/Grid/index.ts +2 -0
- package/src/components/HStack/HStack.stories.tsx +230 -0
- package/src/components/HStack/HStack.tsx +80 -0
- package/src/components/HStack/index.ts +2 -0
- package/src/components/Heading/Heading.stories.tsx +111 -0
- package/src/components/Heading/Heading.tsx +85 -0
- package/src/components/Heading/index.ts +2 -0
- package/src/components/Icon/Icon.stories.tsx +320 -0
- package/src/components/Icon/Icon.tsx +117 -0
- package/src/components/Icon/index.ts +2 -0
- package/src/components/Image/Image.stories.tsx +357 -0
- package/src/components/Image/Image.tsx +168 -0
- package/src/components/Image/index.ts +2 -0
- package/src/components/Input/Input.stories.tsx +164 -0
- package/src/components/Input/Input.tsx +274 -0
- package/src/components/Input/index.ts +2 -0
- package/src/components/Link/Link.stories.tsx +187 -0
- package/src/components/Link/Link.tsx +104 -0
- package/src/components/Link/index.ts +2 -0
- package/src/components/Menu/Menu.stories.tsx +363 -0
- package/src/components/Menu/Menu.tsx +238 -0
- package/src/components/Menu/index.ts +2 -0
- package/src/components/Modal/Modal.stories.tsx +156 -0
- package/src/components/Modal/Modal.tsx +280 -0
- package/src/components/Modal/index.ts +11 -0
- package/src/components/Popover/Popover.stories.tsx +330 -0
- package/src/components/Popover/Popover.tsx +315 -0
- package/src/components/Popover/index.ts +11 -0
- package/src/components/Portal/Portal.stories.tsx +376 -0
- package/src/components/Portal/Portal.tsx +100 -0
- package/src/components/Portal/index.ts +2 -0
- package/src/components/Pressable/Pressable.stories.tsx +338 -0
- package/src/components/Pressable/Pressable.tsx +71 -0
- package/src/components/Pressable/index.ts +2 -0
- package/src/components/Progress/Progress.stories.tsx +131 -0
- package/src/components/Progress/Progress.tsx +219 -0
- package/src/components/Progress/index.ts +2 -0
- package/src/components/Radio/Radio.stories.tsx +101 -0
- package/src/components/Radio/Radio.tsx +234 -0
- package/src/components/Radio/index.ts +2 -0
- package/src/components/Select/Select.stories.tsx +908 -0
- package/src/components/Select/Select.tsx +659 -0
- package/src/components/Select/index.ts +8 -0
- package/src/components/Skeleton/Skeleton.stories.tsx +154 -0
- package/src/components/Skeleton/Skeleton.tsx +192 -0
- package/src/components/Skeleton/index.ts +8 -0
- package/src/components/Slider/Slider.stories.tsx +363 -0
- package/src/components/Slider/Slider.tsx +209 -0
- package/src/components/Slider/index.ts +2 -0
- package/src/components/Spinner/Spinner.stories.tsx +108 -0
- package/src/components/Spinner/Spinner.tsx +121 -0
- package/src/components/Spinner/index.ts +2 -0
- package/src/components/Switch/Switch.stories.tsx +116 -0
- package/src/components/Switch/Switch.tsx +172 -0
- package/src/components/Switch/index.ts +2 -0
- package/src/components/Table/Table.stories.tsx +417 -0
- package/src/components/Table/Table.tsx +233 -0
- package/src/components/Table/index.ts +2 -0
- package/src/components/Text/Text.stories.tsx +93 -0
- package/src/components/Text/Text.tsx +119 -0
- package/src/components/Text/index.ts +2 -0
- package/src/components/Textarea/Textarea.stories.tsx +280 -0
- package/src/components/Textarea/Textarea.tsx +212 -0
- package/src/components/Textarea/index.ts +2 -0
- package/src/components/Toast/Toast.stories.tsx +446 -0
- package/src/components/Toast/Toast.tsx +221 -0
- package/src/components/Toast/index.ts +2 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +354 -0
- package/src/components/Tooltip/Tooltip.tsx +261 -0
- package/src/components/Tooltip/index.ts +2 -0
- package/src/components/VStack/VStack.stories.tsx +183 -0
- package/src/components/VStack/VStack.tsx +76 -0
- package/src/components/VStack/index.ts +2 -0
- package/src/components/index.ts +62 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useControllableState.ts +41 -0
- package/src/hooks/useDisclosure.ts +51 -0
- package/src/index.ts +22 -0
- package/src/stories/Button.stories.tsx +53 -0
- package/src/stories/Button.tsx +101 -0
- package/src/stories/Configure.mdx +364 -0
- package/src/stories/Header.stories.tsx +33 -0
- package/src/stories/Header.tsx +75 -0
- package/src/stories/Page.stories.tsx +25 -0
- package/src/stories/Page.tsx +154 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/styles/index.ts +7 -0
- package/src/styles/tokens.ts +318 -0
- package/src/styles/unistyles.ts +254 -0
- package/src/utils/createContext.tsx +25 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/mergeRefs.ts +21 -0
- package/tsconfig.json +26 -0
- package/urbint-cl-1.0.0.tgz +0 -0
- package/vitest.config.ts +37 -0
- package/vitest.shims.d.ts +1 -0
|
@@ -0,0 +1,1685 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Documentation Data
|
|
3
|
+
* All examples use actual components for full interactivity
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { useState } from 'react';
|
|
7
|
+
import { View, Text as RNText } from 'react-native';
|
|
8
|
+
import { ComponentCategory } from '../types';
|
|
9
|
+
|
|
10
|
+
// Import actual components for interactive examples
|
|
11
|
+
import {
|
|
12
|
+
Box,
|
|
13
|
+
HStack,
|
|
14
|
+
VStack,
|
|
15
|
+
Center,
|
|
16
|
+
Grid,
|
|
17
|
+
Divider,
|
|
18
|
+
Text,
|
|
19
|
+
Heading,
|
|
20
|
+
Link,
|
|
21
|
+
Button,
|
|
22
|
+
Input,
|
|
23
|
+
Textarea,
|
|
24
|
+
Checkbox,
|
|
25
|
+
Radio,
|
|
26
|
+
Switch,
|
|
27
|
+
Select,
|
|
28
|
+
Slider,
|
|
29
|
+
FormControl,
|
|
30
|
+
Alert,
|
|
31
|
+
Toast,
|
|
32
|
+
Progress,
|
|
33
|
+
Spinner,
|
|
34
|
+
Skeleton,
|
|
35
|
+
Avatar,
|
|
36
|
+
Badge,
|
|
37
|
+
Card,
|
|
38
|
+
Fab,
|
|
39
|
+
Accordion,
|
|
40
|
+
AccordionItem,
|
|
41
|
+
AccordionButton,
|
|
42
|
+
AccordionPanel,
|
|
43
|
+
Modal,
|
|
44
|
+
ModalHeader,
|
|
45
|
+
ModalBody,
|
|
46
|
+
ModalFooter,
|
|
47
|
+
Drawer,
|
|
48
|
+
DrawerHeader,
|
|
49
|
+
DrawerBody,
|
|
50
|
+
AlertDialog,
|
|
51
|
+
Popover,
|
|
52
|
+
Tooltip,
|
|
53
|
+
Menu,
|
|
54
|
+
ActionSheet,
|
|
55
|
+
Icon,
|
|
56
|
+
Pressable,
|
|
57
|
+
} from '../../src/components';
|
|
58
|
+
|
|
59
|
+
// Export component categories
|
|
60
|
+
export const COMPONENT_CATEGORIES: ComponentCategory[] = [
|
|
61
|
+
{
|
|
62
|
+
name: 'Layout',
|
|
63
|
+
count: 6,
|
|
64
|
+
description: 'Foundational components for building page layouts and organizing content',
|
|
65
|
+
components: [
|
|
66
|
+
{
|
|
67
|
+
name: 'Box',
|
|
68
|
+
description: 'The most fundamental layout component. A polymorphic container with support for all style props.',
|
|
69
|
+
props: [
|
|
70
|
+
{ name: 'p', type: 'SpacingToken | number', description: 'Padding on all sides' },
|
|
71
|
+
{ name: 'px', type: 'SpacingToken | number', description: 'Horizontal padding' },
|
|
72
|
+
{ name: 'py', type: 'SpacingToken | number', description: 'Vertical padding' },
|
|
73
|
+
{ name: 'bg', type: 'string', description: 'Background color' },
|
|
74
|
+
{ name: 'rounded', type: '"none" | "sm" | "md" | "lg" | "xl" | "full"', description: 'Border radius' },
|
|
75
|
+
{ name: 'w', type: 'number | string', description: 'Width' },
|
|
76
|
+
{ name: 'h', type: 'number | string', description: 'Height' },
|
|
77
|
+
{ name: 'shadow', type: '"5" | "10" | "20" | "30" | "40"', description: 'Shadow elevation' },
|
|
78
|
+
],
|
|
79
|
+
examples: [
|
|
80
|
+
{
|
|
81
|
+
title: 'Basic Box',
|
|
82
|
+
description: 'Box with different padding, backgrounds and border radius',
|
|
83
|
+
code: `<Box p="lg" bg="#00A0CC" rounded="md">
|
|
84
|
+
<Text color="white">Hello</Text>
|
|
85
|
+
</Box>`,
|
|
86
|
+
render: () => (
|
|
87
|
+
<HStack space="md">
|
|
88
|
+
<Box p="lg" bg="#E5E7EB" rounded="md">
|
|
89
|
+
<Text>Default</Text>
|
|
90
|
+
</Box>
|
|
91
|
+
<Box p="lg" bg="#00A0CC" rounded="md">
|
|
92
|
+
<Text style={{ color: '#FFF' }}>Primary</Text>
|
|
93
|
+
</Box>
|
|
94
|
+
<Box p="lg" bg="#E5E7EB" rounded="full">
|
|
95
|
+
<Text>Rounded</Text>
|
|
96
|
+
</Box>
|
|
97
|
+
</HStack>
|
|
98
|
+
),
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
title: 'Box with Shadow',
|
|
102
|
+
description: 'Different shadow elevations',
|
|
103
|
+
code: `<Box p="lg" shadow="20" rounded="md">
|
|
104
|
+
<Text>Elevated</Text>
|
|
105
|
+
</Box>`,
|
|
106
|
+
render: () => (
|
|
107
|
+
<HStack space="lg">
|
|
108
|
+
<Box p="lg" shadow="10" rounded="md" bg="#FFFFFF">
|
|
109
|
+
<Text>Shadow 10</Text>
|
|
110
|
+
</Box>
|
|
111
|
+
<Box p="lg" shadow="20" rounded="md" bg="#FFFFFF">
|
|
112
|
+
<Text>Shadow 20</Text>
|
|
113
|
+
</Box>
|
|
114
|
+
<Box p="lg" shadow="30" rounded="md" bg="#FFFFFF">
|
|
115
|
+
<Text>Shadow 30</Text>
|
|
116
|
+
</Box>
|
|
117
|
+
</HStack>
|
|
118
|
+
),
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'HStack',
|
|
124
|
+
description: 'Horizontal stack layout. Arranges children in a horizontal line.',
|
|
125
|
+
props: [
|
|
126
|
+
{ name: 'space', type: 'SpacingToken | number', description: 'Gap between children' },
|
|
127
|
+
{ name: 'p', type: 'SpacingToken | number', description: 'Padding on all sides' },
|
|
128
|
+
{ name: 'px', type: 'SpacingToken | number', description: 'Horizontal padding' },
|
|
129
|
+
{ name: 'py', type: 'SpacingToken | number', description: 'Vertical padding' },
|
|
130
|
+
{ name: 'alignItems', type: 'FlexAlignType', description: 'Cross-axis alignment' },
|
|
131
|
+
{ name: 'justifyContent', type: 'FlexJustify', description: 'Main-axis alignment' },
|
|
132
|
+
{ name: 'wrap', type: 'boolean', description: 'Allow wrapping' },
|
|
133
|
+
],
|
|
134
|
+
examples: [
|
|
135
|
+
{
|
|
136
|
+
title: 'HStack with spacing',
|
|
137
|
+
code: `<HStack space="md" px="lg" py="sm">
|
|
138
|
+
<Box w={40} h={40} bg="#00A0CC" />
|
|
139
|
+
<Box w={40} h={40} bg="#00A0CC" />
|
|
140
|
+
<Box w={40} h={40} bg="#00A0CC" />
|
|
141
|
+
</HStack>`,
|
|
142
|
+
render: () => (
|
|
143
|
+
<HStack space="md">
|
|
144
|
+
<Box style={{ width: 40, height: 40, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
145
|
+
<Box style={{ width: 40, height: 40, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
146
|
+
<Box style={{ width: 40, height: 40, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
147
|
+
</HStack>
|
|
148
|
+
),
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
title: 'HStack with alignment',
|
|
152
|
+
description: 'Different alignment options',
|
|
153
|
+
code: `<HStack space="md" justifyContent="space-between">
|
|
154
|
+
<Box />
|
|
155
|
+
<Box />
|
|
156
|
+
</HStack>`,
|
|
157
|
+
render: () => (
|
|
158
|
+
<VStack space="md" style={{ width: '100%' }}>
|
|
159
|
+
<HStack space="md" justifyContent="flex-start" style={{ backgroundColor: '#F3F4F6', padding: 8, borderRadius: 4 }}>
|
|
160
|
+
<Box style={{ width: 30, height: 30, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
161
|
+
<Box style={{ width: 30, height: 30, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
162
|
+
<Text variant="caption">flex-start</Text>
|
|
163
|
+
</HStack>
|
|
164
|
+
<HStack space="md" justifyContent="center" style={{ backgroundColor: '#F3F4F6', padding: 8, borderRadius: 4 }}>
|
|
165
|
+
<Box style={{ width: 30, height: 30, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
166
|
+
<Box style={{ width: 30, height: 30, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
167
|
+
<Text variant="caption">center</Text>
|
|
168
|
+
</HStack>
|
|
169
|
+
<HStack space="md" justifyContent="space-between" style={{ backgroundColor: '#F3F4F6', padding: 8, borderRadius: 4 }}>
|
|
170
|
+
<Box style={{ width: 30, height: 30, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
171
|
+
<Text variant="caption">space-between</Text>
|
|
172
|
+
<Box style={{ width: 30, height: 30, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
173
|
+
</HStack>
|
|
174
|
+
</VStack>
|
|
175
|
+
),
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: 'VStack',
|
|
181
|
+
description: 'Vertical stack layout. Arranges children in a vertical column.',
|
|
182
|
+
props: [
|
|
183
|
+
{ name: 'space', type: 'SpacingToken | number', description: 'Gap between children' },
|
|
184
|
+
{ name: 'p', type: 'SpacingToken | number', description: 'Padding on all sides' },
|
|
185
|
+
{ name: 'px', type: 'SpacingToken | number', description: 'Horizontal padding' },
|
|
186
|
+
{ name: 'py', type: 'SpacingToken | number', description: 'Vertical padding' },
|
|
187
|
+
{ name: 'alignItems', type: 'FlexAlignType', description: 'Cross-axis alignment' },
|
|
188
|
+
],
|
|
189
|
+
examples: [
|
|
190
|
+
{
|
|
191
|
+
title: 'VStack with spacing',
|
|
192
|
+
code: `<VStack space="md" px="lg">
|
|
193
|
+
<Box w={100} h={24} bg="#00A0CC" />
|
|
194
|
+
<Box w={80} h={24} bg="#00A0CC" />
|
|
195
|
+
</VStack>`,
|
|
196
|
+
render: () => (
|
|
197
|
+
<VStack space="md">
|
|
198
|
+
<Box style={{ width: 150, height: 24, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
199
|
+
<Box style={{ width: 120, height: 24, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
200
|
+
<Box style={{ width: 100, height: 24, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
201
|
+
</VStack>
|
|
202
|
+
),
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: 'Center',
|
|
208
|
+
description: 'Centers its child both horizontally and vertically.',
|
|
209
|
+
props: [
|
|
210
|
+
{ name: 'children', type: 'ReactNode', required: true, description: 'Content to center' },
|
|
211
|
+
],
|
|
212
|
+
examples: [
|
|
213
|
+
{
|
|
214
|
+
title: 'Centered content',
|
|
215
|
+
code: `<Center style={{ height: 100, backgroundColor: '#F3F4F6' }}>
|
|
216
|
+
<Text>Centered</Text>
|
|
217
|
+
</Center>`,
|
|
218
|
+
render: () => (
|
|
219
|
+
<Center style={{ height: 80, backgroundColor: '#F3F4F6', borderRadius: 8 }}>
|
|
220
|
+
<Text weight="semiBold">Centered Content</Text>
|
|
221
|
+
</Center>
|
|
222
|
+
),
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
name: 'Grid',
|
|
228
|
+
description: 'CSS Grid-like layout for arranging items.',
|
|
229
|
+
props: [
|
|
230
|
+
{ name: 'columns', type: 'number', default: '1', description: 'Number of columns' },
|
|
231
|
+
{ name: 'gap', type: 'SpacingToken | number', default: '0', description: 'Gap between items' },
|
|
232
|
+
],
|
|
233
|
+
examples: [
|
|
234
|
+
{
|
|
235
|
+
title: '3-column grid',
|
|
236
|
+
code: `<Grid columns={3} gap="md">
|
|
237
|
+
{items.map(item => <Box key={item} />)}
|
|
238
|
+
</Grid>`,
|
|
239
|
+
render: () => (
|
|
240
|
+
<Grid columns={3} gap="sm">
|
|
241
|
+
{[1, 2, 3, 4, 5, 6].map(i => (
|
|
242
|
+
<Box key={i} style={{ height: 40, backgroundColor: '#00A0CC', borderRadius: 4 }} />
|
|
243
|
+
))}
|
|
244
|
+
</Grid>
|
|
245
|
+
),
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: 'Divider',
|
|
251
|
+
description: 'Visual separator between content sections.',
|
|
252
|
+
props: [
|
|
253
|
+
{ name: 'orientation', type: '"horizontal" | "vertical"', default: '"horizontal"', description: 'Direction' },
|
|
254
|
+
{ name: 'thickness', type: 'number', default: '1', description: 'Thickness in pixels' },
|
|
255
|
+
],
|
|
256
|
+
examples: [
|
|
257
|
+
{
|
|
258
|
+
title: 'Horizontal Divider',
|
|
259
|
+
code: `<VStack space="md">
|
|
260
|
+
<Text>Above</Text>
|
|
261
|
+
<Divider />
|
|
262
|
+
<Text>Below</Text>
|
|
263
|
+
</VStack>`,
|
|
264
|
+
render: () => (
|
|
265
|
+
<VStack space="md" style={{ width: '100%' }}>
|
|
266
|
+
<Text>Above the divider</Text>
|
|
267
|
+
<Divider />
|
|
268
|
+
<Text>Below the divider</Text>
|
|
269
|
+
</VStack>
|
|
270
|
+
),
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
title: 'Vertical Divider',
|
|
274
|
+
code: `<HStack space="md">
|
|
275
|
+
<Text>Left</Text>
|
|
276
|
+
<Divider orientation="vertical" />
|
|
277
|
+
<Text>Right</Text>
|
|
278
|
+
</HStack>`,
|
|
279
|
+
render: () => (
|
|
280
|
+
<HStack space="md" style={{ height: 40 }}>
|
|
281
|
+
<Text>Left</Text>
|
|
282
|
+
<Divider orientation="vertical" />
|
|
283
|
+
<Text>Right</Text>
|
|
284
|
+
</HStack>
|
|
285
|
+
),
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: 'Typography',
|
|
293
|
+
count: 3,
|
|
294
|
+
description: 'Text components following the Urbint type scale',
|
|
295
|
+
components: [
|
|
296
|
+
{
|
|
297
|
+
name: 'Text',
|
|
298
|
+
description: 'Primary text component with semantic variants.',
|
|
299
|
+
props: [
|
|
300
|
+
{ name: 'variant', type: '"body" | "caption" | "label" | "small"', default: '"body"', description: 'Text style variant' },
|
|
301
|
+
{ name: 'weight', type: '"regular" | "medium" | "semiBold" | "bold"', default: '"regular"', description: 'Font weight' },
|
|
302
|
+
{ name: 'color', type: 'string', description: 'Text color' },
|
|
303
|
+
{ name: 'align', type: '"left" | "center" | "right"', description: 'Text alignment' },
|
|
304
|
+
],
|
|
305
|
+
examples: [
|
|
306
|
+
{
|
|
307
|
+
title: 'Text Variants',
|
|
308
|
+
code: `<Text variant="body">Body text</Text>
|
|
309
|
+
<Text variant="caption">Caption text</Text>`,
|
|
310
|
+
render: () => (
|
|
311
|
+
<VStack space="sm">
|
|
312
|
+
<Text variant="body">Body Text (default)</Text>
|
|
313
|
+
<Text variant="caption">Caption Text (smaller, secondary)</Text>
|
|
314
|
+
<Text variant="label">Label Text</Text>
|
|
315
|
+
<Text variant="small">Small Text</Text>
|
|
316
|
+
</VStack>
|
|
317
|
+
),
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
title: 'Text Weights',
|
|
321
|
+
code: `<Text weight="regular">Regular</Text>
|
|
322
|
+
<Text weight="bold">Bold</Text>`,
|
|
323
|
+
render: () => (
|
|
324
|
+
<VStack space="sm">
|
|
325
|
+
<Text weight="regular">Regular weight</Text>
|
|
326
|
+
<Text weight="medium">Medium weight</Text>
|
|
327
|
+
<Text weight="semiBold">SemiBold weight</Text>
|
|
328
|
+
<Text weight="bold">Bold weight</Text>
|
|
329
|
+
</VStack>
|
|
330
|
+
),
|
|
331
|
+
},
|
|
332
|
+
],
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
name: 'Heading',
|
|
336
|
+
description: 'Semantic heading component for page titles.',
|
|
337
|
+
props: [
|
|
338
|
+
{ name: 'as', type: '"h1" | "h2" | "h3" | "h4"', required: true, description: 'Heading level' },
|
|
339
|
+
{ name: 'color', type: 'string', description: 'Text color' },
|
|
340
|
+
],
|
|
341
|
+
examples: [
|
|
342
|
+
{
|
|
343
|
+
title: 'Heading Levels',
|
|
344
|
+
code: `<Heading as="h1">Page Title</Heading>
|
|
345
|
+
<Heading as="h2">Section Title</Heading>`,
|
|
346
|
+
render: () => (
|
|
347
|
+
<VStack space="md">
|
|
348
|
+
<Heading as="h1">H1 Page Title</Heading>
|
|
349
|
+
<Heading as="h2">H2 Section Title</Heading>
|
|
350
|
+
<Heading as="h3">H3 Subsection</Heading>
|
|
351
|
+
<Heading as="h4">H4 Minor Heading</Heading>
|
|
352
|
+
</VStack>
|
|
353
|
+
),
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
name: 'Link',
|
|
359
|
+
description: 'Interactive text link.',
|
|
360
|
+
props: [
|
|
361
|
+
{ name: 'href', type: 'string', description: 'URL to navigate to' },
|
|
362
|
+
{ name: 'onPress', type: '() => void', description: 'Press handler' },
|
|
363
|
+
{ name: 'isExternal', type: 'boolean', description: 'Opens in new tab' },
|
|
364
|
+
],
|
|
365
|
+
examples: [
|
|
366
|
+
{
|
|
367
|
+
title: 'Link Styles',
|
|
368
|
+
code: `<Link href="/page">Internal Link</Link>
|
|
369
|
+
<Link href="https://..." isExternal>External</Link>`,
|
|
370
|
+
render: () => (
|
|
371
|
+
<HStack space="lg">
|
|
372
|
+
<Link onPress={() => {}}>Internal Link</Link>
|
|
373
|
+
<Link onPress={() => {}} isExternal>External Link</Link>
|
|
374
|
+
</HStack>
|
|
375
|
+
),
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
name: 'Form Controls',
|
|
383
|
+
count: 9,
|
|
384
|
+
description: 'Form inputs and controls for user data collection',
|
|
385
|
+
components: [
|
|
386
|
+
{
|
|
387
|
+
name: 'Button',
|
|
388
|
+
description: 'Primary action component with multiple variants.',
|
|
389
|
+
props: [
|
|
390
|
+
{ name: 'variant', type: '"primary" | "secondary" | "ghost" | "danger" | "outline"', default: '"primary"', description: 'Button style' },
|
|
391
|
+
{ name: 'size', type: '"sm" | "md" | "lg"', default: '"md"', description: 'Button size' },
|
|
392
|
+
{ name: 'isLoading', type: 'boolean', description: 'Loading state' },
|
|
393
|
+
{ name: 'isDisabled', type: 'boolean', description: 'Disabled state' },
|
|
394
|
+
{ name: 'onPress', type: '() => void', description: 'Press handler' },
|
|
395
|
+
],
|
|
396
|
+
examples: [
|
|
397
|
+
{
|
|
398
|
+
title: 'Button Variants',
|
|
399
|
+
description: 'Click buttons to see press feedback',
|
|
400
|
+
code: `<Button variant="primary">Primary</Button>
|
|
401
|
+
<Button variant="secondary">Secondary</Button>
|
|
402
|
+
<Button variant="danger">Danger</Button>`,
|
|
403
|
+
render: () => (
|
|
404
|
+
<HStack space="sm" style={{ flexWrap: 'wrap' }}>
|
|
405
|
+
<Button variant="primary" onPress={() => {}}>Primary</Button>
|
|
406
|
+
<Button variant="secondary" onPress={() => {}}>Secondary</Button>
|
|
407
|
+
<Button variant="danger" onPress={() => {}}>Danger</Button>
|
|
408
|
+
<Button variant="outline" onPress={() => {}}>Outline</Button>
|
|
409
|
+
<Button variant="ghost" onPress={() => {}}>Ghost</Button>
|
|
410
|
+
</HStack>
|
|
411
|
+
),
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
title: 'Button Sizes',
|
|
415
|
+
code: `<Button size="sm">Small</Button>
|
|
416
|
+
<Button size="md">Medium</Button>
|
|
417
|
+
<Button size="lg">Large</Button>`,
|
|
418
|
+
render: () => (
|
|
419
|
+
<HStack space="sm" style={{ alignItems: 'center' }}>
|
|
420
|
+
<Button size="sm" onPress={() => {}}>Small</Button>
|
|
421
|
+
<Button size="md" onPress={() => {}}>Medium</Button>
|
|
422
|
+
<Button size="lg" onPress={() => {}}>Large</Button>
|
|
423
|
+
</HStack>
|
|
424
|
+
),
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
title: 'Button States',
|
|
428
|
+
code: `<Button isLoading>Loading</Button>
|
|
429
|
+
<Button isDisabled>Disabled</Button>`,
|
|
430
|
+
render: () => (
|
|
431
|
+
<HStack space="sm">
|
|
432
|
+
<Button onPress={() => {}}>Normal</Button>
|
|
433
|
+
<Button isLoading onPress={() => {}}>Loading</Button>
|
|
434
|
+
<Button isDisabled>Disabled</Button>
|
|
435
|
+
</HStack>
|
|
436
|
+
),
|
|
437
|
+
},
|
|
438
|
+
],
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
name: 'Input',
|
|
442
|
+
description: 'Text input field with label and validation.',
|
|
443
|
+
props: [
|
|
444
|
+
{ name: 'label', type: 'string', description: 'Input label' },
|
|
445
|
+
{ name: 'placeholder', type: 'string', description: 'Placeholder text' },
|
|
446
|
+
{ name: 'isInvalid', type: 'boolean', description: 'Error state' },
|
|
447
|
+
{ name: 'errorMessage', type: 'string', description: 'Error message' },
|
|
448
|
+
{ name: 'isDisabled', type: 'boolean', description: 'Disable input' },
|
|
449
|
+
{ name: 'size', type: '"sm" | "md" | "lg"', default: '"md"', description: 'Input size' },
|
|
450
|
+
{ name: 'variant', type: '"outline" | "filled"', default: '"outline"', description: 'Input variant' },
|
|
451
|
+
],
|
|
452
|
+
examples: [
|
|
453
|
+
{
|
|
454
|
+
title: 'Interactive Input',
|
|
455
|
+
description: 'Type in the input fields to see them in action',
|
|
456
|
+
code: `<Input placeholder="Enter email..." />
|
|
457
|
+
<Input placeholder="Disabled" isDisabled />`,
|
|
458
|
+
render: () => {
|
|
459
|
+
const InputDemo = () => {
|
|
460
|
+
const [value, setValue] = useState('');
|
|
461
|
+
return (
|
|
462
|
+
<VStack space="md" style={{ width: '100%' }}>
|
|
463
|
+
<Input
|
|
464
|
+
placeholder="Type something..."
|
|
465
|
+
value={value}
|
|
466
|
+
onChangeText={setValue}
|
|
467
|
+
/>
|
|
468
|
+
<Input placeholder="Filled variant" variant="filled" />
|
|
469
|
+
<Input placeholder="Disabled input" isDisabled />
|
|
470
|
+
</VStack>
|
|
471
|
+
);
|
|
472
|
+
};
|
|
473
|
+
return <InputDemo />;
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
title: 'Input Sizes',
|
|
478
|
+
code: `<Input size="sm" placeholder="Small" />
|
|
479
|
+
<Input size="md" placeholder="Medium" />
|
|
480
|
+
<Input size="lg" placeholder="Large" />`,
|
|
481
|
+
render: () => (
|
|
482
|
+
<VStack space="md" style={{ width: '100%' }}>
|
|
483
|
+
<Input size="sm" placeholder="Small input" />
|
|
484
|
+
<Input size="md" placeholder="Medium input" />
|
|
485
|
+
<Input size="lg" placeholder="Large input" />
|
|
486
|
+
</VStack>
|
|
487
|
+
),
|
|
488
|
+
},
|
|
489
|
+
],
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
name: 'Textarea',
|
|
493
|
+
description: 'Multiline text input for longer content.',
|
|
494
|
+
props: [
|
|
495
|
+
{ name: 'placeholder', type: 'string', description: 'Placeholder text' },
|
|
496
|
+
{ name: 'rows', type: 'number', default: '4', description: 'Number of visible rows' },
|
|
497
|
+
{ name: 'isDisabled', type: 'boolean', description: 'Disable textarea' },
|
|
498
|
+
],
|
|
499
|
+
examples: [
|
|
500
|
+
{
|
|
501
|
+
title: 'Interactive Textarea',
|
|
502
|
+
description: 'Type to see multiline input in action',
|
|
503
|
+
code: `<Textarea placeholder="Enter your message..." rows={4} />`,
|
|
504
|
+
render: () => {
|
|
505
|
+
const TextareaDemo = () => {
|
|
506
|
+
const [value, setValue] = useState('');
|
|
507
|
+
return (
|
|
508
|
+
<VStack space="md" style={{ width: '100%' }}>
|
|
509
|
+
<Textarea
|
|
510
|
+
placeholder="Write your message here..."
|
|
511
|
+
value={value}
|
|
512
|
+
onChangeText={setValue}
|
|
513
|
+
rows={4}
|
|
514
|
+
/>
|
|
515
|
+
</VStack>
|
|
516
|
+
);
|
|
517
|
+
};
|
|
518
|
+
return <TextareaDemo />;
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
],
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
name: 'Checkbox',
|
|
525
|
+
description: 'Checkbox for boolean selections.',
|
|
526
|
+
props: [
|
|
527
|
+
{ name: 'label', type: 'string', description: 'Checkbox label' },
|
|
528
|
+
{ name: 'isChecked', type: 'boolean', description: 'Checked state' },
|
|
529
|
+
{ name: 'onChange', type: '(checked: boolean) => void', description: 'Change handler' },
|
|
530
|
+
{ name: 'isDisabled', type: 'boolean', description: 'Disable checkbox' },
|
|
531
|
+
],
|
|
532
|
+
examples: [
|
|
533
|
+
{
|
|
534
|
+
title: 'Interactive Checkboxes',
|
|
535
|
+
description: 'Click to toggle checkbox states',
|
|
536
|
+
code: `<Checkbox label="Accept terms" />
|
|
537
|
+
<Checkbox label="Checked" isChecked />`,
|
|
538
|
+
render: () => {
|
|
539
|
+
const CheckboxDemo = () => {
|
|
540
|
+
const [checked1, setChecked1] = useState(false);
|
|
541
|
+
const [checked2, setChecked2] = useState(true);
|
|
542
|
+
const [checked3, setChecked3] = useState(false);
|
|
543
|
+
return (
|
|
544
|
+
<VStack space="md">
|
|
545
|
+
<Checkbox label="Accept terms and conditions" isChecked={checked1} onChange={setChecked1} />
|
|
546
|
+
<Checkbox label="Subscribe to newsletter" isChecked={checked2} onChange={setChecked2} />
|
|
547
|
+
<Checkbox label="Remember me" isChecked={checked3} onChange={setChecked3} />
|
|
548
|
+
<Checkbox label="Disabled option" isDisabled />
|
|
549
|
+
</VStack>
|
|
550
|
+
);
|
|
551
|
+
};
|
|
552
|
+
return <CheckboxDemo />;
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
],
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
name: 'Radio',
|
|
559
|
+
description: 'Radio button for single selection from a group.',
|
|
560
|
+
props: [
|
|
561
|
+
{ name: 'label', type: 'string', description: 'Radio label' },
|
|
562
|
+
{ name: 'value', type: 'string', required: true, description: 'Radio value' },
|
|
563
|
+
{ name: 'isChecked', type: 'boolean', description: 'Checked state' },
|
|
564
|
+
{ name: 'onChange', type: '(value: string) => void', description: 'Change handler' },
|
|
565
|
+
],
|
|
566
|
+
examples: [
|
|
567
|
+
{
|
|
568
|
+
title: 'Interactive Radio Group',
|
|
569
|
+
description: 'Select an option to see radio behavior',
|
|
570
|
+
code: `<Radio.Group value={value} onChange={setValue}>
|
|
571
|
+
<Radio value="option1" label="Option 1" />
|
|
572
|
+
<Radio value="option2" label="Option 2" />
|
|
573
|
+
</Radio.Group>`,
|
|
574
|
+
render: () => {
|
|
575
|
+
const RadioDemo = () => {
|
|
576
|
+
const [value, setValue] = useState('option1');
|
|
577
|
+
return (
|
|
578
|
+
<VStack space="md">
|
|
579
|
+
<Radio value="option1" label="Option 1" isChecked={value === 'option1'} onChange={() => setValue('option1')} />
|
|
580
|
+
<Radio value="option2" label="Option 2" isChecked={value === 'option2'} onChange={() => setValue('option2')} />
|
|
581
|
+
<Radio value="option3" label="Option 3" isChecked={value === 'option3'} onChange={() => setValue('option3')} />
|
|
582
|
+
</VStack>
|
|
583
|
+
);
|
|
584
|
+
};
|
|
585
|
+
return <RadioDemo />;
|
|
586
|
+
},
|
|
587
|
+
},
|
|
588
|
+
],
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
name: 'Switch',
|
|
592
|
+
description: 'Toggle switch for binary on/off states.',
|
|
593
|
+
props: [
|
|
594
|
+
{ name: 'label', type: 'string', description: 'Switch label' },
|
|
595
|
+
{ name: 'isChecked', type: 'boolean', description: 'Checked state' },
|
|
596
|
+
{ name: 'onChange', type: '(checked: boolean) => void', description: 'Change handler' },
|
|
597
|
+
],
|
|
598
|
+
examples: [
|
|
599
|
+
{
|
|
600
|
+
title: 'Interactive Switches',
|
|
601
|
+
description: 'Toggle switches on and off',
|
|
602
|
+
code: `<Switch label="Notifications" />
|
|
603
|
+
<Switch label="Dark Mode" isChecked />`,
|
|
604
|
+
render: () => {
|
|
605
|
+
const SwitchDemo = () => {
|
|
606
|
+
const [notifications, setNotifications] = useState(true);
|
|
607
|
+
const [darkMode, setDarkMode] = useState(false);
|
|
608
|
+
const [autoSave, setAutoSave] = useState(true);
|
|
609
|
+
return (
|
|
610
|
+
<VStack space="md">
|
|
611
|
+
<Switch label="Notifications" isChecked={notifications} onChange={setNotifications} />
|
|
612
|
+
<Switch label="Dark Mode" isChecked={darkMode} onChange={setDarkMode} />
|
|
613
|
+
<Switch label="Auto-save" isChecked={autoSave} onChange={setAutoSave} />
|
|
614
|
+
</VStack>
|
|
615
|
+
);
|
|
616
|
+
};
|
|
617
|
+
return <SwitchDemo />;
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
],
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
name: 'Select',
|
|
624
|
+
description: 'Dropdown select with popover-style dropdown.',
|
|
625
|
+
props: [
|
|
626
|
+
{ name: 'options', type: 'SelectOption[]', required: true, description: 'Array of options' },
|
|
627
|
+
{ name: 'value', type: 'string', description: 'Selected value' },
|
|
628
|
+
{ name: 'onChange', type: '(value: string) => void', description: 'Change handler' },
|
|
629
|
+
{ name: 'placeholder', type: 'string', default: '"Select an option"', description: 'Placeholder text' },
|
|
630
|
+
{ name: 'size', type: '"sm" | "md" | "lg"', default: '"md"', description: 'Select size' },
|
|
631
|
+
],
|
|
632
|
+
examples: [
|
|
633
|
+
{
|
|
634
|
+
title: 'Interactive Select',
|
|
635
|
+
description: 'Click to open dropdown and select an option',
|
|
636
|
+
code: `<Select
|
|
637
|
+
options={[
|
|
638
|
+
{ label: 'Option 1', value: 'opt1' },
|
|
639
|
+
{ label: 'Option 2', value: 'opt2' },
|
|
640
|
+
]}
|
|
641
|
+
placeholder="Choose..."
|
|
642
|
+
/>`,
|
|
643
|
+
render: () => {
|
|
644
|
+
const SelectDemo = () => {
|
|
645
|
+
const [value, setValue] = useState('');
|
|
646
|
+
return (
|
|
647
|
+
<Select
|
|
648
|
+
options={[
|
|
649
|
+
{ label: 'United States', value: 'us' },
|
|
650
|
+
{ label: 'United Kingdom', value: 'uk' },
|
|
651
|
+
{ label: 'Canada', value: 'ca' },
|
|
652
|
+
{ label: 'Australia', value: 'au' },
|
|
653
|
+
]}
|
|
654
|
+
value={value}
|
|
655
|
+
onChange={setValue}
|
|
656
|
+
placeholder="Select a country..."
|
|
657
|
+
/>
|
|
658
|
+
);
|
|
659
|
+
};
|
|
660
|
+
return <SelectDemo />;
|
|
661
|
+
},
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
title: 'Custom Option Rendering',
|
|
665
|
+
description: 'Select with custom flag icons',
|
|
666
|
+
code: `<Select
|
|
667
|
+
options={options}
|
|
668
|
+
renderOption={({ option }) => (
|
|
669
|
+
<HStack><Text>{option.flag}</Text><Text>{option.label}</Text></HStack>
|
|
670
|
+
)}
|
|
671
|
+
/>`,
|
|
672
|
+
render: () => {
|
|
673
|
+
const CustomSelectDemo = () => {
|
|
674
|
+
const [value, setValue] = useState('');
|
|
675
|
+
const options = [
|
|
676
|
+
{ label: 'United States', value: 'us', flag: '🇺🇸' },
|
|
677
|
+
{ label: 'United Kingdom', value: 'uk', flag: '🇬🇧' },
|
|
678
|
+
{ label: 'Canada', value: 'ca', flag: '🇨🇦' },
|
|
679
|
+
{ label: 'Australia', value: 'au', flag: '🇦🇺' },
|
|
680
|
+
];
|
|
681
|
+
return (
|
|
682
|
+
<Select
|
|
683
|
+
options={options}
|
|
684
|
+
value={value}
|
|
685
|
+
onChange={setValue}
|
|
686
|
+
placeholder="Select a country..."
|
|
687
|
+
renderOption={({ option, isSelected }) => (
|
|
688
|
+
<HStack space="sm" style={{ flex: 1 }}>
|
|
689
|
+
<Text style={{ fontSize: 18 }}>{option.flag}</Text>
|
|
690
|
+
<Text style={{ fontWeight: isSelected ? '600' : '400', color: isSelected ? '#00A0CC' : '#374151' }}>
|
|
691
|
+
{option.label}
|
|
692
|
+
</Text>
|
|
693
|
+
</HStack>
|
|
694
|
+
)}
|
|
695
|
+
renderSelectedValue={({ option, placeholder }) => (
|
|
696
|
+
option ? (
|
|
697
|
+
<HStack space="sm">
|
|
698
|
+
<Text style={{ fontSize: 16 }}>{option.flag}</Text>
|
|
699
|
+
<Text>{option.label}</Text>
|
|
700
|
+
</HStack>
|
|
701
|
+
) : (
|
|
702
|
+
<Text style={{ color: '#9CA3AF' }}>{placeholder}</Text>
|
|
703
|
+
)
|
|
704
|
+
)}
|
|
705
|
+
/>
|
|
706
|
+
);
|
|
707
|
+
};
|
|
708
|
+
return <CustomSelectDemo />;
|
|
709
|
+
},
|
|
710
|
+
},
|
|
711
|
+
],
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
name: 'Slider',
|
|
715
|
+
description: 'Slider input for selecting a value from a range.',
|
|
716
|
+
props: [
|
|
717
|
+
{ name: 'value', type: 'number', description: 'Current value' },
|
|
718
|
+
{ name: 'min', type: 'number', default: '0', description: 'Minimum value' },
|
|
719
|
+
{ name: 'max', type: 'number', default: '100', description: 'Maximum value' },
|
|
720
|
+
{ name: 'step', type: 'number', default: '1', description: 'Step increment' },
|
|
721
|
+
{ name: 'onChange', type: '(value: number) => void', description: 'Change handler' },
|
|
722
|
+
],
|
|
723
|
+
examples: [
|
|
724
|
+
{
|
|
725
|
+
title: 'Interactive Slider',
|
|
726
|
+
description: 'Drag the slider to change the value',
|
|
727
|
+
code: `<Slider value={50} min={0} max={100} onChange={setValue} />`,
|
|
728
|
+
render: () => {
|
|
729
|
+
const SliderDemo = () => {
|
|
730
|
+
const [value, setValue] = useState(50);
|
|
731
|
+
return (
|
|
732
|
+
<VStack space="md" style={{ width: '100%' }}>
|
|
733
|
+
<HStack justifyContent="space-between">
|
|
734
|
+
<Text weight="semiBold">Volume</Text>
|
|
735
|
+
<Text>{value}%</Text>
|
|
736
|
+
</HStack>
|
|
737
|
+
<Slider value={value} min={0} max={100} onChange={setValue} />
|
|
738
|
+
</VStack>
|
|
739
|
+
);
|
|
740
|
+
};
|
|
741
|
+
return <SliderDemo />;
|
|
742
|
+
},
|
|
743
|
+
},
|
|
744
|
+
],
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
name: 'FormControl',
|
|
748
|
+
description: 'Wrapper for form inputs providing label, help text, and error handling.',
|
|
749
|
+
props: [
|
|
750
|
+
{ name: 'label', type: 'string', description: 'Form control label' },
|
|
751
|
+
{ name: 'helperText', type: 'string', description: 'Helper text below input' },
|
|
752
|
+
{ name: 'errorMessage', type: 'string', description: 'Error message' },
|
|
753
|
+
{ name: 'isRequired', type: 'boolean', description: 'Mark as required' },
|
|
754
|
+
{ name: 'isInvalid', type: 'boolean', description: 'Invalid state' },
|
|
755
|
+
],
|
|
756
|
+
examples: [
|
|
757
|
+
{
|
|
758
|
+
title: 'FormControl with Input',
|
|
759
|
+
description: 'Complete form field with label, helper text, and validation',
|
|
760
|
+
code: `<FormControl label="Email" isRequired>
|
|
761
|
+
<Input placeholder="Enter email" />
|
|
762
|
+
</FormControl>`,
|
|
763
|
+
render: () => {
|
|
764
|
+
const FormDemo = () => {
|
|
765
|
+
const [email, setEmail] = useState('');
|
|
766
|
+
const [password, setPassword] = useState('');
|
|
767
|
+
const isEmailInvalid = email.length > 0 && !email.includes('@');
|
|
768
|
+
return (
|
|
769
|
+
<VStack space="lg" style={{ width: '100%' }}>
|
|
770
|
+
<FormControl
|
|
771
|
+
label="Email"
|
|
772
|
+
helperText="We'll never share your email"
|
|
773
|
+
isRequired
|
|
774
|
+
isInvalid={isEmailInvalid}
|
|
775
|
+
errorMessage={isEmailInvalid ? "Please enter a valid email" : undefined}
|
|
776
|
+
>
|
|
777
|
+
<Input
|
|
778
|
+
placeholder="Enter email"
|
|
779
|
+
value={email}
|
|
780
|
+
onChangeText={setEmail}
|
|
781
|
+
isInvalid={isEmailInvalid}
|
|
782
|
+
/>
|
|
783
|
+
</FormControl>
|
|
784
|
+
<FormControl label="Password" isRequired>
|
|
785
|
+
<Input
|
|
786
|
+
placeholder="Enter password"
|
|
787
|
+
secureTextEntry
|
|
788
|
+
value={password}
|
|
789
|
+
onChangeText={setPassword}
|
|
790
|
+
/>
|
|
791
|
+
</FormControl>
|
|
792
|
+
<Button onPress={() => {}}>Submit</Button>
|
|
793
|
+
</VStack>
|
|
794
|
+
);
|
|
795
|
+
};
|
|
796
|
+
return <FormDemo />;
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
],
|
|
800
|
+
},
|
|
801
|
+
],
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
name: 'Feedback',
|
|
805
|
+
count: 5,
|
|
806
|
+
description: 'Components for displaying status and notifications',
|
|
807
|
+
components: [
|
|
808
|
+
{
|
|
809
|
+
name: 'Alert',
|
|
810
|
+
description: 'Contextual feedback messages.',
|
|
811
|
+
props: [
|
|
812
|
+
{ name: 'status', type: '"info" | "success" | "warning" | "error"', default: '"info"', description: 'Alert type' },
|
|
813
|
+
{ name: 'title', type: 'string', required: true, description: 'Alert title' },
|
|
814
|
+
{ name: 'description', type: 'string', description: 'Alert description' },
|
|
815
|
+
],
|
|
816
|
+
examples: [
|
|
817
|
+
{
|
|
818
|
+
title: 'Alert Variants',
|
|
819
|
+
description: 'Different alert types for various contexts',
|
|
820
|
+
code: `<Alert status="success" title="Saved!" />
|
|
821
|
+
<Alert status="error" title="Error" description="Something went wrong" />`,
|
|
822
|
+
render: () => (
|
|
823
|
+
<VStack space="md">
|
|
824
|
+
<Alert status="success" title="Success" description="Your changes have been saved." />
|
|
825
|
+
<Alert status="error" title="Error" description="Something went wrong. Please try again." />
|
|
826
|
+
<Alert status="warning" title="Warning" description="Please review before continuing." />
|
|
827
|
+
<Alert status="info" title="Info" description="New updates are available." />
|
|
828
|
+
</VStack>
|
|
829
|
+
),
|
|
830
|
+
},
|
|
831
|
+
],
|
|
832
|
+
},
|
|
833
|
+
{
|
|
834
|
+
name: 'Toast',
|
|
835
|
+
description: 'Brief notification messages that appear temporarily.',
|
|
836
|
+
props: [
|
|
837
|
+
{ name: 'status', type: '"info" | "success" | "warning" | "error"', default: '"info"', description: 'Toast type' },
|
|
838
|
+
{ name: 'title', type: 'string', required: true, description: 'Toast title' },
|
|
839
|
+
{ name: 'description', type: 'string', description: 'Toast description' },
|
|
840
|
+
{ name: 'duration', type: 'number', default: '3000', description: 'Display duration (ms)' },
|
|
841
|
+
],
|
|
842
|
+
examples: [
|
|
843
|
+
{
|
|
844
|
+
title: 'Show Toast',
|
|
845
|
+
description: 'Click buttons to show different toast types',
|
|
846
|
+
code: `Toast.show({
|
|
847
|
+
status: 'success',
|
|
848
|
+
title: 'Saved!',
|
|
849
|
+
description: 'Changes have been saved.',
|
|
850
|
+
})`,
|
|
851
|
+
render: () => {
|
|
852
|
+
const ToastDemo = () => {
|
|
853
|
+
const showToast = (status: 'success' | 'error' | 'warning' | 'info') => {
|
|
854
|
+
const messages = {
|
|
855
|
+
success: { title: 'Success!', description: 'Operation completed successfully.' },
|
|
856
|
+
error: { title: 'Error', description: 'Something went wrong.' },
|
|
857
|
+
warning: { title: 'Warning', description: 'Please review this action.' },
|
|
858
|
+
info: { title: 'Info', description: 'Here is some information.' },
|
|
859
|
+
};
|
|
860
|
+
Toast.show({ status, ...messages[status] });
|
|
861
|
+
};
|
|
862
|
+
return (
|
|
863
|
+
<HStack space="sm" style={{ flexWrap: 'wrap' }}>
|
|
864
|
+
<Button variant="primary" size="sm" onPress={() => showToast('success')}>Success Toast</Button>
|
|
865
|
+
<Button variant="danger" size="sm" onPress={() => showToast('error')}>Error Toast</Button>
|
|
866
|
+
<Button variant="secondary" size="sm" onPress={() => showToast('warning')}>Warning Toast</Button>
|
|
867
|
+
<Button variant="outline" size="sm" onPress={() => showToast('info')}>Info Toast</Button>
|
|
868
|
+
</HStack>
|
|
869
|
+
);
|
|
870
|
+
};
|
|
871
|
+
return <ToastDemo />;
|
|
872
|
+
},
|
|
873
|
+
},
|
|
874
|
+
],
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
name: 'Progress',
|
|
878
|
+
description: 'Visual indicator of progress.',
|
|
879
|
+
props: [
|
|
880
|
+
{ name: 'value', type: 'number', description: 'Progress value (0-100)' },
|
|
881
|
+
{ name: 'size', type: '"sm" | "md" | "lg"', default: '"md"', description: 'Progress size' },
|
|
882
|
+
{ name: 'colorScheme', type: 'string', description: 'Color scheme' },
|
|
883
|
+
],
|
|
884
|
+
examples: [
|
|
885
|
+
{
|
|
886
|
+
title: 'Interactive Progress',
|
|
887
|
+
description: 'Use buttons to change progress value',
|
|
888
|
+
code: `<Progress value={50} size="md" />`,
|
|
889
|
+
render: () => {
|
|
890
|
+
const ProgressDemo = () => {
|
|
891
|
+
const [value, setValue] = useState(50);
|
|
892
|
+
return (
|
|
893
|
+
<VStack space="lg" style={{ width: '100%' }}>
|
|
894
|
+
<VStack space="sm">
|
|
895
|
+
<HStack justifyContent="space-between">
|
|
896
|
+
<Text weight="semiBold">Upload Progress</Text>
|
|
897
|
+
<Text>{value}%</Text>
|
|
898
|
+
</HStack>
|
|
899
|
+
<Progress value={value} size="md" />
|
|
900
|
+
</VStack>
|
|
901
|
+
<HStack space="sm">
|
|
902
|
+
<Button size="sm" variant="secondary" onPress={() => setValue(Math.max(0, value - 10))}>-10%</Button>
|
|
903
|
+
<Button size="sm" variant="secondary" onPress={() => setValue(Math.min(100, value + 10))}>+10%</Button>
|
|
904
|
+
<Button size="sm" variant="outline" onPress={() => setValue(0)}>Reset</Button>
|
|
905
|
+
</HStack>
|
|
906
|
+
<Divider />
|
|
907
|
+
<Text weight="semiBold">Sizes</Text>
|
|
908
|
+
<VStack space="md" style={{ width: '100%' }}>
|
|
909
|
+
<Progress value={25} size="sm" />
|
|
910
|
+
<Progress value={50} size="md" />
|
|
911
|
+
<Progress value={75} size="lg" />
|
|
912
|
+
</VStack>
|
|
913
|
+
</VStack>
|
|
914
|
+
);
|
|
915
|
+
};
|
|
916
|
+
return <ProgressDemo />;
|
|
917
|
+
},
|
|
918
|
+
},
|
|
919
|
+
],
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
name: 'Spinner',
|
|
923
|
+
description: 'Loading indicator.',
|
|
924
|
+
props: [
|
|
925
|
+
{ name: 'size', type: '"xs" | "sm" | "md" | "lg" | "xl"', default: '"md"', description: 'Spinner size' },
|
|
926
|
+
{ name: 'color', type: 'string', description: 'Spinner color' },
|
|
927
|
+
],
|
|
928
|
+
examples: [
|
|
929
|
+
{
|
|
930
|
+
title: 'Spinner Sizes',
|
|
931
|
+
code: `<Spinner size="sm" />
|
|
932
|
+
<Spinner size="md" />
|
|
933
|
+
<Spinner size="lg" />`,
|
|
934
|
+
render: () => (
|
|
935
|
+
<HStack space="xl" style={{ alignItems: 'center' }}>
|
|
936
|
+
<VStack alignItems="center" space="xs">
|
|
937
|
+
<Spinner size="xs" />
|
|
938
|
+
<Text variant="caption">xs</Text>
|
|
939
|
+
</VStack>
|
|
940
|
+
<VStack alignItems="center" space="xs">
|
|
941
|
+
<Spinner size="sm" />
|
|
942
|
+
<Text variant="caption">sm</Text>
|
|
943
|
+
</VStack>
|
|
944
|
+
<VStack alignItems="center" space="xs">
|
|
945
|
+
<Spinner size="md" />
|
|
946
|
+
<Text variant="caption">md</Text>
|
|
947
|
+
</VStack>
|
|
948
|
+
<VStack alignItems="center" space="xs">
|
|
949
|
+
<Spinner size="lg" />
|
|
950
|
+
<Text variant="caption">lg</Text>
|
|
951
|
+
</VStack>
|
|
952
|
+
<VStack alignItems="center" space="xs">
|
|
953
|
+
<Spinner size="xl" />
|
|
954
|
+
<Text variant="caption">xl</Text>
|
|
955
|
+
</VStack>
|
|
956
|
+
</HStack>
|
|
957
|
+
),
|
|
958
|
+
},
|
|
959
|
+
],
|
|
960
|
+
},
|
|
961
|
+
{
|
|
962
|
+
name: 'Skeleton',
|
|
963
|
+
description: 'Placeholder loading state for content.',
|
|
964
|
+
props: [
|
|
965
|
+
{ name: 'width', type: 'number | string', description: 'Skeleton width' },
|
|
966
|
+
{ name: 'height', type: 'number | string', description: 'Skeleton height' },
|
|
967
|
+
{ name: 'variant', type: '"text" | "circle" | "rect"', default: '"rect"', description: 'Skeleton shape' },
|
|
968
|
+
{ name: 'isLoaded', type: 'boolean', description: 'Toggle loading state' },
|
|
969
|
+
],
|
|
970
|
+
examples: [
|
|
971
|
+
{
|
|
972
|
+
title: 'Interactive Skeleton',
|
|
973
|
+
description: 'Toggle loading state to see content appear',
|
|
974
|
+
code: `<Skeleton width={200} height={16} isLoaded={isLoaded}>
|
|
975
|
+
<Text>Actual content</Text>
|
|
976
|
+
</Skeleton>`,
|
|
977
|
+
render: () => {
|
|
978
|
+
const SkeletonDemo = () => {
|
|
979
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
980
|
+
return (
|
|
981
|
+
<VStack space="lg" style={{ width: '100%' }}>
|
|
982
|
+
<Button
|
|
983
|
+
size="sm"
|
|
984
|
+
variant="secondary"
|
|
985
|
+
onPress={() => setIsLoaded(!isLoaded)}
|
|
986
|
+
>
|
|
987
|
+
{isLoaded ? 'Show Loading' : 'Show Content'}
|
|
988
|
+
</Button>
|
|
989
|
+
<HStack space="md">
|
|
990
|
+
<Skeleton width={50} height={50} style={{ borderRadius: 25 }} isLoaded={isLoaded}>
|
|
991
|
+
<Avatar name="John Doe" size="lg" />
|
|
992
|
+
</Skeleton>
|
|
993
|
+
<VStack space="sm" style={{ flex: 1 }}>
|
|
994
|
+
<Skeleton width="80%" height={16} isLoaded={isLoaded}>
|
|
995
|
+
<Text weight="semiBold">John Doe</Text>
|
|
996
|
+
</Skeleton>
|
|
997
|
+
<Skeleton width="60%" height={14} isLoaded={isLoaded}>
|
|
998
|
+
<Text variant="caption">Software Engineer</Text>
|
|
999
|
+
</Skeleton>
|
|
1000
|
+
</VStack>
|
|
1001
|
+
</HStack>
|
|
1002
|
+
</VStack>
|
|
1003
|
+
);
|
|
1004
|
+
};
|
|
1005
|
+
return <SkeletonDemo />;
|
|
1006
|
+
},
|
|
1007
|
+
},
|
|
1008
|
+
],
|
|
1009
|
+
},
|
|
1010
|
+
],
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
name: 'Data Display',
|
|
1014
|
+
count: 6,
|
|
1015
|
+
description: 'Components for presenting data and content',
|
|
1016
|
+
components: [
|
|
1017
|
+
{
|
|
1018
|
+
name: 'Avatar',
|
|
1019
|
+
description: 'User profile image with fallback.',
|
|
1020
|
+
props: [
|
|
1021
|
+
{ name: 'src', type: 'string', description: 'Image source URL' },
|
|
1022
|
+
{ name: 'name', type: 'string', description: 'Name for initials' },
|
|
1023
|
+
{ name: 'size', type: '"xs" | "sm" | "md" | "lg" | "xl"', default: '"md"', description: 'Avatar size' },
|
|
1024
|
+
{ name: 'showBadge', type: 'boolean', description: 'Show status badge' },
|
|
1025
|
+
],
|
|
1026
|
+
examples: [
|
|
1027
|
+
{
|
|
1028
|
+
title: 'Avatar Sizes',
|
|
1029
|
+
code: `<Avatar name="John Doe" size="sm" />
|
|
1030
|
+
<Avatar name="Jane" size="lg" showBadge />`,
|
|
1031
|
+
render: () => (
|
|
1032
|
+
<HStack space="lg" style={{ alignItems: 'center' }}>
|
|
1033
|
+
<VStack alignItems="center" space="xs">
|
|
1034
|
+
<Avatar name="XS" size="xs" />
|
|
1035
|
+
<Text variant="caption">xs</Text>
|
|
1036
|
+
</VStack>
|
|
1037
|
+
<VStack alignItems="center" space="xs">
|
|
1038
|
+
<Avatar name="SM User" size="sm" />
|
|
1039
|
+
<Text variant="caption">sm</Text>
|
|
1040
|
+
</VStack>
|
|
1041
|
+
<VStack alignItems="center" space="xs">
|
|
1042
|
+
<Avatar name="MD User" size="md" />
|
|
1043
|
+
<Text variant="caption">md</Text>
|
|
1044
|
+
</VStack>
|
|
1045
|
+
<VStack alignItems="center" space="xs">
|
|
1046
|
+
<Avatar name="Large" size="lg" showBadge />
|
|
1047
|
+
<Text variant="caption">lg + badge</Text>
|
|
1048
|
+
</VStack>
|
|
1049
|
+
<VStack alignItems="center" space="xs">
|
|
1050
|
+
<Avatar name="Extra Large" size="xl" />
|
|
1051
|
+
<Text variant="caption">xl</Text>
|
|
1052
|
+
</VStack>
|
|
1053
|
+
</HStack>
|
|
1054
|
+
),
|
|
1055
|
+
},
|
|
1056
|
+
],
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
name: 'Badge',
|
|
1060
|
+
description: 'Small label for status indicators.',
|
|
1061
|
+
props: [
|
|
1062
|
+
{ name: 'variant', type: '"gray" | "red" | "green" | "blue" | "purple" | "orange" | "yellow"', default: '"gray"', description: 'Badge color' },
|
|
1063
|
+
{ name: 'size', type: '"sm" | "md" | "lg"', default: '"md"', description: 'Badge size' },
|
|
1064
|
+
],
|
|
1065
|
+
examples: [
|
|
1066
|
+
{
|
|
1067
|
+
title: 'Badge Variants',
|
|
1068
|
+
code: `<Badge variant="green">Active</Badge>
|
|
1069
|
+
<Badge variant="red">Critical</Badge>`,
|
|
1070
|
+
render: () => (
|
|
1071
|
+
<VStack space="md">
|
|
1072
|
+
<HStack space="sm" style={{ flexWrap: 'wrap' }}>
|
|
1073
|
+
<Badge variant="gray">Default</Badge>
|
|
1074
|
+
<Badge variant="green">Active</Badge>
|
|
1075
|
+
<Badge variant="red">Critical</Badge>
|
|
1076
|
+
<Badge variant="blue">Info</Badge>
|
|
1077
|
+
<Badge variant="purple">New</Badge>
|
|
1078
|
+
<Badge variant="orange">Pending</Badge>
|
|
1079
|
+
<Badge variant="yellow">Warning</Badge>
|
|
1080
|
+
</HStack>
|
|
1081
|
+
<Divider />
|
|
1082
|
+
<Text weight="semiBold">Sizes</Text>
|
|
1083
|
+
<HStack space="sm" style={{ alignItems: 'center' }}>
|
|
1084
|
+
<Badge variant="blue" size="sm">Small</Badge>
|
|
1085
|
+
<Badge variant="blue" size="md">Medium</Badge>
|
|
1086
|
+
<Badge variant="blue" size="lg">Large</Badge>
|
|
1087
|
+
</HStack>
|
|
1088
|
+
</VStack>
|
|
1089
|
+
),
|
|
1090
|
+
},
|
|
1091
|
+
],
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
name: 'Card',
|
|
1095
|
+
description: 'Container for related content.',
|
|
1096
|
+
props: [
|
|
1097
|
+
{ name: 'variant', type: '"elevated" | "outline" | "filled"', default: '"elevated"', description: 'Card style' },
|
|
1098
|
+
{ name: 'padding', type: '"none" | "sm" | "md" | "lg"', default: '"md"', description: 'Internal padding' },
|
|
1099
|
+
],
|
|
1100
|
+
examples: [
|
|
1101
|
+
{
|
|
1102
|
+
title: 'Card Variants',
|
|
1103
|
+
description: 'Different card styles for various use cases',
|
|
1104
|
+
code: `<Card variant="elevated">
|
|
1105
|
+
<Text>Elevated card content</Text>
|
|
1106
|
+
</Card>`,
|
|
1107
|
+
render: () => (
|
|
1108
|
+
<VStack space="lg">
|
|
1109
|
+
<Card variant="elevated">
|
|
1110
|
+
<VStack space="sm">
|
|
1111
|
+
<Text weight="semiBold">Elevated Card</Text>
|
|
1112
|
+
<Text variant="caption">Card with shadow elevation</Text>
|
|
1113
|
+
<HStack space="sm">
|
|
1114
|
+
<Button size="sm" variant="primary" onPress={() => {}}>Action</Button>
|
|
1115
|
+
<Button size="sm" variant="ghost" onPress={() => {}}>Cancel</Button>
|
|
1116
|
+
</HStack>
|
|
1117
|
+
</VStack>
|
|
1118
|
+
</Card>
|
|
1119
|
+
<Card variant="outline">
|
|
1120
|
+
<VStack space="sm">
|
|
1121
|
+
<Text weight="semiBold">Outline Card</Text>
|
|
1122
|
+
<Text variant="caption">Card with border</Text>
|
|
1123
|
+
</VStack>
|
|
1124
|
+
</Card>
|
|
1125
|
+
<Card variant="filled">
|
|
1126
|
+
<VStack space="sm">
|
|
1127
|
+
<Text weight="semiBold">Filled Card</Text>
|
|
1128
|
+
<Text variant="caption">Card with solid background</Text>
|
|
1129
|
+
</VStack>
|
|
1130
|
+
</Card>
|
|
1131
|
+
</VStack>
|
|
1132
|
+
),
|
|
1133
|
+
},
|
|
1134
|
+
],
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
name: 'Table',
|
|
1138
|
+
description: 'Data table for displaying tabular information.',
|
|
1139
|
+
props: [
|
|
1140
|
+
{ name: 'data', type: 'object[]', required: true, description: 'Table data array' },
|
|
1141
|
+
{ name: 'columns', type: 'Column[]', required: true, description: 'Column definitions' },
|
|
1142
|
+
{ name: 'striped', type: 'boolean', description: 'Alternating row colors' },
|
|
1143
|
+
],
|
|
1144
|
+
examples: [
|
|
1145
|
+
{
|
|
1146
|
+
title: 'Table with Status Badges',
|
|
1147
|
+
code: `<Table columns={columns} data={data} />`,
|
|
1148
|
+
render: () => (
|
|
1149
|
+
<View style={{ borderWidth: 1, borderColor: '#E5E7EB', borderRadius: 8, overflow: 'hidden' }}>
|
|
1150
|
+
<View style={{ flexDirection: 'row', backgroundColor: '#F9FAFB', borderBottomWidth: 1, borderBottomColor: '#E5E7EB' }}>
|
|
1151
|
+
<View style={{ flex: 1, padding: 12 }}><Text weight="semiBold">Name</Text></View>
|
|
1152
|
+
<View style={{ flex: 1, padding: 12 }}><Text weight="semiBold">Status</Text></View>
|
|
1153
|
+
<View style={{ flex: 1, padding: 12 }}><Text weight="semiBold">Date</Text></View>
|
|
1154
|
+
</View>
|
|
1155
|
+
{[
|
|
1156
|
+
{ name: 'Project Alpha', status: 'Active', variant: 'green' as const, date: '2024-01-15' },
|
|
1157
|
+
{ name: 'Project Beta', status: 'Pending', variant: 'orange' as const, date: '2024-01-14' },
|
|
1158
|
+
{ name: 'Project Gamma', status: 'Completed', variant: 'gray' as const, date: '2024-01-13' },
|
|
1159
|
+
].map((row, i) => (
|
|
1160
|
+
<View key={i} style={{ flexDirection: 'row', borderBottomWidth: i < 2 ? 1 : 0, borderBottomColor: '#E5E7EB' }}>
|
|
1161
|
+
<View style={{ flex: 1, padding: 12 }}><Text>{row.name}</Text></View>
|
|
1162
|
+
<View style={{ flex: 1, padding: 12 }}><Badge variant={row.variant}>{row.status}</Badge></View>
|
|
1163
|
+
<View style={{ flex: 1, padding: 12 }}><Text variant="caption">{row.date}</Text></View>
|
|
1164
|
+
</View>
|
|
1165
|
+
))}
|
|
1166
|
+
</View>
|
|
1167
|
+
),
|
|
1168
|
+
},
|
|
1169
|
+
],
|
|
1170
|
+
},
|
|
1171
|
+
{
|
|
1172
|
+
name: 'Icon',
|
|
1173
|
+
description: 'SVG icon component with consistent sizing.',
|
|
1174
|
+
props: [
|
|
1175
|
+
{ name: 'name', type: 'string', required: true, description: 'Icon name' },
|
|
1176
|
+
{ name: 'size', type: 'number', default: '24', description: 'Icon size in pixels' },
|
|
1177
|
+
{ name: 'color', type: 'string', description: 'Icon color' },
|
|
1178
|
+
],
|
|
1179
|
+
examples: [
|
|
1180
|
+
{
|
|
1181
|
+
title: 'Icon Sizes and Colors',
|
|
1182
|
+
code: `<Icon name="check" size={24} color="#00A0CC" />`,
|
|
1183
|
+
render: () => (
|
|
1184
|
+
<HStack space="lg" style={{ alignItems: 'center' }}>
|
|
1185
|
+
<Icon name="check" size={16} color="#22C55E" />
|
|
1186
|
+
<Icon name="close" size={20} color="#EF4444" />
|
|
1187
|
+
<Icon name="info" size={24} color="#3B82F6" />
|
|
1188
|
+
<Icon name="warning" size={28} color="#F59E0B" />
|
|
1189
|
+
<Icon name="chevron-right" size={32} color="#6B7280" />
|
|
1190
|
+
</HStack>
|
|
1191
|
+
),
|
|
1192
|
+
},
|
|
1193
|
+
],
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
name: 'Image',
|
|
1197
|
+
description: 'Optimized image component with loading states.',
|
|
1198
|
+
props: [
|
|
1199
|
+
{ name: 'src', type: 'string', required: true, description: 'Image source URL' },
|
|
1200
|
+
{ name: 'alt', type: 'string', required: true, description: 'Alt text' },
|
|
1201
|
+
{ name: 'width', type: 'number | string', description: 'Image width' },
|
|
1202
|
+
{ name: 'height', type: 'number | string', description: 'Image height' },
|
|
1203
|
+
],
|
|
1204
|
+
examples: [
|
|
1205
|
+
{
|
|
1206
|
+
title: 'Image Example',
|
|
1207
|
+
code: `<Image src="https://..." alt="Description" width={200} />`,
|
|
1208
|
+
render: () => (
|
|
1209
|
+
<Center style={{ width: 200, height: 120, backgroundColor: '#E5E7EB', borderRadius: 8 }}>
|
|
1210
|
+
<Text variant="caption" color="#9CA3AF">200 × 120</Text>
|
|
1211
|
+
</Center>
|
|
1212
|
+
),
|
|
1213
|
+
},
|
|
1214
|
+
],
|
|
1215
|
+
},
|
|
1216
|
+
],
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
name: 'Actions',
|
|
1220
|
+
count: 4,
|
|
1221
|
+
description: 'Interactive components for user actions',
|
|
1222
|
+
components: [
|
|
1223
|
+
{
|
|
1224
|
+
name: 'Pressable',
|
|
1225
|
+
description: 'Base pressable component with press states.',
|
|
1226
|
+
props: [
|
|
1227
|
+
{ name: 'onPress', type: '() => void', description: 'Press handler' },
|
|
1228
|
+
{ name: 'onLongPress', type: '() => void', description: 'Long press handler' },
|
|
1229
|
+
{ name: 'disabled', type: 'boolean', description: 'Disable press' },
|
|
1230
|
+
],
|
|
1231
|
+
examples: [
|
|
1232
|
+
{
|
|
1233
|
+
title: 'Interactive Pressable',
|
|
1234
|
+
description: 'Press to see the visual feedback',
|
|
1235
|
+
code: `<Pressable onPress={() => console.log('pressed')}>
|
|
1236
|
+
<Text>Tap me</Text>
|
|
1237
|
+
</Pressable>`,
|
|
1238
|
+
render: () => {
|
|
1239
|
+
const PressableDemo = () => {
|
|
1240
|
+
const [pressCount, setPressCount] = useState(0);
|
|
1241
|
+
return (
|
|
1242
|
+
<VStack space="md" alignItems="center">
|
|
1243
|
+
<Pressable onPress={() => setPressCount(c => c + 1)}>
|
|
1244
|
+
<Box p="lg" bg="#F3F4F6" rounded="md">
|
|
1245
|
+
<Text>Tap me!</Text>
|
|
1246
|
+
</Box>
|
|
1247
|
+
</Pressable>
|
|
1248
|
+
<Text variant="caption">Press count: {pressCount}</Text>
|
|
1249
|
+
</VStack>
|
|
1250
|
+
);
|
|
1251
|
+
};
|
|
1252
|
+
return <PressableDemo />;
|
|
1253
|
+
},
|
|
1254
|
+
},
|
|
1255
|
+
],
|
|
1256
|
+
},
|
|
1257
|
+
{
|
|
1258
|
+
name: 'Fab',
|
|
1259
|
+
description: 'Floating action button for primary screen actions.',
|
|
1260
|
+
props: [
|
|
1261
|
+
{ name: 'icon', type: 'ReactNode', required: true, description: 'FAB icon' },
|
|
1262
|
+
{ name: 'position', type: '"bottom-right" | "bottom-left"', default: '"bottom-right"', description: 'Position' },
|
|
1263
|
+
{ name: 'size', type: '"sm" | "md" | "lg"', default: '"md"', description: 'FAB size' },
|
|
1264
|
+
{ name: 'label', type: 'string', description: 'Extended FAB label' },
|
|
1265
|
+
],
|
|
1266
|
+
examples: [
|
|
1267
|
+
{
|
|
1268
|
+
title: 'FAB Variants',
|
|
1269
|
+
description: 'Click FABs to see interaction',
|
|
1270
|
+
code: `<Fab icon={<Icon name="plus" />} />
|
|
1271
|
+
<Fab icon={<Icon name="plus" />} label="Add New" />`,
|
|
1272
|
+
render: () => {
|
|
1273
|
+
const FabDemo = () => {
|
|
1274
|
+
const [count, setCount] = useState(0);
|
|
1275
|
+
return (
|
|
1276
|
+
<VStack space="lg" alignItems="center">
|
|
1277
|
+
<HStack space="lg">
|
|
1278
|
+
<Fab icon={<Icon name="plus" color="#FFFFFF" />} onPress={() => setCount(c => c + 1)} />
|
|
1279
|
+
<Fab icon={<Icon name="plus" color="#FFFFFF" />} label="Add New" onPress={() => setCount(c => c + 1)} />
|
|
1280
|
+
</HStack>
|
|
1281
|
+
<Text variant="caption">Items added: {count}</Text>
|
|
1282
|
+
</VStack>
|
|
1283
|
+
);
|
|
1284
|
+
};
|
|
1285
|
+
return <FabDemo />;
|
|
1286
|
+
},
|
|
1287
|
+
},
|
|
1288
|
+
],
|
|
1289
|
+
},
|
|
1290
|
+
{
|
|
1291
|
+
name: 'Accordion',
|
|
1292
|
+
description: 'Expandable content sections.',
|
|
1293
|
+
props: [
|
|
1294
|
+
{ name: 'defaultIndex', type: 'string[]', description: 'Initially expanded items' },
|
|
1295
|
+
{ name: 'allowMultiple', type: 'boolean', description: 'Allow multiple sections open' },
|
|
1296
|
+
],
|
|
1297
|
+
examples: [
|
|
1298
|
+
{
|
|
1299
|
+
title: 'Interactive Accordion',
|
|
1300
|
+
description: 'Click sections to expand/collapse',
|
|
1301
|
+
code: `<Accordion>
|
|
1302
|
+
<AccordionItem value="section-1">
|
|
1303
|
+
<AccordionButton>Section 1</AccordionButton>
|
|
1304
|
+
<AccordionPanel>Content</AccordionPanel>
|
|
1305
|
+
</AccordionItem>
|
|
1306
|
+
</Accordion>`,
|
|
1307
|
+
render: () => (
|
|
1308
|
+
<Accordion defaultIndex={['section-1']}>
|
|
1309
|
+
<AccordionItem value="section-1">
|
|
1310
|
+
<AccordionButton>What is Urbint CL?</AccordionButton>
|
|
1311
|
+
<AccordionPanel>
|
|
1312
|
+
<Text variant="caption">
|
|
1313
|
+
Urbint CL is an enterprise-ready React Native component library designed for building
|
|
1314
|
+
consistent and accessible mobile applications.
|
|
1315
|
+
</Text>
|
|
1316
|
+
</AccordionPanel>
|
|
1317
|
+
</AccordionItem>
|
|
1318
|
+
<AccordionItem value="section-2">
|
|
1319
|
+
<AccordionButton>How do I get started?</AccordionButton>
|
|
1320
|
+
<AccordionPanel>
|
|
1321
|
+
<Text variant="caption">
|
|
1322
|
+
Install the package via npm and import the components you need. Check the installation
|
|
1323
|
+
guide for detailed instructions.
|
|
1324
|
+
</Text>
|
|
1325
|
+
</AccordionPanel>
|
|
1326
|
+
</AccordionItem>
|
|
1327
|
+
<AccordionItem value="section-3">
|
|
1328
|
+
<AccordionButton>Is it customizable?</AccordionButton>
|
|
1329
|
+
<AccordionPanel>
|
|
1330
|
+
<Text variant="caption">
|
|
1331
|
+
Yes! All components support theming and can be customized using style props or
|
|
1332
|
+
the theming system.
|
|
1333
|
+
</Text>
|
|
1334
|
+
</AccordionPanel>
|
|
1335
|
+
</AccordionItem>
|
|
1336
|
+
</Accordion>
|
|
1337
|
+
),
|
|
1338
|
+
},
|
|
1339
|
+
],
|
|
1340
|
+
},
|
|
1341
|
+
{
|
|
1342
|
+
name: 'Menu',
|
|
1343
|
+
description: 'Dropdown menu with selectable options.',
|
|
1344
|
+
props: [
|
|
1345
|
+
{ name: 'trigger', type: 'ReactNode', required: true, description: 'Menu trigger' },
|
|
1346
|
+
{ name: 'items', type: 'MenuItem[]', required: true, description: 'Menu items' },
|
|
1347
|
+
],
|
|
1348
|
+
examples: [
|
|
1349
|
+
{
|
|
1350
|
+
title: 'Interactive Menu',
|
|
1351
|
+
description: 'Click the button to open the menu',
|
|
1352
|
+
code: `<Menu trigger={<Button>Options</Button>}>
|
|
1353
|
+
<MenuItem>Profile</MenuItem>
|
|
1354
|
+
<MenuItem>Settings</MenuItem>
|
|
1355
|
+
</Menu>`,
|
|
1356
|
+
render: () => {
|
|
1357
|
+
const MenuDemo = () => {
|
|
1358
|
+
const [selected, setSelected] = useState('');
|
|
1359
|
+
return (
|
|
1360
|
+
<VStack space="md" alignItems="flex-start">
|
|
1361
|
+
<Menu
|
|
1362
|
+
trigger={<Button variant="secondary" onPress={() => {}}>Options ▼</Button>}
|
|
1363
|
+
items={[
|
|
1364
|
+
{ label: 'Profile', onPress: () => setSelected('Profile') },
|
|
1365
|
+
{ label: 'Settings', onPress: () => setSelected('Settings') },
|
|
1366
|
+
{ label: 'Help', onPress: () => setSelected('Help') },
|
|
1367
|
+
{ label: 'Logout', onPress: () => setSelected('Logout'), destructive: true },
|
|
1368
|
+
]}
|
|
1369
|
+
/>
|
|
1370
|
+
{selected && <Text variant="caption">Last selected: {selected}</Text>}
|
|
1371
|
+
</VStack>
|
|
1372
|
+
);
|
|
1373
|
+
};
|
|
1374
|
+
return <MenuDemo />;
|
|
1375
|
+
},
|
|
1376
|
+
},
|
|
1377
|
+
],
|
|
1378
|
+
},
|
|
1379
|
+
],
|
|
1380
|
+
},
|
|
1381
|
+
{
|
|
1382
|
+
name: 'Overlay',
|
|
1383
|
+
count: 7,
|
|
1384
|
+
description: 'Modal dialogs, drawers, and floating UI elements',
|
|
1385
|
+
components: [
|
|
1386
|
+
{
|
|
1387
|
+
name: 'Modal',
|
|
1388
|
+
description: 'Dialog overlay for focused user interactions.',
|
|
1389
|
+
props: [
|
|
1390
|
+
{ name: 'isOpen', type: 'boolean', required: true, description: 'Open state' },
|
|
1391
|
+
{ name: 'onClose', type: '() => void', required: true, description: 'Close handler' },
|
|
1392
|
+
{ name: 'size', type: '"sm" | "md" | "lg" | "xl" | "full"', default: '"md"', description: 'Modal size' },
|
|
1393
|
+
],
|
|
1394
|
+
examples: [
|
|
1395
|
+
{
|
|
1396
|
+
title: 'Interactive Modal',
|
|
1397
|
+
description: 'Click to open modal dialog',
|
|
1398
|
+
code: `<Modal isOpen={isOpen} onClose={onClose}>
|
|
1399
|
+
<ModalHeader>Title</ModalHeader>
|
|
1400
|
+
<ModalBody>Content</ModalBody>
|
|
1401
|
+
<ModalFooter>
|
|
1402
|
+
<Button>Confirm</Button>
|
|
1403
|
+
</ModalFooter>
|
|
1404
|
+
</Modal>`,
|
|
1405
|
+
render: () => {
|
|
1406
|
+
const ModalDemo = () => {
|
|
1407
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1408
|
+
return (
|
|
1409
|
+
<VStack space="md">
|
|
1410
|
+
<Button onPress={() => setIsOpen(true)}>Open Modal</Button>
|
|
1411
|
+
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
|
|
1412
|
+
<ModalHeader>Confirm Action</ModalHeader>
|
|
1413
|
+
<ModalBody>
|
|
1414
|
+
<Text>Are you sure you want to proceed with this action?</Text>
|
|
1415
|
+
</ModalBody>
|
|
1416
|
+
<ModalFooter>
|
|
1417
|
+
<HStack space="sm">
|
|
1418
|
+
<Button variant="ghost" onPress={() => setIsOpen(false)}>Cancel</Button>
|
|
1419
|
+
<Button onPress={() => setIsOpen(false)}>Confirm</Button>
|
|
1420
|
+
</HStack>
|
|
1421
|
+
</ModalFooter>
|
|
1422
|
+
</Modal>
|
|
1423
|
+
</VStack>
|
|
1424
|
+
);
|
|
1425
|
+
};
|
|
1426
|
+
return <ModalDemo />;
|
|
1427
|
+
},
|
|
1428
|
+
},
|
|
1429
|
+
],
|
|
1430
|
+
},
|
|
1431
|
+
{
|
|
1432
|
+
name: 'Drawer',
|
|
1433
|
+
description: 'Slide-out panel from screen edge.',
|
|
1434
|
+
props: [
|
|
1435
|
+
{ name: 'isOpen', type: 'boolean', required: true, description: 'Open state' },
|
|
1436
|
+
{ name: 'onClose', type: '() => void', required: true, description: 'Close handler' },
|
|
1437
|
+
{ name: 'placement', type: '"left" | "right" | "top" | "bottom"', default: '"right"', description: 'Position' },
|
|
1438
|
+
],
|
|
1439
|
+
examples: [
|
|
1440
|
+
{
|
|
1441
|
+
title: 'Interactive Drawer',
|
|
1442
|
+
description: 'Click to open drawer panel',
|
|
1443
|
+
code: `<Drawer isOpen={isOpen} onClose={onClose} placement="right">
|
|
1444
|
+
<DrawerHeader>Menu</DrawerHeader>
|
|
1445
|
+
<DrawerBody>Content</DrawerBody>
|
|
1446
|
+
</Drawer>`,
|
|
1447
|
+
render: () => {
|
|
1448
|
+
const DrawerDemo = () => {
|
|
1449
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1450
|
+
return (
|
|
1451
|
+
<VStack space="md">
|
|
1452
|
+
<Button onPress={() => setIsOpen(true)}>Open Drawer</Button>
|
|
1453
|
+
<Drawer isOpen={isOpen} onClose={() => setIsOpen(false)} placement="right">
|
|
1454
|
+
<DrawerHeader>Navigation</DrawerHeader>
|
|
1455
|
+
<DrawerBody>
|
|
1456
|
+
<VStack space="md">
|
|
1457
|
+
<Pressable onPress={() => setIsOpen(false)}>
|
|
1458
|
+
<Text>Home</Text>
|
|
1459
|
+
</Pressable>
|
|
1460
|
+
<Pressable onPress={() => setIsOpen(false)}>
|
|
1461
|
+
<Text>Profile</Text>
|
|
1462
|
+
</Pressable>
|
|
1463
|
+
<Pressable onPress={() => setIsOpen(false)}>
|
|
1464
|
+
<Text>Settings</Text>
|
|
1465
|
+
</Pressable>
|
|
1466
|
+
</VStack>
|
|
1467
|
+
</DrawerBody>
|
|
1468
|
+
</Drawer>
|
|
1469
|
+
</VStack>
|
|
1470
|
+
);
|
|
1471
|
+
};
|
|
1472
|
+
return <DrawerDemo />;
|
|
1473
|
+
},
|
|
1474
|
+
},
|
|
1475
|
+
],
|
|
1476
|
+
},
|
|
1477
|
+
{
|
|
1478
|
+
name: 'AlertDialog',
|
|
1479
|
+
description: 'Confirmation dialog requiring user action.',
|
|
1480
|
+
props: [
|
|
1481
|
+
{ name: 'isOpen', type: 'boolean', required: true, description: 'Open state' },
|
|
1482
|
+
{ name: 'onClose', type: '() => void', required: true, description: 'Close handler' },
|
|
1483
|
+
{ name: 'onConfirm', type: '() => void', required: true, description: 'Confirm handler' },
|
|
1484
|
+
{ name: 'title', type: 'string', required: true, description: 'Dialog title' },
|
|
1485
|
+
{ name: 'description', type: 'string', description: 'Dialog description' },
|
|
1486
|
+
],
|
|
1487
|
+
examples: [
|
|
1488
|
+
{
|
|
1489
|
+
title: 'Interactive Alert Dialog',
|
|
1490
|
+
description: 'Click to show confirmation dialog',
|
|
1491
|
+
code: `<AlertDialog
|
|
1492
|
+
isOpen={isOpen}
|
|
1493
|
+
title="Delete Item?"
|
|
1494
|
+
onConfirm={handleDelete}
|
|
1495
|
+
/>`,
|
|
1496
|
+
render: () => {
|
|
1497
|
+
const AlertDialogDemo = () => {
|
|
1498
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1499
|
+
const [deleted, setDeleted] = useState(false);
|
|
1500
|
+
return (
|
|
1501
|
+
<VStack space="md">
|
|
1502
|
+
<Button variant="danger" onPress={() => setIsOpen(true)}>Delete Item</Button>
|
|
1503
|
+
{deleted && <Alert status="success" title="Item deleted successfully" />}
|
|
1504
|
+
<AlertDialog
|
|
1505
|
+
isOpen={isOpen}
|
|
1506
|
+
onClose={() => setIsOpen(false)}
|
|
1507
|
+
onConfirm={() => {
|
|
1508
|
+
setDeleted(true);
|
|
1509
|
+
setIsOpen(false);
|
|
1510
|
+
}}
|
|
1511
|
+
title="Delete Item?"
|
|
1512
|
+
description="This action cannot be undone. The item will be permanently removed."
|
|
1513
|
+
/>
|
|
1514
|
+
</VStack>
|
|
1515
|
+
);
|
|
1516
|
+
};
|
|
1517
|
+
return <AlertDialogDemo />;
|
|
1518
|
+
},
|
|
1519
|
+
},
|
|
1520
|
+
],
|
|
1521
|
+
},
|
|
1522
|
+
{
|
|
1523
|
+
name: 'Popover',
|
|
1524
|
+
description: 'Floating content anchored to a trigger element.',
|
|
1525
|
+
props: [
|
|
1526
|
+
{ name: 'trigger', type: 'ReactNode', required: true, description: 'Trigger element' },
|
|
1527
|
+
{ name: 'placement', type: '"top" | "bottom" | "left" | "right"', default: '"bottom"', description: 'Position' },
|
|
1528
|
+
],
|
|
1529
|
+
examples: [
|
|
1530
|
+
{
|
|
1531
|
+
title: 'Interactive Popover',
|
|
1532
|
+
description: 'Click to show popover',
|
|
1533
|
+
code: `<Popover trigger={<Button>Open</Button>}>
|
|
1534
|
+
<Text>Popover content</Text>
|
|
1535
|
+
</Popover>`,
|
|
1536
|
+
render: () => (
|
|
1537
|
+
<HStack space="md">
|
|
1538
|
+
<Popover
|
|
1539
|
+
trigger={<Button variant="secondary" onPress={() => {}}>Show Info</Button>}
|
|
1540
|
+
placement="bottom"
|
|
1541
|
+
>
|
|
1542
|
+
<VStack space="sm" p="md">
|
|
1543
|
+
<Text weight="semiBold">Popover Title</Text>
|
|
1544
|
+
<Text variant="caption">This is additional information displayed in a popover.</Text>
|
|
1545
|
+
</VStack>
|
|
1546
|
+
</Popover>
|
|
1547
|
+
</HStack>
|
|
1548
|
+
),
|
|
1549
|
+
},
|
|
1550
|
+
],
|
|
1551
|
+
},
|
|
1552
|
+
{
|
|
1553
|
+
name: 'Tooltip',
|
|
1554
|
+
description: 'Informational text that appears on hover/press.',
|
|
1555
|
+
props: [
|
|
1556
|
+
{ name: 'label', type: 'string', required: true, description: 'Tooltip text' },
|
|
1557
|
+
{ name: 'placement', type: '"top" | "bottom" | "left" | "right"', default: '"top"', description: 'Position' },
|
|
1558
|
+
],
|
|
1559
|
+
examples: [
|
|
1560
|
+
{
|
|
1561
|
+
title: 'Interactive Tooltip',
|
|
1562
|
+
description: 'Hover or press to see tooltip',
|
|
1563
|
+
code: `<Tooltip label="Helpful tip">
|
|
1564
|
+
<Button>Hover me</Button>
|
|
1565
|
+
</Tooltip>`,
|
|
1566
|
+
render: () => (
|
|
1567
|
+
<HStack space="lg">
|
|
1568
|
+
<Tooltip label="This saves your progress" placement="top">
|
|
1569
|
+
<Button variant="primary" onPress={() => {}}>Save</Button>
|
|
1570
|
+
</Tooltip>
|
|
1571
|
+
<Tooltip label="Delete this item permanently" placement="bottom">
|
|
1572
|
+
<Button variant="danger" onPress={() => {}}>Delete</Button>
|
|
1573
|
+
</Tooltip>
|
|
1574
|
+
</HStack>
|
|
1575
|
+
),
|
|
1576
|
+
},
|
|
1577
|
+
],
|
|
1578
|
+
},
|
|
1579
|
+
{
|
|
1580
|
+
name: 'ActionSheet',
|
|
1581
|
+
description: 'Bottom sheet with action options.',
|
|
1582
|
+
props: [
|
|
1583
|
+
{ name: 'isOpen', type: 'boolean', required: true, description: 'Open state' },
|
|
1584
|
+
{ name: 'onClose', type: '() => void', required: true, description: 'Close handler' },
|
|
1585
|
+
{ name: 'actions', type: 'Action[]', required: true, description: 'Action items' },
|
|
1586
|
+
],
|
|
1587
|
+
examples: [
|
|
1588
|
+
{
|
|
1589
|
+
title: 'Interactive Action Sheet',
|
|
1590
|
+
description: 'Click to show action sheet',
|
|
1591
|
+
code: `<ActionSheet
|
|
1592
|
+
isOpen={isOpen}
|
|
1593
|
+
actions={[
|
|
1594
|
+
{ label: 'Edit', onPress: handleEdit },
|
|
1595
|
+
{ label: 'Delete', onPress: handleDelete, destructive: true },
|
|
1596
|
+
]}
|
|
1597
|
+
/>`,
|
|
1598
|
+
render: () => {
|
|
1599
|
+
const ActionSheetDemo = () => {
|
|
1600
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
1601
|
+
const [lastAction, setLastAction] = useState('');
|
|
1602
|
+
return (
|
|
1603
|
+
<VStack space="md">
|
|
1604
|
+
<Button onPress={() => setIsOpen(true)}>Show Actions</Button>
|
|
1605
|
+
{lastAction && <Text variant="caption">Last action: {lastAction}</Text>}
|
|
1606
|
+
<ActionSheet
|
|
1607
|
+
isOpen={isOpen}
|
|
1608
|
+
onClose={() => setIsOpen(false)}
|
|
1609
|
+
actions={[
|
|
1610
|
+
{ label: 'Edit', onPress: () => { setLastAction('Edit'); setIsOpen(false); } },
|
|
1611
|
+
{ label: 'Duplicate', onPress: () => { setLastAction('Duplicate'); setIsOpen(false); } },
|
|
1612
|
+
{ label: 'Share', onPress: () => { setLastAction('Share'); setIsOpen(false); } },
|
|
1613
|
+
{ label: 'Delete', onPress: () => { setLastAction('Delete'); setIsOpen(false); }, destructive: true },
|
|
1614
|
+
]}
|
|
1615
|
+
/>
|
|
1616
|
+
</VStack>
|
|
1617
|
+
);
|
|
1618
|
+
};
|
|
1619
|
+
return <ActionSheetDemo />;
|
|
1620
|
+
},
|
|
1621
|
+
},
|
|
1622
|
+
],
|
|
1623
|
+
},
|
|
1624
|
+
{
|
|
1625
|
+
name: 'Portal',
|
|
1626
|
+
description: 'Renders children in a different part of the DOM tree.',
|
|
1627
|
+
props: [
|
|
1628
|
+
{ name: 'children', type: 'ReactNode', required: true, description: 'Content to render' },
|
|
1629
|
+
],
|
|
1630
|
+
examples: [
|
|
1631
|
+
{
|
|
1632
|
+
title: 'Portal Usage',
|
|
1633
|
+
description: 'Portals render content outside the parent hierarchy',
|
|
1634
|
+
code: `<Portal>
|
|
1635
|
+
<Modal>Content escapes overflow:hidden</Modal>
|
|
1636
|
+
</Portal>`,
|
|
1637
|
+
render: () => (
|
|
1638
|
+
<Box p="lg" bg="#F3F4F6" rounded="md">
|
|
1639
|
+
<Text variant="caption">
|
|
1640
|
+
Portal renders children at the root level of the app, allowing modals and
|
|
1641
|
+
tooltips to escape overflow:hidden containers. Used internally by Modal,
|
|
1642
|
+
Drawer, and other overlay components.
|
|
1643
|
+
</Text>
|
|
1644
|
+
</Box>
|
|
1645
|
+
),
|
|
1646
|
+
},
|
|
1647
|
+
],
|
|
1648
|
+
},
|
|
1649
|
+
],
|
|
1650
|
+
},
|
|
1651
|
+
{
|
|
1652
|
+
name: 'Utility',
|
|
1653
|
+
count: 1,
|
|
1654
|
+
description: 'Utility components for advanced use cases',
|
|
1655
|
+
components: [
|
|
1656
|
+
{
|
|
1657
|
+
name: 'Portal',
|
|
1658
|
+
description: 'Renders children in a different part of the DOM tree, useful for modals and overlays.',
|
|
1659
|
+
props: [
|
|
1660
|
+
{ name: 'children', type: 'ReactNode', required: true, description: 'Content to render' },
|
|
1661
|
+
{ name: 'containerId', type: 'string', description: 'Target container ID' },
|
|
1662
|
+
],
|
|
1663
|
+
examples: [
|
|
1664
|
+
{
|
|
1665
|
+
title: 'Portal Usage',
|
|
1666
|
+
description: 'Portals render content outside the parent hierarchy',
|
|
1667
|
+
code: `<Portal>
|
|
1668
|
+
<Modal>
|
|
1669
|
+
This modal escapes overflow:hidden
|
|
1670
|
+
</Modal>
|
|
1671
|
+
</Portal>`,
|
|
1672
|
+
render: () => (
|
|
1673
|
+
<Box p="lg" bg="#F3F4F6" rounded="md">
|
|
1674
|
+
<Text variant="caption">
|
|
1675
|
+
Portal renders children at the root level of the app, allowing modals and tooltips
|
|
1676
|
+
to escape overflow:hidden containers.
|
|
1677
|
+
</Text>
|
|
1678
|
+
</Box>
|
|
1679
|
+
),
|
|
1680
|
+
},
|
|
1681
|
+
],
|
|
1682
|
+
},
|
|
1683
|
+
],
|
|
1684
|
+
},
|
|
1685
|
+
];
|