@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,245 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+ import { View, Text } from 'react-native'
3
+ import { Stepper, Step, StepIndicator, StepLabel, StepContent } from './Stepper'
4
+
5
+ const meta: Meta<typeof Stepper> = {
6
+ title: 'Custom/Stepper',
7
+ component: Stepper,
8
+ tags: ['autodocs'],
9
+ argTypes: {
10
+ activeStep: {
11
+ control: { type: 'number', min: 0, max: 4 },
12
+ description: 'Current active step (0-indexed)',
13
+ },
14
+ orientation: {
15
+ control: 'select',
16
+ options: ['horizontal', 'vertical'],
17
+ description: 'Stepper orientation',
18
+ },
19
+ },
20
+ }
21
+
22
+ export default meta
23
+ type Story = StoryObj<typeof Stepper>
24
+
25
+ export const Default: Story = {
26
+ args: {
27
+ activeStep: 1,
28
+ orientation: 'horizontal',
29
+ },
30
+ render: (args) => (
31
+ <Stepper {...args}>
32
+ <Step>
33
+ <StepIndicator />
34
+ <StepLabel>Account</StepLabel>
35
+ </Step>
36
+ <Step>
37
+ <StepIndicator />
38
+ <StepLabel>Profile</StepLabel>
39
+ </Step>
40
+ <Step>
41
+ <StepIndicator />
42
+ <StepLabel>Review</StepLabel>
43
+ </Step>
44
+ </Stepper>
45
+ ),
46
+ }
47
+
48
+ export const Horizontal: Story = {
49
+ render: () => (
50
+ <View style={{ gap: 32 }}>
51
+ <View>
52
+ <Text className="text-text-secondary text-xs mb-4">Step 1 of 4</Text>
53
+ <Stepper activeStep={0} orientation="horizontal">
54
+ <Step>
55
+ <StepIndicator />
56
+ <StepLabel>Details</StepLabel>
57
+ </Step>
58
+ <Step>
59
+ <StepIndicator />
60
+ <StepLabel>Address</StepLabel>
61
+ </Step>
62
+ <Step>
63
+ <StepIndicator />
64
+ <StepLabel>Payment</StepLabel>
65
+ </Step>
66
+ <Step>
67
+ <StepIndicator />
68
+ <StepLabel>Confirm</StepLabel>
69
+ </Step>
70
+ </Stepper>
71
+ </View>
72
+ <View>
73
+ <Text className="text-text-secondary text-xs mb-4">Step 3 of 4</Text>
74
+ <Stepper activeStep={2} orientation="horizontal">
75
+ <Step>
76
+ <StepIndicator />
77
+ <StepLabel>Details</StepLabel>
78
+ </Step>
79
+ <Step>
80
+ <StepIndicator />
81
+ <StepLabel>Address</StepLabel>
82
+ </Step>
83
+ <Step>
84
+ <StepIndicator />
85
+ <StepLabel>Payment</StepLabel>
86
+ </Step>
87
+ <Step>
88
+ <StepIndicator />
89
+ <StepLabel>Confirm</StepLabel>
90
+ </Step>
91
+ </Stepper>
92
+ </View>
93
+ </View>
94
+ ),
95
+ }
96
+
97
+ export const Vertical: Story = {
98
+ render: () => (
99
+ <Stepper activeStep={1} orientation="vertical">
100
+ <Step>
101
+ <StepIndicator />
102
+ <StepLabel>Create Account</StepLabel>
103
+ </Step>
104
+ <Step>
105
+ <StepIndicator />
106
+ <StepLabel>Set Up Profile</StepLabel>
107
+ </Step>
108
+ <Step>
109
+ <StepIndicator />
110
+ <StepLabel>Configure Settings</StepLabel>
111
+ </Step>
112
+ <Step>
113
+ <StepIndicator />
114
+ <StepLabel>Get Started</StepLabel>
115
+ </Step>
116
+ </Stepper>
117
+ ),
118
+ }
119
+
120
+ export const VerticalWithContent: Story = {
121
+ render: () => (
122
+ <Stepper activeStep={1} orientation="vertical">
123
+ <Step>
124
+ <StepIndicator />
125
+ <StepLabel>Create Account</StepLabel>
126
+ <StepContent>
127
+ <Text className="text-text-secondary text-sm">
128
+ Account creation is complete.
129
+ </Text>
130
+ </StepContent>
131
+ </Step>
132
+ <Step>
133
+ <StepIndicator />
134
+ <StepLabel>Set Up Profile</StepLabel>
135
+ <StepContent>
136
+ <View style={{ gap: 8 }}>
137
+ <Text className="text-text-secondary text-sm">
138
+ Fill in your profile details to continue.
139
+ </Text>
140
+ <View className="bg-surface-inset border border-border-default rounded-md px-3 py-2">
141
+ <Text className="text-text-secondary text-sm">Display Name</Text>
142
+ </View>
143
+ </View>
144
+ </StepContent>
145
+ </Step>
146
+ <Step>
147
+ <StepIndicator />
148
+ <StepLabel>Configure Settings</StepLabel>
149
+ <StepContent>
150
+ <Text className="text-text-secondary text-sm">
151
+ Adjust your preferences.
152
+ </Text>
153
+ </StepContent>
154
+ </Step>
155
+ </Stepper>
156
+ ),
157
+ }
158
+
159
+ export const StepStates: Story = {
160
+ render: () => (
161
+ <View style={{ gap: 24 }}>
162
+ <View>
163
+ <Text className="text-text-secondary text-xs mb-4">All steps upcoming</Text>
164
+ <Stepper activeStep={0} orientation="horizontal">
165
+ <Step>
166
+ <StepIndicator />
167
+ <StepLabel>Step 1</StepLabel>
168
+ </Step>
169
+ <Step>
170
+ <StepIndicator />
171
+ <StepLabel>Step 2</StepLabel>
172
+ </Step>
173
+ <Step>
174
+ <StepIndicator />
175
+ <StepLabel>Step 3</StepLabel>
176
+ </Step>
177
+ </Stepper>
178
+ </View>
179
+ <View>
180
+ <Text className="text-text-secondary text-xs mb-4">All steps completed</Text>
181
+ <Stepper activeStep={3} orientation="horizontal">
182
+ <Step>
183
+ <StepIndicator />
184
+ <StepLabel>Step 1</StepLabel>
185
+ </Step>
186
+ <Step>
187
+ <StepIndicator />
188
+ <StepLabel>Step 2</StepLabel>
189
+ </Step>
190
+ <Step>
191
+ <StepIndicator />
192
+ <StepLabel>Step 3</StepLabel>
193
+ </Step>
194
+ </Stepper>
195
+ </View>
196
+ </View>
197
+ ),
198
+ }
199
+
200
+ export const WithErrorState: Story = {
201
+ render: () => (
202
+ <Stepper activeStep={2} orientation="horizontal">
203
+ <Step>
204
+ <StepIndicator />
205
+ <StepLabel>Account</StepLabel>
206
+ </Step>
207
+ <Step status="error">
208
+ <StepIndicator />
209
+ <StepLabel>Verification</StepLabel>
210
+ </Step>
211
+ <Step>
212
+ <StepIndicator />
213
+ <StepLabel>Complete</StepLabel>
214
+ </Step>
215
+ </Stepper>
216
+ ),
217
+ }
218
+
219
+ export const ActiveStepProgression: Story = {
220
+ render: () => (
221
+ <View style={{ gap: 24 }}>
222
+ {[0, 1, 2, 3].map((activeStep) => (
223
+ <View key={activeStep}>
224
+ <Text className="text-text-secondary text-xs mb-2">
225
+ Active step: {activeStep}
226
+ </Text>
227
+ <Stepper activeStep={activeStep} orientation="horizontal">
228
+ <Step>
229
+ <StepIndicator />
230
+ <StepLabel>Account</StepLabel>
231
+ </Step>
232
+ <Step>
233
+ <StepIndicator />
234
+ <StepLabel>Profile</StepLabel>
235
+ </Step>
236
+ <Step>
237
+ <StepIndicator />
238
+ <StepLabel>Review</StepLabel>
239
+ </Step>
240
+ </Stepper>
241
+ </View>
242
+ ))}
243
+ </View>
244
+ ),
245
+ }
@@ -0,0 +1,230 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { render, screen } from '@testing-library/react'
3
+ import { axe } from 'jest-axe'
4
+ import {
5
+ Stepper,
6
+ Step,
7
+ StepIndicator,
8
+ StepLabel,
9
+ StepContent,
10
+ } from './Stepper'
11
+
12
+ function renderStepper(activeStep = 1) {
13
+ return render(
14
+ <Stepper activeStep={activeStep}>
15
+ <Step>
16
+ <StepIndicator />
17
+ <StepLabel>Account</StepLabel>
18
+ </Step>
19
+ <Step>
20
+ <StepIndicator />
21
+ <StepLabel>Profile</StepLabel>
22
+ </Step>
23
+ <Step>
24
+ <StepIndicator />
25
+ <StepLabel>Review</StepLabel>
26
+ </Step>
27
+ </Stepper>
28
+ )
29
+ }
30
+
31
+ describe('Stepper', () => {
32
+ it('renders all steps', () => {
33
+ renderStepper(0)
34
+ expect(screen.getByText('Account')).toBeInTheDocument()
35
+ expect(screen.getByText('Profile')).toBeInTheDocument()
36
+ expect(screen.getByText('Review')).toBeInTheDocument()
37
+ })
38
+
39
+ it('renders step numbers', () => {
40
+ renderStepper(0)
41
+ expect(screen.getByText('1')).toBeInTheDocument()
42
+ expect(screen.getByText('2')).toBeInTheDocument()
43
+ expect(screen.getByText('3')).toBeInTheDocument()
44
+ })
45
+
46
+ describe('active step', () => {
47
+ it('shows first step as active when activeStep is 0', () => {
48
+ renderStepper(0)
49
+ expect(screen.getByText('Account')).toBeInTheDocument()
50
+ expect(screen.getByText('1')).toBeInTheDocument()
51
+ })
52
+
53
+ it('shows checkmark for completed steps', () => {
54
+ renderStepper(2)
55
+ // Steps 0 and 1 should be completed, showing checkmarks
56
+ const checkmarks = screen.getAllByText('\u2713')
57
+ expect(checkmarks.length).toBe(2)
58
+ })
59
+
60
+ it('shows number for upcoming steps', () => {
61
+ renderStepper(0)
62
+ expect(screen.getByText('2')).toBeInTheDocument()
63
+ expect(screen.getByText('3')).toBeInTheDocument()
64
+ })
65
+ })
66
+
67
+ describe('orientation', () => {
68
+ it('renders horizontally by default', () => {
69
+ renderStepper(1)
70
+ expect(screen.getByText('Account')).toBeInTheDocument()
71
+ })
72
+
73
+ it('renders vertically', () => {
74
+ render(
75
+ <Stepper activeStep={1} orientation="vertical">
76
+ <Step>
77
+ <StepIndicator />
78
+ <StepLabel>Step 1</StepLabel>
79
+ </Step>
80
+ <Step>
81
+ <StepIndicator />
82
+ <StepLabel>Step 2</StepLabel>
83
+ </Step>
84
+ </Stepper>
85
+ )
86
+ expect(screen.getByText('Step 1')).toBeInTheDocument()
87
+ expect(screen.getByText('Step 2')).toBeInTheDocument()
88
+ })
89
+ })
90
+
91
+ describe('Step status override', () => {
92
+ it('allows explicit error status on a step', () => {
93
+ render(
94
+ <Stepper activeStep={1}>
95
+ <Step status="error">
96
+ <StepIndicator />
97
+ <StepLabel>Failed Step</StepLabel>
98
+ </Step>
99
+ <Step>
100
+ <StepIndicator />
101
+ <StepLabel>Next Step</StepLabel>
102
+ </Step>
103
+ </Stepper>
104
+ )
105
+ expect(screen.getByText('Failed Step')).toBeInTheDocument()
106
+ })
107
+
108
+ it('allows explicit completed status override', () => {
109
+ render(
110
+ <Stepper activeStep={0}>
111
+ <Step status="completed">
112
+ <StepIndicator />
113
+ <StepLabel>Done Step</StepLabel>
114
+ </Step>
115
+ <Step>
116
+ <StepIndicator />
117
+ <StepLabel>Current</StepLabel>
118
+ </Step>
119
+ </Stepper>
120
+ )
121
+ // The overridden step should show checkmark despite being at index 0 with activeStep 0
122
+ expect(screen.getByText('\u2713')).toBeInTheDocument()
123
+ })
124
+ })
125
+
126
+ describe('StepIndicator', () => {
127
+ it('renders custom icon', () => {
128
+ render(
129
+ <Stepper activeStep={0}>
130
+ <Step>
131
+ <StepIndicator icon={<span data-testid="custom-icon">★</span>} />
132
+ <StepLabel>Custom</StepLabel>
133
+ </Step>
134
+ </Stepper>
135
+ )
136
+ expect(screen.getByTestId('custom-icon')).toBeInTheDocument()
137
+ })
138
+
139
+ it('renders step number for upcoming steps', () => {
140
+ render(
141
+ <Stepper activeStep={0}>
142
+ <Step>
143
+ <StepIndicator />
144
+ <StepLabel>First</StepLabel>
145
+ </Step>
146
+ <Step>
147
+ <StepIndicator />
148
+ <StepLabel>Second</StepLabel>
149
+ </Step>
150
+ </Stepper>
151
+ )
152
+ expect(screen.getByText('2')).toBeInTheDocument()
153
+ })
154
+ })
155
+
156
+ describe('StepContent', () => {
157
+ it('renders content only for active step', () => {
158
+ render(
159
+ <Stepper activeStep={1} orientation="vertical">
160
+ <Step>
161
+ <StepIndicator />
162
+ <StepLabel>Step 1</StepLabel>
163
+ <StepContent>Step 1 content</StepContent>
164
+ </Step>
165
+ <Step>
166
+ <StepIndicator />
167
+ <StepLabel>Step 2</StepLabel>
168
+ <StepContent>Step 2 content</StepContent>
169
+ </Step>
170
+ </Stepper>
171
+ )
172
+ expect(screen.queryByText('Step 1 content')).not.toBeInTheDocument()
173
+ expect(screen.getByText('Step 2 content')).toBeInTheDocument()
174
+ })
175
+
176
+ it('hides content for non-active steps', () => {
177
+ render(
178
+ <Stepper activeStep={0} orientation="vertical">
179
+ <Step>
180
+ <StepIndicator />
181
+ <StepLabel>Step 1</StepLabel>
182
+ <StepContent>Active content</StepContent>
183
+ </Step>
184
+ <Step>
185
+ <StepIndicator />
186
+ <StepLabel>Step 2</StepLabel>
187
+ <StepContent>Hidden content</StepContent>
188
+ </Step>
189
+ </Stepper>
190
+ )
191
+ expect(screen.getByText('Active content')).toBeInTheDocument()
192
+ expect(screen.queryByText('Hidden content')).not.toBeInTheDocument()
193
+ })
194
+ })
195
+
196
+ describe('connectors', () => {
197
+ it('renders connectors between steps', () => {
198
+ renderStepper(1)
199
+ // Connectors exist between steps; just verify all labels render (connectors are visual)
200
+ expect(screen.getByText('Account')).toBeInTheDocument()
201
+ expect(screen.getByText('Profile')).toBeInTheDocument()
202
+ expect(screen.getByText('Review')).toBeInTheDocument()
203
+ })
204
+ })
205
+
206
+ describe('accessibility', () => {
207
+ it('has no accessibility violations', async () => {
208
+ const { container } = renderStepper(1)
209
+ const results = await axe(container)
210
+ expect(results).toHaveNoViolations()
211
+ })
212
+
213
+ it('has no accessibility violations in vertical orientation', async () => {
214
+ const { container } = render(
215
+ <Stepper activeStep={0} orientation="vertical">
216
+ <Step>
217
+ <StepIndicator />
218
+ <StepLabel>Step 1</StepLabel>
219
+ </Step>
220
+ <Step>
221
+ <StepIndicator />
222
+ <StepLabel>Step 2</StepLabel>
223
+ </Step>
224
+ </Stepper>
225
+ )
226
+ const results = await axe(container)
227
+ expect(results).toHaveNoViolations()
228
+ })
229
+ })
230
+ })