| name | Atlassian Design System |
| description | Build collaborative team interfaces with Atlassian Design System—a React-based system used in Jira, Confluence, and Trello with design tokens, dynamic tables, flags, inline editing, and emphasis on team workflows. Trigger this skill when designing project management tools, team collaboration UIs, issue tracking systems, or workflow-heavy applications. |
What Is Atlassian Design System?
Atlassian Design System powers tools like Jira, Confluence, and Trello. It prioritizes team collaboration, information hierarchy, and flexible layouts for workflows like issue tracking, content management, and project planning. Built in React with design tokens for theming. Every component supports light/dark modes and accessibility out of the box.
Core Design Principles
1. Information Hierarchy
Team members need to understand status at a glance. Color, typography weight, and positioning guide the eye to what matters: priority issues, team assignments, deadlines.
2. Workflow-Centric
Components enable common actions: create, comment, assign, transition status, link related items. Layouts adapt to different workflow states.
3. Composable Tokens
Design decisions (colors, spacing, shadows) are parameterized as tokens. Teams apply consistent styling without repeating values. Supports theming (light/dark).
4. Inline and Non-Modal
Atlassian favors inline editing, inline pickers, and smaller overlays over heavy modals. Less disruption, faster workflows.
Visual Language
Colors (Light Mode):
- Primary: #0052CC (blue) for CTAs, status updates
- Secondary: #626F86 (gray) for supportive text
- Background: #FFFFFF, subtle container #F7F8F9
- Status: Green (#216E4E) success, Yellow (#974F0C) warning, Red (#AE2A19) error
- Text: #161B22 (body), #626F86 (secondary)
Typography:
- Body: 14px / 20px line-height
- Headings: 16px (h3), 20px (h2), 24px (h1), weight 600
- Font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif
Spacing (8px base):
- xs: 4px, sm: 8px, md: 12px, lg: 16px, xl: 24px, xxl: 32px
- Use CSS variables:
var(--ds-space-100) through var(--ds-space-800)
Elevation & Shadows:
- Subtle:
0 1px 1px rgba(9, 30, 66, 0.13)
- Raised:
0 4px 8px rgba(9, 30, 66, 0.13)
- Overlay:
0 8px 16px rgba(9, 30, 66, 0.15)
Component Patterns
Dynamic Table with Inline Actions
Table that responds to row hover, enables inline editing, shows contextual menus.
import { Table } from '@atlaskit/dynamic-table';
import { Button } from '@atlaskit/button';
import { MoreIcon } from '@atlaskit/icon';
export function IssueTable({ issues }) {
return (
<Table
head={{
cells: [
{ key: 'key', content: 'Key' },
{ key: 'summary', content: 'Summary' },
{ key: 'assignee', content: 'Assignee' },
{ key: 'status', content: 'Status' },
{ key: 'actions', content: '' }
]
}}
rows={issues.map(issue => ({
key: issue.key,
cells: [
{ key: 'key', content: <a href={`/issue/${issue.key}`}>{issue.key}</a> },
{ key: 'summary', content: issue.summary },
{ key: 'assignee', content: issue.assignee?.name },
{ key: 'status', content: <Badge appearance="default">{issue.status}</Badge> },
{
key: 'actions',
content: (
<Button iconBefore={<MoreIcon />} appearance="subtle" onClick={() => {}} />
)
}
]
}))}
/>
);
}
Flag (Toast-like Notification)
Non-intrusive notification for workflow feedback.
import { Flag, FlagGroup } from '@atlaskit/flag';
import { CheckCircleIcon } from '@atlaskit/icon';
export function NotificationCenter() {
const [flags, setFlags] = useState([]);
return (
<FlagGroup onDismissed={(id) => setFlags(f => f.filter(x => x.id !== id))}>
{flags.map(flag => (
<Flag
key={flag.id}
id={flag.id}
icon={<CheckCircleIcon primaryColor="green" />}
title={flag.title}
description={flag.description}
actions={[{ content: 'Undo', onClick: () => {} }]}
/>
))}
</FlagGroup>
);
}
Modal Dialog
Focused interaction for complex tasks (create issue, link related items).
import { ModalDialog, ModalHeader, ModalBody, ModalFooter } from '@atlaskit/modal-dialog';
import { Button } from '@atlaskit/button';
export function CreateIssueModal({ onClose, onSubmit }) {
const [formData, setFormData] = useState({});
return (
<ModalDialog onClose={onClose}>
<ModalHeader>
<h2>Create Issue</h2>
</ModalHeader>
<ModalBody>
<TextField
name="summary"
placeholder="What needs to be done?"
onChange={(e) => setFormData({ ...formData, summary: e.target.value })}
/>
<Select
name="project"
options={[{ label: 'Project A', value: 'proj-a' }]}
/>
</ModalBody>
<ModalFooter>
<Button onClick={onClose}>Cancel</Button>
<Button appearance="primary" onClick={() => onSubmit(formData)}>Create</Button>
</ModalFooter>
</ModalDialog>
);
}
Tree Component (Hierarchy View)
For navigating nested structures (page hierarchies in Confluence, folder trees).
import { Tree, Item, ItemGroup } from '@atlaskit/tree';
export function PageHierarchy() {
return (
<Tree
contents={[
{
id: '1',
children: ['2', '3'],
data: { title: 'Project Overview' },
isExpanded: true
},
{
id: '2',
children: [],
data: { title: 'Getting Started' },
isExpanded: false
},
{
id: '3',
children: [],
data: { title: 'API Documentation' },
isExpanded: false
}
]}
onExpand={(id) => console.log('expanded', id)}
renderItem={({ item, provided, snapshot }) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
padding: '8px',
paddingLeft: `${(item.depth || 0) * 16}px`,
backgroundColor: snapshot.isDraggingOver ? '#F7F8F9' : 'transparent'
}}
>
{item.data.title}
</div>
)}
/>
);
}
Code Generation Guidance
Use Atlassian when:
- Building issue/task tracking systems (like Jira)
- Creating collaborative content platforms (like Confluence)
- Designing team workspace UIs
- Building workflow-heavy, flexible layouts
React patterns:
- Import from
@atlaskit/xyz: button, modal-dialog, dynamic-table, tree, flag, inline-edit
- Use
@atlaskit/tokens for design token access: token('color.text.subtlest')
- Support light/dark mode via theme provider
- Design tokens:
spacing, color, elevation, font
CSS for custom components:
- Spacing:
padding: var(--ds-space-400) (16px)
- Colors:
color: var(--ds-text-subtlest)
- Shadows:
box-shadow: var(--ds-elevation-surface-raised)
- Transitions:
transition: all 150ms ease-in-out
Accessibility
- Focus indicators: Always visible blue outline, 2px width
- ARIA:
role="button", aria-expanded, aria-selected on interactive elements
- Semantic HTML: Tables use
<table>, forms use <label> for inputs
- Color contrast: AA compliant, no reliance on color alone for status
- Keyboard: Full keyboard navigation, arrow keys for trees/tables, Enter to activate
Examples
Example 1: Jira-like Issue Tracker
Input: "Create an issue list page with filtering by assignee, status, and priority with inline editing"
import { DynamicTable } from '@atlaskit/dynamic-table';
import { Select } from '@atlaskit/select';
import { Badge } from '@atlaskit/badge';
export default function IssueTracker() {
const [issues, setIssues] = useState([...]);
const [filters, setFilters] = useState({ assignee: null, status: null });
const filteredIssues = issues.filter(i =>
(!filters.assignee || i.assignee?.id === filters.assignee.value) &&
(!filters.status || i.status === filters.status.value)
);
return (
<div style={{ padding: '16px' }}>
<div style={{ display: 'flex', gap: '16px', marginBottom: '16px' }}>
<Select
inputId="assignee-filter"
name="assignee"
placeholder="Assignee"
options={assigneeOptions}
onChange={(opt) => setFilters({ ...filters, assignee: opt })}
/>
<Select
inputId="status-filter"
name="status"
placeholder="Status"
options={statusOptions}
onChange={(opt) => setFilters({ ...filters, status: opt })}
/>
</div>
<DynamicTable
head={{
cells: [
{ key: 'key', content: 'Key', width: 10 },
{ key: 'summary', content: 'Summary' },
{ key: 'assignee', content: 'Assignee' },
{ key: 'status', content: 'Status' },
{ key: 'priority', content: 'Priority' }
]
}}
rows={filteredIssues.map(issue => ({
key: issue.id,
cells: [
{ key: 'key', content: issue.key },
{ key: 'summary', content: issue.summary },
{ key: 'assignee', content: issue.assignee?.name || '—' },
{ key: 'status', content: <Badge>{issue.status}</Badge> },
{ key: 'priority', content: issue.priority }
]
}))}
/>
</div>
);
}
Example 2: Confluence-like Page Tree Navigation
Input: "Build a sidebar showing a tree of documentation pages with expand/collapse and active state"
import { Tree } from '@atlaskit/tree';
import { ItemGroup } from '@atlaskit/item';
export function DocSidebar({ pages, activePage, onNavigate }) {
return (
<nav style={{ width: '250px', padding: '16px', borderRight: '1px solid #EBECF0' }}>
<Tree
contents={buildTreeContents(pages)}
onExpand={(nodeId) => console.log('expanded', nodeId)}
renderItem={({ item, provided }) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
paddingLeft: `${(item.depth || 0) * 16}px`,
paddingTop: '8px',
paddingBottom: '8px',
cursor: 'pointer',
backgroundColor: item.id === activePage?.id ? '#F7F8F9' : 'transparent',
color: item.id === activePage?.id ? '#0052CC' : '#161B22',
fontWeight: item.id === activePage?.id ? '600' : '400'
}}
onClick={() => onNavigate(item.id)}
>
{item.data.title}
</div>
)}
/>
</nav>
);
}