diff --git a/.changeset/timeline-clip-sidebar-options.md b/.changeset/timeline-clip-sidebar-options.md new file mode 100644 index 00000000000..cef6fe7fdd2 --- /dev/null +++ b/.changeset/timeline-clip-sidebar-options.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Timeline: Update `clipSidebar` prop to accept `'start'`, `'end'`, or `'both'` in addition to `boolean`. Use `'start'` to only clip the top, `'end'` to only clip the bottom, or `'both'`/`true` to clip both ends. diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-colorblind-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-colorblind-linux.png new file mode 100644 index 00000000000..5a46c33fd92 Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-dimmed-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-dimmed-linux.png new file mode 100644 index 00000000000..faf00037b79 Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-high-contrast-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-high-contrast-linux.png new file mode 100644 index 00000000000..b4175de1a6d Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-linux.png new file mode 100644 index 00000000000..5a46c33fd92 Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-tritanopia-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-tritanopia-linux.png new file mode 100644 index 00000000000..5a46c33fd92 Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-colorblind-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-colorblind-linux.png new file mode 100644 index 00000000000..9d796bcccab Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-high-contrast-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-high-contrast-linux.png new file mode 100644 index 00000000000..bbe686da026 Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-linux.png new file mode 100644 index 00000000000..9d796bcccab Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-tritanopia-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-tritanopia-linux.png new file mode 100644 index 00000000000..9d796bcccab Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-End-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-colorblind-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-colorblind-linux.png new file mode 100644 index 00000000000..c8184559bac Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-dimmed-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-dimmed-linux.png new file mode 100644 index 00000000000..57df4b4fbf9 Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-high-contrast-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-high-contrast-linux.png new file mode 100644 index 00000000000..a3a36c6088c Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-linux.png new file mode 100644 index 00000000000..c8184559bac Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-tritanopia-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-tritanopia-linux.png new file mode 100644 index 00000000000..c8184559bac Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-colorblind-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-colorblind-linux.png new file mode 100644 index 00000000000..ceb8cf3d8c0 Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-high-contrast-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-high-contrast-linux.png new file mode 100644 index 00000000000..1e9ead71ceb Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-linux.png new file mode 100644 index 00000000000..ceb8cf3d8c0 Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-linux.png differ diff --git a/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-tritanopia-linux.png b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-tritanopia-linux.png new file mode 100644 index 00000000000..ceb8cf3d8c0 Binary files /dev/null and b/.playwright/snapshots/components/Timeline.test.ts-snapshots/Timeline-Clip-Sidebar-Start-light-tritanopia-linux.png differ diff --git a/e2e/components/Timeline.test.ts b/e2e/components/Timeline.test.ts index ed8a8d4953a..316d88faaf8 100644 --- a/e2e/components/Timeline.test.ts +++ b/e2e/components/Timeline.test.ts @@ -11,6 +11,14 @@ const stories = [ title: 'Clip Sidebar', id: 'components-timeline-features--clip-sidebar', }, + { + title: 'Clip Sidebar Start', + id: 'components-timeline-features--clip-sidebar-start', + }, + { + title: 'Clip Sidebar End', + id: 'components-timeline-features--clip-sidebar-end', + }, { title: 'Condensed Items', id: 'components-timeline-features--condensed-items', diff --git a/packages/react/src/Timeline/Timeline.docs.json b/packages/react/src/Timeline/Timeline.docs.json index 35f24010491..159297b9183 100644 --- a/packages/react/src/Timeline/Timeline.docs.json +++ b/packages/react/src/Timeline/Timeline.docs.json @@ -10,6 +10,12 @@ { "id": "components-timeline-features--clip-sidebar" }, + { + "id": "components-timeline-features--clip-sidebar-start" + }, + { + "id": "components-timeline-features--clip-sidebar-end" + }, { "id": "components-timeline-features--condensed-items" }, @@ -24,8 +30,8 @@ "props": [ { "name": "clipSidebar", - "type": "boolean", - "description": "Hides the sidebar above the first Timeline.Item and below the last Timeline.Item." + "type": "| boolean | 'start' | 'end' | 'both'", + "description": "Controls which ends of the sidebar are clipped. When set to `true` or `'both'`, hides the sidebar above the first and below the last Timeline.Item. Use `'start'` to only clip the top or `'end'` to only clip the bottom." } ], "subcomponents": [ diff --git a/packages/react/src/Timeline/Timeline.features.stories.tsx b/packages/react/src/Timeline/Timeline.features.stories.tsx index c924b48ee7f..b997ad10baf 100644 --- a/packages/react/src/Timeline/Timeline.features.stories.tsx +++ b/packages/react/src/Timeline/Timeline.features.stories.tsx @@ -34,6 +34,40 @@ export const ClipSidebar = () => ( ) +export const ClipSidebarStart = () => ( + + + + + + This is a message + + + + + + This is a message + + +) + +export const ClipSidebarEnd = () => ( + + + + + + This is a message + + + + + + This is a message + + +) + export const CondensedItems = () => ( diff --git a/packages/react/src/Timeline/Timeline.module.css b/packages/react/src/Timeline/Timeline.module.css index f90a195d71b..a841e6b909d 100644 --- a/packages/react/src/Timeline/Timeline.module.css +++ b/packages/react/src/Timeline/Timeline.module.css @@ -2,7 +2,8 @@ display: flex; flex-direction: column; - &:where([data-clip-sidebar]) { + &:where([data-clip-sidebar='start']), + &:where([data-clip-sidebar='both']) { .TimelineItem:first-child { padding-top: 0; @@ -10,7 +11,10 @@ top: var(--base-size-12); } } + } + &:where([data-clip-sidebar='end']), + &:where([data-clip-sidebar='both']) { .TimelineItem:last-child { padding-bottom: 0; diff --git a/packages/react/src/Timeline/Timeline.stories.tsx b/packages/react/src/Timeline/Timeline.stories.tsx index ceb1c5d6db3..fd03321f503 100644 --- a/packages/react/src/Timeline/Timeline.stories.tsx +++ b/packages/react/src/Timeline/Timeline.stories.tsx @@ -72,3 +72,10 @@ Playground.args = { clipSidebar: false, condensed: false, } + +Playground.argTypes = { + clipSidebar: { + control: {type: 'select'}, + options: [false, true, 'start', 'end', 'both'], + }, +} diff --git a/packages/react/src/Timeline/Timeline.tsx b/packages/react/src/Timeline/Timeline.tsx index 772acbbfff8..00ccee8345b 100644 --- a/packages/react/src/Timeline/Timeline.tsx +++ b/packages/react/src/Timeline/Timeline.tsx @@ -2,17 +2,24 @@ import {clsx} from 'clsx' import React from 'react' import classes from './Timeline.module.css' -type StyledTimelineProps = {clipSidebar?: boolean; className?: string} +type StyledTimelineProps = {clipSidebar?: boolean | 'start' | 'end' | 'both'; className?: string} export type TimelineProps = StyledTimelineProps & React.ComponentPropsWithoutRef<'div'> +function resolveClipSidebar(clipSidebar: TimelineProps['clipSidebar']): string | undefined { + if (clipSidebar === true || clipSidebar === 'both') return 'both' + if (clipSidebar === 'start' || clipSidebar === 'end') return clipSidebar + return undefined +} + const Timeline = React.forwardRef(({clipSidebar, className, ...props}, forwardRef) => { + const resolvedClipSidebar = resolveClipSidebar(clipSidebar) return (
) }) diff --git a/packages/react/src/Timeline/__tests__/Timeline.test.tsx b/packages/react/src/Timeline/__tests__/Timeline.test.tsx index 30715ddbef7..11a575a3e09 100644 --- a/packages/react/src/Timeline/__tests__/Timeline.test.tsx +++ b/packages/react/src/Timeline/__tests__/Timeline.test.tsx @@ -7,9 +7,34 @@ import classes from '../Timeline.module.css' describe('Timeline', () => { implementsClassName(Timeline, classes.Timeline) - it('renders with clipSidebar prop', () => { + it('renders with clipSidebar prop (boolean)', () => { const {container} = render() - expect(container).toMatchSnapshot() + expect(container.firstChild).toHaveAttribute('data-clip-sidebar', 'both') + }) + + it('renders with clipSidebar="both"', () => { + const {container} = render() + expect(container.firstChild).toHaveAttribute('data-clip-sidebar', 'both') + }) + + it('renders with clipSidebar="start"', () => { + const {container} = render() + expect(container.firstChild).toHaveAttribute('data-clip-sidebar', 'start') + }) + + it('renders with clipSidebar="end"', () => { + const {container} = render() + expect(container.firstChild).toHaveAttribute('data-clip-sidebar', 'end') + }) + + it('does not render data-clip-sidebar when clipSidebar is false', () => { + const {container} = render() + expect(container.firstChild).not.toHaveAttribute('data-clip-sidebar') + }) + + it('does not render data-clip-sidebar when clipSidebar is not provided', () => { + const {container} = render() + expect(container.firstChild).not.toHaveAttribute('data-clip-sidebar') }) }) diff --git a/packages/react/src/Timeline/__tests__/Timeline.types.test.tsx b/packages/react/src/Timeline/__tests__/Timeline.types.test.tsx index 9e723c6e98d..7d83cad1333 100644 --- a/packages/react/src/Timeline/__tests__/Timeline.types.test.tsx +++ b/packages/react/src/Timeline/__tests__/Timeline.types.test.tsx @@ -12,6 +12,28 @@ export function shouldAcceptCallWithNoProps() { ) } +export function shouldAcceptClipSidebarValues() { + return ( + <> + + + + + + + + ) +} + +export function shouldNotAcceptInvalidClipSidebarValues() { + return ( + <> + {/* @ts-expect-error invalid string value should not be accepted */} + + + ) +} + export function shouldNotAcceptSystemProps() { return ( <> diff --git a/packages/react/src/Timeline/__tests__/__snapshots__/Timeline.test.tsx.snap b/packages/react/src/Timeline/__tests__/__snapshots__/Timeline.test.tsx.snap index 07e7ebe6f73..542aaab3ecf 100644 --- a/packages/react/src/Timeline/__tests__/__snapshots__/Timeline.test.tsx.snap +++ b/packages/react/src/Timeline/__tests__/__snapshots__/Timeline.test.tsx.snap @@ -1,14 +1,5 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`Timeline > renders with clipSidebar prop 1`] = ` -
-
-
-`; - exports[`Timeline.Item > renders with condensed prop 1`] = `