@titan-design/react-ui 0.0.2 → 0.1.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.
Files changed (206) hide show
  1. package/dist/{chunk-NA3EES23.mjs → chunk-MGW37MPO.mjs} +26 -4
  2. package/dist/chunk-MGW37MPO.mjs.map +1 -0
  3. package/dist/index.d.mts +115 -2
  4. package/dist/index.d.ts +115 -2
  5. package/dist/index.js +262 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +225 -3
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/theme/index.d.mts +124 -109
  10. package/dist/theme/index.d.ts +124 -109
  11. package/dist/theme/index.js +24 -1
  12. package/dist/theme/index.js.map +1 -1
  13. package/dist/theme/index.mjs +1 -1
  14. package/package.json +12 -5
  15. package/src/components/custom/DateTime/DateTime.stories.tsx +180 -0
  16. package/src/components/custom/DateTime/DateTime.test.tsx +152 -0
  17. package/src/components/custom/DateTime/DateTime.tsx +235 -0
  18. package/src/components/custom/DateTime/index.ts +2 -0
  19. package/src/components/custom/EmptyState/EmptyState.stories.tsx +99 -0
  20. package/src/components/custom/EmptyState/EmptyState.test.tsx +106 -0
  21. package/src/components/custom/EmptyState/EmptyState.tsx +68 -0
  22. package/src/components/custom/EmptyState/index.ts +2 -0
  23. package/src/components/custom/Metric/Metric.stories.tsx +133 -0
  24. package/src/components/custom/Metric/Metric.test.tsx +120 -0
  25. package/src/components/custom/Metric/Metric.tsx +92 -0
  26. package/src/components/custom/Metric/index.ts +2 -0
  27. package/src/components/custom/Sidebar/Sidebar.stories.tsx +227 -0
  28. package/src/components/custom/Sidebar/Sidebar.test.tsx +185 -0
  29. package/src/components/custom/Sidebar/Sidebar.tsx +257 -0
  30. package/src/components/custom/Sidebar/index.ts +18 -0
  31. package/src/components/custom/Table/Table.stories.tsx +481 -0
  32. package/src/components/custom/Table/Table.test.tsx +531 -0
  33. package/src/components/custom/Table/Table.tsx +696 -0
  34. package/src/components/custom/Table/index.ts +22 -0
  35. package/src/components/custom/Typography/Typography.stories.tsx +153 -0
  36. package/src/components/custom/Typography/Typography.test.tsx +107 -0
  37. package/src/components/custom/Typography/Typography.tsx +218 -0
  38. package/src/components/custom/Typography/index.ts +19 -0
  39. package/src/components/custom/index.ts +8 -0
  40. package/src/components/custom/stepper/Stepper.stories.tsx +245 -0
  41. package/src/components/custom/stepper/Stepper.test.tsx +230 -0
  42. package/src/components/custom/stepper/Stepper.tsx +250 -0
  43. package/src/components/custom/stepper/index.ts +10 -0
  44. package/src/components/index.ts +5 -0
  45. package/src/components/ui/alert/Alert.stories.tsx +154 -0
  46. package/src/components/ui/alert/Alert.test.tsx +202 -0
  47. package/src/components/ui/alert/Alert.tsx +170 -0
  48. package/src/components/ui/alert/index.ts +8 -0
  49. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +299 -0
  50. package/src/components/ui/autocomplete/Autocomplete.test.tsx +247 -0
  51. package/src/components/ui/autocomplete/Autocomplete.tsx +332 -0
  52. package/src/components/ui/autocomplete/index.ts +2 -0
  53. package/src/components/ui/avatar/Avatar.stories.tsx +105 -0
  54. package/src/components/ui/avatar/Avatar.test.tsx +135 -0
  55. package/src/components/ui/avatar/Avatar.tsx +168 -0
  56. package/src/components/ui/avatar/index.ts +2 -0
  57. package/src/components/ui/badge/Badge.stories.tsx +100 -0
  58. package/src/components/ui/badge/Badge.test.tsx +86 -0
  59. package/src/components/ui/badge/Badge.tsx +105 -0
  60. package/src/components/ui/badge/index.ts +2 -0
  61. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +70 -0
  62. package/src/components/ui/breadcrumbs/Breadcrumbs.test.tsx +156 -0
  63. package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +127 -0
  64. package/src/components/ui/breadcrumbs/index.ts +2 -0
  65. package/src/components/ui/button/Button.stories.tsx +216 -0
  66. package/src/components/ui/button/Button.test.tsx +132 -0
  67. package/src/components/ui/button/Button.tsx +242 -0
  68. package/src/components/ui/button/index.ts +10 -0
  69. package/src/components/ui/card/Card.stories.tsx +443 -0
  70. package/src/components/ui/card/Card.test.tsx +265 -0
  71. package/src/components/ui/card/Card.tsx +380 -0
  72. package/src/components/ui/card/index.ts +20 -0
  73. package/src/components/ui/checkbox/Checkbox.stories.tsx +126 -0
  74. package/src/components/ui/checkbox/Checkbox.test.tsx +152 -0
  75. package/src/components/ui/checkbox/Checkbox.tsx +163 -0
  76. package/src/components/ui/checkbox/index.ts +2 -0
  77. package/src/components/ui/chip/Chip.stories.tsx +112 -0
  78. package/src/components/ui/chip/Chip.test.tsx +119 -0
  79. package/src/components/ui/chip/Chip.tsx +151 -0
  80. package/src/components/ui/chip/index.ts +2 -0
  81. package/src/components/ui/collapse/Collapse.stories.tsx +313 -0
  82. package/src/components/ui/collapse/Collapse.test.tsx +298 -0
  83. package/src/components/ui/collapse/Collapse.tsx +275 -0
  84. package/src/components/ui/collapse/index.ts +18 -0
  85. package/src/components/ui/data-row/DataRow.stories.tsx +78 -0
  86. package/src/components/ui/data-row/DataRow.test.tsx +78 -0
  87. package/src/components/ui/data-row/DataRow.tsx +29 -0
  88. package/src/components/ui/data-row/index.ts +2 -0
  89. package/src/components/ui/divider/Divider.stories.tsx +71 -0
  90. package/src/components/ui/divider/Divider.test.tsx +55 -0
  91. package/src/components/ui/divider/Divider.tsx +37 -0
  92. package/src/components/ui/divider/index.ts +2 -0
  93. package/src/components/ui/drawer/Drawer.stories.tsx +228 -0
  94. package/src/components/ui/drawer/Drawer.test.tsx +142 -0
  95. package/src/components/ui/drawer/Drawer.tsx +228 -0
  96. package/src/components/ui/drawer/index.ts +9 -0
  97. package/src/components/ui/form-field/FormField.stories.tsx +260 -0
  98. package/src/components/ui/form-field/FormField.test.tsx +280 -0
  99. package/src/components/ui/form-field/FormField.tsx +308 -0
  100. package/src/components/ui/form-field/index.ts +2 -0
  101. package/src/components/ui/help-tip/HelpTip.stories.tsx +250 -0
  102. package/src/components/ui/help-tip/HelpTip.test.tsx +198 -0
  103. package/src/components/ui/help-tip/HelpTip.tsx +229 -0
  104. package/src/components/ui/help-tip/index.ts +2 -0
  105. package/src/components/ui/icon-box/IconBox.stories.tsx +139 -0
  106. package/src/components/ui/icon-box/IconBox.test.tsx +120 -0
  107. package/src/components/ui/icon-box/IconBox.tsx +57 -0
  108. package/src/components/ui/icon-box/index.ts +1 -0
  109. package/src/components/ui/index.ts +36 -0
  110. package/src/components/ui/input/Input.stories.tsx +192 -0
  111. package/src/components/ui/input/Input.test.tsx +86 -0
  112. package/src/components/ui/input/Input.tsx +273 -0
  113. package/src/components/ui/input/index.ts +2 -0
  114. package/src/components/ui/link/Link.stories.tsx +78 -0
  115. package/src/components/ui/link/Link.test.tsx +94 -0
  116. package/src/components/ui/link/Link.tsx +86 -0
  117. package/src/components/ui/link/index.ts +2 -0
  118. package/src/components/ui/list-item/ListItem.stories.tsx +146 -0
  119. package/src/components/ui/list-item/ListItem.test.tsx +128 -0
  120. package/src/components/ui/list-item/ListItem.tsx +89 -0
  121. package/src/components/ui/list-item/index.ts +14 -0
  122. package/src/components/ui/menu/Menu.stories.tsx +180 -0
  123. package/src/components/ui/menu/Menu.test.tsx +353 -0
  124. package/src/components/ui/menu/Menu.tsx +222 -0
  125. package/src/components/ui/menu/index.ts +2 -0
  126. package/src/components/ui/modal/Modal.stories.tsx +350 -0
  127. package/src/components/ui/modal/Modal.test.tsx +159 -0
  128. package/src/components/ui/modal/Modal.tsx +254 -0
  129. package/src/components/ui/modal/index.ts +19 -0
  130. package/src/components/ui/popover/Popover.stories.tsx +190 -0
  131. package/src/components/ui/popover/Popover.test.tsx +277 -0
  132. package/src/components/ui/popover/Popover.tsx +162 -0
  133. package/src/components/ui/popover/index.ts +2 -0
  134. package/src/components/ui/progress/Progress.stories.tsx +190 -0
  135. package/src/components/ui/progress/Progress.test.tsx +181 -0
  136. package/src/components/ui/progress/Progress.tsx +320 -0
  137. package/src/components/ui/progress/index.ts +9 -0
  138. package/src/components/ui/radio/Radio.stories.tsx +199 -0
  139. package/src/components/ui/radio/Radio.test.tsx +166 -0
  140. package/src/components/ui/radio/Radio.tsx +200 -0
  141. package/src/components/ui/radio/index.ts +2 -0
  142. package/src/components/ui/section/Section.stories.tsx +111 -0
  143. package/src/components/ui/section/Section.test.tsx +121 -0
  144. package/src/components/ui/section/Section.tsx +52 -0
  145. package/src/components/ui/section/index.ts +6 -0
  146. package/src/components/ui/select/Select.stories.tsx +286 -0
  147. package/src/components/ui/select/Select.test.tsx +180 -0
  148. package/src/components/ui/select/Select.tsx +236 -0
  149. package/src/components/ui/select/index.ts +2 -0
  150. package/src/components/ui/skeleton/Skeleton.stories.tsx +153 -0
  151. package/src/components/ui/skeleton/Skeleton.test.tsx +162 -0
  152. package/src/components/ui/skeleton/Skeleton.tsx +229 -0
  153. package/src/components/ui/skeleton/index.ts +16 -0
  154. package/src/components/ui/spinner/Spinner.stories.tsx +67 -0
  155. package/src/components/ui/spinner/Spinner.test.tsx +67 -0
  156. package/src/components/ui/spinner/Spinner.tsx +72 -0
  157. package/src/components/ui/spinner/index.ts +2 -0
  158. package/src/components/ui/stack/Stack.stories.tsx +127 -0
  159. package/src/components/ui/stack/Stack.test.tsx +184 -0
  160. package/src/components/ui/stack/Stack.tsx +76 -0
  161. package/src/components/ui/stack/index.ts +2 -0
  162. package/src/components/ui/surface/Surface.stories.tsx +91 -0
  163. package/src/components/ui/surface/Surface.test.tsx +63 -0
  164. package/src/components/ui/surface/Surface.tsx +51 -0
  165. package/src/components/ui/surface/index.ts +1 -0
  166. package/src/components/ui/switch/Switch.stories.tsx +111 -0
  167. package/src/components/ui/switch/Switch.test.tsx +112 -0
  168. package/src/components/ui/switch/Switch.tsx +103 -0
  169. package/src/components/ui/switch/index.ts +2 -0
  170. package/src/components/ui/tabs/Tabs.stories.tsx +213 -0
  171. package/src/components/ui/tabs/Tabs.test.tsx +192 -0
  172. package/src/components/ui/tabs/Tabs.tsx +253 -0
  173. package/src/components/ui/tabs/index.ts +16 -0
  174. package/src/components/ui/toast/Toast.stories.tsx +255 -0
  175. package/src/components/ui/toast/Toast.test.tsx +207 -0
  176. package/src/components/ui/toast/Toast.tsx +327 -0
  177. package/src/components/ui/toast/index.ts +8 -0
  178. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +415 -0
  179. package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +224 -0
  180. package/src/components/ui/toolbar-button/ToolbarButton.tsx +307 -0
  181. package/src/components/ui/toolbar-button/index.ts +7 -0
  182. package/src/components/ui/tooltip/Tooltip.stories.tsx +126 -0
  183. package/src/components/ui/tooltip/Tooltip.test.tsx +179 -0
  184. package/src/components/ui/tooltip/Tooltip.tsx +143 -0
  185. package/src/components/ui/tooltip/index.ts +2 -0
  186. package/src/index.ts +10 -0
  187. package/src/test/setup.ts +19 -0
  188. package/src/theme/Colors.stories.tsx +258 -0
  189. package/src/theme/config.ts +193 -0
  190. package/src/theme/elevation.stories.tsx +346 -0
  191. package/src/theme/elevation.test.ts +27 -0
  192. package/src/theme/elevation.ts +567 -0
  193. package/src/theme/index.ts +39 -0
  194. package/src/theme/shadows.stories.tsx +523 -0
  195. package/src/theme/shadows.ts +439 -0
  196. package/src/theme/tokens/index.ts +2 -0
  197. package/src/theme/tokens/primitives.ts +354 -0
  198. package/src/theme/tokens/semantic.ts +381 -0
  199. package/src/types/jest-axe.d.ts +16 -0
  200. package/src/types/nativewind.d.ts +54 -0
  201. package/src/utils/cn.ts +14 -0
  202. package/src/utils/colors.ts +140 -0
  203. package/src/utils/form.ts +188 -0
  204. package/src/utils/index.ts +29 -0
  205. package/src/utils/useTheme.ts +72 -0
  206. package/dist/chunk-NA3EES23.mjs.map +0 -1
@@ -0,0 +1,128 @@
1
+ import { describe, it, expect, vi } from 'vitest'
2
+ import { render, screen, fireEvent } from '@testing-library/react'
3
+ import { axe } from 'jest-axe'
4
+ import { View, Text } from 'react-native'
5
+ import {
6
+ ListItem,
7
+ ListItemIcon,
8
+ ListItemContent,
9
+ ListItemTrailing,
10
+ ListItemDivider,
11
+ } from './ListItem'
12
+
13
+ function MockIcon({ size = 20 }: { size?: number; className?: string }) {
14
+ return <View testID="mock-icon" style={{ width: size, height: size }} />
15
+ }
16
+
17
+ function ChevronIcon({ size = 16 }: { size?: number; className?: string }) {
18
+ return <Text>{'>'}</Text>
19
+ }
20
+
21
+ describe('ListItem', () => {
22
+ it('renders compound children', () => {
23
+ render(
24
+ <ListItem>
25
+ <ListItemIcon icon={MockIcon} />
26
+ <ListItemContent title="Profile" subtitle="Edit your profile" />
27
+ <ListItemTrailing>
28
+ <Text>{'>'}</Text>
29
+ </ListItemTrailing>
30
+ </ListItem>
31
+ )
32
+
33
+ expect(screen.getByTestId('mock-icon')).toBeInTheDocument()
34
+ expect(screen.getByText('Profile')).toBeInTheDocument()
35
+ expect(screen.getByText('Edit your profile')).toBeInTheDocument()
36
+ expect(screen.getByText('>')).toBeInTheDocument()
37
+ })
38
+
39
+ it('handles press events when onPress is provided', () => {
40
+ const onPress = vi.fn()
41
+ render(
42
+ <ListItem onPress={onPress} testID="list-item">
43
+ <ListItemContent title="Pressable item" />
44
+ </ListItem>
45
+ )
46
+
47
+ fireEvent.click(screen.getByTestId('list-item'))
48
+ expect(onPress).toHaveBeenCalledTimes(1)
49
+ })
50
+
51
+ it('uses View when onPress is not provided', () => {
52
+ const { container } = render(
53
+ <ListItem testID="list-item">
54
+ <ListItemContent title="Static item" />
55
+ </ListItem>
56
+ )
57
+
58
+ // Without onPress, should not have button role
59
+ expect(screen.queryByRole('button')).not.toBeInTheDocument()
60
+ expect(screen.getByText('Static item')).toBeInTheDocument()
61
+ })
62
+ })
63
+
64
+ describe('ListItemContent', () => {
65
+ it('renders title', () => {
66
+ render(<ListItemContent title="Settings" />)
67
+ expect(screen.getByText('Settings')).toBeInTheDocument()
68
+ })
69
+
70
+ it('renders title and subtitle', () => {
71
+ render(<ListItemContent title="Wi-Fi" subtitle="Connected" />)
72
+ expect(screen.getByText('Wi-Fi')).toBeInTheDocument()
73
+ expect(screen.getByText('Connected')).toBeInTheDocument()
74
+ })
75
+
76
+ it('omits subtitle when not provided', () => {
77
+ render(<ListItemContent title="Bluetooth" />)
78
+ expect(screen.getByText('Bluetooth')).toBeInTheDocument()
79
+ expect(screen.queryByText('Connected')).not.toBeInTheDocument()
80
+ })
81
+ })
82
+
83
+ describe('ListItemTrailing', () => {
84
+ it('renders trailing content', () => {
85
+ render(
86
+ <ListItemTrailing>
87
+ <Text>Badge</Text>
88
+ </ListItemTrailing>
89
+ )
90
+ expect(screen.getByText('Badge')).toBeInTheDocument()
91
+ })
92
+ })
93
+
94
+ describe('ListItemDivider', () => {
95
+ it('renders with inset by default', () => {
96
+ const { container } = render(<ListItemDivider testID="divider" />)
97
+ expect(screen.getByTestId('divider')).toBeInTheDocument()
98
+ })
99
+
100
+ it('renders full-width when inset is false', () => {
101
+ render(<ListItemDivider inset={false} testID="divider-full" />)
102
+ expect(screen.getByTestId('divider-full')).toBeInTheDocument()
103
+ })
104
+ })
105
+
106
+ describe('ListItem accessibility', () => {
107
+ it('has no accessibility violations', async () => {
108
+ const { container } = render(
109
+ <ListItem>
110
+ <ListItemContent title="Accessible item" subtitle="With subtitle" />
111
+ </ListItem>
112
+ )
113
+
114
+ const results = await axe(container)
115
+ expect(results).toHaveNoViolations()
116
+ })
117
+
118
+ it('has no accessibility violations when pressable', async () => {
119
+ const { container } = render(
120
+ <ListItem onPress={() => {}} accessibilityRole="button">
121
+ <ListItemContent title="Pressable item" />
122
+ </ListItem>
123
+ )
124
+
125
+ const results = await axe(container)
126
+ expect(results).toHaveNoViolations()
127
+ })
128
+ })
@@ -0,0 +1,89 @@
1
+ import React from 'react'
2
+ import { View, Text, Pressable, type ViewProps, type PressableProps } from 'react-native'
3
+ import { cn } from '../../../utils/cn'
4
+
5
+ // --- ListItem (container) ---
6
+
7
+ export interface ListItemProps extends PressableProps {
8
+ className?: string
9
+ children: React.ReactNode
10
+ }
11
+
12
+ export function ListItem({ className, children, onPress, ...props }: ListItemProps) {
13
+ const Container = onPress ? Pressable : View
14
+ const containerProps = onPress ? { onPress, ...props } : props
15
+
16
+ return (
17
+ <Container
18
+ className={cn('flex-row items-center py-3 px-4 min-h-[48px]', className)}
19
+ {...(containerProps as any)}
20
+ >
21
+ {children}
22
+ </Container>
23
+ )
24
+ }
25
+
26
+ // --- ListItemIcon (leading slot) ---
27
+
28
+ export interface ListItemIconProps extends ViewProps {
29
+ icon: React.ComponentType<{ size?: number; className?: string }>
30
+ className?: string
31
+ }
32
+
33
+ export function ListItemIcon({ icon: Icon, className, ...props }: ListItemIconProps) {
34
+ return (
35
+ <View className={cn('mr-3 items-center justify-center', className)} {...props}>
36
+ <Icon size={20} className="text-text-secondary" />
37
+ </View>
38
+ )
39
+ }
40
+
41
+ // --- ListItemContent (title + subtitle) ---
42
+
43
+ export interface ListItemContentProps extends ViewProps {
44
+ title: string
45
+ subtitle?: string
46
+ className?: string
47
+ }
48
+
49
+ export function ListItemContent({ title, subtitle, className, ...props }: ListItemContentProps) {
50
+ return (
51
+ <View className={cn('flex-1 justify-center', className)} {...props}>
52
+ <Text className="text-sm font-medium text-text-primary">{title}</Text>
53
+ {subtitle && (
54
+ <Text className="text-xs text-text-secondary mt-0.5">{subtitle}</Text>
55
+ )}
56
+ </View>
57
+ )
58
+ }
59
+
60
+ // --- ListItemTrailing (right-side slot) ---
61
+
62
+ export interface ListItemTrailingProps extends ViewProps {
63
+ className?: string
64
+ children: React.ReactNode
65
+ }
66
+
67
+ export function ListItemTrailing({ className, children, ...props }: ListItemTrailingProps) {
68
+ return (
69
+ <View className={cn('ml-3 items-center justify-center', className)} {...props}>
70
+ {children}
71
+ </View>
72
+ )
73
+ }
74
+
75
+ // --- ListItemDivider ---
76
+
77
+ export interface ListItemDividerProps extends ViewProps {
78
+ inset?: boolean
79
+ className?: string
80
+ }
81
+
82
+ export function ListItemDivider({ inset = true, className, ...props }: ListItemDividerProps) {
83
+ return (
84
+ <View
85
+ className={cn('h-px bg-divider', inset ? 'ml-14' : '', className)}
86
+ {...props}
87
+ />
88
+ )
89
+ }
@@ -0,0 +1,14 @@
1
+ export {
2
+ ListItem,
3
+ ListItemIcon,
4
+ ListItemContent,
5
+ ListItemTrailing,
6
+ ListItemDivider,
7
+ } from './ListItem'
8
+ export type {
9
+ ListItemProps,
10
+ ListItemIconProps,
11
+ ListItemContentProps,
12
+ ListItemTrailingProps,
13
+ ListItemDividerProps,
14
+ } from './ListItem'
@@ -0,0 +1,180 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import { View, Text } from 'react-native'
3
+ import { Menu, MenuTrigger, MenuList, MenuItem, MenuDivider, MenuGroup } from './Menu'
4
+ import { Button, ButtonText } from '../button/Button'
5
+
6
+ const meta: Meta<typeof Menu> = {
7
+ title: 'Components/Menu',
8
+ component: Menu,
9
+ tags: ['autodocs'],
10
+ argTypes: {
11
+ isOpen: {
12
+ control: 'boolean',
13
+ description: 'Controlled open state',
14
+ },
15
+ },
16
+ decorators: [
17
+ (Story) => (
18
+ <View style={{ minHeight: 300, padding: 16 }}>
19
+ <Story />
20
+ </View>
21
+ ),
22
+ ],
23
+ }
24
+
25
+ export default meta
26
+ type Story = StoryObj<typeof Menu>
27
+
28
+ export const Default: Story = {
29
+ render: () => (
30
+ <Menu>
31
+ <MenuTrigger>
32
+ <Button variant="outline" color="primary">
33
+ <ButtonText>Options</ButtonText>
34
+ </Button>
35
+ </MenuTrigger>
36
+ <MenuList>
37
+ <MenuItem onPress={() => {}}>Edit</MenuItem>
38
+ <MenuItem onPress={() => {}}>Duplicate</MenuItem>
39
+ <MenuItem onPress={() => {}}>Share</MenuItem>
40
+ </MenuList>
41
+ </Menu>
42
+ ),
43
+ }
44
+
45
+ export const WithGroups: Story = {
46
+ render: () => (
47
+ <Menu>
48
+ <MenuTrigger>
49
+ <Button variant="outline" color="primary">
50
+ <ButtonText>Actions</ButtonText>
51
+ </Button>
52
+ </MenuTrigger>
53
+ <MenuList>
54
+ <MenuGroup label="Edit">
55
+ <MenuItem onPress={() => {}}>Cut</MenuItem>
56
+ <MenuItem onPress={() => {}}>Copy</MenuItem>
57
+ <MenuItem onPress={() => {}}>Paste</MenuItem>
58
+ </MenuGroup>
59
+ <MenuDivider />
60
+ <MenuGroup label="View">
61
+ <MenuItem onPress={() => {}}>Zoom In</MenuItem>
62
+ <MenuItem onPress={() => {}}>Zoom Out</MenuItem>
63
+ <MenuItem onPress={() => {}}>Reset Zoom</MenuItem>
64
+ </MenuGroup>
65
+ </MenuList>
66
+ </Menu>
67
+ ),
68
+ }
69
+
70
+ function EditIcon({ size = 14 }: { size?: number }) {
71
+ return (
72
+ <Text style={{ fontSize: size, lineHeight: size }}>&#9998;</Text>
73
+ )
74
+ }
75
+
76
+ function TrashIcon({ size = 14 }: { size?: number }) {
77
+ return (
78
+ <Text style={{ fontSize: size, lineHeight: size }}>&#128465;</Text>
79
+ )
80
+ }
81
+
82
+ function CopyIcon({ size = 14 }: { size?: number }) {
83
+ return (
84
+ <Text style={{ fontSize: size, lineHeight: size }}>&#128203;</Text>
85
+ )
86
+ }
87
+
88
+ export const WithIcons: Story = {
89
+ render: () => (
90
+ <Menu>
91
+ <MenuTrigger>
92
+ <Button variant="outline" color="primary">
93
+ <ButtonText>More</ButtonText>
94
+ </Button>
95
+ </MenuTrigger>
96
+ <MenuList>
97
+ <MenuItem icon={<EditIcon />} onPress={() => {}}>Edit</MenuItem>
98
+ <MenuItem icon={<CopyIcon />} onPress={() => {}}>Duplicate</MenuItem>
99
+ <MenuDivider />
100
+ <MenuItem icon={<TrashIcon />} onPress={() => {}} isDestructive>Delete</MenuItem>
101
+ </MenuList>
102
+ </Menu>
103
+ ),
104
+ }
105
+
106
+ export const DestructiveItem: Story = {
107
+ render: () => (
108
+ <Menu>
109
+ <MenuTrigger>
110
+ <Button variant="outline" color="primary">
111
+ <ButtonText>Manage</ButtonText>
112
+ </Button>
113
+ </MenuTrigger>
114
+ <MenuList>
115
+ <MenuItem onPress={() => {}}>Edit Profile</MenuItem>
116
+ <MenuItem onPress={() => {}}>Change Password</MenuItem>
117
+ <MenuDivider />
118
+ <MenuItem onPress={() => {}} isDestructive>Delete Account</MenuItem>
119
+ </MenuList>
120
+ </Menu>
121
+ ),
122
+ }
123
+
124
+ export const WithDividers: Story = {
125
+ render: () => (
126
+ <Menu>
127
+ <MenuTrigger>
128
+ <Button variant="outline" color="primary">
129
+ <ButtonText>File</ButtonText>
130
+ </Button>
131
+ </MenuTrigger>
132
+ <MenuList>
133
+ <MenuItem onPress={() => {}}>New File</MenuItem>
134
+ <MenuItem onPress={() => {}}>Open File</MenuItem>
135
+ <MenuDivider />
136
+ <MenuItem onPress={() => {}}>Save</MenuItem>
137
+ <MenuItem onPress={() => {}}>Save As</MenuItem>
138
+ <MenuDivider />
139
+ <MenuItem onPress={() => {}}>Export</MenuItem>
140
+ </MenuList>
141
+ </Menu>
142
+ ),
143
+ }
144
+
145
+ export const DisabledItems: Story = {
146
+ render: () => (
147
+ <Menu>
148
+ <MenuTrigger>
149
+ <Button variant="outline" color="primary">
150
+ <ButtonText>Edit</ButtonText>
151
+ </Button>
152
+ </MenuTrigger>
153
+ <MenuList>
154
+ <MenuItem onPress={() => {}}>Undo</MenuItem>
155
+ <MenuItem onPress={() => {}} isDisabled>Redo</MenuItem>
156
+ <MenuDivider />
157
+ <MenuItem onPress={() => {}}>Cut</MenuItem>
158
+ <MenuItem onPress={() => {}}>Copy</MenuItem>
159
+ <MenuItem onPress={() => {}} isDisabled>Paste</MenuItem>
160
+ </MenuList>
161
+ </Menu>
162
+ ),
163
+ }
164
+
165
+ export const Controlled: Story = {
166
+ render: () => (
167
+ <Menu isOpen>
168
+ <MenuTrigger>
169
+ <Button variant="outline" color="primary">
170
+ <ButtonText>Always Open</ButtonText>
171
+ </Button>
172
+ </MenuTrigger>
173
+ <MenuList>
174
+ <MenuItem onPress={() => {}}>Item One</MenuItem>
175
+ <MenuItem onPress={() => {}}>Item Two</MenuItem>
176
+ <MenuItem onPress={() => {}}>Item Three</MenuItem>
177
+ </MenuList>
178
+ </Menu>
179
+ ),
180
+ }