@melodicdev/components
v1.0.4
Published
Themeable UI component library built on the Melodic Framework
Maintainers
Readme
@melodicdev/components
Themeable UI components built on the Melodic Framework.
Install
npm install @melodicdev/components @melodicdev/core@melodicdev/core is a peer dependency.
Quick Start
1. Add the stylesheet
Add a single <link> tag to your HTML. It includes design tokens (light + dark themes) and the Phosphor icon fonts — everything the components need to render correctly:
<link melodic-styles rel="stylesheet"
href="https://unpkg.com/@melodicdev/components/assets/melodic-components.css">Production tip: Pin to a specific version and use the minified build to avoid unexpected changes:
<link melodic-styles rel="stylesheet" href="https://unpkg.com/@melodicdev/[email protected]/assets/melodic-components.min.css">
The melodic-styles attribute has no special browser meaning — it's just a convenient selector if you ever need to find or replace the element from JavaScript:
document.querySelector('link[melodic-styles]').href = '...new-url...';2. Apply a theme
Set data-theme on <html> to activate light or dark mode:
<html data-theme="light">Or use the JS theme API to apply and switch themes dynamically (including system/OS preference):
import { applyTheme, toggleTheme } from '@melodicdev/components/theme';
applyTheme('light'); // data-theme="light"
applyTheme('dark'); // data-theme="dark"
applyTheme('system'); // follows OS preference, auto-updates
toggleTheme(); // flip between light and dark3. Import and use components
import '@melodicdev/components/button';
import '@melodicdev/components/input';
// etc.<ml-button>Save</ml-button>
<ml-input placeholder="Search..."></ml-input>That's it. No additional setup needed for icons or fonts — they're bundled in melodic-components.css.
CDN / No-Build Usage
If you're not using a bundler, you can load everything — styles, fonts, and all components — with just two tags. No npm, no build step required:
<!doctype html>
<html data-theme="light">
<head>
<link melodic-styles rel="stylesheet"
href="https://unpkg.com/@melodicdev/[email protected]/assets/melodic-components.min.css">
<script type="module"
src="https://unpkg.com/@melodicdev/[email protected]/assets/melodic-components.min.js"></script>
</head>
<body>
<ml-button>Hello</ml-button>
<ml-icon icon="star"></ml-icon>
</body>
</html>The JS bundle includes the full Melodic framework (core, forms, routing, HTTP, dependency injection, and state management) — no separate script needed. All components register themselves automatically when the script loads.
The theme API is available as a named export from the module:
<script type="module">
import { applyTheme } from 'https://unpkg.com/@melodicdev/[email protected]/assets/melodic-components.min.js';
applyTheme('dark');
</script>Bundler / Framework Setup
If you'd rather serve fonts locally (for offline use, CSP restrictions, etc.) instead of using the CDN, copy the assets from the package:
Vite:
npm install -D vite-plugin-static-copy// vite.config.ts
import { viteStaticCopy } from 'vite-plugin-static-copy';
export default defineConfig({
plugins: [
viteStaticCopy({
targets: [
{ src: 'node_modules/@melodicdev/components/assets', dest: '.' }
]
})
]
});Then reference the local copy in your HTML:
<link melodic-styles rel="stylesheet" href="/assets/melodic-components.css">Icons
The ml-icon component uses Phosphor Icons via font ligatures. The fonts are included in melodic-components.css — no separate setup needed if you're using the stylesheet above.
import '@melodicdev/components/icon';<ml-icon icon="house"></ml-icon>
<ml-icon icon="gear" size="lg"></ml-icon>
<ml-icon icon="heart" format="fill"></ml-icon>| Property | Type | Default | Description |
|----------|------|---------|-------------|
| icon | string | '' | Icon name (ligature). Browse at phosphoricons.com |
| format | 'regular' | 'bold' | 'fill' | 'light' | 'thin' | 'regular' | Icon weight/style |
| size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Icon size (12 / 16 / 24 / 32 / 48px) |
Custom color:
ml-icon {
--ml-icon-color: var(--ml-color-primary);
}Duotone icons are not available — the Phosphor duotone font does not support ligatures.
Documentation
Components
- Theming — Token system, applying themes, creating custom themes, overriding styles
- Forms — button, button-group, input, textarea, checkbox, radio, radio-card-group, toggle, select, slider, date-picker, form-field
- Foundation — card, divider, stack, container
- Feedback — spinner, alert, progress, toast
- Data Display — avatar, badge, badge-group, tag, list, activity-feed, table, data-grid, calendar-view
- Navigation — tabs, breadcrumb, pagination, sidebar, steps
- Overlays — dialog, drawer, popover, dropdown, tooltip
- Sections — app-shell, page-header, hero-section
Utilities & Helpers
- Utilities — positioning, accessibility (focus trap, live regions), virtual scrolling, style utilities
- Directives & Functions — clickOutside, newID, theme functions, design token objects
Naming Conventions
Elements
All components use kebab-case with the ml- prefix:
ml-button, ml-input, ml-select, ml-checkbox, ml-data-grid, etc.Events
All custom events use the ml: namespace prefix:
ml:click, ml:change, ml:input, ml:open, ml:close, ml:select, ml:sort, etc.Listening in a Melodic template:
<ml-button @ml:click=${this.handleClick}>Save</ml-button>
<ml-input @ml:change=${this.handleChange}></ml-input>
<ml-select @ml:open=${this.onOpen} @ml:close=${this.onClose}></ml-select>Common Types
type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
type Placement =
| 'top' | 'top-start' | 'top-end'
| 'bottom' | 'bottom-start' | 'bottom-end'
| 'left' | 'left-start' | 'left-end'
| 'right' | 'right-start' | 'right-end';
type ThemeMode = 'light' | 'dark' | 'system';Theme System
Override tokens globally via CSS:
:root {
--ml-color-primary: #7c3aed;
--ml-color-primary-hover: #6d28d9;
--ml-radius: 0.375rem;
}See Theming for the full token reference, custom theme creation, dark mode setup, and per-component style overrides.
