
Product
Introducing Supply Chain Attack Campaigns Tracking in the Socket Dashboard
Campaign-level threat intelligence in Socket now shows when active supply chain attacks affect your repositories and packages.
@canonical/design-system
Advanced tools
An OWL ontology for modeling UI design systems as structured, queryable knowledge graphs. Built to bridge the gap between design specifications and implementation by establishing a shared semantic vocabulary for components, patterns, layouts, and their re
An OWL ontology for modeling UI design systems as structured, queryable knowledge graphs. Built to bridge the gap between design specifications and implementation by establishing a shared semantic vocabulary for components, patterns, layouts, and their relationships.
Core Philosophy: A design system is more than a component library - it's a formal language. By modeling UI elements ontologically, we enable machine-readable specifications, automated consistency checking, and intelligent tooling that understands design intent.
The ontology organizes UI elements into a hierarchy:
UIElement (root)
βββ UIBlock (visual/abstract entity for composing UIs)
βββ Component - Implementable UI piece (Button, Badge, Card...)
βββ Pattern - Reusable solution to UX problems
βββ Layout - Opinionated space division for navigation
βββ Subcomponent - Part of a parent component
Components are organized by Tiers (scope/applicability) and can be customized through ModifierFamilies (variant axes).
@prefix dso: <https://ds.canonical.com/ontology#> .
@prefix ds: <https://ds.canonical.com/data/> .
ds:global.component.button a dso:Component ;
dso:name "Button" ;
dso:description "Buttons trigger actions within an interface" ;
dso:tier ds:global ;
dso:hasModifierFamily ds:global.modifier_family.importance ;
dso:whenToUse "For primary actions that transform or submit data" ;
dso:whenNotToUse "For navigation - use links instead" .
Components belong to tiers that define their scope:
| Tier | Description | Example Components |
|---|---|---|
global | Universal components | Button, Badge, Card, Accordion |
global_form | Form-specific | Input, Select, Checkbox |
apps | Application UI | Navigation, Toolbar, FileTree |
apps_wpe | WordPress-specific | WPE variants |
site | Marketing/website | Hero, Footer |
stores | E-commerce | Product card, Cart |
documentation | Docs-specific | Code block, API reference |
Modifiers provide systematic variation through ModifierFamilies:
ds:global.modifier_family.importance a dso:ModifierFamily ;
dso:name "Importance" ;
dso:hasModifier ds:global.modifier.primary,
ds:global.modifier.secondary,
ds:global.modifier.tertiary .
ds:global.component.button
dso:hasModifierFamily ds:global.modifier_family.importance .
Available modifier families:
data/{tier}/component/@prefix dso: <https://ds.canonical.com/ontology#> .
@prefix ds: <https://ds.canonical.com/data/> .
ds:apps.component.file_tree a dso:Component ;
dso:name "FileTree" ;
dso:description "Hierarchical file browser for navigating directory structures" ;
dso:tier ds:apps ;
dso:whenToUse "When users need to navigate nested file hierarchies" ;
dso:figmaLink <https://figma.com/file/...> .
Layouts define how space is divided for a domain of information:
ds:apps.layout.sidebar a dso:Layout ;
dso:name "Sidebar Layout" ;
dso:domain "Application navigation" ;
dso:grid "1fr 4fr" ;
dso:gridAreas "sidebar main" ;
dso:targetDevices "desktop, tablet" .
Patterns are reusable solutions to UX problems:
ds:global.pattern.empty_state a dso:Pattern ;
dso:name "Empty State" ;
dso:description "Guidance shown when a container has no content" ;
dso:tier ds:global ;
dso:whenToUse "When a list, table, or container is empty" ;
dso:guidelines "Include illustration, message, and action" .
Use subcomponents for parts that belong to a parent:
ds:global.subcomponent.button_icon a dso:Subcomponent ;
dso:name "Button Icon" ;
dso:parentComponent ds:global.component.button ;
dso:standalone false .
Using sem tools:
# Find all global components
sem lookup dso:Component --filter 'tier=ds:global'
# Get context for a specific component
sem context ds:global.component.button
# Find components using a modifier family
sem sparql "SELECT ?c WHERE { ?c dso:hasModifierFamily ds:global.modifier_family.criticality }"
| Class | Description | Instances |
|---|---|---|
UIElement | Root class for all design system entities | - |
UIBlock | Visual/abstract entity for composing UIs | - |
Component | Implementable UI piece | 50 |
Pattern | Reusable UX solution | 21 |
Layout | Space division for navigation | 9 |
Subcomponent | Part of a component | 13 |
Modifier | Variant option | 31 |
ModifierFamily | Grouping of related modifiers | 9 |
Tier | Scope/applicability level | 7 |
Property | Configurable component property | 2 |
Token | Design token reference | - |
ImplementationObject | Platform-specific implementation | - |
ImplementationLibrary | Implementation library | - |
| Property | Range | Description |
|---|---|---|
name | string | Display name |
description | string | What this block is/does |
tier | Tier | Scope classification |
whenToUse | string | Usage guidance |
whenNotToUse | string | Anti-patterns |
guidelines | string | Design guidelines |
variants | string | Available variants |
figmaLink | anyURI | Link to Figma designs |
wireframeLink | anyURI | Link to wireframes |
anatomy | anyURI | Link to anatomy diagram |
hasModifierFamily | ModifierFamily | Applicable variant axes |
hasProperty | Property | Configurable properties |
usesToken | Token | Design tokens used |
| Property | Range | Description |
|---|---|---|
domain | string | Information domain |
grid | string | CSS grid definition |
gridAreas | string | Named grid areas |
targetDevices | string | Supported devices |
| Property | Domain | Range | Description |
|---|---|---|---|
hasSubcomponent | Component | Subcomponent | Composition |
parentComponent | Subcomponent | Component | Inverse of above |
hasModifierFamily | UIBlock | ModifierFamily | Variant axes |
hasModifier | ModifierFamily | Modifier | Variant options |
| Property | Domain | Range | Description |
|---|---|---|---|
implementsBlock | ImplementationObject | UIBlock | Links code to spec |
library | ImplementationObject | ImplementationLibrary | Source library |
libraryTier | ImplementationLibrary | Tier | Library's tier |
After a decade using Vanilla Framework (CSS library), Canonical observed that visual consistency worked well but led to challenges:
An ontology addresses these by:
1. Separation of Concept and Implementation
The ontology separates the what (UIBlock) from the how (ImplementationObject). A Button concept can have multiple implementations across React, Web Components, or Flutter while maintaining semantic identity.
2. Tiered Scoping
Not all components belong everywhere. Tiers make scope explicit - global components are universal, while apps-tier components may not make sense on marketing sites.
3. Systematic Variation
ModifierFamilies provide principled variation. Instead of ad-hoc props like isImportant, isPrimary, variant="critical", the ontology models Importance and Criticality as distinct axes that components can opt into.
4. Documentation as Data
Usage guidelines, when-to-use patterns, and design rationale are first-class properties - queryable, versionable, and programmatically accessible.
design-system/
βββ definitions/
β βββ ontology.ttl # TBox: Classes, properties
βββ data/
β βββ global/ # Global tier instances
β β βββ component/ # Button, Badge, Card...
β β βββ pattern/ # Empty state, Loading...
β β βββ layout/ # Grid layouts
β β βββ modifier/ # Primary, Secondary...
β β βββ modifier_family/ # Importance, Criticality...
β βββ apps/ # Apps tier
β βββ site/ # Site tier
β βββ ... # Other tiers
βββ sem.toml # Package manifest
βββ README.md # This file
@prefix dso: <https://ds.canonical.com/ontology#> . # Ontology (TBox)
@prefix ds: <https://ds.canonical.com/data/> . # Instances (ABox)
Instances follow the pattern: {tier}.{class}.{name}
ds:global.component.button
ds:apps.layout.sidebar
ds:global.modifier_family.importance
The design system data is extracted from Coda and transformed to RDF:
bun install
# Create .env with Coda API key
echo "CODA_API_KEY=your-token" > .env
# Extract and transform
bun run ds:list # List available tables
bun run ds:extract # Extract to JSON
bun run ds:transform # Transform to JSON-LD/Turtle
The collect-implementations script scans codebases for @implements annotations and generates RDF linking implementations to their design system specifications.
design-system.json config file in your project root:{
"name": "my-component-library",
"platform": "react",
"description": "React implementation of the design system",
"link": "https://github.com/org/my-library",
"documentation": "https://docs.example.com/components",
"tier": "ds:global",
"prefix": {
"short": "ds",
"namespace": "https://ds.canonical.com/"
},
"pattern": "src/**/*.tsx",
"outputDir": "data"
}
| Field | Required | Description |
|---|---|---|
name | Yes | Library identifier (e.g., "pragma-react") |
platform | Yes | Framework/platform (react, vue, angular, etc.) |
description | No | Human-readable library description |
link | Yes | Main repository or package URL |
documentation | No | Documentation URL if different from link |
tier | No | Design system tier reference (e.g., "ds:global") |
prefix.short | Yes | Namespace prefix used in annotations (e.g., "ds") |
prefix.namespace | Yes | Full namespace URI |
pattern | Yes | Glob pattern for files to scan |
outputDir | No | Output directory for .ttl files (default: "data") |
Add @implements annotations as comments in your component files:
// @implements ds:global.component.button
export function Button({ children, ...props }) {
return <button {...props}>{children}</button>;
}
Annotation formats:
// @implements ds:global.component.button// @implements ds:global.component.button@1.0.0// @implements ds:global.component.button [draft]From within your project directory (where design-system.json is located):
# Using bun directly
bun /path/to/design-system/src/collect-implementations.ts
# Or if installed globally/linked
collect-implementations
The collector generates two Turtle files in the configured output directory:
implementationLibrary.ttl - Defines the implementation library:
lib:my-component-library a dso:ImplementationLibrary ;
dso:name "my-component-library" ;
dso:platform "react" ;
dso:link <https://github.com/org/my-library> .
implementationObjects.ttl - Links each annotated file to its spec:
lib:my-component-library.button a dso:ImplementationObject ;
dso:implementsBlock ds:global.component.button ;
dso:library lib:my-component-library ;
dso:sourceFile "src/components/Button.tsx" .
# 1. Navigate to your component library
cd my-react-library
# 2. Add annotations to components
echo '// @implements ds:global.component.button' >> src/Button.tsx
# 3. Run the collector
bun ~/code/cn/design-system/src/collect-implementations.ts
# Output:
# Scanning src/**/*.tsx for @implements annotations...
# Found 1 valid implementation(s):
# - ds:global.component.button
# Written: data/implementationLibrary.ttl
# Written: data/implementationObjects.ttl
# Done!
0.1.0 - Initial release with component/pattern/layout hierarchy, tier organization, and modifier system
FAQs
An OWL ontology for modeling UI design systems as structured, queryable knowledge graphs. Built to bridge the gap between design specifications and implementation by establishing a shared semantic vocabulary for components, patterns, layouts, and their re
We found that @canonical/design-system demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 26 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Campaign-level threat intelligence in Socket now shows when active supply chain attacks affect your repositories and packages.

Research
Malicious PyPI package sympy-dev targets SymPy users, a Python symbolic math library with 85 million monthly downloads.

Security News
Node.js 25.4.0 makes require(esm) stable, formalizing CommonJS and ESM compatibility across supported Node versions.