Skip to content

Commit

Permalink
Merge ee0ad14 into 8cc14f7
Browse files Browse the repository at this point in the history
  • Loading branch information
francinelucca authored Nov 5, 2024
2 parents 8cc14f7 + ee0ad14 commit 8ca70c0
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 104 deletions.
5 changes: 5 additions & 0 deletions .changeset/famous-trainers-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": minor
---

fix(Timeline): render as unordered list
1 change: 1 addition & 0 deletions packages/react/src/FeatureFlags/DefaultFeatureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export const DefaultFeatureFlags = FeatureFlagScope.create({
primer_react_action_list_item_as_button: false,
primer_react_select_panel_with_modern_action_list: false,
primer_react_overlay_overflow: false,
primer_react_timeline_as_list: false,
})
4 changes: 4 additions & 0 deletions packages/react/src/Timeline/Timeline.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
"type": "SystemStyleObject"
}
]
},
{
"name": "Timeline.Group",
"props": []
}
]
}
139 changes: 79 additions & 60 deletions packages/react/src/Timeline/Timeline.features.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Timeline from './Timeline'
import Octicon from '../Octicon'
import {GitBranchIcon, GitCommitIcon, GitMergeIcon} from '@primer/octicons-react'
import Link from '../Link'
import {FeatureFlags} from '../FeatureFlags'

export default {
title: 'Components/Timeline/Features',
Expand All @@ -18,73 +19,91 @@ export default {
} as Meta<ComponentProps<typeof Timeline>>

export const ClipSidebar = () => (
<Timeline clipSidebar>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline>
<FeatureFlags flags={{primer_react_timeline_as_list: true}}>
<Timeline clipSidebar>
<Timeline.Group>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline.Group>
</Timeline>
</FeatureFlags>
)

export const CondensedItems = () => (
<Timeline>
<Timeline.Item condensed>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item condensed>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline>
<FeatureFlags flags={{primer_react_timeline_as_list: true}}>
<Timeline>
<Timeline.Group>
<Timeline.Item condensed>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item condensed>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline.Group>
</Timeline>
</FeatureFlags>
)

export const TimelineBreak = () => (
<Timeline>
<Timeline.Item>
<Timeline.Badge sx={{bg: 'done.emphasis'}}>
<Octicon icon={GitMergeIcon} color="fg.onEmphasis" aria-label="Merged" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Break />
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitBranchIcon} aria-label="Branch" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline>
<FeatureFlags flags={{primer_react_timeline_as_list: true}}>
<Timeline>
<Timeline.Group>
<Timeline.Item>
<Timeline.Badge sx={{bg: 'done.emphasis'}}>
<Octicon icon={GitMergeIcon} color="fg.onEmphasis" aria-label="Merged" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline.Group>
<Timeline.Break />
<Timeline.Group>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitBranchIcon} aria-label="Branch" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline.Group>
</Timeline>
</FeatureFlags>
)

export const WithInlineLinks = () => (
<Timeline>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>
<Link
href="#"
sx={{fontWeight: 'bold', color: 'fg.default', mr: 1, '&:hover': {color: 'var(--fgColor-accent)'}}}
muted
>
Monalisa
</Link>
enabled auto-merge (squash)
</Timeline.Body>
</Timeline.Item>
</Timeline>
<FeatureFlags flags={{primer_react_timeline_as_list: true}}>
<Timeline>
<Timeline.Group>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>
<Link
href="#"
sx={{fontWeight: 'bold', color: 'fg.default', mr: 1, '&:hover': {color: 'var(--fgColor-accent)'}}}
muted
>
Monalisa
</Link>
enabled auto-merge (squash)
</Timeline.Body>
</Timeline.Item>
</Timeline.Group>
</Timeline>
</FeatureFlags>
)
89 changes: 49 additions & 40 deletions packages/react/src/Timeline/Timeline.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {ComponentProps} from '../utils/types'
import Timeline from './Timeline'
import Octicon from '../Octicon'
import {GitCommitIcon} from '@primer/octicons-react'
import {FeatureFlags} from '../FeatureFlags'

export default {
title: 'Components/Timeline',
Expand All @@ -17,49 +18,57 @@ export default {
} as Meta<ComponentProps<typeof Timeline>>

export const Default = () => (
<Timeline>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline>
<FeatureFlags flags={{primer_react_timeline_as_list: true}}>
<Timeline>
<Timeline.Group>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline.Group>
</Timeline>
</FeatureFlags>
)

export const Playground: StoryFn<ComponentProps<typeof Timeline>> = args => (
<Timeline {...args}>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline>
<FeatureFlags flags={{primer_react_timeline_as_list: true}}>
<Timeline {...args}>
<Timeline.Group>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
<Timeline.Item>
<Timeline.Badge>
<Octicon icon={GitCommitIcon} aria-label="Commit" />
</Timeline.Badge>
<Timeline.Body>This is a message</Timeline.Body>
</Timeline.Item>
</Timeline.Group>
</Timeline>
</FeatureFlags>
)

Playground.args = {
Expand Down
47 changes: 44 additions & 3 deletions packages/react/src/Timeline/Timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,20 @@ import {get} from '../constants'
import type {SxProp} from '../sx'
import sx from '../sx'
import type {ComponentProps} from '../utils/types'
import {useFeatureFlag} from '../FeatureFlags'
import {warning} from '../utils/warning'

const Timeline = styled.div<{clipSidebar?: boolean} & SxProp>`
display: flex;
flex-direction: column;
list-style: none;
.Timeline-Group {
padding-inline-start: 0;
margin-block-start: 0;
margin-block-end: 0;
}
${props =>
props.clipSidebar &&
css`
Expand All @@ -27,7 +37,7 @@ const Timeline = styled.div<{clipSidebar?: boolean} & SxProp>`

type StyledTimelineItemProps = {condensed?: boolean} & SxProp

const TimelineItem = styled.div.attrs<StyledTimelineItemProps>(props => ({
const StyledTimelineItem = styled.div.attrs<StyledTimelineItemProps>(props => ({
className: clsx('Timeline-Item', props.className),
}))<StyledTimelineItemProps>`
display: flex;
Expand Down Expand Up @@ -68,6 +78,16 @@ const TimelineItem = styled.div.attrs<StyledTimelineItemProps>(props => ({
${sx};
`

export type TimelineItemsProps<As extends React.ElementType> = {
as?: As
} & SxProp &
React.ComponentProps<As>

function TimelineItem<As extends React.ElementType>(props: TimelineItemsProps<As>) {
const asList = useFeatureFlag('primer_react_timeline_as_list')
return <StyledTimelineItem as={asList ? 'li' : 'div'} {...props} />
}

export type TimelineBadgeProps = {children?: React.ReactNode} & SxProp

const TimelineBadge = (props: TimelineBadgeProps) => {
Expand Down Expand Up @@ -108,7 +128,7 @@ const TimelineBody = styled.div<SxProp>`
${sx};
`

const TimelineBreak = styled.div<SxProp>`
const StyledTimelineBreak = styled.div<SxProp>`
position: relative;
z-index: 1;
height: 24px;
Expand All @@ -121,6 +141,26 @@ const TimelineBreak = styled.div<SxProp>`
${sx};
`

function TimelineBreak(props: ComponentProps<typeof StyledTimelineBreak>) {
const asList = useFeatureFlag('primer_react_timeline_as_list')
return <StyledTimelineBreak aria-hidden={asList ? true : undefined} {...props} />
}

function TimelineGroup({children, ...props}: React.ComponentPropsWithoutRef<'ul'>) {
const asList = useFeatureFlag('primer_react_timeline_as_list')
warning(
!asList,
`Timeline.Group is only meant to be used with the timeline as list feature, you may want to turn on the 'primer_react_timeline_as_list' feature flag. Using Timeline.Group without this feature may have unintended consequences`,
)
return (
<Box as={asList ? 'ul' : 'div'} className="Timeline-Group" {...props}>
{children}
</Box>
)
}

TimelineGroup.displayName = 'Timeline.Group'

TimelineItem.displayName = 'Timeline.Item'

TimelineBadge.displayName = 'Timeline.Badge'
Expand All @@ -130,12 +170,13 @@ TimelineBody.displayName = 'Timeline.Body'
TimelineBreak.displayName = 'Timeline.Break'

export type TimelineProps = ComponentProps<typeof Timeline>
export type TimelineItemsProps = ComponentProps<typeof TimelineItem>
export type TimelineBodyProps = ComponentProps<typeof TimelineBody>
export type TimelineBreakProps = ComponentProps<typeof TimelineBreak>
export type TimelineGroupProps = ComponentProps<typeof TimelineGroup>
export default Object.assign(Timeline, {
Item: TimelineItem,
Badge: TimelineBadge,
Body: TimelineBody,
Break: TimelineBreak,
Group: TimelineGroup,
})
Loading

0 comments on commit 8ca70c0

Please sign in to comment.