πŸš€ Launch Week Day 3:Introducing Supply Chain Attack Campaigns Tracking.Learn More β†’
Socket
Book a DemoInstallSign in
Socket

@canonical/design-system

Package Overview
Dependencies
Maintainers
26
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@canonical/design-system

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

latest
npmnpm
Version
0.1.0
Version published
Maintainers
26
Created
Source

Design System Ontology

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.

Quick Start

1. Core Concepts

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).

2. Defining a Component

@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" .

3. Tiered Organization

Components belong to tiers that define their scope:

TierDescriptionExample Components
globalUniversal componentsButton, Badge, Card, Accordion
global_formForm-specificInput, Select, Checkbox
appsApplication UINavigation, Toolbar, FileTree
apps_wpeWordPress-specificWPE variants
siteMarketing/websiteHero, Footer
storesE-commerceProduct card, Cart
documentationDocs-specificCode block, API reference

4. Modifier System

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:

  • Importance - Visual hierarchy (primary, secondary, tertiary)
  • Criticality - Severity levels (success, warning, error)
  • Density - Spacing variants (compact, default, comfortable)
  • Lifecycle - State (draft, active, deprecated)
  • Anticipation - Expected interaction type

How-To Guides

How to Add a New Component

  • Determine the appropriate tier based on scope
  • Create a Turtle file in data/{tier}/component/
  • Define required properties: name, description, tier
  • Link to applicable modifier families
  • Add usage guidelines (whenToUse, whenNotToUse)
@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/...> .

How to Define a Layout

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" .

How to Create a Pattern

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" .

How to Model Component Composition

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 .

How to Query the Design System

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 }"

Reference

Classes

ClassDescriptionInstances
UIElementRoot class for all design system entities-
UIBlockVisual/abstract entity for composing UIs-
ComponentImplementable UI piece50
PatternReusable UX solution21
LayoutSpace division for navigation9
SubcomponentPart of a component13
ModifierVariant option31
ModifierFamilyGrouping of related modifiers9
TierScope/applicability level7
PropertyConfigurable component property2
TokenDesign token reference-
ImplementationObjectPlatform-specific implementation-
ImplementationLibraryImplementation library-

UIBlock Properties

PropertyRangeDescription
namestringDisplay name
descriptionstringWhat this block is/does
tierTierScope classification
whenToUsestringUsage guidance
whenNotToUsestringAnti-patterns
guidelinesstringDesign guidelines
variantsstringAvailable variants
figmaLinkanyURILink to Figma designs
wireframeLinkanyURILink to wireframes
anatomyanyURILink to anatomy diagram
hasModifierFamilyModifierFamilyApplicable variant axes
hasPropertyPropertyConfigurable properties
usesTokenTokenDesign tokens used

Layout-Specific Properties

PropertyRangeDescription
domainstringInformation domain
gridstringCSS grid definition
gridAreasstringNamed grid areas
targetDevicesstringSupported devices

Component Relationships

PropertyDomainRangeDescription
hasSubcomponentComponentSubcomponentComposition
parentComponentSubcomponentComponentInverse of above
hasModifierFamilyUIBlockModifierFamilyVariant axes
hasModifierModifierFamilyModifierVariant options

Implementation Bridge

PropertyDomainRangeDescription
implementsBlockImplementationObjectUIBlockLinks code to spec
libraryImplementationObjectImplementationLibrarySource library
libraryTierImplementationLibraryTierLibrary's tier

Explanation

Why an Ontology?

After a decade using Vanilla Framework (CSS library), Canonical observed that visual consistency worked well but led to challenges:

  • Inconsistent terminology - Same component, different names across teams
  • Implicit relationships - Component composition undocumented
  • Lost design rationale - Why decisions were made
  • Fragmented specifications - Figma, docs, code out of sync

An ontology addresses these by:

  • Establishing shared vocabulary - One name, one meaning
  • Explicit relationships - Queryable component graph
  • Structured metadata - Guidelines, rationale, links preserved
  • Machine-readable specs - Enables tooling and validation

Design Principles

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.

Architecture

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

Namespaces

@prefix dso: <https://ds.canonical.com/ontology#> .  # Ontology (TBox)
@prefix ds:  <https://ds.canonical.com/data/> .      # Instances (ABox)

URI Convention

Instances follow the pattern: {tier}.{class}.{name}

ds:global.component.button
ds:apps.layout.sidebar
ds:global.modifier_family.importance

Dependencies

  • sem_v1 - Semantic package infrastructure
  • artifact - Artifact lifecycle management

Data Pipeline

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

Implementation Collector

The collect-implementations script scans codebases for @implements annotations and generates RDF linking implementations to their design system specifications.

Setup

  • Create a 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"
}

Configuration Options

FieldRequiredDescription
nameYesLibrary identifier (e.g., "pragma-react")
platformYesFramework/platform (react, vue, angular, etc.)
descriptionNoHuman-readable library description
linkYesMain repository or package URL
documentationNoDocumentation URL if different from link
tierNoDesign system tier reference (e.g., "ds:global")
prefix.shortYesNamespace prefix used in annotations (e.g., "ds")
prefix.namespaceYesFull namespace URI
patternYesGlob pattern for files to scan
outputDirNoOutput directory for .ttl files (default: "data")

Annotating Components

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:

  • Basic: // @implements ds:global.component.button
  • With version: // @implements ds:global.component.button@1.0.0
  • Draft status: // @implements ds:global.component.button [draft]

Running the Collector

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

Output

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" .
    

Example Workflow

# 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!

Version

0.1.0 - Initial release with component/pattern/layout hierarchy, tier organization, and modifier system

References

  • Canonical's Design System: Towards a Design System Ontology
  • Vanilla Framework

FAQs

Package last updated on 20 Jan 2026

Did you know?

Socket

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.

Install

Related posts