duskmoon-elements
DuskMoon Elements
43 custom element packages built on @duskmoon-dev/el-base. Each element is a standard Web Component with Shadow DOM.
Installation
# Individual element
bun add @duskmoon-dev/el-button
# All elements at once
bun add @duskmoon-dev/elements
Registration
// Option 1: Explicit (tree-shakable)
import { register } from '@duskmoon-dev/el-button';
register();
// Option 2: Side-effect auto-register
import '@duskmoon-dev/el-button/register';
// Option 3: Register all elements
import { registerAll } from '@duskmoon-dev/elements';
registerAll();
Usage in HTML
<el-dm-button variant="filled" color="primary" size="md">
Click me
</el-dm-button>
<el-dm-dialog id="my-dialog">
<span slot="header">Title</span>
Dialog content here.
<div slot="footer">
<el-dm-button onclick="this.closest('el-dm-dialog').hide()">Close</el-dm-button>
</div>
</el-dm-dialog>
Properties & Attributes
Set via HTML attributes (kebab-case) or JS properties (camelCase). Properties with reflect: true sync both directions.
<!-- HTML attributes -->
<el-dm-button variant="outlined" disabled>Save</el-dm-button>
<!-- JS properties -->
<script>
const btn = document.querySelector('el-dm-button');
btn.variant = 'outlined';
btn.disabled = true;
</script>
Common properties across elements:
| Property | Type | Description |
|---|---|---|
variant |
String | Visual variant (filled, outlined, soft, text, ghost) |
color |
String | Color theme (primary, secondary, success, warning, error, info) |
size |
String | Size (sm, md, lg) |
disabled |
Boolean | Disable interaction |
Complex data (arrays, objects) must be set via JS — use attribute: false:
const table = document.querySelector('el-dm-table');
table.columns = [{ field: 'name', header: 'Name' }];
table.data = [{ name: 'Alice' }, { name: 'Bob' }];
Events
Listen with addEventListener. Events bubble and are composed (cross shadow DOM).
const table = document.querySelector('el-dm-table');
table.addEventListener('sort', (e) => {
console.log(e.detail); // { column: 'name', direction: 'asc' }
});
table.addEventListener('row-click', (e) => {
console.log(e.detail); // { row: {...}, rowIndex: 0 }
});
Common events:
| Element | Event | Detail |
|---|---|---|
| dialog | open, close |
— |
| table | sort |
{ column, direction } |
| table | select |
{ selectedIds, selectedRows } |
| table | page-change |
{ page, pageSize } |
| pagination | page-change |
{ page } |
| tabs | tab-change |
{ index, tab } |
| input | dm-input, dm-change |
{ value } |
Slots
Named slots project light DOM content into the element's shadow DOM.
<el-dm-button>
<span slot="prefix">🔍</span>
Search
<span slot="suffix">→</span>
</el-dm-button>
<el-dm-card>
<span slot="header">Card Title</span>
Card body content
<div slot="footer">Footer</div>
</el-dm-card>
Common slots: (default), header, footer, prefix, suffix, empty, actions.
CSS Parts
Style shadow DOM internals from outside using ::part():
el-dm-button::part(button) {
border-radius: 0;
}
el-dm-dialog::part(backdrop) {
backdrop-filter: blur(4px);
}
el-dm-table::part(thead) {
background: var(--color-surface-container-high);
}
Theming
Elements use CSS custom properties from @duskmoon-dev/el-base. Apply a preset theme:
import { applyTheme } from '@duskmoon-dev/el-base';
applyTheme(document.documentElement, 'moonlight'); // dark
applyTheme(document.documentElement, 'sunshine'); // light
// Also: 'ocean', 'forest', 'rose'
Override individual variables:
:root {
--color-primary: oklch(60% 0.15 250);
--color-surface: #ffffff;
}
Key variables: --color-primary, --color-surface, --color-on-surface, --color-outline, --color-surface-container.
See references/core-api.md for full CSS variable list.
Batched Rendering
Property changes are batched via queueMicrotask. Multiple changes in the same tick produce a single re-render:
const el = document.querySelector('el-dm-button');
el.variant = 'outlined';
el.color = 'error';
el.size = 'lg';
// → single re-render
References
- Element catalog — all 43 packages by category with class names
- Core API — BaseElement API, mixins, style utilities, CSS variables, themes, validation
For CSS art elements (<el-dm-art-*>), see the duskmoon-art-elements skill.
More from gsmlg-dev/code-agent
elixir-architect
Use when designing or architecting Elixir/Phoenix applications, creating comprehensive project documentation, planning OTP supervision trees, defining domain models with Ash Framework, structuring multi-app projects with path-based dependencies, or preparing handoff documentation for Director/Implementor AI collaboration
17flutter-reducing-app-size
Measures and optimizes the size of Flutter application bundles for deployment. Use when minimizing download size or meeting app store package constraints.
17flutter-animating-apps
Implements animated effects, transitions, and motion in a Flutter app. Use when adding visual feedback, shared element transitions, or physics-based animations.
17flutter-managing-state
Manages application and ephemeral state in a Flutter app. Use when sharing data between widgets or handling complex UI state transitions.
17flutter-handling-concurrency
Executes long-running tasks in background isolates to keep the UI responsive. Use when performing heavy computations or parsing large datasets.
16flutter-caching-data
Implements caching strategies for Flutter apps to improve performance and offline support. Use when retaining app data locally to reduce network requests or speed up startup.
16