From duskmoon-ui
When using npm package `@duskmoon-dev/core`, this skill shows how to install, configure, and use the CSS component library
npx claudepluginhub gsmlg-dev/code-agent --plugin duskmoon-uiThis skill uses the workspace's default tool permissions.
`@duskmoon-dev/core` is a CSS-only component library for Tailwind CSS v4 with Material Design 3's extended color system.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Automates semantic versioning and release workflow for Claude Code plugins: bumps versions in package.json, marketplace.json, plugin.json; verifies builds; creates git tags, GitHub releases, changelogs.
@duskmoon-dev/core is a CSS-only component library for Tailwind CSS v4 with Material Design 3's extended color system.
# Bun
bun add @duskmoon-dev/core tailwindcss@^4.0.0
# npm
npm install @duskmoon-dev/core tailwindcss@^4.0.0
# pnpm
pnpm add @duskmoon-dev/core tailwindcss@^4.0.0
@import "tailwindcss";
@import "@duskmoon-dev/core";
@import "tailwindcss";
@plugin "@duskmoon-dev/core/plugin";
The @plugin approach registers MD3 color tokens into Tailwind's theme, enabling utility classes like bg-primary, text-on-surface, etc.
Apply theme via data-theme attribute on HTML element:
<html data-theme="sunshine"> <!-- Light theme -->
<html data-theme="moonlight"> <!-- Dark theme -->
btn - Buttons with variants: btn-primary, btn-secondary, btn-tertiary, btn-outline, btn-ghost, btn-text, btn-loadingcircle-menu - Radial navigation menu: circle-menu-toggler, circle-menu-list, circle-menu-item, circle-menu-label, circle-menu-primary, circle-menu-secondary, circle-menu-tertiary, circle-menu-info, circle-menu-success, circle-menu-warning, circle-menu-error, circle-menu-sm, circle-menu-lgfile-upload - Drag-and-drop file uploader: file-upload-dropzone, file-upload-primary, file-upload-compact, file-upload-button, file-upload-sm, file-upload-lg, file-upload-ghosttoggle-btn - Toggle buttons and groups: toggle-btn-active, toggle-btn-primary, toggle-btn-ghost, toggle-btn-sm, toggle-btn-lg, toggle-group, toggle-segmented, toggle-chip, toggle-filled, toggle-outlinedinput - Text inputs: input-primary, input-secondary, input-errortextarea - Multi-line text: textarea-primary, textarea-resize-none, textarea-resize-verticalselect - Dropdown selection: select-primary, select-filled, select-outlinedcascader - Hierarchical selection: cascader, cascader-panel, cascader-menucheckbox - Checkboxes: checkbox-primary, checkbox-indeterminate, checkbox-groupradio - Radio buttons: radio-primary, radio-group, radio-group-horizontalswitch - Toggle switches: switch-primary, switch-secondaryslider - Range sliderssegment-control - Segmented buttons: segment-control, segment-control-itemautocomplete - Search with suggestionsdatepicker - Calendar: date, datetime, date range, datetime range pickerstime-input - Time selection: time-input, time-input-pickerfile-upload - Drag-and-drop file uploaderrating - Star/heart ratingsotp-input - OTP verification: otp-input, otp-input-fieldpin-input - PIN entry: pin-input, pin-input-maskedmulti-select - Multiple selection: multi-select, multi-select-tagtree-select - Hierarchical dropdown: tree-select, tree-select-nodeform-group - Form layout: form-group, form-label, helper-text, fieldsettheme-controller - Theme switching: theme-controller (inline switch), theme-controller-dropdown, theme-controller-item, theme-controller-labelcard - Content containers: card-body, card-titlebadge - Status indicators: badge-primary, badge-dotavatar - User images: avatar-lg, avatar-status-onlinechip - Tags/filters: chip-primary, chip-removabletable - Data tables: table-hover, table-stripedlist - Vertical lists: list-item, list-item-interactivetimeline - Chronological eventsskeleton - Loading placeholders: skeleton-text, skeleton-circle, skeleton-rect, skeleton-wave, skeleton-avatar, skeleton-button, skeleton-card, skeleton-groupcode-block - Styled code containers: code-header, code-title, code-language, code-content, code-block-compact, code-block-borderlessalert - Messages: alert-success, alert-error, alert-warning, alert-infodialog - Modal dialogs: dialog-backdrop, dialog-mdmodal - Full overlaystoast - Notifications: toast-success, toast-showsnackbar - Brief messagesprogress - Loading: progress-primary, progress-indeterminateskeleton - Placeholders: skeleton-text, skeleton-circletooltip - Hover info: tooltip-top, tooltip-bottombreadcrumbs - Breadcrumb navigation: breadcrumb-item, breadcrumb-item-active, breadcrumb-item-disabled, breadcrumb-link, breadcrumb-separator, breadcrumb-icon, breadcrumb-home, breadcrumb-home-icon, breadcrumb-ellipsis, breadcrumbs-contained, breadcrumbs-sm, breadcrumbs-lg, breadcrumbs-nowrapnavbar - Top navigation: navbar-surface-container-high, navbar-start, navbar-center, navbar-endtabs - Tab navigation: tab, tab-active, tabs-boxed, tabs-lifted, tab-sm, tab-lg, tab-xsmenu - Dropdown/context menu: menu-item, menu-title, menu-horizontal, menu-verticaldrawer - Side panels: drawer-left, drawer-opennested-menu - Collapsible sidebar: nested-menu, nested-menu-title, nested-menu-bordered, nested-menu-compactpagination - Page navigation: pagination-item, pagination-item-active, pagination-item-disabled, pagination-prev, pagination-next, pagination-ellipsis, pagination-compact, pagination-responsive, pagination-info, pagination-input, pagination-item-active-primary, pagination-item-active-secondary, pagination-item-active-tertiarybottom-nav - Mobile navigation: bottom-nav-itemstepper - Multi-step: stepper-step-active, stepper-step-completeddivider - Separators: divider-dashed, divider-verticalappbar - Action bars: appbar-top, appbar-bottommarkdown-body - GitHub-style markdown typography: single class applied to a container, styles all child elements (headings, code, tables, blockquotes, lists)grid-cols-auto-fill-* - Responsive grid with auto-fill: grid-cols-auto-fill-48, grid-cols-auto-fill-64grid-cols-auto-fit-* - Responsive grid with auto-fit: grid-cols-auto-fit-48, grid-cols-auto-fit-64sr-only - Screen reader only (visually hidden but accessible)not-sr-only - Undo sr-only for focus statesaccordion - Expandable panels: accordion-item-openbottomsheet - Mobile panels: bottom-sheet-showpopover - Contextual overlays: popover-top, popover-showcollapse - Collapsible content<button class="btn btn-primary">Primary</button>
<button class="btn btn-secondary btn-outline">Outlined</button>
<button class="btn btn-tertiary btn-ghost">Ghost</button>
<button class="btn btn-primary btn-loading">Loading...</button>
<div class="card">
<div class="card-body">
<h2 class="card-title">Title</h2>
<p>Content</p>
</div>
</div>
<input type="text" class="input" placeholder="Default" />
<input type="text" class="input input-primary" placeholder="Primary" />
<input type="text" class="input input-error" placeholder="Error" />
<div class="alert alert-success">Success message</div>
<div class="alert alert-error">Error message</div>
<div class="alert alert-warning">Warning message</div>
<div class="alert alert-info">Info message</div>
<nav class="navbar navbar-surface-container-high">
<div class="navbar-start">
<a class="navbar-brand">Logo</a>
</div>
<div class="navbar-center">
<a class="navbar-item navbar-item-active">Home</a>
<a class="navbar-item">About</a>
</div>
</nav>
<div class="tabs">
<button class="tab tab-active">Tab 1</button>
<button class="tab">Tab 2</button>
</div>
<div class="dialog-backdrop dialog-backdrop-show">
<div class="dialog dialog-md">
<div class="dialog-header">
<h2 class="dialog-title">Title</h2>
</div>
<div class="dialog-body">Content</div>
<div class="dialog-actions">
<button class="btn btn-text">Cancel</button>
<button class="btn btn-filled">Confirm</button>
</div>
</div>
</div>
<ul class="nested-menu nested-menu-bordered">
<li class="nested-menu-title">Getting Started</li>
<li><a href="/install">Installation</a></li>
<li><a href="/config" class="active">Configuration</a></li>
<li>
<details open>
<summary>Components</summary>
<ul>
<li><a href="/button">Button</a></li>
<li><a href="/card">Card</a></li>
</ul>
</details>
</li>
</ul>
<!-- Inline switch mode -->
<div class="theme-controller">
<input type="radio" name="theme" value="sunshine" class="theme-controller-item" checked />
<label class="theme-controller-label">Light</label>
<input type="radio" name="theme" value="moonlight" class="theme-controller-item" />
<label class="theme-controller-label">Dark</label>
</div>
<!-- Dropdown mode -->
<details class="theme-controller-dropdown">
<summary class="theme-controller-trigger">Theme</summary>
<div class="theme-controller-menu">
<input type="radio" name="theme" value="sunshine" class="theme-controller-item" checked />
<label class="theme-controller-label">Sunshine</label>
<input type="radio" name="theme" value="moonlight" class="theme-controller-item" />
<label class="theme-controller-label">Moonlight</label>
</div>
</details>
<!-- Single toggle -->
<button class="toggle-btn toggle-btn-active">Bold</button>
<!-- Toggle group -->
<div class="toggle-group">
<button class="toggle-btn toggle-btn-active">Left</button>
<button class="toggle-btn">Center</button>
<button class="toggle-btn">Right</button>
</div>
<!-- Auto-fill: Fixed column size, empty space on right -->
<div class="grid grid-cols-auto-fill-48 gap-4">
<div class="card">Item 1</div>
<div class="card">Item 2</div>
<div class="card">Item 3</div>
</div>
<!-- Auto-fit: Columns stretch to fill container -->
<div class="grid grid-cols-auto-fit-64 gap-4">
<div class="card">Item 1</div>
<div class="card">Item 2</div>
</div>
<!-- Backgrounds -->
<div class="bg-primary">Primary</div>
<div class="bg-secondary">Secondary</div>
<div class="bg-tertiary">Tertiary</div>
<div class="bg-surface-container">Surface</div>
<!-- Text -->
<p class="text-primary">Primary</p>
<p class="text-on-surface">On surface</p>
<p class="text-on-surface-variant">Muted</p>
<!-- Semantic -->
<div class="bg-success text-success-content">Success</div>
<div class="bg-error text-error-content">Error</div>
.custom {
background-color: var(--color-primary);
color: var(--color-primary-content);
border-color: var(--color-outline);
}
// Switch to dark theme
document.documentElement.dataset.theme = 'moonlight';
// Switch to light theme
document.documentElement.dataset.theme = 'sunshine';
Import all components and themes at once:
/* In your CSS file */
@import "tailwindcss";
@import "@duskmoon-dev/core";
Import only the CSS you need for smaller bundle sizes:
/* CSS imports */
@import "@duskmoon-dev/core/components/button";
@import "@duskmoon-dev/core/components/card";
@import "@duskmoon-dev/core/components/input";
@import "@duskmoon-dev/core/components/alert";
// Import component styles in JS/TS
import '@duskmoon-dev/core/components/button';
import '@duskmoon-dev/core/components/card';
import '@duskmoon-dev/core/components/input';
/* Import specific themes */
@import "@duskmoon-dev/core/themes/sunshine";
@import "@duskmoon-dev/core/themes/moonlight";
All components available for individual import:
| Import Path | Component |
|---|---|
@duskmoon-dev/core/components/accordion | Accordion |
@duskmoon-dev/core/components/alert | Alert |
@duskmoon-dev/core/components/appbar | App Bar |
@duskmoon-dev/core/components/autocomplete | Autocomplete |
@duskmoon-dev/core/components/avatar | Avatar |
@duskmoon-dev/core/components/badge | Badge |
@duskmoon-dev/core/components/bottom-navigation | Bottom Navigation |
@duskmoon-dev/core/components/bottomsheet | Bottom Sheet |
@duskmoon-dev/core/components/button | Button |
@duskmoon-dev/core/components/card | Card |
@duskmoon-dev/core/components/cascader | Cascader |
@duskmoon-dev/core/components/checkbox | Checkbox |
@duskmoon-dev/core/components/chip | Chip |
@duskmoon-dev/core/components/circle-menu | Circle Menu |
@duskmoon-dev/core/components/code-block | Code Block |
@duskmoon-dev/core/components/collapse | Collapse |
@duskmoon-dev/core/components/datepicker | Date Picker |
@duskmoon-dev/core/components/dialog | Dialog |
@duskmoon-dev/core/components/divider | Divider |
@duskmoon-dev/core/components/drawer | Drawer |
@duskmoon-dev/core/components/file-upload | File Upload |
@duskmoon-dev/core/components/form | Form |
@duskmoon-dev/core/components/form-group | Form Group |
@duskmoon-dev/core/components/input | Input |
@duskmoon-dev/core/components/list | List |
@duskmoon-dev/core/components/markdown-body | Markdown Body |
@duskmoon-dev/core/components/modal | Modal |
@duskmoon-dev/core/components/multi-select | Multi-Select |
@duskmoon-dev/core/components/navigation | Navigation (Navbar/Tabs/Menu) |
@duskmoon-dev/core/components/nested-menu | Nested Menu |
@duskmoon-dev/core/components/otp-input | OTP Input |
@duskmoon-dev/core/components/pin-input | PIN Input |
@duskmoon-dev/core/components/popover | Popover |
@duskmoon-dev/core/components/progress | Progress |
@duskmoon-dev/core/components/radio | Radio |
@duskmoon-dev/core/components/rating | Rating |
@duskmoon-dev/core/components/segment-control | Segment Control |
@duskmoon-dev/core/components/select | Select |
@duskmoon-dev/core/components/skeleton | Skeleton |
@duskmoon-dev/core/components/slider | Slider |
@duskmoon-dev/core/components/snackbar | Snackbar |
@duskmoon-dev/core/components/stepper | Stepper |
@duskmoon-dev/core/components/switch | Switch |
@duskmoon-dev/core/components/table | Table |
@duskmoon-dev/core/components/textarea | Textarea |
@duskmoon-dev/core/components/theme-controller | Theme Controller |
@duskmoon-dev/core/components/time-input | Time Input |
@duskmoon-dev/core/components/timeline | Timeline |
@duskmoon-dev/core/components/toast | Toast |
@duskmoon-dev/core/components/toggle | Toggle |
@duskmoon-dev/core/components/tooltip | Tooltip |
@duskmoon-dev/core/components/tree-select | Tree Select |
Each component exports a named css export containing the CSS string:
// Import the css named export
import { css as buttonCSS } from '@duskmoon-dev/core/components/button';
import { css as cardCSS } from '@duskmoon-dev/core/components/card';
import { css as inputCSS } from '@duskmoon-dev/core/components/input';
Example usage in a custom element:
import { css as buttonCSS } from '@duskmoon-dev/core/components/button';
// Strip @layer wrapper for Shadow DOM compatibility
const coreStyles = buttonCSS.replace(/@layer\s+components\s*\{/, '').replace(/\}\s*$/, '');
class MyButton extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
// Add styles to shadow DOM
const style = document.createElement('style');
style.textContent = coreStyles;
this.shadowRoot.appendChild(style);
}
}
Note: The CSS is wrapped in @layer components { } for Tailwind CSS cascade layers. When using in Shadow DOM, strip the @layer wrapper as shown above.