A minimal, framework-agnostic UI component library based on GitLab's Pajamas design system, built on Web Components (Lit). It also ships a Slippers (GitLab marketing) theme you can switch to at runtime.
Because the components are standard custom elements, they work anywhere HTML does — vanilla JS, Vue, React, Svelte, etc. — with no framework dependency.
Installation
Drawstrings is published to its GitLab project package registry. Point npm at that registry, then install.
Add to your project's .npmrc (replace <project_id> with the numeric ID shown on the
project's overview page, and provide a token with read_package_registry scope):
registry=https://gitlab.com/api/v4/projects/<project_id>/packages/npm/
//gitlab.com/api/v4/projects/<project_id>/packages/npm/:_authToken=${GITLAB_TOKEN}
npm install drawstrings
Quick start
Import the package to register every gl-* custom element, and import the stylesheet to load
the design tokens and themes:
import 'drawstrings' // registers the gl-* elements
import 'drawstrings/styles' // → drawstrings.css (design tokens + Pajamas/Slippers themes)
<gl-button variant="confirm">Save</gl-button>
<gl-badge variant="success">Passed</gl-badge>
<gl-alert variant="info" title="Heads up">Pipeline finished.</gl-alert>
Each component's own styling lives in Shadow DOM, so the elements render even without the
stylesheet — but drawstrings/styles provides the canonical token values and is required for
theming (the Slippers theme and any --gl-* overrides live there). The CSS is a separate
artifact, so importing only the JS will not pull it in.
Browser / CDN (no build step)
The IIFE build exposes a global Drawstrings and self-registers the elements:
<link rel="stylesheet" href="drawstrings/dist/drawstrings.css" />
<script src="drawstrings/dist/drawstrings.min.js"></script>
<gl-button variant="confirm">Save</gl-button>
Framework usage
The elements are framework-agnostic. Two notes:
Vue 3 — tell the compiler that
gl-*tags are custom elements so it doesn't try to resolve them as Vue components:// vite.config.js vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('gl-') } } })React — attributes (strings/booleans) work directly. For rich properties (arrays/objects like
gl-select'soptions), set them via a ref, or use React 19's improved custom-element property handling.
Theming (Pajamas ↔ Slippers)
Pajamas is the default. Switching to Slippers is a pure token swap — no re-render, no
per-component config. Set data-design-system on the document root, or use the helper:
import { setDesignSystem, getDesignSystem } from 'drawstrings'
setDesignSystem('slippers') // or 'pajamas' (default)
getDesignSystem() // → 'slippers'
Equivalently, in markup:
<html data-design-system="slippers">
…
</html>
The attribute cascades to every component (custom properties inherit through Shadow DOM), so a single toggle re-skins the whole page.
Customizing tokens
All styling flows through --gl-* CSS custom properties. Override them at :root (or any
scope) to tune the look without forking components:
:root {
/* Brand the primary action */
--gl-button-confirm-bg: #7759c2;
/* Or remap the palette wholesale */
--gl-color-blue-500: #1a73e8;
}
Component-specific tokens (e.g. --gl-button-confirm-bg, --gl-link-color) fall back to the
semantic color scale (--gl-color-blue-500, …), which falls back to a literal default — so you
can override at whichever level you need.
Icons
<gl-icon> renders from a built-in registry of Pajamas icons:
<gl-icon name="check" size="16" label="Done"></gl-icon>
Custom icons / sprites: add to the registry with
registerIcon(name, svg, viewBox?), or point at a GitLab SVG sprite withsetSpriteUrl(url).Slippers marketing icons are large and shipped as an opt-in entry that registers them under
slp-*names:import 'drawstrings/slippers-icons'<gl-icon name="slp-announce-release" size="32"></gl-icon>
Development
npm run dev # Vite dev server + demo page (index.html)
npm run build # build dist/ (ESM, CJS, IIFE, CSS, types)
npm run typecheck # tsc --noEmit
npm run test:e2e # Playwright smoke tests against the demo page
The demo page includes a Pajamas/Slippers switcher to preview both themes.