
Security News
Socket Releases Free Certified Patches for Critical vm2 Sandbox Escape
A critical vm2 sandbox escape can allow untrusted JavaScript to break isolation and execute commands on the host Node.js process.
@ubnt/uids-tokens
Advanced tools
UniFi Design System tokens ā the single source of truth for design tokens across all platforms.
The single source of truth for UniFi Design System tokens. Built with Style Dictionary, sourced from Figma Variables API.
| Resource | URL |
|---|---|
| Token Browser | uids-tokens.uidev.tools |
| Token Scout Report | uids-tokens.uidev.tools/latest/report.html |
| npm Package | @ubnt/uids-tokens |
| Repository | github.com/ubiquiti/uids-tokens |
Figma (Variables API) ā fetch script ā tokens/*.json ā Style Dictionary ā dist/
Tokens are defined as JSON (DTCG format) in tokens/, transformed by Style Dictionary into multiple output formats, and published as an npm package.
| Import path | Format | Description |
|---|---|---|
@ubnt/uids-tokens | JS/TS | Default export (same as styled-components) |
@ubnt/uids-tokens/css-tokens | CSS | CSS custom properties with light/dark theme support |
@ubnt/uids-tokens/styled-components | JS/TS | Typed tokens object for CSS-in-JS |
@ubnt/uids-tokens/tokens.json | JSON | Flat JSON of all resolved tokens |
@ubnt/uids-tokens/theme | JS/TS | createTheme(mode) ā nested theme object for styled-components |
@ubnt/uids-tokens/compat | JS/TS | migrateTokenName() ā mapping from legacy token names |
bun install
bun run build
This runs Style Dictionary and outputs:
dist/css-tokens/variables.css ā CSS custom propertiesdist/styled-components/index.mjs + index.d.ts ā JS/TS moduledist/tokens.json ā flat JSONdist/theme/index.mjs + index.d.ts ā theme adapterdist/compat/index.mjs + index.d.ts ā compat mappingbun run build # must build tokens first
bun run site:dev # starts Vite dev server
/* Import the CSS file in your app entry point */
@import '@ubnt/uids-tokens/css-tokens';
.my-component {
color: var(--desktop-color-text-1);
background: var(--desktop-color-depth-bg-0);
padding: var(--desktop-spacing-medium);
border-radius: var(--desktop-radius-small);
}
Theme support is built in ā set data-theme="light" or data-theme="dark" on your root element:
<html data-theme="light">
<!-- Themed tokens are automatically applied -->
</html>
Token keys use kebab-case matching the CSS variable names (without --). This matches the UIC internal design token convention.
import { tokens } from '@ubnt/uids-tokens/styled-components'
// Fully typed ā autocomplete works
tokens['desktop-color-ublue-06-light'] // '#0066ff'
tokens['desktop-spacing-medium'] // '16px'
tokens['desktop-radius-small'] // '4px'
Prefer CSS
var()in styled-components ā the JS export is meant for non-CSS contexts like chart libraries or JS calculations. Usingvar()eliminates re-renders on theme change.
The theme adapter provides a createTheme(mode) function that returns a nested, typed theme object ā designed for apps using styled-components ThemeProvider.
import { createTheme } from '@ubnt/uids-tokens/theme'
import type { Theme, ThemeMode } from '@ubnt/uids-tokens/theme'
const theme = createTheme('light')
theme.color.neutral[3] // '#eeeff1'
theme.color.primary // '#006eff' (ublue-06)
theme.color.text[1] // '#212327'
theme.spacing.md // 16
theme.radius.sm // 4
theme.font.size.md // 14
theme.font.weight.bold // 700
theme.zIndex.modal // 1300
theme.animation.easing.easeInOut // 'cubic-bezier(0.4, 0, 0.2, 1)'
The theme is generated at build time by Style Dictionary ā not hand-maintained. It covers all token categories: color (10 scales + semantic aliases), spacing, radius, font, shadow, sizing, opacity, z-index, animation, blur, and viewport.
For gradual migration from @ubnt/ui-components token systems, the compat layer maps old names to new names:
import { migrateTokenName, compatMap } from '@ubnt/uids-tokens/compat'
// designToken['desktop-spacing-base-04'] style (network-fe)
migrateTokenName('desktop-spacing-base-04') // 'desktop-spacing-xsmall'
// theme.palette.neutralNN style (portal)
migrateTokenName('neutral03') // 'desktop-color-neutral-03'
// designToken('color-neutral-00', mode) style (protect)
migrateTokenName('color-neutral-00') // 'desktop-color-neutral-00'
// cssVariables.motifs.dark.uiNN style (network-fe)
migrateTokenName('ui07') // 'desktop-color-neutral-07'
240 mappings covering all legacy access patterns across the 4 main consumer apps.
Token Scout scans Ubiquiti app repos to measure token adoption, detect freestyle (hardcoded) values, and identify Figma drift.
Live report: uids-tokens.uidev.tools/latest/report.html
# Run against configured apps (see audit/audit.config.json)
bun run scout
# Individual subcommands
bun run scout:freestyle # Scan for freestyle values only
bun run scout:drift # Detect Figma drift only
bun run scout:inventory # Generate token inventory only
# Build report for deployment
bun run scout:report # Generates report + copies to site/public/report/
Token systems ā uids-tokens CSS vars, designToken, cssVariables, theme.palette, theme.alias, useTheme, SPACE_* constants, appTheme/ProtectTheme, Tailwind classes.
Freestyle values ā hardcoded hex colors, RGB/RGBA, spacing px values, border-radius, font-size, font-weight in style contexts.
Figma drift ā tokens in source but missing from build, tokens in build but not in Figma, value mismatches.
Edit audit/audit.config.json to point at consumer app repos:
{
"apps": [
{ "name": "unifi-portal", "path": "../unifi-portal" },
{ "name": "unifi-network-fe", "path": "../unifi-network-fe" }
]
}
This repo includes a script that pulls design token variables from Figma's Variables REST API and writes them as Style Dictionary JSON files.
Create a Figma personal access token at https://developers.figma.com/docs/rest-api/authentication/#access-tokens
file_variables:readCopy the example env file:
cp .env.example .env
Fill in your credentials:
FIGMA_TOKEN=your-personal-access-token
FIGMA_FILE_KEY=your-figma-file-key
The file key is the alphanumeric string in your Figma URL:
https://www.figma.com/design/ABC123/My-File ā ABC123
bun run tokens:fetch
Options:
-k, --file-key <key> Override FIGMA_FILE_KEY
-t, --token <token> Override FIGMA_TOKEN
--published Fetch published variables instead of local
-o, --output-dir <dir> Output directory (default: project root)
--dry-run Preview output without writing files
-h, --help Show help
After fetching, rebuild tokens:
bun run build
To point at your organization's Figma file instead of a personal one:
FIGMA_FILE_KEY in .env (or in GitHub repo secrets)FIGMA_TOKEN if needed (ensure it has access to the org file)bun run tokens:fetch to pull the new tokensNo code changes needed ā the file key and token are the only configuration.
Trigger via Actions ā Fetch Tokens | Dispatch ā Run workflow.
This fetches tokens from Figma, commits any changes, and opens a PR.
When you push a version tag (v*), the Publish Package | Latest workflow automatically builds and publishes to npm, then deploys the docs site and Token Scout report.
| Secret | Description |
|---|---|
FIGMA_TOKEN | Figma personal access token |
FIGMA_FILE_KEY | Figma file key |
NPMRC | npm authentication (.npmrc contents) |
This project uses commit-and-tag-version (the maintained fork of standard-version) for versioning and changelog generation.
Releases are a two-step process so you can review the changelog before publishing.
Step 1 ā Prepare (bumps version, generates changelog, commits + tags locally):
bun run release:prepare:patch # 0.0.0 ā 0.0.1
bun run release:prepare:minor # 0.0.1 ā 0.1.0
bun run release:prepare:major # 0.1.0 ā 1.0.0
Step 2 ā Review the generated CHANGELOG.md. If you need to make edits:
# Edit CHANGELOG.md, then amend the release commit
git add CHANGELOG.md && git commit --amend --no-edit
Step 3 ā Publish (pushes the commit + tag, triggers npm publish + docs deploy):
bun run release:publish
Trigger via Actions ā Publish Package | Alpha ā Run workflow to publish under the alpha npm tag.
All tokens follow a {platform}-{category}-{name} pattern. Most tokens are prefixed with desktop-.
| Prefix | CSS variable example | JS/TS key example |
|---|---|---|
desktop-color- | --desktop-color-neutral-06 | desktop-color-neutral-06-light |
desktop-spacing- | --desktop-spacing-medium | desktop-spacing-medium |
desktop-sizing- | --desktop-sizing-density-medium | desktop-sizing-density-medium |
desktop-radius- | --desktop-radius-small | desktop-radius-small |
desktop-shadow- | --desktop-shadow-blur-base | desktop-shadow-blur-base |
desktop-font- | --desktop-font-weight-semibold | desktop-font-weight-semibold |
desktop-opacity- | --desktop-opacity-87 | desktop-opacity-87 |
desktop-z-index- | --desktop-z-index-modal | desktop-z-index-modal |
desktop-duration- | --desktop-duration-fast | desktop-duration-fast |
desktop-easing- | --desktop-easing-ease-in-out | desktop-easing-ease-in-out |
desktop-blur- | --desktop-blur-lg | desktop-blur-lg |
viewport- | --viewport-12 | viewport-12 |
color- (semantic) | --color-input-bg-enabled | color-input-bg-enabled-light |
Color tokens have theme variants as suffixes: -light, -dark, and -on-color. In CSS output, themed tokens are resolved per data-theme attribute. In JS/TS output, each variant is a separate key (e.g. desktop-color-neutral-06-light, desktop-color-neutral-06-dark).
| Category | Source file | Tokens | Description |
|---|---|---|---|
| Color (base) | tokens/color-level-1/base.json | 143 scales | Neutral, ublue, red, green, orange, purple, aqua, lime, yellow, navy (4 modes each) |
| Color (semantic) | tokens/color-level-2/base.json | 3 | Input bg aliases (light/dark) |
| Spacing | tokens/spacing/base.json | 15 | none through xxlarge-3 (0ā80px) |
| Sizing | tokens/sizing/base.json | 8 | Component density + icon sizes |
| Typography | tokens/typography/base.json | 21 | Font size (ui-sans + inter), weight, family |
| Radius | tokens/radius/base.json | 7 | none, small, medium, large, infinity |
| Shadow | tokens/shadow/base.json | 6 | Offset, blur, spread primitives |
| Viewport | tokens/viewport/base.json | 4 | Breakpoints (375, 768, 1200, 1440) |
| Opacity | tokens/opacity/base.json | 13 | 0ā0.98 scale (extracted from on-color-alpha) |
| Z-Index | tokens/z-index/base.json | 5 | base, dropdown, sticky, modal, toast |
| Animation | tokens/animation/base.json | 6 | Duration (fast/normal/slow) + easing curves |
| Blur | tokens/blur/base.json | 4 | none, sm, md, lg |
Most Ubiquiti apps (e.g. unifi-portal) use Emotion with a theme object from @ubnt/ui-components that provides tokens via theme.palette.*, theme.space.*, etc. This section explains how to migrate from that pattern to CSS variables from this package.
pnpm add @ubnt/uids-tokens
import '@ubnt/ui-components/styles/normalize.css';
import '@ubnt/ui-components/styles/reset.css';
import '@ubnt/uids-tokens/css-tokens';
No other setup is needed ā CssVariableProvider from @ubnt/ui-components already sets data-theme on the body, which activates the correct light/dark values automatically.
Every ${({ theme }) => theme.palette.xxx} callback becomes a plain var() reference:
// Before ā JS callback on every render
const Card = styled.div`
background-color: ${({ theme }) => theme.palette.neutral01};
border: 1px solid ${({ theme }) => theme.palette.neutral03};
border-radius: ${({ theme }) => theme.radius.small}px;
padding: ${({ theme }) => theme.space.medium}px;
color: ${({ theme }) => theme.palette.text1};
`;
// After ā pure CSS, no JS callbacks
const Card = styled.div`
background-color: var(--desktop-color-neutral-01);
border: 1px solid var(--desktop-color-neutral-03);
border-radius: var(--desktop-radius-small);
padding: var(--desktop-spacing-medium);
color: var(--desktop-color-text-1);
`;
The mapping from theme.palette.* (camelCase) to CSS variables (kebab-case) is straightforward:
| Emotion theme | CSS variable |
|---|---|
theme.palette.neutral00 | var(--desktop-color-neutral-00) |
theme.palette.neutral12 | var(--desktop-color-neutral-12) |
theme.palette.ublue06 | var(--desktop-color-ublue-06) |
theme.palette.green06 | var(--desktop-color-green-06) |
theme.palette.red06 | var(--desktop-color-red-06) |
theme.palette.text1 | var(--desktop-color-text-1) |
theme.palette.text3 | var(--desktop-color-text-3) |
theme.palette.depthBg0 | var(--desktop-color-depth-bg-0) |
theme.palette.depthBg2 | var(--desktop-color-depth-bg-2) |
theme.palette.globalPrimary | var(--desktop-color-global-primary) |
theme.palette.aquaGradient | var(--desktop-color-aqua-gradient) |
theme.radius.small | var(--desktop-radius-small) |
theme.space.medium | var(--desktop-spacing-medium) |
Important: CSS variables include the unit, so don't add px after them. Write padding: var(--desktop-spacing-medium); not padding: var(--desktop-spacing-medium)px;.
For programmatic migration, use the compat mapping ā migrateTokenName() handles all known patterns.
Use CSS variables (@ubnt/uids-tokens/css-tokens) for everything in styled components and CSS. Only use the JS export when you need raw token values in JavaScript:
import { tokens } from '@ubnt/uids-tokens';
// Charting libraries that need raw color values
const chartConfig = {
color: tokens['desktop-color-ublue-06-light'],
};
// Dynamic calculations that need numeric values
const spacingPx = parseInt(tokens['desktop-spacing-medium'], 10) * 2;
ThemeProviderpalette.tsuids-tokens/
āāā .github/workflows/ # GitHub Actions
ā āāā deploy-docs.yml # Deploys docs + report to uidev.tools
ā āāā fetch-tokens.yml # Reusable fetch workflow
ā āāā fetch-tokens.dispatch.yml # Manual trigger
ā āāā publish-package.yml # Reusable publish workflow
ā āāā publish-package.latest.yml # Publish on tag push
ā āāā publish-package.alpha.yml # Publish alpha channel
āāā audit/ # Token Scout ā adoption scanner
ā āāā src/
ā ā āāā index.ts # CLI entry point
ā ā āāā types.ts # Type definitions
ā ā āāā reporter/ # HTML report generator (Scout-style)
ā ā āāā drift/ # Figma drift detection
ā ā āāā freestyle/ # Freestyle scanner + token system detection
ā ā āāā inventory/ # Token inventory builder
ā āāā audit.config.json # Default app config
ā āāā audit-output/ # Generated reports
āāā dist/ # Build output (gitignored)
ā āāā css-tokens/variables.css
ā āāā styled-components/index.mjs + index.d.ts
ā āāā theme/index.mjs + index.d.ts
ā āāā compat/index.mjs + index.d.ts
ā āāā tokens.json
āāā site/ # Vite token browser (uids-tokens.uidev.tools)
āāā infra/ # CloudFront functions for routing
āāā scripts/
ā āāā figma-fetch/ # Figma Variables API fetch
āāā src/
ā āāā compat/ # Compat mapping source
āāā tokens/ # Source token files (DTCG JSON)
ā āāā animation/
ā āāā blur/
ā āāā color-level-1/
ā āāā color-level-2/
ā āāā opacity/
ā āāā radius/
ā āāā shadow/
ā āāā sizing/
ā āāā spacing/
ā āāā typography/
ā āāā viewport/
ā āāā z-index/
āāā build/ # Style Dictionary build pipeline
ā āāā index.ts # Entry point
ā āāā helpers.ts # Shared helpers
ā āāā transforms.ts # Custom transforms
ā āāā formats/ # Custom output formats (css, js, theme)
āāā package.json
āāā llms.txt # Machine-readable context for LLMs
āāā tsconfig.json
The following issues need to be resolved in the Figma variables file. See docs/FIGMA_FIXES.md for full details.
"boid" instead of "bold")frosted-glass, black, white missing desktop-color- prefixui-sans and inter variants with different valuesmob-bg-seconday (missing "r", should be mob-bg-secondary)color-data-experience-needimprv (unclear abbreviation)tokens/color/base.json maps to an empty collectionviewport wrapper group produces double-prefixed names (--viewport-viewport-*)on-color and on-color-alpha modeson-color and on-color-alpha values are identical (missing alpha channel?)FAQs
UniFi Design System tokens ā the single source of truth for design tokens across all platforms.
The npm package @ubnt/uids-tokens receives a total of 0 weekly downloads. As such, @ubnt/uids-tokens popularity was classified as not popular.
We found that @ubnt/uids-tokens demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Ā It has 226 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.

Security News
A critical vm2 sandbox escape can allow untrusted JavaScript to break isolation and execute commands on the host Node.js process.

Research
Five malicious NuGet packages impersonate Chinese .NET libraries to deploy a stealer targeting browser credentials, crypto wallets, SSH keys, and local files.

Security News
pnpm 11 turns on a 1-day Minimum Release Age and blocks exotic subdeps by default, adding safeguards against fast-moving supply chain attacks.