The ToggleButton component is an interactive button that maintains a checked/unchecked state. It combines the visual appearance of a button with the behavior of a checkbox, perfect for toggleable actions.
Basic Usage
import { ToggleButton } from 'reshaped';
import { useState } from 'react';
function Example() {
const [checked, setChecked] = useState(false);
return (
<ToggleButton
checked={checked}
onChange={({ checked }) => setChecked(checked)}
>
Toggle me
</ToggleButton>
);
}
Uncontrolled Mode
import { ToggleButton } from 'reshaped';
function UncontrolledExample() {
return (
<ToggleButton
defaultChecked
onChange={({ checked }) => console.log('Checked:', checked)}
>
Auto-managed state
</ToggleButton>
);
}
Custom Selection Styling
import { ToggleButton } from 'reshaped';
function StyledToggle() {
return (
<ToggleButton
variant="outline"
selectedColor="primary"
selectedVariant="solid"
defaultChecked={false}
>
Select me
</ToggleButton>
);
}
With Icon
import { ToggleButton } from 'reshaped';
import { Heart } from './icons';
import { useState } from 'react';
function FavoriteButton() {
const [liked, setLiked] = useState(false);
return (
<ToggleButton
icon={Heart}
checked={liked}
selectedColor="critical"
onChange={({ checked }) => setLiked(checked)}
>
Like
</ToggleButton>
);
}
Value of the toggle button, enables controlled mode
Default value of the toggle button, enables uncontrolled mode
Value of the toggle button used when inside a ToggleButtonGroup
onChange
(args: { checked: boolean, value: string, event: Event }) => void
Callback when the toggle button value changes
variant
'solid' | 'outline' | 'ghost' | 'faded'
default:"outline"
Component render variant
selectedColor
'primary' | 'critical' | 'positive' | 'neutral'
default:"neutral"
Component color scheme when selected
selectedVariant
'solid' | 'outline' | 'ghost' | 'faded'
Component variant when selected
color
'primary' | 'critical' | 'positive' | 'neutral'
Component color scheme
size
'small' | 'medium' | 'large'
Button size
Icon to display in the button
Make button take full width of parent
Inherits all other props from the Button component.
When to Use
- Filters: Toggle filter options on/off
- Favorites: Mark items as favorites
- Settings: Toggle feature flags or preferences
- Views: Switch between different view modes
- Selections: Allow users to select options that can be toggled
- Toolbar Actions: Toggle formatting or tool states
Composition Patterns
Filter Buttons
import { ToggleButton, Stack } from 'reshaped';
import { useState } from 'react';
function FilterBar() {
const [filters, setFilters] = useState({
active: false,
pending: false,
completed: false
});
const toggleFilter = (key) => {
setFilters(prev => ({ ...prev, [key]: !prev[key] }));
};
return (
<Stack direction="row" gap={2}>
<ToggleButton
checked={filters.active}
onChange={() => toggleFilter('active')}
>
Active
</ToggleButton>
<ToggleButton
checked={filters.pending}
onChange={() => toggleFilter('pending')}
>
Pending
</ToggleButton>
<ToggleButton
checked={filters.completed}
onChange={() => toggleFilter('completed')}
>
Completed
</ToggleButton>
</Stack>
);
}
Icon-Only Toggle
import { ToggleButton, Tooltip } from 'reshaped';
import { Star } from './icons';
import { useState } from 'react';
function StarButton({ itemId }) {
const [starred, setStarred] = useState(false);
return (
<Tooltip text={starred ? 'Unstar' : 'Star'}>
<ToggleButton
icon={Star}
checked={starred}
selectedColor="warning"
selectedVariant="solid"
onChange={({ checked }) => setStarred(checked)}
attributes={{ 'aria-label': starred ? 'Unstar' : 'Star' }}
/>
</Tooltip>
);
}
View Mode Switcher
import { ToggleButton, Stack } from 'reshaped';
import { Grid, List } from './icons';
import { useState } from 'react';
function ViewSwitcher({ onChange }) {
const [view, setView] = useState('grid');
const handleChange = (newView) => {
setView(newView);
onChange(newView);
};
return (
<Stack direction="row" gap={1}>
<ToggleButton
icon={Grid}
checked={view === 'grid'}
onChange={() => handleChange('grid')}
attributes={{ 'aria-label': 'Grid view' }}
/>
<ToggleButton
icon={List}
checked={view === 'list'}
onChange={() => handleChange('list')}
attributes={{ 'aria-label': 'List view' }}
/>
</Stack>
);
}
Multi-Select Toolbar
import { ToggleButton, Stack, Text } from 'reshaped';
import { Bold, Italic, Underline } from './icons';
import { useState } from 'react';
function FormattingToolbar() {
const [formatting, setFormatting] = useState({
bold: false,
italic: false,
underline: false
});
const toggle = (key) => {
setFormatting(prev => ({ ...prev, [key]: !prev[key] }));
};
return (
<Stack gap={2}>
<Stack direction="row" gap={1}>
<ToggleButton
icon={Bold}
checked={formatting.bold}
onChange={() => toggle('bold')}
size="small"
attributes={{ 'aria-label': 'Bold' }}
/>
<ToggleButton
icon={Italic}
checked={formatting.italic}
onChange={() => toggle('italic')}
size="small"
attributes={{ 'aria-label': 'Italic' }}
/>
<ToggleButton
icon={Underline}
checked={formatting.underline}
onChange={() => toggle('underline')}
size="small"
attributes={{ 'aria-label': 'Underline' }}
/>
</Stack>
<Text variant="caption-1">
Active: {Object.entries(formatting)
.filter(([_, active]) => active)
.map(([key]) => key)
.join(', ') || 'None'}
</Text>
</Stack>
);
}
Toggle with Loading State
import { ToggleButton } from 'reshaped';
import { useState } from 'react';
function AsyncToggle({ onToggle }) {
const [checked, setChecked] = useState(false);
const [loading, setLoading] = useState(false);
const handleChange = async ({ checked: newChecked }) => {
setLoading(true);
try {
await onToggle(newChecked);
setChecked(newChecked);
} catch (error) {
console.error('Failed to toggle:', error);
} finally {
setLoading(false);
}
};
return (
<ToggleButton
checked={checked}
loading={loading}
onChange={handleChange}
>
Subscribe
</ToggleButton>
);
}