@prioticket/design-system-web
v1.10.1
Published
A comprehensive Web Components library built with **Lit** that provides Material Design components for Prioticket applications. This library is designed to work seamlessly across any frontend framework or in vanilla HTML.
Maintainers
Readme
Prioticket Design System Web
A comprehensive Web Components library built with Lit that provides Material Design components for Prioticket applications. This library is designed to work seamlessly across any frontend framework or in vanilla HTML.
Features
- 🎨 Material Design 3 - Built on Google's official Material Web components
- 🌈 Dynamic Theming - Real-time theme switching without page reload
- 🌐 Framework Agnostic - Works with Angular, React, Vue, PHP, or any web technology
- 📦 Tree Shakable - Load only the components you need
- 🎯 TypeScript - Full type safety and excellent developer experience
- 🔧 Customizable - Flexible theming with CSS custom properties
- ⚡ Performance Optimized - Individual component bundles for maximum efficiency
- 🎪 Modern Standards - ES Modules, Web Components, and HTTP/2 friendly
Installation
npm install @prioticket/design-system-webReact projects
We publish official wrappers as @prioticket/design-system-react. The web package is a peer dependency of the React package, so install both at the same version:
npm install @prioticket/design-system-web @prioticket/design-system-reactOnly one copy of @prioticket/design-system-web may exist in your dependency tree (npm ls @prioticket/design-system-web must show a single entry), because each component registers itself with customElements.define. See packages/react/README.md for setup and usage details.
Usage Guide
1. Quick Start with CDN (PHP, plain HTML, Claude artifacts)
Two ways to use the library without a bundler. Both serve everything from jsDelivr, which mirrors
npm. The single-script files are new: standalone.js ships from 1.10.0-beta.1 and
standalone-fonts.js from 1.10.0-beta.2, and neither exists in 1.9.0, where the URLs below
return 404. The examples use 1.10.0-beta.2; move to 1.10.0 once it is stable
(npm view @prioticket/design-system-web dist-tags).
Option A · two scripts, nothing else. standalone.js carries every component, Lit, Material
Web and floating-ui, and injects the theme tokens on load. standalone-fonts.js registers Proxima
Nova and Material Symbols Rounded with the font files inlined, so the page fetches no font from
any host. Together they are the whole setup, and the only one that works inside a Claude chat
artifact, whose sandbox loads scripts from jsDelivr but no stylesheet from it and no font file
from any CDN.
<!DOCTYPE html>
<html>
<head>
<!-- Every component, with the theme tokens applied. Load it once, and never next to the ES modules. -->
<script src="https://cdn.jsdelivr.net/npm/@prioticket/[email protected]/dist/standalone.js"></script>
<!-- Proxima Nova and the icon font, inlined. 830 KB, cached by jsDelivr like any other file. -->
<script src="https://cdn.jsdelivr.net/npm/@prioticket/[email protected]/dist/standalone-fonts.js"></script>
</head>
<body>
<pd-button>Click me</pd-button>
<script>
// Theming helpers are on the global the bundle defines.
// PrioticketDesignSystem.applyTheme({ colorPrimary: '#0f766e', colorOnPrimary: '#ffffff' });
</script>
</body>
</html>Leave out standalone-fonts.js and the components still work, but text falls back to Helvetica
Neue and Arial and every icon shows its ligature name (calendar_month) instead of a glyph. On a
normal page that can link stylesheets, dist/fonts-only.css from jsDelivr does the same job as the
fonts script and lets the browser fetch each face only when it is used.
Option B · import map, tree-shakable. Load only the components you use as ES modules. The
import map resolves the bare specifiers the modules use. Do not load the modules through
jsDelivr's /+esm endpoint: it bundles a private copy of Material Web into each file, and the
second copy throws "md-focus-ring" has already been used on registration.
<!DOCTYPE html>
<html>
<head>
<!-- Theme tokens plus both fonts, served from the package itself. -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@prioticket/[email protected]/dist/theme-with-fonts.css">
<script type="importmap">
{
"imports": {
"lit": "https://cdn.jsdelivr.net/npm/[email protected]/index.js",
"lit/": "https://cdn.jsdelivr.net/npm/[email protected]/",
"lit-html": "https://cdn.jsdelivr.net/npm/[email protected]/lit-html.js",
"lit-html/": "https://cdn.jsdelivr.net/npm/[email protected]/",
"lit-element": "https://cdn.jsdelivr.net/npm/[email protected]/lit-element.js",
"lit-element/": "https://cdn.jsdelivr.net/npm/[email protected]/",
"@lit/reactive-element": "https://cdn.jsdelivr.net/npm/@lit/[email protected]/reactive-element.js",
"@lit/reactive-element/": "https://cdn.jsdelivr.net/npm/@lit/[email protected]/",
"@material/web": "https://cdn.jsdelivr.net/npm/@material/[email protected]/index.js",
"@material/web/": "https://cdn.jsdelivr.net/npm/@material/[email protected]/",
"tslib": "https://cdn.jsdelivr.net/npm/[email protected]/tslib.es6.js",
"tslib/": "https://cdn.jsdelivr.net/npm/[email protected]/",
"@floating-ui/dom": "https://cdn.jsdelivr.net/npm/@floating-ui/[email protected]/+esm"
}
}
</script>
</head>
<body>
<pd-button>Click me</pd-button>
<script type="module">
import "https://cdn.jsdelivr.net/npm/@prioticket/[email protected]/dist/components/pd-button.es.js";
</script>
</body>
</html>The versions in the map are the ones this release depends on; @floating-ui/dom is required by
the tooltips. Inside a Claude artifact the stylesheet link is blocked, so paste theme-only.css
into a <style> block and add standalone-fonts.js as a script for the fonts.
Notes:
- Chromium-based browsers run Option B directly from
file://URLs. For Safari/Firefox or when sharing with others, serve the folder over HTTP. - Both options register every element unguarded: load the library once per page, one way, never both.
2. Usage with a Bundler (Framework Integration)
Angular
Step 1: Add CSS to angular.json
This tells the Angular CLI to include the theme styles in your application's global CSS bundle.
"styles": [
"src/styles.css",
"node_modules/@prioticket/design-system-web/dist/theme-only.css"
]Step 1.5: Add Material Icons to index.html
Add the Material Icons font to your src/index.html file:
<head>
<!-- Other head content -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,[email protected],100..700,0..1,-50..200&display=block">
</head>Step 2: Import Components and Add Schema
In your Angular component, import the components to register them and add CUSTOM_ELEMENTS_SCHEMA.
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
// Import components by their package path
import '@prioticket/design-system-web/components/pd-button';
@Component({
selector: 'app-example',
template: `<pd-button>Hello from Angular</pd-button>`,
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class ExampleComponent {}React / Vue / Other Frameworks
Similar pattern - install via npm, import the CSS file, and import individual components:
// Import the theme CSS (exact method depends on your bundler)
import '@prioticket/design-system-web/dist/theme-only.css';
// Import components
import '@prioticket/design-system-web/components/pd-button';
// Use in JSX/template
<pd-button>Hello from React</pd-button>Available Components
| Component | Description | CDN Import Path |
|-----------|-------------|-----------------|
| pd-alert | Inline alerts | components/pd-alert.es.js |
| pd-avatar | Avatars (with pd-avatar-wrapper) | components/pd-avatar.es.js |
| pd-badge-counter | Counter badges | components/pd-badge-counter.es.js |
| pd-badge-label | Label badges (with pd-badge-group) | components/pd-badge-label.es.js |
| pd-bottom-sheet | Bottom sheets | components/pd-bottom-sheet.es.js |
| pd-box | Layout box with card styling | components/pd-box.es.js |
| pd-button | Material Design buttons | components/pd-button.es.js |
| pd-button-group | Standard button groups | components/pd-button-group.es.js |
| pd-card | Cards for content grouping | components/pd-card.es.js |
| pd-carousel | Carousels (with pd-carousel-item) | components/pd-carousel.es.js |
| pd-connected-button-group | Connected button groups | components/pd-connected-button-group.es.js |
| pd-checkbox | Checkboxes | components/pd-checkbox.es.js |
| pd-chip | Chips for tags/filters | components/pd-chip.es.js |
| pd-date-picker | Single date picker | components/pd-date-picker.es.js |
| pd-date-range-picker | Date range picker with min/max clamping | components/pd-date-range-picker.es.js |
| pd-dialog | Modal dialogs (basic, confirmation, dismissible, slot layouts; not dismissible by backdrop unless closable-by-backdrop) | components/pd-dialog.es.js |
| pd-empty-state | Empty states | components/pd-empty-state.es.js |
| pd-expandable-card | Expandable cards with collapsible content | components/pd-expandable-card.es.js |
| pd-fab | Floating action buttons | components/pd-fab.es.js |
| pd-extended-fab | Extended floating action buttons | components/pd-extended-fab.es.js |
| pd-horizontal-card | Horizontal cards | components/pd-horizontal-card.es.js |
| pd-icon | Material Design icons | components/pd-icon.es.js |
| pd-icon-wrapper | Icon wrapper | components/pd-icon-wrapper.es.js |
| pd-icon-button | Icon buttons | components/pd-icon-button.es.js |
| pd-list | Lists with items | components/pd-list.es.js |
| pd-menu | Dropdown menus | components/pd-menu.es.js |
| pd-menu-item | Individual menu items | components/pd-menu-item.es.js |
| pd-progress | Progress indicators | components/pd-progress.es.js |
| pd-radio | Radio buttons | components/pd-radio.es.js |
| pd-rich-tooltip | Rich tooltips | components/pd-rich-tooltip.es.js |
| pd-segmented-button | Segmented button controls | components/pd-segmented-button.es.js |
| pd-segmented-stepper | Segmented stepper navigation | components/pd-segmented-stepper.es.js |
| pd-select | Select dropdowns | components/pd-select.es.js |
| pd-side-sheet | Side sheets | components/pd-side-sheet.es.js |
| pd-skeleton | Loading skeletons | components/pd-skeleton.es.js |
| pd-slider | Range sliders | components/pd-slider.es.js |
| pd-snackbar | Snackbars (with pd-snackbar-queue) | components/pd-snackbar.es.js |
| pd-split-button | Split buttons | components/pd-split-button.es.js |
| pd-stacked-card | Stacked cards | components/pd-stacked-card.es.js |
| pd-stepper | Step indicators | components/pd-stepper.es.js |
| pd-switch | Toggle switches | components/pd-switch.es.js |
| pd-toggle-button | Toggle buttons | components/pd-toggle-button.es.js |
| pd-tooltip | Plain tooltips | components/pd-tooltip.es.js |
| pd-table | Data table with sorting, selection, pagination, editing and reordering | components/pd-table.es.js |
| pd-tabs | Tab navigation | components/pd-tabs.es.js |
| pd-text-field | Text input fields | components/pd-text-field.es.js |
| pd-time-picker | Time picker | components/pd-time-picker.es.js |
Dynamic Theming
The design system supports real-time theme switching without page reload. Apply custom themes dynamically to match your brand or user preferences.
Basic Usage
// Import the theming system
import { initialize } from '@prioticket/design-system-web/theming';
// Apply a custom theme
await initialize({
theme: {
colorPrimary: '#ff6600',
colorOnPrimary: '#ffffff',
colorSurface: '#fff8f5',
shapeCornerSmall: '8px'
}
});CDN Usage
<script type="module">
import { initialize } from 'https://cdn.jsdelivr.net/npm/@prioticket/design-system-web@latest/dist/theming.es.js';
// Apply orange theme
await initialize({
theme: {
colorPrimary: '#ff6600',
colorPrimaryContainer: '#fff3e8',
shapeCornerMedium: '12px'
}
});
</script>Supported Theme Tokens
- Colors (14):
colorPrimary,colorOnPrimary,colorPrimaryContainer,colorOnPrimaryContainer,colorSecondary,colorOnSecondary,colorSecondaryContainer,colorOnSecondaryContainer,colorSurface,colorOnSurface,colorBackground,colorOnBackground,colorError,colorOnError - Charts (6):
colorChart1tocolorChart6, the categorical series palette (--pd-chart-1to--pd-chart-6).colorChart1followscolorPrimaryunless you set it. No interaction states are derived for chart colours. - Shapes (3):
shapeCornerSmall,shapeCornerMedium,shapeCornerLarge
These 23 keys are the whole theming API. For each colour you set, the matching -hover, -focus and -pressed tokens are derived automatically (5%, 10% and 15% alpha, as in the stylesheet); pass deriveInteractionStates: false to opt out. All other --md-sys-* tokens, such as outline, on-surface-variant and the surface-container-* ramp, are fixed Prioticket house style. Override those CSS variables directly if you need them. tonal buttons and selected segments use colorSecondaryContainer, so set it alongside colorPrimary when rebranding.
import { applyTheme, resetTheme } from '@prioticket/design-system-web/theming';
applyTheme({ colorPrimary: '#166534', colorOnPrimaryContainer: '#166534', colorOnSecondaryContainer: '#166534' });
resetTheme(); // back to the stylesheet's built-in themeinitialize({ theme: {} }) applies the default theme.
Framework Examples
React:
useEffect(() => {
initialize({
theme: { colorPrimary: '#4caf50' }
});
}, []);Angular:
ngOnInit() {
initialize({
theme: { colorPrimary: '#2196f3' }
});
}Live Demo
Run npm run dev and visit /demo-theming.html to see real-time theme switching in action.
Charts
Charts are not web components of this design system. React apps use shadcn/ui charts (Recharts v3, Tailwind v4) and the companion package @prioticket/design-system-charts supplies the theme: a bridge stylesheet that points shadcn's chart variables at the design tokens, and a shadcn registry item that installs shadcn's chart wrapper plus the bridge in one command.
npx shadcn@latest add @prioticket/chartimport '@prioticket/design-system-web/theme-with-fonts.css';
import '@prioticket/design-system-charts/shadcn.css';Series are coloured with var(--chart-1) to var(--chart-6); series 1 follows colorPrimary and every slot is settable through applyTheme(). Setup, rules and the variable mapping are in packages/charts/README.md; the decision, the palette's status and what changed are in CHARTS-RELEASE-NOTE.md. Vanilla and PHP pages use the same --pd-chart-N tokens with a framework-agnostic library such as ECharts or Chart.js.
Quick reference for AI agents and new consumers
CLAUDE.md is the single-page guide for agents and new consumers. It ships in this package, so in a consuming app it is at node_modules/@prioticket/design-system-web/CLAUDE.md; point your agent at that file. It covers: install rules, where the source of truth lives, the theming contract, which button variant reads which token, the generated React event prop names, and known behaviour to design around. The points that cost new consumers the most time:
- Components are controlled. You own the state and set it after each event. Only
pd-dialogcloses itself after an action button; resync from itsclosedevent. pd-dialogslots are the default slot andactions. The title is theheadlineproperty.pd-radio-groupemits onechangeper selection withdetail.value; the child radio's own event stays on the radio.pd-segmented-buttonemitsselectionchange, which isonSelectionchangein React.pd-selectvalueisstring[]inmultiplemode. The placeholder appears once the label floats.pd-tablerow types need an index signature ([key: string]: unknown).dist/types/*.d.tsandcustom-elements.jsonare authoritative when any markdown disagrees.
Customizing Fonts
The design system is built to work with any font stack. The theme CSS uses CSS custom properties:
/* Override Prioticket fonts with your own */
:root {
--md-sys-typescale-body-large-font: "Your Font", Arial, sans-serif;
--md-sys-typescale-title-medium-font: "Your Font", Arial, sans-serif;
--md-sys-typescale-headline-small-font: "Your Font", Arial, sans-serif;
}CSS Architecture
- theme-only.css (14KB) - All component styles without fonts
- fonts-only.css (1.3KB) - Just Prioticket font declarations
- theme-with-fonts.css (15.7KB) - Complete theme including fonts
- fonts/ - Font files (~232KB total)
Choose theme-only.css to use your existing fonts, or theme-with-fonts.css for the complete Prioticket experience.
Performance Best Practices
- Load only what you need - Import individual components via CDN
- Use theme-only.css - If you already have fonts, skip the font files
- Leverage HTTP/2 - Multiple small files load efficiently on modern servers
- CDN for Lit - Load the Lit dependency from a fast CDN
- Conditional loading - In server-side apps, only load components used on each page
Browser Support
- Chrome 84+
- Firefox 90+
- Safari 14+
- Edge 84+
Development
# Install dependencies
yarn install
# Start development server
yarn dev
# Build the library
yarn build
# Run Storybook
yarn storybookContributing
This project is open for internal contributions. See our documentation:
- CONTRIBUTING.md - Complete developer guide for adding components and features
- RELEASE-SETUP.md - CI/CD setup and release workflow
Quick Start for Contributors
- Clone the repository
- Install dependencies:
yarn install - Create a feature branch from
development - Make your changes and test in Storybook:
yarn storybook - Write tests:
yarn test - Commit using Conventional Commits:
git commit -m "feat: Add new feature" - Push and create a Merge Request to
development
Our automated CI/CD will handle versioning and publishing based on your commit messages.
Source Code
The source code for this library is proprietary and maintained in a private repository at Prioticket.
Support
For questions or bug reports, please contact the Prioticket development team internally.
