@googleforcreators/design-system package provides a comprehensive set of React UI components used throughout the Web Stories editor and dashboard. All components are built with TypeScript and styled-components.
Installation
npm install @googleforcreators/design-system
Peer Dependencies
This package requires:{
"react": "^17.0.2",
"react-dom": "^17.0.2",
"styled-components": "^5.3.11"
}
Components
The design system exports a comprehensive set of UI components:Buttons
- Button
- ToggleButton
import { Button, ButtonSize, ButtonType, ButtonVariant } from '@googleforcreators/design-system';
function MyComponent() {
return (
<>
<Button
size={ButtonSize.Medium}
type={ButtonType.Primary}
onClick={() => console.log('clicked')}
>
Click Me
</Button>
<Button
size={ButtonSize.Small}
type={ButtonType.Secondary}
disabled
>
Disabled
</Button>
</>
);
}
import { ToggleButton } from '@googleforcreators/design-system';
function MyComponent() {
const [isToggled, setIsToggled] = useState(false);
return (
<ToggleButton
isToggled={isToggled}
onClick={() => setIsToggled(!isToggled)}
>
Toggle Me
</ToggleButton>
);
}
Button Props
size:ButtonSize.Small | ButtonSize.Medium | ButtonSize.Largetype:ButtonType.Primary | ButtonType.Secondary | ButtonType.Tertiary | ButtonType.Quaternaryvariant:ButtonVariant.Rectangle | ButtonVariant.Circle | ButtonVariant.Squaredisabled: booleanonClick: click handler
Form Controls
- Input
- NumericInput
- Checkbox
- Switch
import { Input } from '@googleforcreators/design-system';
function MyComponent() {
const [value, setValue] = useState('');
return (
<Input
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Enter text..."
aria-label="Text input"
/>
);
}
import { NumericInput } from '@googleforcreators/design-system';
function MyComponent() {
const [value, setValue] = useState(0);
return (
<NumericInput
value={value}
onChange={setValue}
min={0}
max={100}
unit="px"
aria-label="Width"
/>
);
}
import { Checkbox } from '@googleforcreators/design-system';
function MyComponent() {
const [checked, setChecked] = useState(false);
return (
<Checkbox
checked={checked}
onChange={(e) => setChecked(e.target.checked)}
>
Accept terms
</Checkbox>
);
}
import { Switch } from '@googleforcreators/design-system';
function MyComponent() {
const [enabled, setEnabled] = useState(false);
return (
<Switch
value={enabled}
onChange={setEnabled}
label="Enable feature"
/>
);
}
Layout & Navigation
Modal
import { Modal } from '@googleforcreators/design-system';
function MyComponent() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Button onClick={() => setIsOpen(true)}>Open Modal</Button>
<Modal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
title="Modal Title"
>
<p>Modal content goes here</p>
</Modal>
</>
);
}
Dialog
import { Dialog } from '@googleforcreators/design-system';
function ConfirmDialog({ isOpen, onClose, onConfirm }) {
return (
<Dialog
isOpen={isOpen}
onClose={onClose}
title="Confirm Action"
actions={
<>
<Button onClick={onClose}>Cancel</Button>
<Button type={ButtonType.Primary} onClick={onConfirm}>
Confirm
</Button>
</>
}
>
Are you sure you want to proceed?
</Dialog>
);
}
Popup
import { Popup, PopupProvider } from '@googleforcreators/design-system';
function App() {
return (
<PopupProvider>
<MyComponent />
</PopupProvider>
);
}
function MyComponent() {
const [isOpen, setIsOpen] = useState(false);
const anchorRef = useRef(null);
return (
<>
<Button ref={anchorRef} onClick={() => setIsOpen(true)}>
Open Popup
</Button>
<Popup
anchor={anchorRef}
isOpen={isOpen}
onClose={() => setIsOpen(false)}
>
Popup content
</Popup>
</>
);
}
Menus & Navigation
ContextMenu
import {
ContextMenu,
ContextMenuProvider,
ContextMenuComponents
} from '@googleforcreators/design-system';
const { Item, Separator, Group } = ContextMenuComponents;
function MyComponent() {
return (
<ContextMenuProvider>
<ContextMenu
items={[
<Item onClick={() => console.log('Edit')}>Edit</Item>,
<Item onClick={() => console.log('Copy')}>Copy</Item>,
<Separator />,
<Group label="More Options">
<Item onClick={() => console.log('Delete')}>Delete</Item>
</Group>
]}
>
Right-click me
</ContextMenu>
</ContextMenuProvider>
);
}
DropDown
import { DropDown } from '@googleforcreators/design-system';
function MyComponent() {
const [selected, setSelected] = useState('option1');
const options = [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' },
{ value: 'option3', label: 'Option 3' },
];
return (
<DropDown
options={options}
value={selected}
onChange={setSelected}
placeholder="Select option..."
/>
);
}
Feedback Components
- Snackbar
- Tooltip
- Banner
import { SnackbarProvider, useSnackbar } from '@googleforcreators/design-system';
function App() {
return (
<SnackbarProvider>
<MyComponent />
</SnackbarProvider>
);
}
function MyComponent() {
const { showSnackbar } = useSnackbar();
const handleSave = async () => {
try {
await saveData();
showSnackbar({
message: 'Saved successfully!',
dismissable: true,
});
} catch (error) {
showSnackbar({
message: 'Error saving',
dismissable: true,
});
}
};
return <Button onClick={handleSave}>Save</Button>;
}
import { Tooltip } from '@googleforcreators/design-system';
function MyComponent() {
return (
<Tooltip title="This is a helpful tooltip">
<Button>Hover me</Button>
</Tooltip>
);
}
import { Banner } from '@googleforcreators/design-system';
function MyComponent() {
return (
<Banner
onClose={() => console.log('closed')}
closeButtonLabel="Dismiss"
>
Important information here!
</Banner>
);
}
Progress Indicators
- LoadingSpinner
- CircularProgress
- LoadingBar
import { LoadingSpinner } from '@googleforcreators/design-system';
function MyComponent() {
return <LoadingSpinner />;
}
import { CircularProgress } from '@googleforcreators/design-system';
function MyComponent() {
const [progress, setProgress] = useState(0);
return (
<CircularProgress
value={progress}
max={100}
aria-label="Upload progress"
/>
);
}
import { LoadingBar } from '@googleforcreators/design-system';
function MyComponent() {
const [isLoading, setIsLoading] = useState(true);
return isLoading && <LoadingBar />;
}
Typography
import {
Text,
Headline,
Display,
TextSize
} from '@googleforcreators/design-system';
function MyComponent() {
return (
<>
<Display size={TextSize.Large}>Display Text</Display>
<Headline size={TextSize.Medium}>Headline</Headline>
<Text size={TextSize.Small}>Body text</Text>
</>
);
}
Utility Components
Search
import { Search } from '@googleforcreators/design-system';
function MyComponent() {
const [searchTerm, setSearchTerm] = useState('');
return (
<Search
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Search..."
/>
);
}
Slider
import { Slider } from '@googleforcreators/design-system';
function MyComponent() {
const [value, setValue] = useState(50);
return (
<Slider
value={value}
onChange={setValue}
min={0}
max={100}
aria-label="Volume"
/>
);
}
InfiniteScroller
import { InfiniteScroller } from '@googleforcreators/design-system';
function MyComponent() {
const loadMore = async () => {
// Load more items
};
return (
<InfiniteScroller
onLoadMore={loadMore}
hasMore={hasMoreItems}
>
{items.map(item => <Item key={item.id} {...item} />)}
</InfiniteScroller>
);
}
Icons
The design system includes a comprehensive icon set:import { Icons } from '@googleforcreators/design-system';
function MyComponent() {
return (
<>
<Icons.Checkmark />
<Icons.Close />
<Icons.ArrowDown />
<Icons.Plus />
</>
);
}
Theme
Access theme constants and helpers:import {
lightMode,
THEME_CONSTANTS,
themeHelpers,
ThemeGlobals
} from '@googleforcreators/design-system';
import { ThemeProvider } from 'styled-components';
import styled from 'styled-components';
function App() {
return (
<ThemeProvider theme={lightMode}>
<ThemeGlobals.GlobalStyle />
<MyComponent />
</ThemeProvider>
);
}
// Using theme in styled components
const StyledDiv = styled.div`
color: ${({ theme }) => theme.colors.fg.primary};
${({ theme }) => themeHelpers.focusableOutlineCSS(theme.colors.border.focus)};
`;
Storage Utilities
import {
localStore,
LOCAL_STORAGE_PREFIX,
sessionStore,
SESSION_STORAGE_PREFIX
} from '@googleforcreators/design-system';
// Local storage
localStore.setItem('key', { data: 'value' });
const data = localStore.getItem('key');
// Session storage
sessionStore.setItem('tempKey', 'value');
const tempData = sessionStore.getItem('tempKey');
Keyboard Navigation
import {
useKeyboardNavigation,
useGridViewKeys
} from '@googleforcreators/design-system';
function MyList() {
const { currentIndex, handleKeyDown } = useKeyboardNavigation({
itemCount: items.length,
onSelect: (index) => selectItem(items[index]),
});
return (
<div onKeyDown={handleKeyDown}>
{items.map((item, index) => (
<div key={item.id} aria-selected={index === currentIndex}>
{item.name}
</div>
))}
</div>
);
}
Accessibility
All components follow accessibility best practices:- Proper ARIA attributes
- Keyboard navigation support
- Focus management
- Screen reader support
import { VisuallyHidden } from '@googleforcreators/design-system';
function MyComponent() {
return (
<button>
<Icons.Delete />
<VisuallyHidden>Delete item</VisuallyHidden>
</button>
);
}
Modal Setup
Before using modals, you must set the app element for accessibility:
import { setAppElement } from '@googleforcreators/design-system';
setAppElement('#root');