From 9302b398ad4277828fbb42b0c1c95bd91f5f1ca6 Mon Sep 17 00:00:00 2001 From: PixeledCode Date: Wed, 28 May 2025 17:43:32 +0530 Subject: [PATCH 1/8] feat(timeline): add interactive title --- .../components/timeline/src/TimelineItem.tsx | 63 ++++++++++++++----- .../components/timeline/src/types.ts | 18 ++++++ .../timeline/stories/index.stories.tsx | 32 ++++++++++ 3 files changed, 99 insertions(+), 14 deletions(-) diff --git a/packages/paste-core/components/timeline/src/TimelineItem.tsx b/packages/paste-core/components/timeline/src/TimelineItem.tsx index 564e10cffb..ff906ef1ef 100644 --- a/packages/paste-core/components/timeline/src/TimelineItem.tsx +++ b/packages/paste-core/components/timeline/src/TimelineItem.tsx @@ -1,5 +1,8 @@ import { Box } from "@twilio-paste/box"; +import { Button } from "@twilio-paste/button"; import { css, styled } from "@twilio-paste/styling-library"; +import { Text } from "@twilio-paste/text"; +import { Truncate } from "@twilio-paste/truncate"; import React from "react"; import { TimelineGroupContext } from "./TimelineContext"; @@ -9,7 +12,18 @@ import type { TimelineItemProps } from "./types"; const TimelineItem = React.forwardRef( ( - { children, icon, timestamp, title, collapsible = false, collapsibleHeading, element = "TIMELINE_ITEM", ...props }, + { + children, + icon, + timestamp, + title, + collapsible = false, + collapsibleHeading, + element = "TIMELINE_ITEM", + onClick, + disabled, + ...props + }, ref, ) => { const isGrouped = React.useContext(TimelineGroupContext); @@ -63,18 +77,39 @@ const TimelineItem = React.forwardRef( columnGap="space10" paddingBottom="space60" > - - {title} - + {onClick ? ( + + ) : ( + + {title} + + )} {collapsible ? ( @@ -94,7 +129,7 @@ const TimelineItem = React.forwardRef( {timestamp} ) : null} - {children} + {children ? {children} : null} )} diff --git a/packages/paste-core/components/timeline/src/types.ts b/packages/paste-core/components/timeline/src/types.ts index d549f01d5c..053a2d6a6d 100644 --- a/packages/paste-core/components/timeline/src/types.ts +++ b/packages/paste-core/components/timeline/src/types.ts @@ -66,6 +66,24 @@ export type TimelineItemProps = { * @memberof TimelineItemProps */ element?: BoxProps["element"]; + + /** + * Add an action to the timeline item. + * + * @default undefined + * @type {React.MouseEventHandler} + * @memberof TimelineItemProps + */ + onClick?: React.MouseEventHandler; + + /** + * If true, the timeline item will be disabled + * + * @type {boolean} + * @memberof TimelineItemProps + * @default false + */ + disabled?: boolean; } & HTMLPasteProps<"li">; export type TimelineItemIconProps = { diff --git a/packages/paste-core/components/timeline/stories/index.stories.tsx b/packages/paste-core/components/timeline/stories/index.stories.tsx index e20f7b15d4..eca64de291 100644 --- a/packages/paste-core/components/timeline/stories/index.stories.tsx +++ b/packages/paste-core/components/timeline/stories/index.stories.tsx @@ -103,6 +103,38 @@ export const TimelineGrouped = (): React.ReactNode => { ); }; +export const TimelineInteractive = (): React.ReactNode => { + return ( + + + + {}} /> + {}} + /> + {}} /> + + + {}} + /> + {}} /> + {}} + disabled + /> + + + + ); +}; + const allItems = [ { date: "August 10, 2024", text: "Event title" }, { date: "August 11, 2024", text: "Event title" }, From 8d59625a72c3c1afcf374ed084614bd8d8d55143 Mon Sep 17 00:00:00 2001 From: PixeledCode Date: Wed, 28 May 2025 19:50:21 +0530 Subject: [PATCH 2/8] feat(timeline): update width of content wrapper --- packages/paste-core/components/timeline/src/TimelineItem.tsx | 2 ++ .../paste-core/components/timeline/src/TimelineItemGroup.tsx | 2 +- .../paste-core/components/timeline/stories/index.stories.tsx | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/paste-core/components/timeline/src/TimelineItem.tsx b/packages/paste-core/components/timeline/src/TimelineItem.tsx index ff906ef1ef..e1d25a1aca 100644 --- a/packages/paste-core/components/timeline/src/TimelineItem.tsx +++ b/packages/paste-core/components/timeline/src/TimelineItem.tsx @@ -76,6 +76,7 @@ const TimelineItem = React.forwardRef( flexDirection="column" columnGap="space10" paddingBottom="space60" + width="100%" > {onClick ? ( diff --git a/packages/paste-core/components/timeline/src/TimelineItemGroup.tsx b/packages/paste-core/components/timeline/src/TimelineItemGroup.tsx index 4188abef0e..3024f2112d 100644 --- a/packages/paste-core/components/timeline/src/TimelineItemGroup.tsx +++ b/packages/paste-core/components/timeline/src/TimelineItemGroup.tsx @@ -30,7 +30,7 @@ export const TimelineItemGroup = React.forwardRef - + {timestamp} diff --git a/packages/paste-core/components/timeline/stories/index.stories.tsx b/packages/paste-core/components/timeline/stories/index.stories.tsx index eca64de291..a3fb6deeac 100644 --- a/packages/paste-core/components/timeline/stories/index.stories.tsx +++ b/packages/paste-core/components/timeline/stories/index.stories.tsx @@ -105,7 +105,7 @@ export const TimelineGrouped = (): React.ReactNode => { export const TimelineInteractive = (): React.ReactNode => { return ( - + {}} /> From 7953cd4d1997b9655861fb0721f1457de4fac00f Mon Sep 17 00:00:00 2001 From: PixeledCode Date: Wed, 28 May 2025 19:51:02 +0530 Subject: [PATCH 3/8] feat(timeline): add typedocs --- .../components/timeline/type-docs.json | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/paste-core/components/timeline/type-docs.json b/packages/paste-core/components/timeline/type-docs.json index a91117a0c2..843e4acfa8 100644 --- a/packages/paste-core/components/timeline/type-docs.json +++ b/packages/paste-core/components/timeline/type-docs.json @@ -2194,6 +2194,13 @@ "required": false, "externalProp": true }, + "disabled": { + "type": "boolean", + "defaultValue": false, + "required": false, + "externalProp": false, + "description": "If true, the timeline item will be disabled" + }, "draggable": { "type": "Booleanish", "defaultValue": null, @@ -2433,10 +2440,11 @@ "externalProp": true }, "onClick": { - "type": "MouseEventHandler", - "defaultValue": null, + "type": "MouseEventHandler &\n MouseEventHandler", + "defaultValue": "undefined", "required": false, - "externalProp": true + "externalProp": false, + "description": "Add an action to the timeline item." }, "onClickCapture": { "type": "MouseEventHandler", @@ -3923,6 +3931,13 @@ "required": false, "externalProp": true }, + "disabled": { + "type": "boolean", + "defaultValue": false, + "required": false, + "externalProp": false, + "description": "If true, the timeline item will be disabled" + }, "draggable": { "type": "Booleanish", "defaultValue": null, @@ -4162,10 +4177,11 @@ "externalProp": true }, "onClick": { - "type": "MouseEventHandler", - "defaultValue": null, + "type": "MouseEventHandler &\n MouseEventHandler", + "defaultValue": "undefined", "required": false, - "externalProp": true + "externalProp": false, + "description": "Add an action to the timeline item." }, "onClickCapture": { "type": "MouseEventHandler", From 852280509c161e11448b582b30fa7ba85c954431 Mon Sep 17 00:00:00 2001 From: PixeledCode Date: Wed, 28 May 2025 19:52:37 +0530 Subject: [PATCH 4/8] feat(timeline): add changeset --- .changeset/fuzzy-lobsters-wait.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/fuzzy-lobsters-wait.md diff --git a/.changeset/fuzzy-lobsters-wait.md b/.changeset/fuzzy-lobsters-wait.md new file mode 100644 index 0000000000..e344cedbe4 --- /dev/null +++ b/.changeset/fuzzy-lobsters-wait.md @@ -0,0 +1,6 @@ +--- +"@twilio-paste/timeline": minor +"@twilio-paste/core": minor +--- + +[Timeline] add a new prop called `onClick` to `TimelineItem` that makes the title interactive From 39b948de6dcd755224e50db21bb1efa11e89cac0 Mon Sep 17 00:00:00 2001 From: PixeledCode Date: Wed, 28 May 2025 19:59:32 +0530 Subject: [PATCH 5/8] feat(timeline): fix build --- packages/paste-core/components/timeline/package.json | 6 ++++++ .../paste-core/components/timeline/src/TimelineItem.tsx | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/paste-core/components/timeline/package.json b/packages/paste-core/components/timeline/package.json index 94140fa835..adc83b4871 100644 --- a/packages/paste-core/components/timeline/package.json +++ b/packages/paste-core/components/timeline/package.json @@ -36,7 +36,9 @@ "@twilio-paste/detail-text": "^4.0.0", "@twilio-paste/disclosure-primitive": "^3.0.0", "@twilio-paste/icons": "^13.0.0", + "@twilio-paste/paragraph": "^11.0.1", "@twilio-paste/reakit-library": "^3.0.0", + "@twilio-paste/skeleton-loader": "^7.0.1", "@twilio-paste/spinner": "^15.0.0", "@twilio-paste/stack": "^9.0.0", "@twilio-paste/style-props": "^10.0.0", @@ -44,6 +46,7 @@ "@twilio-paste/summary-detail": "^2.0.0", "@twilio-paste/text": "^11.0.0", "@twilio-paste/theme": "^12.0.0", + "@twilio-paste/truncate": "^15.0.1", "@twilio-paste/types": "^7.0.0", "@twilio-paste/uid-library": "^3.0.0", "@types/react": "^17.0.2 || ^18.0.27 || ^19.0.0", @@ -63,7 +66,9 @@ "@twilio-paste/detail-text": "^4.0.1", "@twilio-paste/disclosure-primitive": "^3.0.1", "@twilio-paste/icons": "^13.0.1", + "@twilio-paste/paragraph": "^11.0.1", "@twilio-paste/reakit-library": "^3.0.1", + "@twilio-paste/skeleton-loader": "^7.0.1", "@twilio-paste/spinner": "^15.0.1", "@twilio-paste/stack": "^9.0.1", "@twilio-paste/style-props": "^10.0.1", @@ -71,6 +76,7 @@ "@twilio-paste/summary-detail": "^2.0.1", "@twilio-paste/text": "^11.0.1", "@twilio-paste/theme": "^12.0.1", + "@twilio-paste/truncate": "^15.0.1", "@twilio-paste/types": "^7.0.1", "@twilio-paste/uid-library": "^3.0.1", "@types/react": "^19.0.8", diff --git a/packages/paste-core/components/timeline/src/TimelineItem.tsx b/packages/paste-core/components/timeline/src/TimelineItem.tsx index e1d25a1aca..609e4cf493 100644 --- a/packages/paste-core/components/timeline/src/TimelineItem.tsx +++ b/packages/paste-core/components/timeline/src/TimelineItem.tsx @@ -1,7 +1,6 @@ import { Box } from "@twilio-paste/box"; import { Button } from "@twilio-paste/button"; import { css, styled } from "@twilio-paste/styling-library"; -import { Text } from "@twilio-paste/text"; import { Truncate } from "@twilio-paste/truncate"; import React from "react"; From cbe37bb13b8f6687279c126e0cb27b95f2ba7cb1 Mon Sep 17 00:00:00 2001 From: PixeledCode Date: Wed, 28 May 2025 19:59:57 +0530 Subject: [PATCH 6/8] feat(timeline): update yarn lock --- yarn.lock | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/yarn.lock b/yarn.lock index 97bfbcfa79..7ce29c58fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15269,7 +15269,9 @@ __metadata: "@twilio-paste/detail-text": ^4.0.1 "@twilio-paste/disclosure-primitive": ^3.0.1 "@twilio-paste/icons": ^13.0.1 + "@twilio-paste/paragraph": ^11.0.1 "@twilio-paste/reakit-library": ^3.0.1 + "@twilio-paste/skeleton-loader": ^7.0.1 "@twilio-paste/spinner": ^15.0.1 "@twilio-paste/stack": ^9.0.1 "@twilio-paste/style-props": ^10.0.1 @@ -15277,6 +15279,7 @@ __metadata: "@twilio-paste/summary-detail": ^2.0.1 "@twilio-paste/text": ^11.0.1 "@twilio-paste/theme": ^12.0.1 + "@twilio-paste/truncate": ^15.0.1 "@twilio-paste/types": ^7.0.1 "@twilio-paste/uid-library": ^3.0.1 "@types/react": ^19.0.8 @@ -15297,7 +15300,9 @@ __metadata: "@twilio-paste/detail-text": ^4.0.0 "@twilio-paste/disclosure-primitive": ^3.0.0 "@twilio-paste/icons": ^13.0.0 + "@twilio-paste/paragraph": ^11.0.1 "@twilio-paste/reakit-library": ^3.0.0 + "@twilio-paste/skeleton-loader": ^7.0.1 "@twilio-paste/spinner": ^15.0.0 "@twilio-paste/stack": ^9.0.0 "@twilio-paste/style-props": ^10.0.0 @@ -15305,6 +15310,7 @@ __metadata: "@twilio-paste/summary-detail": ^2.0.0 "@twilio-paste/text": ^11.0.0 "@twilio-paste/theme": ^12.0.0 + "@twilio-paste/truncate": ^15.0.1 "@twilio-paste/types": ^7.0.0 "@twilio-paste/uid-library": ^3.0.0 "@types/react": ^17.0.2 || ^18.0.27 || ^19.0.0 From d1678a7b5f40673d8b045fa133291b7cf5a5af7d Mon Sep 17 00:00:00 2001 From: PixeledCode Date: Wed, 28 May 2025 20:26:01 +0530 Subject: [PATCH 7/8] feat(ai-chat): update docs --- .../component-examples/TimelineExamples.ts | 35 +++++++++++++++++++ .../src/pages/components/timeline/index.mdx | 17 +++++++++ 2 files changed, 52 insertions(+) diff --git a/packages/paste-website/src/component-examples/TimelineExamples.ts b/packages/paste-website/src/component-examples/TimelineExamples.ts index 0be64e6b96..77f6dda3db 100644 --- a/packages/paste-website/src/component-examples/TimelineExamples.ts +++ b/packages/paste-website/src/component-examples/TimelineExamples.ts @@ -206,6 +206,41 @@ const TimelineGrouped = () => { render() `.trim(); +export const TimelineInteractiveTitle = ` +const TimelineInteractiveTitle = () => { + return ( + + + + {}} /> + {}} + /> + {}} /> + + + {}} + /> + {}} /> + {}} + disabled + /> + + + + ); +}; +render() +`.trim(); + export const TimelineComposition = ` const TimelineComposition = () => { return ( diff --git a/packages/paste-website/src/pages/components/timeline/index.mdx b/packages/paste-website/src/pages/components/timeline/index.mdx index 7f67f39df0..056400b180 100644 --- a/packages/paste-website/src/pages/components/timeline/index.mdx +++ b/packages/paste-website/src/pages/components/timeline/index.mdx @@ -40,6 +40,7 @@ import { TimelineComposition, TimelineGrouped, TimelineIcon, + TimelineInteractiveTitle, TimelineStart, TimelineTimestamp, } from "../../../component-examples/TimelineExamples.ts"; @@ -205,6 +206,22 @@ However, for collapsible Timeline items, if no timestamp is provided, a heading {TimelineGrouped} +### Timeline with interactive title + +Use the `onClick` prop on the `TimelineItem` to make the title interactive. This is useful when you want to provide additional context or actions related to the event. + + + {TimelineInteractiveTitle} + + ## Timeline event loading ### Load more From 8845a8a6e79a2751699bab6c31c69256e3db78c2 Mon Sep 17 00:00:00 2001 From: PixeledCode Date: Thu, 29 May 2025 13:57:23 +0530 Subject: [PATCH 8/8] feat(ai-chat): update docs --- .../src/pages/components/timeline/index.mdx | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/packages/paste-website/src/pages/components/timeline/index.mdx b/packages/paste-website/src/pages/components/timeline/index.mdx index 056400b180..9aeade6aeb 100644 --- a/packages/paste-website/src/pages/components/timeline/index.mdx +++ b/packages/paste-website/src/pages/components/timeline/index.mdx @@ -90,6 +90,10 @@ Timelines can be used in different use cases, such as tracking milestones, monit ### Accessibility + + The toggle button when using the `collapsible` prop: `collapsible` TimelineItems use the Summary Detail component. The toggle button is labeled by the value of the `timestamp` prop. If the value is too verbose for a screen reader or not a clear label for the collapsed content, provide a helpful label for the button using the collapsibleLabelText prop on TimelineItem. + + Timeline is an ordered list (<ol>) and TimelineItem is a list item (<li>). @@ -135,6 +139,26 @@ Use a basic Timeline as the default option to display a series of events that ne {TimelineBasic} +### Timeline with interactive title + +Use the `onClick` prop on the `TimelineItem` to make the title interactive. Use interactive titles only when the Timeline Event links to a specific moment in another view or surface. + + + These titles should be used only when the event exists elsewhere and the user needs to be redirected to that exact point in time. If the event doesn't have a corresponding view, use a non-interactive title instead. + + + + {TimelineInteractiveTitle} + + ### Timeline with icons Use a Timeline with icons to highlight events that would benefit from a visual cue to make the event more noticeable. @@ -206,22 +230,6 @@ However, for collapsible Timeline items, if no timestamp is provided, a heading {TimelineGrouped} -### Timeline with interactive title - -Use the `onClick` prop on the `TimelineItem` to make the title interactive. This is useful when you want to provide additional context or actions related to the event. - - - {TimelineInteractiveTitle} - - ## Timeline event loading ### Load more