Skip to content

Commit e93b4e6

Browse files
committed
feat(timeline): add interactive title
1 parent cddfffd commit e93b4e6

File tree

3 files changed

+99
-14
lines changed

3 files changed

+99
-14
lines changed

packages/paste-core/components/timeline/src/TimelineItem.tsx

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { Box } from "@twilio-paste/box";
2+
import { Button } from "@twilio-paste/button";
23
import { css, styled } from "@twilio-paste/styling-library";
4+
import { Text } from "@twilio-paste/text";
5+
import { Truncate } from "@twilio-paste/truncate";
36
import React from "react";
47

58
import { TimelineGroupContext } from "./TimelineContext";
@@ -9,7 +12,18 @@ import type { TimelineItemProps } from "./types";
912

1013
const TimelineItem = React.forwardRef<HTMLLIElement, TimelineItemProps>(
1114
(
12-
{ children, icon, timestamp, title, collapsible = false, collapsibleHeading, element = "TIMELINE_ITEM", ...props },
15+
{
16+
children,
17+
icon,
18+
timestamp,
19+
title,
20+
collapsible = false,
21+
collapsibleHeading,
22+
element = "TIMELINE_ITEM",
23+
onClick,
24+
disabled,
25+
...props
26+
},
1327
ref,
1428
) => {
1529
const isGrouped = React.useContext(TimelineGroupContext);
@@ -63,18 +77,39 @@ const TimelineItem = React.forwardRef<HTMLLIElement, TimelineItemProps>(
6377
columnGap="space10"
6478
paddingBottom="space60"
6579
>
66-
<Box
67-
element={`${element}_TITLE`}
68-
as="span"
69-
color="colorText"
70-
paddingY="space10"
71-
fontWeight="fontWeightSemibold"
72-
lineHeight="lineHeight20"
73-
fontSize="fontSize30"
74-
letterSpacing="-0.28px"
75-
>
76-
{title}
77-
</Box>
80+
{onClick ? (
81+
<Button
82+
element={`${element}_TITLE_INTERACTIVE`}
83+
variant="reset"
84+
size="reset"
85+
onClick={onClick}
86+
textDecoration="underline"
87+
paddingY="space10"
88+
fontWeight="fontWeightSemibold"
89+
lineHeight="lineHeight20"
90+
fontSize="fontSize30"
91+
letterSpacing="-0.28px"
92+
_hover={{ color: "colorTextLink" }}
93+
_focus={{ color: "colorTextLink", boxShadow: "shadowFocus" }}
94+
_disabled={{ color: "colorTextWeaker" }}
95+
disabled={disabled}
96+
>
97+
<Truncate title={title}>{title}</Truncate>
98+
</Button>
99+
) : (
100+
<Box
101+
element={`${element}_TITLE`}
102+
as="span"
103+
color="colorText"
104+
paddingY="space10"
105+
fontWeight="fontWeightSemibold"
106+
lineHeight="lineHeight20"
107+
fontSize="fontSize30"
108+
letterSpacing="-0.28px"
109+
>
110+
{title}
111+
</Box>
112+
)}
78113

79114
{collapsible ? (
80115
<TimelineItemCollapsible element={element} timestamp={timestamp ? timestamp : collapsibleHeading}>
@@ -94,7 +129,7 @@ const TimelineItem = React.forwardRef<HTMLLIElement, TimelineItemProps>(
94129
{timestamp}
95130
</Box>
96131
) : null}
97-
<Box element={`${element}_CONTENT`}>{children}</Box>
132+
{children ? <Box element={`${element}_CONTENT`}>{children}</Box> : null}
98133
</>
99134
)}
100135
</Box>

packages/paste-core/components/timeline/src/types.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,24 @@ export type TimelineItemProps = {
6666
* @memberof TimelineItemProps
6767
*/
6868
element?: BoxProps["element"];
69+
70+
/**
71+
* Add an action to the timeline item.
72+
*
73+
* @default undefined
74+
* @type {React.MouseEventHandler<HTMLButtonElement>}
75+
* @memberof TimelineItemProps
76+
*/
77+
onClick?: React.MouseEventHandler<HTMLButtonElement>;
78+
79+
/**
80+
* If true, the timeline item will be disabled
81+
*
82+
* @type {boolean}
83+
* @memberof TimelineItemProps
84+
* @default false
85+
*/
86+
disabled?: boolean;
6987
} & HTMLPasteProps<"li">;
7088

7189
export type TimelineItemIconProps = {

packages/paste-core/components/timeline/stories/index.stories.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,38 @@ export const TimelineGrouped = (): React.ReactNode => {
103103
);
104104
};
105105

106+
export const TimelineInteractive = (): React.ReactNode => {
107+
return (
108+
<Box maxWidth="200px">
109+
<Timeline>
110+
<TimelineItemGroup timestamp="Today – Wednesday, April 9, 2025">
111+
<TimelineItem title="Invoice billing issue for March cycle resolved" timestamp="9:12 AM" onClick={() => {}} />
112+
<TimelineItem
113+
title="Clarification on service tier limits for standard accounts"
114+
timestamp="11:26 AM"
115+
onClick={() => {}}
116+
/>
117+
<TimelineItem title="New user onboarding questions and setup steps" timestamp="1:45 PM" onClick={() => {}} />
118+
</TimelineItemGroup>
119+
<TimelineItemGroup timestamp="Yesterday – Tuesday, April 8, 2025">
120+
<TimelineItem
121+
title="Account verification delay and next steps discussed"
122+
timestamp="10:15 AM"
123+
onClick={() => {}}
124+
/>
125+
<TimelineItem title="Custom domain setup assistance provided" timestamp="4:38 PM" onClick={() => {}} />
126+
<TimelineItem
127+
title="Request to add additional admins to workspace"
128+
timestamp="6:09 PM"
129+
onClick={() => {}}
130+
disabled
131+
/>
132+
</TimelineItemGroup>
133+
</Timeline>
134+
</Box>
135+
);
136+
};
137+
106138
const allItems = [
107139
{ date: "August 10, 2024", text: "Event title" },
108140
{ date: "August 11, 2024", text: "Event title" },

0 commit comments

Comments
 (0)