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`] = `