Skip to content

Commit 513b488

Browse files
committed
feat: implement alternative positioning
1 parent f7176c6 commit 513b488

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

src/components/Timeline.css

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
}
1414

1515
.timeline__line {
16+
position: absolute;
1617
background-color: var(--timeline-line-color);
1718
width: var(--timeline-line-width);
1819
height: 100%;
19-
margin-inline: auto;
20+
left: 50%;
21+
transform: translateX(-50%);
2022
}
2123

2224
.timeline-item {
@@ -99,3 +101,25 @@
99101
.timeline-item--left .timeline-item__marker {
100102
order: 1;
101103
}
104+
105+
/* left positioning */
106+
.timeline--left .timeline__line {
107+
left: 0;
108+
}
109+
110+
.timeline--left .timeline-item--right {
111+
left: 0;
112+
width: 100%;
113+
}
114+
115+
/* right positioning */
116+
.timeline--right .timeline__line {
117+
right: 0;
118+
left: unset;
119+
transform: translateX(50%);
120+
}
121+
122+
.timeline--right .timeline-item--left {
123+
right: 0;
124+
width: 100%;
125+
}

src/components/Timeline.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import './Timeline.css';
22
import { Key, useEffect, useRef } from 'react';
33
import { PropsWithKey, TimelineItem, TimelineItemProps } from './TimelineItem';
44
import { OffsetConfig, resolveOffsets } from '../models/offset';
5+
import { Positioning } from '../models/positioning';
56

67
export type TimelineProps = {
78
items: PropsWithKey<TimelineItemProps>[];
9+
positioning: Positioning;
810
gap?: number;
911
offset?: OffsetConfig;
1012
minMarkerGap?: number;
@@ -14,14 +16,15 @@ export type TimelineProps = {
1416
};
1517

1618
const defaultTimelineConfig: Partial<TimelineProps> = {
19+
positioning: 'alternating',
1720
gap: 50,
1821
offset: 50,
1922
minMarkerGap: 50,
2023
dateFormat: 'P',
2124
};
2225

2326
export function Timeline(props: TimelineProps) {
24-
const { items, gap, offset, minMarkerGap, className, dateFormat, dateLocale } = { ...defaultTimelineConfig, ...props };
27+
const { items, positioning, gap, offset, minMarkerGap, className, dateFormat, dateLocale } = { ...defaultTimelineConfig, ...props };
2528

2629
const timelineRef = useRef<HTMLDivElement>(null);
2730
const itemsRef = useRef<Map<Key, HTMLElement>>();
@@ -54,7 +57,7 @@ export function Timeline(props: TimelineProps) {
5457
elements.forEach((item) => {
5558
const element = item;
5659

57-
if (leftHeight > rightHeight) {
60+
if ((positioning !== 'right' && leftHeight > rightHeight) || positioning === 'left') {
5861
leftHeight += getMinMarkerGapCompensation(leftHeight, rightHeight);
5962

6063
element.style.top = `${rightHeight}px`;
@@ -84,7 +87,7 @@ export function Timeline(props: TimelineProps) {
8487
useEffect(positionTimelineItems, [itemsRef]);
8588

8689
return (
87-
<div className={['timeline', className].join(' ')} ref={timelineRef}>
90+
<div className={['timeline', `timeline--${positioning}`, className].join(' ')} ref={timelineRef}>
8891
<div className="timeline__line" />
8992
{items.map((item) => (
9093
<TimelineItem

src/models/positioning.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type Positioning = 'left' | 'right' | 'alternating';

0 commit comments

Comments
 (0)