A React component for rendering interactive phylogenetic trees from Newick strings. Supports rectangular and circular layouts, zoom/pan, a full editing toolkit, and an optional synchronized sequence alignment panel.
Built on D3 and packaged as a zero-config drop-in — one import, one prop.
- Features
- Installation
- Quick start
- With a sequence alignment
- Props
- CSS import
- Dark mode
- Theming with CSS variables
- Tree editing tools
- Alignment panel
- Export
- Server-side rendering
- Newick format
- FASTA matching
- TypeScript
- Browser support
- License
| Category | Capabilities |
|---|---|
| Layout | Rectangular and circular trees; phylogram (branch-length scaled) and cladogram (uniform) modes |
| Navigation | Zoom with mouse wheel, pan by dragging, fit-to-view button |
| Editing | Reroot (click any node or midpoint), flip branches, swap sibling clades, ladderize ascending/descending |
| Collapse | Click any internal node to collapse into a named, colored triangle; rename and recolor via an inline editor |
| Coloring | Paint any node, clade, or subtree with a color picker; reset individual nodes or all at once |
| Labels | Toggle leaf labels, bootstrap values, branch lengths; right-align labels with dotted leader lines (phylogram) |
| Search | Highlight matching taxa by name; keyboard navigation (⌘F / Ctrl+F, Enter, Esc) |
| Alignment | Synchronized FASTA viewer with nucleotide and amino acid color schemes, scrolls in sync with the tree |
| Export | Download as SVG, PNG, PDF, or Newick |
| Dark mode | Full dark theme controlled by data-theme="dark" on <html> |
| Resize | Drag handle at the bottom of the viewer to adjust height at runtime |
npm install reactreejsPeer dependencies (install separately if not already in your project):
npm install react react-domSupported peer versions: React 18 and 19.
import { Reactree } from 'reactreejs';
import 'reactreejs/style.css';
export default function App() {
const newick = '((Homo_sapiens:0.09,Pan_troglodytes:0.11):0.07,(Mus_musculus:0.23,Rattus_norvegicus:0.21):0.14);';
return <Reactree newick={newick} />;
}The stylesheet import is required — see CSS import.
Pass a fasta string to enable the alignment panel. An Alignment toggle button will appear in the toolbar. When activated, a synchronized sequence viewer opens alongside the tree, scrolling in sync as you pan.
import { Reactree } from 'reactreejs';
import 'reactreejs/style.css';
const newick = '((Homo_sapiens:0.09,Anopheles:0.36):0.07,Mimivirus:1.22);';
const fasta = `
>Homo_sapiens
MTEYKLVVVGAGGVGKSALTIQLIQNHFVDEYDPTIEDSY
>Anopheles
MTEYKLVVVGAGGVGKSALTIQLIQNHFVDEYDPTIEDS-
>Mimivirus
----KLVVVGAGGVGKSALTIQL-QNHFVDEYDPTIEDS-
`.trim();
export default function App() {
return (
<Reactree
newick={newick}
fasta={fasta}
defaultHeight={600}
/>
);
}Sequence type (nucleotide vs. amino acid) is detected automatically from the sequence content.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
newick |
string |
Yes | — | Newick tree string. Supports branch lengths (:0.123) and internal node labels (used as bootstrap values). |
defaultHeight |
number |
No | 520 |
Initial viewer height in pixels. The user can resize at runtime via the drag handle. |
fasta |
string |
No | — | Multi-FASTA sequence string. Enables the alignment panel. Sequences are matched to leaf names by case-insensitive, underscore-normalised lookup. |
The component stylesheet must be imported explicitly — without it, layout, spacing, and theming will not work:
import 'reactreejs/style.css';Import it once, at the top level of your application (e.g. main.tsx, _app.tsx, or your root layout). Do not import it more than once.
The stylesheet defines all design tokens as CSS custom properties on :root. You can override any of them after the import — see Theming with CSS variables.
reactreejs reads the data-theme attribute on <html> and reacts to changes via a MutationObserver. No context providers or additional configuration are needed.
Enable dark mode:
document.documentElement.setAttribute('data-theme', 'dark');Return to light mode:
document.documentElement.removeAttribute('data-theme');
// or equivalently:
document.documentElement.setAttribute('data-theme', 'light');React toggle example:
function ThemeToggle() {
const [dark, setDark] = React.useState(false);
function toggle() {
const next = !dark;
setDark(next);
if (next) {
document.documentElement.setAttribute('data-theme', 'dark');
} else {
document.documentElement.removeAttribute('data-theme');
}
}
return <button onClick={toggle}>{dark ? 'Light' : 'Dark'} mode</button>;
}Respecting the OS preference on first load:
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-theme', 'dark');
}The component switches instantly — the MutationObserver fires on every attribute change and triggers a re-render.
All visual tokens are exposed as CSS custom properties. Import reactreejs/style.css, then override whatever you need in your own stylesheet:
/* your-app.css — loaded after reactreejs/style.css */
:root {
--clr-primary-a0: #7c3aed; /* accent color (buttons, highlights) */
--clr-surface-a0: #fafaf9; /* main background */
--font-family: 'Inter', sans-serif;
}| Variable | Default | Role |
|---|---|---|
--clr-primary-a0 |
#0071f2 |
Accent — active buttons, focus rings, highlights |
--clr-surface-a0 |
#ffffff |
Main background (toolbar, panels) |
--clr-surface-a10 |
#f8fafc |
Secondary surface (input backgrounds) |
--clr-surface-a20 |
#f1f5f9 |
Tertiary surface (hover states) |
--clr-text-primary |
#0f172a |
Primary text |
--clr-text-secondary |
#475569 |
Secondary / muted text |
--clr-border |
#e2e8f0 |
Borders and dividers |
--clr-input-bg |
#f8fafc |
Input field backgrounds |
| Variable | Dark value | Role |
|---|---|---|
--clr-primary-a0 |
#3b82f6 |
Accent — brighter blue for dark backgrounds |
--clr-surface-a0 |
#0f172a |
Main background |
--clr-surface-a10 |
#1e293b |
Secondary surface |
--clr-surface-a20 |
#334155 |
Tertiary surface / hover |
--clr-text-primary |
#f8fafc |
Primary text |
--clr-text-secondary |
#94a3b8 |
Secondary / muted text |
--clr-border |
#334155 |
Borders and dividers |
--clr-input-bg |
#1e293b |
Input field backgrounds |
| Variable | Default | Role |
|---|---|---|
--font-family |
'Segoe UI', Tahoma, Geneva, Verdana, sans-serif |
UI font (toolbar, labels, panels) |
You can override tokens for dark mode only by targeting the same selector:
[data-theme='dark'] {
--clr-primary-a0: #a78bfa; /* softer violet accent in dark mode */
--clr-surface-a0: #020617; /* deeper background */
}All editing tools are available in the toolbar above the tree. Operations are non-destructive — an Undo button (⌘Z / Ctrl+Z) steps back through the edit history, and Reset returns to the original tree.
| Tool | Description |
|---|---|
| Rect / Circ | Switch between rectangular and circular (radial) layout |
| Phylogram / Cladogram | Toggle branch-length scaling on or off |
| Reroot | Click any node to set it as the new root; or use Midpoint to root at the midpoint of the longest path |
| Flip | Reverse the child order of any internal node |
| Swap | Select two sibling nodes to swap their positions |
| Ladderize | Sort all clades by leaf count, ascending or descending |
| Color | Paint any node or clade with a color picker; Reset clears individual nodes |
| Align labels | Right-align leaf labels with dotted leader lines (phylogram only) |
| Bootstrap / Branch length | Toggle label display on internal nodes |
| Collapse | Click an internal node to collapse into a named triangle; click again to open the editor and rename or recolor it |
| Search | Filter and highlight taxa by name (⌘F / Ctrl+F) |
When fasta is provided, a toggle button labeled Alignment appears in the toolbar. Clicking it opens a sequence panel to the right of the tree.
- Sequences scroll vertically in sync with the tree — the row for each taxon stays aligned with its leaf label.
- Color schemes switch automatically based on detected sequence type: nucleotide (A/T/C/G coloring) or amino acid (residue-class coloring).
- A legend for the active color scheme is shown at the top of the alignment panel.
- Horizontal scrolling is independent from the tree.
Sequence matching is case-insensitive and underscore-tolerant — Homo_sapiens in the tree will match >Homo sapiens in the FASTA header, and vice versa.
The Download menu in the toolbar provides four formats:
| Format | Notes |
|---|---|
| SVG | Lossless vector, includes the full tree as rendered |
| PNG | Rasterised at the current viewport size |
| Single-page PDF via jsPDF, suitable for figures | |
| Newick | Exports the current (possibly rerooted/rearranged) tree as a Newick string |
reactreejs uses D3, the Canvas API, and document/window directly. It is not compatible with SSR as-is.
Next.js — dynamic import with ssr: false:
import dynamic from 'next/dynamic';
const Reactree = dynamic(
() => import('reactreejs').then(m => m.Reactree),
{ ssr: false }
);
export default function Page() {
return <Reactree newick="((A:0.1,B:0.2):0.3,C:0.4);" />;
}Remix / other SSR frameworks: wrap the import in a useEffect or use a client-only boundary to ensure it loads exclusively in the browser.
The parser accepts standard Newick with optional branch lengths and optional internal node labels:
((A:0.1,B:0.2):0.3,(C:0.4,D:0.1):0.2); # branch lengths
((A,B)90,(C,D)85); # bootstrap values as internal labels
((A:0.1,B:0.2)90:0.3,(C:0.4,D:0.1)85:0.2); # both
(A,B,C); # no lengths, no bootstraps
The trailing semicolon is optional. Internal node labels that parse as numbers in the range [0, 100] are treated as bootstrap support values and displayed when the Bootstrap label mode is active.
Leaf names are matched to FASTA sequence headers by a two-step lookup:
- Exact match after normalising underscores to spaces and lower-casing both sides.
- Partial match — if no exact match is found, the first header that contains the leaf name (or vice versa) is used.
Leaves with no matching sequence are shown in the tree normally; their alignment row is simply empty.
Types for the component props are exported from the package:
import type { ReactreeProps } from 'reactreejs';type ReactreeProps = {
newick: string;
defaultHeight?: number;
fasta?: string;
};reactreejs targets modern evergreen browsers (Chrome, Firefox, Safari, Edge). It requires:
- ES2020 (optional chaining, nullish coalescing)
- SVG and Canvas API support
MutationObserver(for dark mode reactivity)
It is not tested in Internet Explorer and will not work there.
MIT