Primitives
All 30 basic primitives, live, one anchor per component — link an anchor (e.g. /design-system/primitives/#toggle) when filing an issue against a primitive. Source of truth: portal-ds/ds/primitives/ (the portal-ds snapshot).
| Primitive | What it is | Source | Full demo |
|---|---|---|---|
| Button | primary / secondary / ghost / danger actions | portal-ds/ds/primitives/Button.tsx | buttons → |
| Badge | small tonal label | portal-ds/ds/primitives/Badge.tsx | badges → |
| StatusPill | state chip with optional dot | portal-ds/ds/primitives/StatusPill.tsx | badges → |
| IconChip | toned icon square | portal-ds/ds/primitives/IconChip.tsx | badges → |
| NotificationBadge | unread count bubble | portal-ds/ds/primitives/NotificationBadge.tsx | badges → |
| Card | the base surface | portal-ds/ds/primitives/Card.tsx | cards → |
| CompactCard | headered dense card | portal-ds/ds/primitives/CompactCard.tsx | cards → |
| ActionCard | icon + label link/CTA card | portal-ds/ds/primitives/ActionCard.tsx | cards → |
| ActionCardRow | section header + grid of ActionCards | portal-ds/ds/primitives/ActionCardRow.tsx | cards → |
| LockableToolCard | gated tool entry (card) | portal-ds/ds/primitives/LockableToolCard.tsx | cards → |
| LockableToolRow | gated tool entry (row) | portal-ds/ds/primitives/LockableToolRow.tsx | lists → |
| Input | single-line text input | portal-ds/ds/primitives/Input.tsx | forms → |
| Textarea | multi-line input | portal-ds/ds/primitives/Textarea.tsx | forms → |
| Select | native select, DS-skinned | portal-ds/ds/primitives/Select.tsx | forms → |
| Label | form control label | portal-ds/ds/primitives/Label.tsx | forms → |
| Field | label + hint + error wrapper | portal-ds/ds/primitives/Field.tsx | forms → |
| Toggle | controlled switch | portal-ds/ds/primitives/Toggle.tsx | forms → |
| Alert | inline toned message | portal-ds/ds/primitives/Alert.tsx | feedback → |
| EmptyState | nothing-here placeholder | portal-ds/ds/primitives/EmptyState.tsx | feedback → |
| ErrorState | load-failure placeholder | portal-ds/ds/primitives/ErrorState.tsx | feedback → |
| Skeleton / SkeletonText | loading placeholders | portal-ds/ds/primitives/Skeleton.tsx | feedback → |
| ListRow | icon + title + action row | portal-ds/ds/primitives/ListRow.tsx | lists → |
| CompactListItem | dense list line | portal-ds/ds/primitives/CompactListItem.tsx | lists → |
| SectionHeader | uppercase section label | portal-ds/ds/primitives/SectionHeader.tsx | navigation → |
| PageHeader | page title block | portal-ds/ds/primitives/PageHeader.tsx | navigation → |
| PageTabs | horizontal link tabs | portal-ds/ds/primitives/PageTabs.tsx | navigation → |
| SideTabs | vertical link rail | portal-ds/ds/primitives/SideTabs.tsx | navigation → |
| ProgressSteps | numbered step rail | portal-ds/ds/primitives/ProgressSteps.tsx | workflow → |
| PageContainer | page width frame (wraps this page) | portal-ds/ds/primitives/PageContainer.tsx | navigation → |
| cn | class-merge utility (clsx + tailwind-merge) | portal-ds/ds/primitives/cn.ts | — |
Badge
portal-ds/ds/primitives/Badge.tsx
StatusPill
portal-ds/ds/primitives/StatusPill.tsx
IconChip
portal-ds/ds/primitives/IconChip.tsx
NotificationBadge
portal-ds/ds/primitives/NotificationBadge.tsx
Card
portal-ds/ds/primitives/Card.tsx
CompactCard
portal-ds/ds/primitives/CompactCard.tsx
Roster
Card body content.
ActionCard
portal-ds/ds/primitives/ActionCard.tsx
Browse the directory.
CTA-button form.
ActionCardRow
portal-ds/ds/primitives/ActionCardRow.tsx
Ways to get involved
LockableToolCard
portal-ds/ds/primitives/LockableToolCard.tsx
Data export
Locked tool.
Requires the director role.
LockableToolRow
portal-ds/ds/primitives/LockableToolRow.tsx
Input
portal-ds/ds/primitives/Input.tsx
Textarea
portal-ds/ds/primitives/Textarea.tsx
Select
portal-ds/ds/primitives/Select.tsx
Label
portal-ds/ds/primitives/Label.tsx
Field
portal-ds/ds/primitives/Field.tsx
Digits only.
Enter a 5-digit zip.
Toggle
portal-ds/ds/primitives/Toggle.tsx
Alert
portal-ds/ds/primitives/Alert.tsx
EmptyState
portal-ds/ds/primitives/EmptyState.tsx
You're all caught up
No notifications right now.
ErrorState
portal-ds/ds/primitives/ErrorState.tsx
Something went wrong
We couldn't load your teams.
Skeleton / SkeletonText
portal-ds/ds/primitives/Skeleton.tsx
ListRow
portal-ds/ds/primitives/ListRow.tsx
CompactListItem
portal-ds/ds/primitives/CompactListItem.tsx
SectionHeader
portal-ds/ds/primitives/SectionHeader.tsx
Your teams
Members
PageHeader
portal-ds/ds/primitives/PageHeader.tsx
Your dashboard
Everything you need to get involved.
PageTabs
portal-ds/ds/primitives/PageTabs.tsx
SideTabs
portal-ds/ds/primitives/SideTabs.tsx
ProgressSteps
portal-ds/ds/primitives/ProgressSteps.tsx
- Apply
- Verify email
- Pick a team
- March
PageContainer
portal-ds/ds/primitives/PageContainer.tsx — the width frame already wrapping every page of this catalog (no nested demo; see the page you're reading).
Width variants and gutters are demoed on the navigation & page structure page.
cn
portal-ds/ds/primitives/cn.ts — clsx + tailwind-merge; utility, nothing to render.
last conflicting class wins