
Security News
ECMAScript 2025 Finalized with Iterator Helpers, Set Methods, RegExp.escape, and More
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.
react-chrono
Advanced tools
A flexible and modern timeline component for React.
React Chrono is a modern timeline component for React that offers a variety of features and customization options. It allows you to render timelines in horizontal, vertical, and vertical-alternating modes, display images and videos, and much more.
# Using yarn
yarn add react-chrono
# Using npm
npm install react-chrono
Ensure you wrap the Chrono
component in a container with a specified width
and height
.
By default, if no mode
is specified, the component renders in HORIZONTAL
mode.
import React from "react";
import { Chrono } from "react-chrono";
const App = () => {
const items = [
{
title: "May 1940",
cardTitle: "Dunkirk",
url: "http://www.history.com",
cardSubtitle: "Men of the British Expeditionary Force (BEF) wade out to a destroyer...",
cardDetailedText: "Men of the British Expeditionary Force (BEF) wade out to a destroyer during the evacuation from Dunkirk.",
media: {
type: "IMAGE",
source: {
url: "http://someurl/image.jpg"
}
}
},
// ... more items
];
return (
<div style={{ width: "800px", height: "400px" }}>
<Chrono items={items} />
</div>
);
};
export default App;
To render the timeline vertically, set the mode
prop to VERTICAL
.
<div style={{ width: '300px', height: '950px' }}>
<Chrono items={items} mode="VERTICAL" />
</div>
For a layout where cards alternate sides, use VERTICAL_ALTERNATING
.
<div style={{ width: '500px', height: '950px' }}>
<Chrono items={items} mode="VERTICAL_ALTERNATING" />
</div>
React Chrono offers a wide range of props for customization.
Name | Type | Default | Description |
---|---|---|---|
items | TimelineItemModel[] | [] | An array of Timeline Item objects to display. |
mode | 'HORIZONTAL' , 'VERTICAL' , 'VERTICAL_ALTERNATING' | 'HORIZONTAL' | Sets the layout mode of the timeline. Changed to HORIZONTAL from VERTICAL_ALTERNATING for new projects. |
theme | Theme | {...} | Customizes colors. See Theming & Styling for details. |
Each object in the items
array can have the following properties:
Property | Type | Description |
---|---|---|
title | string | Title of the timeline item (often a date or short label). |
cardTitle | string | Title displayed on the timeline card. |
cardSubtitle | string | Subtitle text displayed on the timeline card. |
cardDetailedText | string or string[] | Detailed text for the card. An array of strings will render each string as a separate paragraph. |
media | TimelineMediaModel | Object to configure image or video display. See Media Handling. |
url | string | URL associated with the timeline item's title. Clicking the title will navigate to this URL. |
date | Date or string | Date to be used in the title. If provided, this will override the title property for display purposes. |
timelineContent | ReactNode | Custom React content to render inside the card. Overrides cardDetailedText . See Rendering Custom Content. |
items | TimelineItemModel[] | Array of timeline items for creating Nested Timelines. |
active | boolean | If true, this item will be initially active (only for the first matching item). |
id | string | A unique identifier for the timeline item. |
visible | boolean | Controls the visibility of the timeline item. |
Example TimelineItemModel
:
{
title: "May 1940",
cardTitle: "Dunkirk",
cardSubtitle: "Evacuation of Allied soldiers from the beaches and harbour of Dunkirk, France.",
cardDetailedText: ["Paragraph one about Dunkirk.", "Paragraph two providing more details."],
media: {
type: "IMAGE", // "VIDEO"
source: {
url: "http://someurl/dunkirk.jpg"
},
name: "Dunkirk Evacuation"
},
url: "https://en.wikipedia.org/wiki/Dunkirk_evacuation",
// For nested timeline:
// items: [{ cardTitle: 'Sub-event 1' }, { cardTitle: 'Sub-event 2' }]
}
Name | Type | Default | Description |
---|---|---|---|
activeItemIndex | number | 0 | Index of the timeline item to be active on load. |
disableNavOnKey | boolean | false | Disables keyboard navigation (LEFT/RIGHT for Horizontal, UP/DOWN for Vertical). |
disableClickOnCircle | boolean | false | Disables click action on timeline points/circles. |
disableAutoScrollOnClick | boolean | false | Prevents auto-scrolling to the active card when a timeline card or point is clicked. |
onItemSelected | function | Callback function invoked when a timeline item is selected. Passes item data and index. | |
onScrollEnd | function | Callback function invoked when the end of the timeline is reached during scrolling. | |
focusActiveItemOnLoad | boolean | true | Automatically scrolls to and focuses on the activeItemIndex when the timeline loads. |
disableInteraction | boolean | false | Disables all user interactions with the timeline (clicks, keyboard navigation). |
enableQuickJump | boolean | true | Allows quick jumping to a timeline item via controls (if toolbar is enabled). |
useReadMore | boolean | true | Enables a "read more" button if card content exceeds available space. Set to false to always show all text. |
Keyboard Navigation:
Name | Type | Default | Description |
---|---|---|---|
cardHeight | number | 200 | Minimum height (in pixels) of timeline cards. |
cardWidth | number | 450 | Maximum width (in pixels) of timeline cards. |
itemWidth | number | 300 | Width (in pixels) of each timeline section in HORIZONTAL mode. |
contentDetailsHeight | number | 150 | Height (in pixels) of the detailed content area within a card if cardDetailedText is used. |
lineWidth | number | 3 | Width (in pixels) of the main timeline track line. |
timelinePointDimension | number | 16 | Diameter (in pixels) of the circular points on the timeline. |
nestedCardHeight | number | 150 | Height (in pixels) of cards within a nested timeline. |
scrollable | boolean or { scrollbar: boolean } | true | Makes VERTICAL and VERTICAL_ALTERNATING modes scrollable. Set to { scrollbar: true } to show the scrollbar. |
enableBreakPoint | boolean | true | If true, VERTICAL_ALTERNATING mode automatically switches to VERTICAL mode when responsiveBreakPoint is reached. |
responsiveBreakPoint | number | 768 | Viewport width (in pixels) at which VERTICAL_ALTERNATING mode switches to VERTICAL if enableBreakPoint is true. Default changed to 768 . |
cardPositionHorizontal | 'TOP' or 'BOTTOM' | 'BOTTOM' | Positions the card above or below the timeline in HORIZONTAL mode. Default changed to 'BOTTOM' . |
flipLayout | boolean | false | Reverses the layout direction (e.g., Right-to-Left for horizontal, or swaps sides for vertical alternating). |
showAllCardsHorizontal | boolean | false | In HORIZONTAL mode, displays all cards simultaneously instead of only the active one. |
The media
object within a Timeline Item configures images or videos.
media Property | Type | Description |
---|---|---|
type | 'IMAGE' or 'VIDEO' | Specifies the type of media. |
source | { url: string, type?: string } | url : URL of the image or video. type (for video): e.g., 'mp4' , 'webm' . |
name | string | Alt text for images or a descriptive name for videos. |
active | boolean | (Video only) If true, video will attempt to play when its card becomes active. |
id | string | A unique ID for the media element. |
videoOptions | HTMLVideoElement attributes | (Video only) An object containing standard HTML5 video attributes like loop , muted , autoPlay , etc. |
Image Example:
media: {
type: "IMAGE",
name: "dunkirk beach",
source: {
url: "http://someurl/image.jpg"
}
}
Video Example (auto-plays when active, muted):
media: {
type: "VIDEO",
name: "Pearl Harbor",
source: {
url: "/pearl-harbor.mp4", // or "https://www.youtube.com/embed/f6cz9gtMTeI"
type: "mp4" // Optional for local files if extension is clear, useful for YouTube embeds
},
videoOptions: { autoPlay: true, muted: true }
}
Media Settings Prop (mediaSettings
):
This top-level prop on <Chrono>
controls global media display:
Name | Type | Default | Description |
---|---|---|---|
align | 'left' , 'right' , 'center' | 'left' | Alignment of media within the card. Default changed to 'left' . |
fit | 'cover' , 'contain' , 'fill' , 'none' , 'scale-down' | 'cover' | CSS object-fit property for images. |
<Chrono items={items} mediaSettings={{ align: 'right', fit: 'contain' }} />
Name | Type | Default | Description |
---|---|---|---|
borderLessCards | boolean | false | Removes borders and shadows from timeline cards for a flatter look. |
cardLess | boolean | false | Hides timeline cards, showing only titles/points. Useful for a very compact timeline. |
disableTimelinePoint | boolean | false | Hides the circular points on the timeline track. |
timelinePointShape | 'circle' , 'square' , 'diamond' | 'circle' | Configures the shape of the points on the timeline. |
textOverlay | boolean | false | Displays text content as an overlay on top of media elements. Requires text property in timeline items. |
parseDetailsAsHTML | boolean | false | If true, cardDetailedText will be parsed as HTML. Use with caution due to XSS risks if content is user-supplied. |
titleDateFormat | string | 'MMM DD, YYYY' | Date format for item titles when using the date property in items. Supports all day.js formats. |
textDensity | 'LOW' or 'HIGH' | 'HIGH' | Configures the amount of text displayed in cards. 'LOW' might truncate more aggressively. |
Text Overlay Mode:
Enable textOverlay
and provide a text
property in your items
.
const items = [
{
title: 'First item',
media: { type: 'IMAGE', source: { url: 'https://example.com/image.jpg' }},
text: 'This is the caption for the first item, appearing over the image.'
}
];
<Chrono items={items} textOverlay />;
Use the theme
prop to customize colors:
<Chrono
items={items}
theme={{
primary: 'red', // Main timeline color (points, lines)
secondary: 'blue', // Background color for timeline cards or other elements depending on mode
cardBgColor: 'yellow', // Background color of the timeline cards
cardForeColor: 'black', // Text color within timeline cards
titleColor: 'black', // Color of the timeline item titles (e.g., dates)
titleColorActive: 'red', // Color of the active timeline item title
}}
/>
For a complete list of themeable properties, please refer to the
Theme
type definition in the source code or Storybook examples.
Dark Mode Toggle:
Name | Type | Default | Description |
---|---|---|---|
enableDarkToggle | boolean | false | Adds a toggle switch to the toolbar for enabling dark mode (if dark theme is configured). |
onThemeChange | function | Callback invoked when the theme changes, e.g., via the dark mode toggle. Passes the new theme object. |
Name | Type | Default | Description |
---|---|---|---|
slideShow | boolean | false | Enables slideshow mode and shows play/pause controls in the toolbar. |
slideItemDuration | number | 2000 | Duration (in milliseconds) each timeline item remains active during a slideshow. Default changed to 2000 . |
slideShowType | 'reveal' , 'slide_from_sides' , 'slide_in' | Varies by mode | Type of animation for slideshow transitions. Defaults: VERTICAL -> 'reveal' , VERTICAL_ALTERNATING -> 'slide_from_sides' , HORIZONTAL -> 'slide_in' . |
<Chrono items={items} slideShow slideItemDuration={3000} />
Slideshow can be stopped by clicking the stop button or pressing ESC.
Name | Type | Default | Description |
---|---|---|---|
searchPlaceholder | string | "Search..." | Placeholder text for the search input in the toolbar. |
searchAriaLabel | string | "Search timeline" | ARIA label for the search input for accessibility. |
clearSearch | string | "Clear search" | Text/ARIA label for the clear search button. |
<Chrono
items={data}
searchPlaceholder="Find in timeline..."
/>
Search functionality is part of the toolbar. To hide search (and the toolbar), set
disableToolbar={true}
.
Name | Type | Default | Description |
---|---|---|---|
allowDynamicUpdate | boolean | false | Enables dynamic updates of timeline items. If true, changes to the items prop will re-render the timeline. |
noUniqueId | boolean | false | Prevents generating a unique ID for the timeline wrapper. Use with uniqueId if you need to set a specific ID. |
uniqueId | string | Sets a custom unique ID for the timeline wrapper. Useful with noUniqueId={true} . | |
disableToolbar | boolean | false | Hides the entire toolbar/control panel. |
toolbarPosition | 'TOP' or 'BOTTOM' | 'TOP' | Positions the toolbar at the top or bottom of the timeline. |
highlightCardsOnHover | boolean | false | Highlights timeline cards on mouse hover. |
Pass React elements as children to <Chrono>
. Each child will be rendered into a timeline card. This can be combined with the items
prop to provide titles or other metadata.
const customItems = [
{ title: '2023-01-01', cardTitle: 'Event One' },
{ title: '2023-02-15', cardTitle: 'Event Two' },
];
<Chrono mode="VERTICAL" items={customItems}>
<div>
<h4>Custom Content for Event One</h4>
<p>This is fully custom JSX rendered in the first card.</p>
</div>
<div>
<img src="<url_to_image>" alt="Custom Image" style={{width: "100%"}} />
<p>An image in the second card.</p>
</div>
</Chrono>
Provide images for timeline points by wrapping them in a div
with className="chrono-icons"
as a child of <Chrono>
. Icons are applied sequentially.
<Chrono items={items} mode="VERTICAL_ALTERNATING">
{/* Custom content for cards (optional) */}
<div>Card 1 Content</div>
<div>Card 2 Content</div>
{/* Custom icons for timeline points */}
<div className="chrono-icons">
<img src="image1.svg" alt="icon1" />
<img src="image2.svg" alt="icon2" />
{/* Add more images for more items */}
</div>
</Chrono>
Create timelines within timeline cards by providing an items
array within a parent timeline item.
const itemsWithNested = [
{
title: 'Main Event 1',
cardTitle: 'Chapter 1',
items: [ // Nested timeline
{ cardTitle: 'Sub-event 1.1', cardSubtitle: 'Details for 1.1' },
{ cardTitle: 'Sub-event 1.2', media: { type: "IMAGE", source: { url: '...' } } },
],
},
{ title: 'Main Event 2', cardTitle: 'Chapter 2' },
];
<Chrono mode="VERTICAL" items={itemsWithNested} nestedCardHeight={120} />
Apply your own CSS classes to various parts of the timeline using the classNames
prop.
<Chrono
items={items}
classNames={{
card: 'my-custom-card',
cardMedia: 'my-card-media',
cardSubTitle: 'my-card-subtitle',
cardText: 'my-card-text',
cardTitle: 'my-card-title',
controls: 'my-timeline-controls', // Class for the toolbar
title: 'my-timeline-title', // Class for the item titles (e.g., dates)
timelinePoint: 'my-timeline-point',
timelineTrack: 'my-timeline-track',
}}
/>
Adjust font sizes for card elements using the fontSizes
prop.
<Chrono
items={data}
fontSizes={{
cardSubtitle: '0.85rem',
cardText: '0.8rem',
cardTitle: '1.1rem',
title: '0.9rem', // Font size for the main timeline titles (dates)
}}
/>
Customize the alt
text for toolbar navigation buttons via buttonTexts
.
<Chrono
items={data}
buttonTexts={{
first: 'Jump to First Item',
last: 'Jump to Last Item',
next: 'View Next Item',
previous: 'View Previous Item',
play: 'Start Slideshow',
stop: 'Stop Slideshow', // Added for completeness
jumpTo: 'Jump to specific item' // Added for completeness
}}
/>
Default buttonTexts
values:
Property | Value |
---|---|
first | 'Go to First' |
last | 'Go to Last' |
next | 'Next' |
previous | 'Previous' |
play | 'Play Slideshow' |
stop | 'Stop Slideshow' |
jumpTo | 'Jump to' |
Explore various configurations of React Chrono:
items
propSee a comprehensive demo showcasing many features:
Dive into a wide variety of examples hosted on Storybook:
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Lint CSS
pnpm lint:css
# ESLint
pnpm eslint
# Prettier
pnpm lint
# Build library
pnpm rollup
# Run unit tests
pnpm test
# Run Cypress tests (interactive)
pnpm cypress:test # or pnpm cypress open
# Run Cypress tests in headless mode
pnpm cypress:headless
# Run Cypress tests in quiet mode (headless, less output)
pnpm cypress:quiet
Contributions are welcome! Please follow these steps:
git checkout -b new-feature
).git commit -am 'Add: New amazing feature'
).git push origin new-feature
).Please read CONTRIBUTING.md
for more details on the process and CODE_OF_CONDUCT.md
.
Special thanks to BrowserStack for providing an Open Source License for testing.
Distributed under the MIT license. See LICENSE
for more information.
Prabhu Murthy β @prabhumurthy2 β prabhu.m.murthy@gmail.com GitHub: https://github.com/prabhuignoto
Thanks to these wonderful people (emoji key):
Alois π | Koji π | Alexandre Girard π» | Ryuya π | Taqi Abbas π» | megasoft78 π» | EricοΌδΉ¦ηοΌ π» |
Christophe Bernard π» |
This project follows the all-contributors specification. Contributions of any kind are welcome!
FAQs
A Modern Timeline component for React
The npm package react-chrono receives a total of 11,081 weekly downloads. As such, react-chrono popularity was classified as popular.
We found that react-chrono demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
ECMAScript 2025 introduces Iterator Helpers, Set methods, JSON modules, and more in its latest spec update approved by Ecma in June 2025.
Security News
A new Node.js homepage button linking to paid support for EOL versions has sparked a heated discussion among contributors and the wider community.
Research
North Korean threat actors linked to the Contagious Interview campaign return with 35 new malicious npm packages using a stealthy multi-stage malware loader.