@utilitywarehouse/hearth-react-native 0.27.3 → 0.28.0-testid-fix-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 (150) hide show
  1. package/.turbo/turbo-build.log +5 -4
  2. package/.turbo/turbo-lint.log +70 -69
  3. package/CHANGELOG.md +110 -0
  4. package/build/components/Combobox/Combobox.context.d.ts +13 -0
  5. package/build/components/Combobox/Combobox.context.js +9 -0
  6. package/build/components/Combobox/Combobox.d.ts +6 -0
  7. package/build/components/Combobox/Combobox.js +246 -0
  8. package/build/components/Combobox/Combobox.props.d.ts +180 -0
  9. package/build/components/Combobox/Combobox.props.js +1 -0
  10. package/build/components/Combobox/ComboboxOption.d.ts +6 -0
  11. package/build/components/Combobox/ComboboxOption.js +56 -0
  12. package/build/components/Combobox/index.d.ts +4 -0
  13. package/build/components/Combobox/index.js +3 -0
  14. package/build/components/DatePicker/TimePicker.d.ts +3 -0
  15. package/build/components/DatePicker/TimePicker.js +84 -0
  16. package/build/components/DatePicker/time-picker/animated-math.d.ts +4 -0
  17. package/build/components/DatePicker/time-picker/animated-math.js +19 -0
  18. package/build/components/DatePicker/time-picker/period-native.d.ts +6 -0
  19. package/build/components/DatePicker/time-picker/period-native.js +17 -0
  20. package/build/components/DatePicker/time-picker/period-picker.d.ts +6 -0
  21. package/build/components/DatePicker/time-picker/period-picker.js +10 -0
  22. package/build/components/DatePicker/time-picker/period-web.d.ts +6 -0
  23. package/build/components/DatePicker/time-picker/period-web.js +21 -0
  24. package/build/components/DatePicker/time-picker/wheel-native.d.ts +8 -0
  25. package/build/components/DatePicker/time-picker/wheel-native.js +19 -0
  26. package/build/components/DatePicker/time-picker/wheel-picker/index.d.ts +2 -0
  27. package/build/components/DatePicker/time-picker/wheel-picker/index.js +2 -0
  28. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.d.ts +16 -0
  29. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.js +97 -0
  30. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.d.ts +21 -0
  31. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.js +88 -0
  32. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.d.ts +23 -0
  33. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.js +21 -0
  34. package/build/components/DatePicker/time-picker/wheel-web.d.ts +8 -0
  35. package/build/components/DatePicker/time-picker/wheel-web.js +146 -0
  36. package/build/components/DatePicker/time-picker/wheel.d.ts +8 -0
  37. package/build/components/DatePicker/time-picker/wheel.js +10 -0
  38. package/build/components/Modal/Modal.js +26 -42
  39. package/build/components/Modal/Modal.web.js +3 -3
  40. package/build/components/Pagination/Pagination.d.ts +6 -0
  41. package/build/components/Pagination/Pagination.js +125 -0
  42. package/build/components/Pagination/Pagination.props.d.ts +26 -0
  43. package/build/components/Pagination/Pagination.props.js +1 -0
  44. package/build/components/Pagination/Pagination.utils.d.ts +2 -0
  45. package/build/components/Pagination/Pagination.utils.js +20 -0
  46. package/build/components/Pagination/Pagination.utils.test.d.ts +1 -0
  47. package/build/components/Pagination/Pagination.utils.test.js +16 -0
  48. package/build/components/Pagination/index.d.ts +2 -0
  49. package/build/components/Pagination/index.js +1 -0
  50. package/build/components/SafeAreaView/SafeAreaView.d.ts +5 -0
  51. package/build/components/SafeAreaView/SafeAreaView.js +117 -0
  52. package/build/components/SafeAreaView/SafeAreaView.props.d.ts +17 -0
  53. package/build/components/SafeAreaView/SafeAreaView.props.js +1 -0
  54. package/build/components/SafeAreaView/index.d.ts +2 -0
  55. package/build/components/SafeAreaView/index.js +1 -0
  56. package/build/components/Select/Select.d.ts +1 -1
  57. package/build/components/Select/Select.js +6 -5
  58. package/build/components/Select/Select.props.d.ts +4 -0
  59. package/build/components/Select/SelectOption.d.ts +1 -1
  60. package/build/components/Select/SelectOption.js +2 -2
  61. package/build/components/Table/Table.context.d.ts +12 -0
  62. package/build/components/Table/Table.context.js +9 -0
  63. package/build/components/Table/Table.d.ts +6 -0
  64. package/build/components/Table/Table.js +71 -0
  65. package/build/components/Table/Table.props.d.ts +56 -0
  66. package/build/components/Table/Table.props.js +1 -0
  67. package/build/components/Table/Table.utils.d.ts +5 -0
  68. package/build/components/Table/Table.utils.js +48 -0
  69. package/build/components/Table/Table.utils.test.d.ts +1 -0
  70. package/build/components/Table/Table.utils.test.js +71 -0
  71. package/build/components/Table/TableBody.d.ts +6 -0
  72. package/build/components/Table/TableBody.js +16 -0
  73. package/build/components/Table/TableCell.d.ts +10 -0
  74. package/build/components/Table/TableCell.js +44 -0
  75. package/build/components/Table/TableHeader.d.ts +6 -0
  76. package/build/components/Table/TableHeader.js +24 -0
  77. package/build/components/Table/TableHeaderCell.d.ts +10 -0
  78. package/build/components/Table/TableHeaderCell.js +97 -0
  79. package/build/components/Table/TablePagination.d.ts +6 -0
  80. package/build/components/Table/TablePagination.js +7 -0
  81. package/build/components/Table/TableRow.d.ts +8 -0
  82. package/build/components/Table/TableRow.js +25 -0
  83. package/build/components/Table/index.d.ts +8 -0
  84. package/build/components/Table/index.js +7 -0
  85. package/build/components/Timeline/Timeline.d.ts +6 -0
  86. package/build/components/Timeline/Timeline.js +34 -0
  87. package/build/components/Timeline/Timeline.props.d.ts +47 -0
  88. package/build/components/Timeline/Timeline.props.js +1 -0
  89. package/build/components/Timeline/TimelineItem.d.ts +6 -0
  90. package/build/components/Timeline/TimelineItem.js +235 -0
  91. package/build/components/Timeline/index.d.ts +3 -0
  92. package/build/components/Timeline/index.js +2 -0
  93. package/build/components/VerificationInput/VerificationInput.js +3 -3
  94. package/build/components/index.d.ts +5 -0
  95. package/build/components/index.js +5 -0
  96. package/build/tokens/components/dark/timeline.d.ts +2 -2
  97. package/build/tokens/components/dark/timeline.js +2 -2
  98. package/docs/components/AllComponents.web.tsx +106 -23
  99. package/docs/llm-docs/unistyles-llms-full.txt +1132 -534
  100. package/docs/llm-docs/unistyles-llms-small.txt +37 -37
  101. package/package.json +4 -4
  102. package/src/components/Combobox/Combobox.context.ts +26 -0
  103. package/src/components/Combobox/Combobox.docs.mdx +277 -0
  104. package/src/components/Combobox/Combobox.figma.tsx +60 -0
  105. package/src/components/Combobox/Combobox.props.ts +187 -0
  106. package/src/components/Combobox/Combobox.stories.tsx +233 -0
  107. package/src/components/Combobox/Combobox.tsx +446 -0
  108. package/src/components/Combobox/ComboboxOption.tsx +100 -0
  109. package/src/components/Combobox/index.ts +9 -0
  110. package/src/components/Modal/Modal.tsx +52 -74
  111. package/src/components/Modal/Modal.web.tsx +3 -3
  112. package/src/components/Pagination/Pagination.docs.mdx +99 -0
  113. package/src/components/Pagination/Pagination.figma.tsx +20 -0
  114. package/src/components/Pagination/Pagination.props.ts +28 -0
  115. package/src/components/Pagination/Pagination.stories.tsx +88 -0
  116. package/src/components/Pagination/Pagination.tsx +248 -0
  117. package/src/components/Pagination/Pagination.utils.test.ts +20 -0
  118. package/src/components/Pagination/Pagination.utils.ts +37 -0
  119. package/src/components/Pagination/index.ts +2 -0
  120. package/src/components/SafeAreaView/SafeAreaView.props.ts +20 -0
  121. package/src/components/SafeAreaView/SafeAreaView.tsx +173 -0
  122. package/src/components/SafeAreaView/index.ts +2 -0
  123. package/src/components/Select/Select.props.ts +4 -0
  124. package/src/components/Select/Select.tsx +35 -28
  125. package/src/components/Select/SelectOption.tsx +2 -0
  126. package/src/components/Table/Table.context.tsx +23 -0
  127. package/src/components/Table/Table.docs.mdx +239 -0
  128. package/src/components/Table/Table.figma.tsx +65 -0
  129. package/src/components/Table/Table.props.ts +65 -0
  130. package/src/components/Table/Table.stories.tsx +399 -0
  131. package/src/components/Table/Table.tsx +127 -0
  132. package/src/components/Table/Table.utils.test.ts +82 -0
  133. package/src/components/Table/Table.utils.ts +72 -0
  134. package/src/components/Table/TableBody.tsx +25 -0
  135. package/src/components/Table/TableCell.tsx +67 -0
  136. package/src/components/Table/TableHeader.tsx +41 -0
  137. package/src/components/Table/TableHeaderCell.tsx +136 -0
  138. package/src/components/Table/TablePagination.tsx +10 -0
  139. package/src/components/Table/TableRow.tsx +42 -0
  140. package/src/components/Table/index.ts +16 -0
  141. package/src/components/Timeline/Timeline.docs.mdx +177 -0
  142. package/src/components/Timeline/Timeline.figma.tsx +89 -0
  143. package/src/components/Timeline/Timeline.props.ts +51 -0
  144. package/src/components/Timeline/Timeline.stories.tsx +102 -0
  145. package/src/components/Timeline/Timeline.tsx +48 -0
  146. package/src/components/Timeline/TimelineItem.tsx +293 -0
  147. package/src/components/Timeline/index.ts +9 -0
  148. package/src/components/VerificationInput/VerificationInput.tsx +3 -0
  149. package/src/components/index.ts +5 -0
  150. package/src/tokens/components/dark/timeline.ts +2 -2
@@ -0,0 +1,67 @@
1
+ import { ReactNode } from 'react';
2
+ import { View, ViewStyle } from 'react-native';
3
+ import { StyleSheet } from 'react-native-unistyles';
4
+ import { BodyText } from '../BodyText';
5
+ import { useTableContext } from './Table.context';
6
+ import { TableCellProps } from './Table.props';
7
+ import { getColumnStyle } from './Table.utils';
8
+
9
+ const renderContent = (children?: ReactNode, weight: 'regular' | 'semibold' = 'regular') => {
10
+ if (typeof children === 'string' || typeof children === 'number') {
11
+ return (
12
+ <BodyText size="md" weight={weight}>
13
+ {children}
14
+ </BodyText>
15
+ );
16
+ }
17
+
18
+ return children;
19
+ };
20
+
21
+ const TableCell = ({
22
+ children,
23
+ style,
24
+ ...props
25
+ }: TableCellProps & { columnIndex?: number; isLast?: boolean; isLastRow?: boolean }) => {
26
+ const { columnWidths, container, hasPagination } = useTableContext();
27
+ const { columnIndex = 0, isLast, isLastRow, ...rest } = props;
28
+ const removeBottomBorder = Boolean(isLastRow && container !== 'none' && !hasPagination);
29
+ const columnStyle = getColumnStyle(columnWidths[columnIndex], 120);
30
+
31
+ return (
32
+ <View
33
+ {...rest}
34
+ style={[
35
+ styles.cell,
36
+ columnStyle,
37
+ isLast && styles.lastCell,
38
+ removeBottomBorder && styles.lastRowCell,
39
+ style as ViewStyle,
40
+ ]}
41
+ >
42
+ {renderContent(children)}
43
+ </View>
44
+ );
45
+ };
46
+
47
+ TableCell.displayName = 'TableCell';
48
+
49
+ const styles = StyleSheet.create(theme => ({
50
+ cell: {
51
+ minHeight: theme.components.table.cell.minHeight,
52
+ justifyContent: 'center',
53
+ padding: theme.components.table.cell.padding,
54
+ borderRightWidth: theme.components.table.cell.borderWidth,
55
+ borderBottomWidth: theme.components.table.cell.borderWidth,
56
+ borderColor: theme.color.border.subtle,
57
+ backgroundColor: theme.color.surface.neutral.strong,
58
+ },
59
+ lastCell: {
60
+ borderRightWidth: 0,
61
+ },
62
+ lastRowCell: {
63
+ borderBottomWidth: 0,
64
+ },
65
+ }));
66
+
67
+ export default TableCell;
@@ -0,0 +1,41 @@
1
+ import { Children, cloneElement, isValidElement } from 'react';
2
+ import { View, ViewStyle } from 'react-native';
3
+ import { TableHeaderProps } from './Table.props';
4
+
5
+ const TableHeader = ({ children, color = 'purple', style, ...props }: TableHeaderProps) => {
6
+ const items = Children.toArray(children);
7
+
8
+ return (
9
+ <View {...props} style={[styles.header, style as ViewStyle]}>
10
+ {items.map((child, index) => {
11
+ if (!isValidElement(child)) {
12
+ return child;
13
+ }
14
+
15
+ return cloneElement(
16
+ child as React.ReactElement<{
17
+ color?: 'purple' | 'white';
18
+ columnIndex?: number;
19
+ isLast?: boolean;
20
+ }>,
21
+ {
22
+ color,
23
+ columnIndex: index,
24
+ isLast: index === items.length - 1,
25
+ }
26
+ );
27
+ })}
28
+ </View>
29
+ );
30
+ };
31
+
32
+ TableHeader.displayName = 'TableHeader';
33
+
34
+ const styles = {
35
+ header: {
36
+ flexDirection: 'row' as const,
37
+ width: '100%' as const,
38
+ },
39
+ };
40
+
41
+ export default TableHeader;
@@ -0,0 +1,136 @@
1
+ import { cloneElement, isValidElement, ReactNode } from 'react';
2
+ import { View, ViewStyle } from 'react-native';
3
+ import { StyleSheet } from 'react-native-unistyles';
4
+ import { BodyText } from '../BodyText';
5
+ import { useTableContext } from './Table.context';
6
+ import type { TableHeaderCellProps } from './Table.props';
7
+ import { getColumnStyle } from './Table.utils';
8
+
9
+ const renderContent = (
10
+ children?: ReactNode,
11
+ weight: 'regular' | 'semibold' = 'semibold',
12
+ color: 'purple' | 'white' = 'white'
13
+ ) => {
14
+ if (typeof children === 'string' || typeof children === 'number') {
15
+ return (
16
+ <BodyText size="md" weight={weight} style={styles.text} inverted={color === 'purple'}>
17
+ {children}
18
+ </BodyText>
19
+ );
20
+ }
21
+
22
+ return children;
23
+ };
24
+
25
+ const TableHeaderCell = ({
26
+ children,
27
+ color = 'white',
28
+ row = false,
29
+ style,
30
+ trailingContent,
31
+ ...props
32
+ }: TableHeaderCellProps & { columnIndex?: number; isLast?: boolean; isLastRow?: boolean }) => {
33
+ const { columnWidths, container, hasPagination } = useTableContext();
34
+ const { columnIndex = 0, isLast, isLastRow, ...rest } = props;
35
+ const removeBottomBorder = Boolean(row && isLastRow && container !== 'none' && !hasPagination);
36
+ const columnStyle = getColumnStyle(columnWidths[columnIndex], 120);
37
+
38
+ styles.useVariants({ color, row });
39
+
40
+ const trailingElement =
41
+ trailingContent && isValidElement(trailingContent)
42
+ ? (trailingContent as React.ReactElement<{ inverted?: boolean }>)
43
+ : null;
44
+
45
+ const resolvedTrailingContent =
46
+ trailingElement && !row && 'inverted' in (trailingElement.props ?? {})
47
+ ? cloneElement(trailingElement, {
48
+ inverted: color === 'purple',
49
+ })
50
+ : trailingContent;
51
+
52
+ return (
53
+ <View
54
+ {...rest}
55
+ style={[
56
+ styles.cell,
57
+ columnStyle,
58
+ isLast && styles.lastCell,
59
+ removeBottomBorder && styles.lastRowCell,
60
+ style as ViewStyle,
61
+ ]}
62
+ >
63
+ <View style={styles.content}>
64
+ {renderContent(children, 'semibold', color)}
65
+ {resolvedTrailingContent ? (
66
+ <View style={styles.trailing}>{resolvedTrailingContent}</View>
67
+ ) : null}
68
+ </View>
69
+ </View>
70
+ );
71
+ };
72
+
73
+ TableHeaderCell.displayName = 'TableHeaderCell';
74
+
75
+ const styles = StyleSheet.create(theme => ({
76
+ cell: {
77
+ minHeight: theme.components.table.headerCell.height,
78
+ justifyContent: 'center',
79
+ paddingHorizontal: theme.components.table.headerCell.paddingHorizontal,
80
+ paddingVertical: theme.components.table.headerCell.paddingVertical,
81
+ borderRightWidth: theme.components.table.headerCell.borderWidth,
82
+ borderBottomWidth: theme.components.table.headerCell.borderWidth,
83
+ borderColor: theme.color.border.subtle,
84
+ backgroundColor: theme.color.surface.neutral.strong,
85
+ variants: {
86
+ color: {
87
+ purple: {
88
+ borderColor: theme.color.interactive.brand.foreground.strong,
89
+ backgroundColor: theme.color.surface.brand.default,
90
+ },
91
+ white: {
92
+ borderColor: theme.color.border.subtle,
93
+ backgroundColor: theme.color.surface.neutral.strong,
94
+ },
95
+ },
96
+ row: {
97
+ true: {
98
+ minHeight: theme.components.table.cell.minHeight,
99
+ paddingHorizontal: theme.components.table.cell.padding,
100
+ paddingVertical: theme.components.table.cell.padding,
101
+ borderRightWidth: theme.components.table.cell.borderWidth,
102
+ borderBottomWidth: theme.components.table.cell.borderWidth,
103
+ borderColor: theme.color.border.subtle,
104
+ backgroundColor: theme.color.surface.neutral.strong,
105
+ },
106
+ },
107
+ },
108
+ },
109
+ lastCell: {
110
+ borderRightWidth: 0,
111
+ },
112
+ lastRowCell: {
113
+ borderBottomWidth: 0,
114
+ },
115
+ content: {
116
+ flexDirection: 'row',
117
+ alignItems: 'center',
118
+ justifyContent: 'space-between',
119
+ gap: theme.components.table.headerCell.gap,
120
+ },
121
+ trailing: {
122
+ flexShrink: 0,
123
+ },
124
+ text: {
125
+ flexShrink: 1,
126
+ variants: {
127
+ row: {
128
+ true: {
129
+ color: theme.color.text.primary,
130
+ },
131
+ },
132
+ },
133
+ },
134
+ }));
135
+
136
+ export default TableHeaderCell;
@@ -0,0 +1,10 @@
1
+ import { Pagination } from '../Pagination';
2
+ import type { TablePaginationProps } from './Table.props';
3
+
4
+ const TablePagination = (props: TablePaginationProps) => {
5
+ return <Pagination {...props} />;
6
+ };
7
+
8
+ TablePagination.displayName = 'TablePagination';
9
+
10
+ export default TablePagination;
@@ -0,0 +1,42 @@
1
+ import { Children, cloneElement, isValidElement } from 'react';
2
+ import { View } from 'react-native';
3
+ import { TableRowProps } from './Table.props';
4
+
5
+ const TableRow = ({ children, ...props }: TableRowProps & { isLastRow?: boolean }) => {
6
+ const items = Children.toArray(children);
7
+ const { isLastRow = false, ...rest } = props;
8
+
9
+ return (
10
+ <View {...rest} style={[styles.row, rest.style]}>
11
+ {items.map((child, index) => {
12
+ if (!isValidElement(child)) {
13
+ return child;
14
+ }
15
+
16
+ return cloneElement(
17
+ child as React.ReactElement<{
18
+ columnIndex?: number;
19
+ isLast?: boolean;
20
+ isLastRow?: boolean;
21
+ }>,
22
+ {
23
+ isLast: index === items.length - 1,
24
+ columnIndex: index,
25
+ isLastRow,
26
+ }
27
+ );
28
+ })}
29
+ </View>
30
+ );
31
+ };
32
+
33
+ TableRow.displayName = 'TableRow';
34
+
35
+ const styles = {
36
+ row: {
37
+ flexDirection: 'row' as const,
38
+ width: '100%' as const,
39
+ },
40
+ };
41
+
42
+ export default TableRow;
@@ -0,0 +1,16 @@
1
+ export { default as Table } from './Table';
2
+ export type {
3
+ TableBodyProps,
4
+ TableCellProps,
5
+ TableHeaderCellProps,
6
+ TableHeaderProps,
7
+ TablePaginationProps,
8
+ TableProps,
9
+ TableRowProps,
10
+ } from './Table.props';
11
+ export { default as TableBody } from './TableBody';
12
+ export { default as TableCell } from './TableCell';
13
+ export { default as TableHeader } from './TableHeader';
14
+ export { default as TableHeaderCell } from './TableHeaderCell';
15
+ export { default as TablePagination } from './TablePagination';
16
+ export { default as TableRow } from './TableRow';
@@ -0,0 +1,177 @@
1
+ import { Canvas, Controls, Meta } from '@storybook/addon-docs/blocks';
2
+ import { Badge, BodyText, Box, Card, Center, Timeline, TimelineItem } from '../..';
3
+ import { BackToTopButton, UsageWrap, ViewFigmaButton } from '../../../docs/components';
4
+ import * as Stories from './Timeline.stories';
5
+
6
+ <Meta title="Components / Timeline" />
7
+
8
+ <BackToTopButton />
9
+
10
+ <ViewFigmaButton url="https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=10592-5483&t=pZwKJYFo1y1QRQD1-4" />
11
+
12
+ # Timeline
13
+
14
+ Timeline presents a sequence of related stops or steps using either a static stop indicator or a progress state indicator. Each item supports a label, optional helper text, and optional custom content.
15
+
16
+ - [Playground](#playground)
17
+ - [Usage](#usage)
18
+ - [Props](#props)
19
+ - [Examples](#examples)
20
+ - [Accessibility](#accessibility)
21
+
22
+ ## Playground
23
+
24
+ <Canvas of={Stories.Playground} />
25
+
26
+ <Controls of={Stories.Playground} />
27
+
28
+ ## Usage
29
+
30
+ <UsageWrap>
31
+ <Center>
32
+ <Box style={{ width: 300 }}>
33
+ <Timeline variant="progress">
34
+ <TimelineItem label="Ordered" helperText="We have received your order" state="complete" />
35
+ <TimelineItem label="Packed" helperText="Your items are ready" state="complete" />
36
+ <TimelineItem label="Out for delivery" helperText="Arriving today" state="active" />
37
+ <TimelineItem label="Delivered" helperText="Pending" state="incomplete" />
38
+ </Timeline>
39
+ </Box>
40
+ </Center>
41
+ </UsageWrap>
42
+
43
+ ```tsx
44
+ import { Timeline, TimelineItem } from '@utilitywarehouse/hearth-react-native';
45
+
46
+ const MyComponent = () => (
47
+ <Timeline variant="progress">
48
+ <TimelineItem label="Ordered" helperText="We have received your order" state="complete" />
49
+ <TimelineItem label="Packed" helperText="Your items are ready" state="complete" />
50
+ <TimelineItem label="Out for delivery" helperText="Arriving today" state="active" />
51
+ <TimelineItem label="Delivered" helperText="Pending" state="incomplete" />
52
+ </Timeline>
53
+ );
54
+ ```
55
+
56
+ ## Props
57
+
58
+ ### Timeline Props
59
+
60
+ | Property | Type | Description | Default |
61
+ | ---------- | ------------------------ | --------------------------------------------- | ---------- |
62
+ | `children` | `ReactNode` | Child `TimelineItem` components. | Required |
63
+ | `variant` | `'static' \| 'progress'` | Controls the indicator style for child items. | `'static'` |
64
+
65
+ ### TimelineItem Props
66
+
67
+ | Property | Type | Description | Default |
68
+ | ------------ | ---------------------------------------- | -------------------------------------------------------- | -------------- |
69
+ | `label` | `string` | Primary label text. | Required |
70
+ | `helperText` | `string` | Optional supporting text beneath the label. | `undefined` |
71
+ | `state` | `'complete' \| 'active' \| 'incomplete'` | Progress state used when `variant="progress"`. | `'incomplete'` |
72
+ | `children` | `ReactNode` | Optional custom content rendered below the text content. | `undefined` |
73
+
74
+ ## Examples
75
+
76
+ ### Variants
77
+
78
+ <UsageWrap>
79
+ <Center>
80
+ <Box style={{ width: 320 }}>
81
+ <Timeline variant="progress">
82
+ <TimelineItem label="Account created" helperText="Done" state="complete" />
83
+ <TimelineItem label="Documents uploaded" helperText="Done" state="complete" />
84
+ <TimelineItem label="Verification" helperText="In progress" state="active" />
85
+ <TimelineItem label="Decision" helperText="Pending" state="incomplete" />
86
+ </Timeline>
87
+ <Box style={{ height: 24 }} />
88
+ <Timeline variant="static">
89
+ <TimelineItem label="Collected" helperText="08:15" />
90
+ <TimelineItem label="Sorted" helperText="10:40" />
91
+ <TimelineItem label="Out for delivery" helperText="13:25" />
92
+ </Timeline>
93
+ </Box>
94
+ </Center>
95
+ </UsageWrap>
96
+
97
+ ```tsx
98
+ import { Box, Timeline, TimelineItem } from '@utilitywarehouse/hearth-react-native';
99
+
100
+ const MyComponent = () => (
101
+ <Box>
102
+ <Timeline variant="progress">
103
+ <TimelineItem label="Account created" helperText="Done" state="complete" />
104
+ <TimelineItem label="Documents uploaded" helperText="Done" state="complete" />
105
+ <TimelineItem label="Verification" helperText="In progress" state="active" />
106
+ <TimelineItem label="Decision" helperText="Pending" state="incomplete" />
107
+ </Timeline>
108
+
109
+ <Timeline variant="static">
110
+ <TimelineItem label="Collected" helperText="08:15" />
111
+ <TimelineItem label="Sorted" helperText="10:40" />
112
+ <TimelineItem label="Out for delivery" helperText="13:25" />
113
+ </Timeline>
114
+ </Box>
115
+ );
116
+ ```
117
+
118
+ ### Custom Content
119
+
120
+ <UsageWrap>
121
+ <Center>
122
+ <Box style={{ width: 320 }}>
123
+ <Timeline variant="progress">
124
+ <TimelineItem
125
+ label="Application started"
126
+ helperText="We have saved your draft"
127
+ state="complete"
128
+ />
129
+ <TimelineItem label="Additional information" helperText="Action needed" state="active">
130
+ <Card variant="subtle" spacing="md">
131
+ <Badge>Required</Badge>
132
+ <Box>
133
+ <BodyText size="sm">Upload proof of address to continue.</BodyText>
134
+ </Box>
135
+ </Card>
136
+ </TimelineItem>
137
+ <TimelineItem label="Review complete" helperText="Pending" state="incomplete" />
138
+ </Timeline>
139
+ </Box>
140
+ </Center>
141
+ </UsageWrap>
142
+
143
+ ```tsx
144
+ import {
145
+ Badge,
146
+ BodyText,
147
+ Box,
148
+ Card,
149
+ Timeline,
150
+ TimelineItem,
151
+ } from '@utilitywarehouse/hearth-react-native';
152
+
153
+ const MyComponent = () => (
154
+ <Timeline variant="progress">
155
+ <TimelineItem
156
+ label="Application started"
157
+ helperText="We have saved your draft"
158
+ state="complete"
159
+ />
160
+ <TimelineItem label="Additional information" helperText="Action needed" state="active">
161
+ <Card variant="subtle" spacing="md">
162
+ <Badge>Required</Badge>
163
+ <BodyText size="sm">Upload proof of address to continue.</BodyText>
164
+ </Card>
165
+ </TimelineItem>
166
+ <TimelineItem label="Review complete" helperText="Pending" state="incomplete" />
167
+ </Timeline>
168
+ );
169
+ ```
170
+
171
+ ## Accessibility
172
+
173
+ Timeline uses `accessibilityRole="list"` on the root so assistive technologies can understand the sequence as a grouped set of steps.
174
+
175
+ Each `TimelineItem` exposes a combined accessibility label made up of the label, helper text, and progress state when the progress variant is used.
176
+
177
+ When you provide custom content, make sure any interactive elements inside that content have their own accessible labels and hints. The timeline item itself is announced, but nested actions still need explicit accessibility metadata when they are actionable.
@@ -0,0 +1,89 @@
1
+ import figma from '@figma/code-connect';
2
+ import { Timeline, TimelineItem } from '.';
3
+
4
+ figma.connect(
5
+ Timeline,
6
+ 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=10592-5483&t=pZwKJYFo1y1QRQD1-4',
7
+ {
8
+ props: {
9
+ items: figma.children('Progress'),
10
+ },
11
+ variant: {
12
+ Variant: 'Progress',
13
+ },
14
+ example: props => <Timeline variant="progress">{props.items}</Timeline>,
15
+ }
16
+ );
17
+
18
+ figma.connect(
19
+ Timeline,
20
+ 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=10592-5483&t=pZwKJYFo1y1QRQD1-4',
21
+ {
22
+ props: {
23
+ items: figma.children('Static'),
24
+ },
25
+ variant: {
26
+ Variant: 'Static',
27
+ },
28
+ example: props => <Timeline variant="static">{props.items}</Timeline>,
29
+ }
30
+ );
31
+
32
+ figma.connect(
33
+ TimelineItem,
34
+ 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=10562-2810&t=pZwKJYFo1y1QRQD1-4',
35
+ {
36
+ props: {
37
+ label: figma.string('Label'),
38
+ helperText: figma.boolean('Helper text?', { true: figma.string('Helper text') }),
39
+ state: figma.enum('State', {
40
+ Complete: 'complete',
41
+ Active: 'active',
42
+ Incomplete: 'incomplete',
43
+ }),
44
+ customContent: figma.boolean('Custom content?', {
45
+ true: figma.instance('Slot'),
46
+ }),
47
+ },
48
+ example: props => (
49
+ <TimelineItem
50
+ variant="progress"
51
+ position="middle"
52
+ label={props.label}
53
+ helperText={props.helperText}
54
+ state={props.state}
55
+ >
56
+ {props.customContent}
57
+ </TimelineItem>
58
+ ),
59
+ }
60
+ );
61
+
62
+ figma.connect(
63
+ TimelineItem,
64
+ 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=10592-5189&t=pZwKJYFo1y1QRQD1-4',
65
+ {
66
+ props: {
67
+ label: figma.string('Label'),
68
+ helperText: figma.boolean('Helper text?', { true: figma.string('Helper text') }),
69
+ customContent: figma.boolean('Custom content?', {
70
+ true: figma.instance('Slot'),
71
+ }),
72
+ position: figma.enum('Variant', {
73
+ Start: 'start',
74
+ Middle: 'middle',
75
+ End: 'end',
76
+ }),
77
+ },
78
+ example: props => (
79
+ <TimelineItem
80
+ variant="static"
81
+ position={props.position}
82
+ label={props.label}
83
+ helperText={props.helperText}
84
+ >
85
+ {props.customContent}
86
+ </TimelineItem>
87
+ ),
88
+ }
89
+ );
@@ -0,0 +1,51 @@
1
+ import { ViewProps } from 'react-native';
2
+
3
+ export type TimelineVariant = 'static' | 'progress';
4
+ export type TimelineItemState = 'complete' | 'active' | 'incomplete';
5
+ export type TimelineItemPosition = 'single' | 'start' | 'middle' | 'end';
6
+
7
+ export interface TimelineProps extends ViewProps {
8
+ /**
9
+ * Child TimelineItem components.
10
+ */
11
+ children: React.ReactNode;
12
+ /**
13
+ * Controls the indicator style used by all child timeline items.
14
+ * @default 'static'
15
+ */
16
+ variant?: TimelineVariant;
17
+ }
18
+
19
+ export interface TimelineItemProps extends ViewProps {
20
+ /**
21
+ * The primary label for the timeline item.
22
+ */
23
+ label: string;
24
+ /**
25
+ * Optional supporting text displayed beneath the label.
26
+ */
27
+ helperText?: string;
28
+ /**
29
+ * Visual state for progress timelines.
30
+ * @default 'incomplete'
31
+ */
32
+ state?: TimelineItemState;
33
+ /**
34
+ * Optional custom content rendered beneath the text content.
35
+ */
36
+ children?: React.ReactNode;
37
+ /**
38
+ * The timeline variant used when the item is rendered standalone.
39
+ * Items inside Timeline receive this automatically.
40
+ * @default 'static'
41
+ */
42
+ variant?: TimelineVariant;
43
+ /**
44
+ * The item's position in the timeline used to draw connectors.
45
+ * Items inside Timeline receive this automatically.
46
+ * @default 'single'
47
+ */
48
+ position?: TimelineItemPosition;
49
+ }
50
+
51
+ export default TimelineProps;