A React component that replicates the Gemini Deep Research thinking panel style with expandable sections and source links
npm install react-thinking-panelA React component that replicates the Gemini Deep Research thinking panel style with expandable sections and source links.
- ð Timeline Design - Vertical line with dot markers for flow visualization
- ðĻ CSS Variables - Fully customizable colors via CSS custom properties
- ð Dark Mode - Built-in dark mode support (auto or manual)
- ð§ Flexible Icons - Built-in icons or custom React nodes
- ðĶ TypeScript - Full type definitions included
- ðŠķ Lightweight - No dependencies (peer dependency on React only)
``bash`
npm install react-thinking-panelor
yarn add react-thinking-panelor
pnpm add react-thinking-panel
`tsx
import { ThinkingPanel } from 'react-thinking-panel';
import 'react-thinking-panel/styles.css';
function App() {
const [expanded, setExpanded] = useState(true);
return (
expanded={expanded}
onToggle={() => setExpanded(!expanded)}
sections={[
{
icon: 'sparkle',
title: 'Analysis',
content: 'Analyzing the problem...'
},
{
icon: 'brain',
title: 'Deep Thinking',
content: ['First paragraph.', 'Second paragraph.']
}
]}
/>
);
}
`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| title | string | 'æč·Ŋ' | Panel header title |titleIcon
| | ReactNode | - | Custom icon before title |expanded
| | boolean | true | Whether panel is expanded |onToggle
| | () => void | - | Toggle callback |sections
| | ThinkingSection[] | required | Thinking sections |researching
| | ResearchingSection | - | Source links section |className
| | string | - | Container class |headerClassName
| | string | - | Header class |contentClassName
| | string | - | Content area class |darkMode
| | boolean | - | Force dark mode |style
| | CSSProperties | - | Inline styles |
| Prop | Type | Description |
|------|------|-------------|
| title | string | Section title |content
| | string \| string[] | Paragraph(s) content |icon
| | 'sparkle' \| 'search' \| 'brain' \| 'bulb' \| string | Built-in or emoji icon |iconNode
| | ReactNode | Custom icon (overrides icon) |className
| | string | Section class |
| Prop | Type | Description |
|------|------|-------------|
| title | string | Section title |icon
| | 'google' \| 'search' \| string | Built-in or emoji icon |iconNode
| | ReactNode | Custom icon |links
| | SourceLink[] | Source links |className
| | string | Section class |
| Prop | Type | Description |
|------|------|-------------|
| domain | string | Domain name (e.g., "github.com") |title
| | string | Link title |url
| | string | Full URL |icon
| | string | Custom favicon URL |
Override these CSS custom properties to customize colors:
`css`
:root {
/ Light Mode /
--tp-bg: #ffffff;
--tp-border: #e5e7eb;
--tp-title-color: #374151;
--tp-section-icon-color: #f59e0b;
--tp-paragraph-color: #4b5563;
/ Timeline /
--tp-timeline-line-color: #e5e7eb;
--tp-timeline-dot-color: #3b82f6;
--tp-timeline-dot-size: 8px;
--tp-timeline-line-width: 2px;
/ ... see styles.css for all variables /
}
Auto (via media query):
`css`
@media (prefers-color-scheme: dark) {
:root { / dark colors / }
}
Manual:
`tsx`
Or apply .tp-dark class to a parent element.
`tsx
import { FaRobot } from 'react-icons/fa';
{
title: 'Custom Icon',
content: 'Using react-icons',
iconNode:
}
]}
/>
`
`tsx``
expanded={expanded}
onToggle={() => setExpanded(!expanded)}
sections={[
{ icon: 'sparkle', title: 'Analysis', content: '...' }
]}
researching={{
title: 'Researching websites',
icon: 'google',
links: [
{ domain: 'github.com', title: 'Repository', url: 'https://github.com/...' },
{ domain: 'arxiv.org', title: 'Paper', url: 'https://arxiv.org/...' }
]
}}
/>
MIT