|
1 | 1 | import {clsx} from 'clsx'
|
2 |
| -import React, {type HTMLProps} from 'react' |
3 |
| -import styled, {css} from 'styled-components' |
| 2 | +import React from 'react' |
4 | 3 | import Box from '../Box'
|
5 |
| -import {get} from '../constants' |
6 | 4 | import type {SxProp} from '../sx'
|
7 |
| -import sx from '../sx' |
8 |
| -import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent' |
9 |
| -import {useFeatureFlag} from '../FeatureFlags' |
10 | 5 | import classes from './Timeline.module.css'
|
11 | 6 | import {defaultSxProp} from '../utils/defaultSxProp'
|
12 | 7 |
|
13 |
| -const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_ga' |
14 |
| - |
15 | 8 | type StyledTimelineProps = {clipSidebar?: boolean; className?: string} & SxProp
|
16 | 9 |
|
17 |
| -const ToggleTimeline = toggleStyledComponent( |
18 |
| - CSS_MODULES_FEATURE_FLAG, |
19 |
| - 'div', |
20 |
| - styled.div<StyledTimelineProps>` |
21 |
| - display: flex; |
22 |
| - flex-direction: column; |
23 |
| - ${props => |
24 |
| - props.clipSidebar && |
25 |
| - css` |
26 |
| - .Timeline-Item:first-child { |
27 |
| - padding-top: 0; |
28 |
| - } |
29 |
| -
|
30 |
| - .Timeline-Item:last-child { |
31 |
| - padding-bottom: 0; |
32 |
| - } |
33 |
| - `} |
34 |
| -
|
35 |
| - ${sx}; |
36 |
| - `, |
37 |
| -) |
| 10 | +export type TimelineProps = StyledTimelineProps & React.ComponentPropsWithoutRef<'div'> |
38 | 11 |
|
39 |
| -export type TimelineProps = StyledTimelineProps & HTMLProps<HTMLDivElement> |
| 12 | +const Timeline = React.forwardRef<HTMLDivElement, TimelineProps>( |
| 13 | + ({clipSidebar, className, sx: sxProp = defaultSxProp, ...props}, forwardRef) => { |
| 14 | + if (sxProp !== defaultSxProp) { |
| 15 | + return ( |
| 16 | + <Box |
| 17 | + as="div" |
| 18 | + sx={sxProp} |
| 19 | + {...props} |
| 20 | + className={clsx(className, classes.Timeline)} |
| 21 | + ref={forwardRef} |
| 22 | + data-clip-sidebar={clipSidebar ? '' : undefined} |
| 23 | + /> |
| 24 | + ) |
| 25 | + } |
40 | 26 |
|
41 |
| -const Timeline = React.forwardRef<HTMLElement, TimelineProps>(function Timeline( |
42 |
| - {clipSidebar, className, ...props}, |
43 |
| - forwardRef, |
44 |
| -) { |
45 |
| - const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG) |
46 |
| - if (enabled) { |
47 | 27 | return (
|
48 |
| - <ToggleTimeline |
| 28 | + <div |
49 | 29 | {...props}
|
50 | 30 | className={clsx(className, classes.Timeline)}
|
51 | 31 | ref={forwardRef}
|
52 | 32 | data-clip-sidebar={clipSidebar ? '' : undefined}
|
53 | 33 | />
|
54 | 34 | )
|
55 |
| - } |
56 |
| - |
57 |
| - return <ToggleTimeline {...props} className={className} ref={forwardRef} clipSidebar={clipSidebar} /> |
58 |
| -}) |
| 35 | + }, |
| 36 | +) |
59 | 37 |
|
60 | 38 | Timeline.displayName = 'Timeline'
|
61 | 39 |
|
62 | 40 | type StyledTimelineItemProps = {condensed?: boolean; className?: string} & SxProp
|
63 | 41 |
|
64 |
| -const ToggleTimelineItem = toggleStyledComponent( |
65 |
| - CSS_MODULES_FEATURE_FLAG, |
66 |
| - 'div', |
67 |
| - styled.div.attrs<StyledTimelineItemProps>(props => ({ |
68 |
| - className: clsx('Timeline-Item', props.className), |
69 |
| - }))<StyledTimelineItemProps>` |
70 |
| - display: flex; |
71 |
| - position: relative; |
72 |
| - padding: ${get('space.3')} 0; |
73 |
| - margin-left: ${get('space.3')}; |
74 |
| -
|
75 |
| - &::before { |
76 |
| - position: absolute; |
77 |
| - top: 0; |
78 |
| - bottom: 0; |
79 |
| - left: 0; |
80 |
| - display: block; |
81 |
| - width: 2px; |
82 |
| - content: ''; |
83 |
| - background-color: ${get('colors.border.muted')}; |
84 |
| - } |
85 |
| -
|
86 |
| - ${props => |
87 |
| - props.condensed && |
88 |
| - css` |
89 |
| - padding-top: ${get('space.1')}; |
90 |
| - padding-bottom: 0; |
91 |
| - &:last-child { |
92 |
| - padding-bottom: ${get('space.3')}; |
93 |
| - } |
94 |
| -
|
95 |
| - .TimelineItem-Badge { |
96 |
| - height: 16px; |
97 |
| - margin-top: ${get('space.2')}; |
98 |
| - margin-bottom: ${get('space.2')}; |
99 |
| - color: ${get('colors.fg.muted')}; |
100 |
| - background-color: ${get('colors.canvas.default')}; |
101 |
| - border: 0; |
102 |
| - } |
103 |
| - `} |
104 |
| -
|
105 |
| - ${sx}; |
106 |
| - `, |
107 |
| -) |
108 |
| - |
109 | 42 | /**
|
110 | 43 | * @deprecated Use the `TimelineItemProps` type instead
|
111 | 44 | */
|
112 |
| -export type TimelineItemsProps = StyledTimelineItemProps & HTMLProps<HTMLDivElement> |
| 45 | +export type TimelineItemsProps = StyledTimelineItemProps & SxProp & React.ComponentPropsWithoutRef<'div'> |
113 | 46 |
|
114 |
| -export type TimelineItemProps = StyledTimelineItemProps & HTMLProps<HTMLDivElement> |
| 47 | +export type TimelineItemProps = StyledTimelineItemProps & SxProp & React.ComponentPropsWithoutRef<'div'> |
115 | 48 |
|
116 |
| -const TimelineItem = React.forwardRef<HTMLElement, TimelineItemProps>(function TimelineItem( |
117 |
| - {condensed, className, ...props}, |
118 |
| - forwardRef, |
119 |
| -) { |
120 |
| - const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG) |
121 |
| - if (enabled) { |
| 49 | +const TimelineItem = React.forwardRef<HTMLDivElement, TimelineItemProps>( |
| 50 | + ({condensed, className, sx: sxProp = defaultSxProp, ...props}, forwardRef) => { |
| 51 | + if (sxProp !== defaultSxProp) { |
| 52 | + return ( |
| 53 | + <Box |
| 54 | + as="div" |
| 55 | + {...props} |
| 56 | + className={clsx(className, 'Timeline-Item', classes.TimelineItem)} |
| 57 | + ref={forwardRef} |
| 58 | + data-condensed={condensed ? '' : undefined} |
| 59 | + sx={sxProp} |
| 60 | + /> |
| 61 | + ) |
| 62 | + } |
122 | 63 | return (
|
123 |
| - <ToggleTimelineItem |
| 64 | + <div |
124 | 65 | {...props}
|
125 |
| - className={clsx(className, classes.TimelineItem)} |
| 66 | + className={clsx(className, 'Timeline-Item', classes.TimelineItem)} |
126 | 67 | ref={forwardRef}
|
127 | 68 | data-condensed={condensed ? '' : undefined}
|
128 | 69 | />
|
129 | 70 | )
|
130 |
| - } |
131 |
| - |
132 |
| - return <ToggleTimelineItem {...props} className={className} ref={forwardRef} condensed={condensed} /> |
133 |
| -}) |
| 71 | + }, |
| 72 | +) |
134 | 73 |
|
135 | 74 | TimelineItem.displayName = 'TimelineItem'
|
136 | 75 |
|
137 | 76 | export type TimelineBadgeProps = {children?: React.ReactNode; className?: string} & SxProp &
|
138 | 77 | React.ComponentPropsWithoutRef<'div'>
|
139 | 78 |
|
140 |
| -const TimelineBadge = ({sx, className, ...props}: TimelineBadgeProps) => { |
141 |
| - const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG) |
142 |
| - if (enabled) { |
143 |
| - if (sx !== defaultSxProp) { |
144 |
| - return ( |
145 |
| - <div className={classes.TimelineBadgeWrapper}> |
146 |
| - <Box {...props} sx={sx} className={clsx(className, classes.TimelineBadge)} /> |
147 |
| - </div> |
148 |
| - ) |
149 |
| - } |
| 79 | +const TimelineBadge = ({sx: sxProp = defaultSxProp, className, ...props}: TimelineBadgeProps) => { |
| 80 | + if (sxProp !== defaultSxProp) { |
150 | 81 | return (
|
151 | 82 | <div className={classes.TimelineBadgeWrapper}>
|
152 |
| - <div {...props} className={clsx(className, classes.TimelineBadge)} /> |
| 83 | + <Box {...props} sx={sxProp} className={clsx(className, classes.TimelineBadge)} /> |
153 | 84 | </div>
|
154 | 85 | )
|
155 | 86 | }
|
156 | 87 | return (
|
157 |
| - <Box position="relative" zIndex={1}> |
158 |
| - <Box |
159 |
| - display="flex" |
160 |
| - className="TimelineItem-Badge" |
161 |
| - flexShrink={0} |
162 |
| - borderRadius="50%" |
163 |
| - borderWidth="2px" |
164 |
| - borderStyle="solid" |
165 |
| - borderColor="canvas.default" |
166 |
| - overflow="hidden" |
167 |
| - color="fg.muted" |
168 |
| - bg="timeline.badgeBg" |
169 |
| - width="32px" |
170 |
| - height="32px" |
171 |
| - mr={2} |
172 |
| - ml="-15px" |
173 |
| - alignItems="center" |
174 |
| - justifyContent="center" |
175 |
| - sx={sx} |
176 |
| - > |
177 |
| - {props.children} |
178 |
| - </Box> |
179 |
| - </Box> |
| 88 | + <div className={classes.TimelineBadgeWrapper}> |
| 89 | + <div {...props} className={clsx(className, classes.TimelineBadge)} /> |
| 90 | + </div> |
180 | 91 | )
|
181 | 92 | }
|
182 | 93 |
|
183 | 94 | TimelineBadge.displayName = 'Timeline.Badge'
|
184 | 95 |
|
185 |
| -const ToggleTimelineBody = toggleStyledComponent( |
186 |
| - CSS_MODULES_FEATURE_FLAG, |
187 |
| - 'div', |
188 |
| - styled.div<SxProp>` |
189 |
| - min-width: 0; |
190 |
| - max-width: 100%; |
191 |
| - margin-top: ${get('space.1')}; |
192 |
| - color: ${get('colors.fg.muted')}; |
193 |
| - flex: auto; |
194 |
| - font-size: ${get('fontSizes.1')}; |
195 |
| - ${sx}; |
196 |
| - `, |
197 |
| -) |
198 |
| - |
199 | 96 | export type TimelineBodyProps = {
|
200 | 97 | /** Class name for custom styling */
|
201 | 98 | className?: string
|
202 | 99 | } & SxProp &
|
203 |
| - HTMLProps<HTMLDivElement> |
204 |
| - |
205 |
| -const TimelineBody = React.forwardRef<HTMLElement, TimelineBodyProps>(function TimelineBody( |
206 |
| - {className, ...props}, |
207 |
| - forwardRef, |
208 |
| -) { |
209 |
| - const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG) |
210 |
| - if (enabled) { |
211 |
| - return <ToggleTimelineBody {...props} className={clsx(className, classes.TimelineBody)} ref={forwardRef} /> |
212 |
| - } |
| 100 | + React.ComponentPropsWithoutRef<'div'> |
213 | 101 |
|
214 |
| - return <ToggleTimelineBody {...props} className={className} ref={forwardRef} /> |
215 |
| -}) |
| 102 | +const TimelineBody = React.forwardRef<HTMLDivElement, TimelineBodyProps>( |
| 103 | + ({className, sx: sxProp = defaultSxProp, ...props}, forwardRef) => { |
| 104 | + if (sxProp !== defaultSxProp) { |
| 105 | + return <Box as="div" {...props} className={clsx(className, classes.TimelineBody)} ref={forwardRef} sx={sxProp} /> |
| 106 | + } |
| 107 | + return <div {...props} className={clsx(className, classes.TimelineBody)} ref={forwardRef} /> |
| 108 | + }, |
| 109 | +) |
216 | 110 |
|
217 | 111 | TimelineBody.displayName = 'TimelineBody'
|
218 | 112 |
|
219 |
| -const ToggleTimelineBreak = toggleStyledComponent( |
220 |
| - CSS_MODULES_FEATURE_FLAG, |
221 |
| - 'div', |
222 |
| - styled.div<SxProp>` |
223 |
| - position: relative; |
224 |
| - z-index: 1; |
225 |
| - height: 24px; |
226 |
| - margin: 0; |
227 |
| - margin-bottom: -${get('space.3')}; |
228 |
| - margin-left: 0; |
229 |
| - background-color: ${get('colors.canvas.default')}; |
230 |
| - border: 0; |
231 |
| - border-top: ${get('space.1')} solid ${get('colors.border.default')}; |
232 |
| - ${sx}; |
233 |
| - `, |
234 |
| -) |
235 |
| - |
236 | 113 | export type TimelineBreakProps = {
|
237 | 114 | /** Class name for custom styling */
|
238 | 115 | className?: string
|
239 | 116 | } & SxProp &
|
240 |
| - HTMLProps<HTMLDivElement> |
241 |
| - |
242 |
| -const TimelineBreak = React.forwardRef<HTMLElement, TimelineBreakProps>(function TimelineBreak( |
243 |
| - {className, ...props}, |
244 |
| - forwardRef, |
245 |
| -) { |
246 |
| - const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG) |
247 |
| - if (enabled) { |
248 |
| - return <ToggleTimelineBreak {...props} className={clsx(className, classes.TimelineBreak)} ref={forwardRef} /> |
249 |
| - } |
| 117 | + React.ComponentPropsWithoutRef<'div'> |
250 | 118 |
|
251 |
| - return <ToggleTimelineBreak {...props} className={className} ref={forwardRef} /> |
252 |
| -}) |
| 119 | +const TimelineBreak = React.forwardRef<HTMLDivElement, TimelineBreakProps>( |
| 120 | + ({className, sx: sxProp = defaultSxProp, ...props}, forwardRef) => { |
| 121 | + if (sxProp !== defaultSxProp) { |
| 122 | + return <Box as="div" {...props} className={clsx(className, classes.TimelineBreak)} ref={forwardRef} sx={sxProp} /> |
| 123 | + } |
| 124 | + return <div {...props} className={clsx(className, classes.TimelineBreak)} ref={forwardRef} /> |
| 125 | + }, |
| 126 | +) |
253 | 127 |
|
254 | 128 | TimelineBreak.displayName = 'TimelineBreak'
|
255 | 129 |
|
|
0 commit comments