Loading...
Loading...
Phoenix Duskmoon UI component library for Elixir/Phoenix LiveView applications. Use when building UIs with `phoenix_duskmoon` — covers installation, CSS/JS setup, component usage patterns (dm_* prefix), slots, form inputs, icons, CSS art, and the v9 custom elements architecture. Trigger on: adding phoenix_duskmoon to a Phoenix project, using dm_* components, configuring themes, setting up hooks, or integrating @duskmoon-dev/core CSS design system.
npx skill4agent add gsmlg-dev/code-agent phoenix-duskmoon-ui<el-dm-*>@duskmoon-dev/core# mix.exs
{:phoenix_duskmoon, "~> 9.0"}bun add @duskmoon-dev/core @duskmoon-dev/elements @duskmoon-dev/css-art @duskmoon-dev/art-elementsapp_web.exdefp html_helpers do
quote do
use PhoenixDuskmoon.Component # all dm_* UI components
use PhoenixDuskmoon.ArtComponent # all dm_art_* decorative components
end
endassets/css/app.css@import "tailwindcss";
@plugin "@duskmoon-dev/core/plugin";
@import "@duskmoon-dev/core/themes/sunshine";
@import "@duskmoon-dev/core/themes/moonlight";
@import "@duskmoon-dev/core/components";assets/css/element-theme-bridge.css@import "@duskmoon-dev/css-art/eclipse.css";
@import "@duskmoon-dev/css-art/snow.css";
/* ... etc */assets/js/app.jsimport { LiveSocket } from "phoenix_live_view";
import * as DuskmoonHooks from "phoenix_duskmoon/hooks";
let liveSocket = new LiveSocket("/live", Socket, {
params: { _csrf_token: csrfToken },
hooks: DuskmoonHooks
});hooks: { ...DuskmoonHooks, ...MyHooks }import "@duskmoon-dev/el-button/register";
import "@duskmoon-dev/el-card/register";
// ... register each el-* package you use<el-dm-*>HEEX Components (dm_btn, dm_card)
|
Custom Elements (<el-dm-button>, <el-dm-card>)
|
@duskmoon-dev/core (CSS variables, design tokens)dm-componentdm-component--variantdm-component__element"accent""tertiary"| Hook | Used by | Purpose |
|---|---|---|
| Any | Bridges custom element events to LiveView |
| Form | Adds |
| | Theme toggle + localStorage persistence |
| Spotlight search component | Cmd/Ctrl+K keyboard shortcut |
| | IntersectionObserver for scroll-based nav |
dm_idclassvariantcolorsizedisabledrest| Function | Module | Description |
|---|---|---|
| Action.Button | Button with variants, confirm dialog, noise effect |
| Action.Link | LiveView-aware link (navigate/patch/href) |
| Action.Dropdown | Popover-based dropdown with trigger + content slots |
| Action.Menu | Anchored menu with placement control |
| Action.Toggle | Toggle button group (segmented, chip, etc.) |
| Function | Module | Description |
|---|---|---|
| DataDisplay.Accordion | Multi-panel expand/collapse |
| DataDisplay.Avatar | User avatar with status indicators |
| DataDisplay.Badge | Label badge with color variants |
| DataDisplay.Card | Content card with title/action slots |
| DataDisplay.Chip | Deletable chip/tag |
| DataDisplay.Collapse | Single collapsible panel |
| DataDisplay.Flash | Flash messages |
| DataDisplay.List | Structured list with icons and subtitles |
| DataDisplay.Markdown | Markdown renderer with syntax highlighting |
| DataDisplay.Pagination | Page navigation |
| DataDisplay.Popover | Contextual overlay with trigger |
| DataDisplay.Progress | Linear/circular progress |
| DataDisplay.Skeleton | 8 skeleton variants (text, avatar, card, table, list, form, comment, base) |
| DataDisplay.Stat | Stat display with icon slot |
| DataDisplay.Table | Data table with streaming support |
| DataDisplay.Timeline | Vertical/horizontal timeline |
| DataDisplay.Tooltip | Tooltip wrapper |
| Function | Module | Description |
|---|---|---|
| DataEntry.Form | Form container + layout helpers ( |
| DataEntry.Input | Universal input (30+ types via |
| DataEntry.CompactInput | Compact variant of input |
| DataEntry.Checkbox | Checkbox with label |
| DataEntry.Radio | Radio button with label |
| DataEntry.Select | Select dropdown |
| DataEntry.Switch | Toggle switch |
| DataEntry.Slider | Range slider |
| DataEntry.Textarea | Multi-line text input |
| DataEntry.Rating | Star rating |
| DataEntry.SegmentControl | Segmented control |
| DataEntry.MultiSelect | Multi-select with tags |
| DataEntry.Autocomplete | Autocomplete input |
| DataEntry.OtpInput | OTP code input |
| DataEntry.PinInput | PIN input |
| DataEntry.FileUpload | File upload area |
| DataEntry.TimeInput | Time picker |
| DataEntry.Cascader | Cascading select |
| DataEntry.TreeSelect | Tree-structured select |
| DataEntry.MarkdownInput | Markdown editor with preview |
| Function | Module | Description |
|---|---|---|
| Feedback.Dialog | Modal dialog with trigger/title/body/footer slots |
| Feedback.Loading | Loading indicators |
| Feedback.Toast | Toast notifications |
| Feedback.Snackbar | Snackbar messages |
| Function | Module | Description |
|---|---|---|
| Navigation.Actionbar | Action toolbar with left/right slots |
| Navigation.Appbar | Top navigation bar |
| Navigation.BottomNav | Mobile bottom navigation |
| Navigation.Breadcrumb | Breadcrumb trail |
| Navigation.LeftMenu | Sidebar menu |
| Navigation.Navbar | Horizontal navbar (start/center/end) |
| Navigation.NestedMenu | Nested collapsible menu |
| Navigation.PageFooter | Page footer with sections |
| Navigation.PageHeader | Page header with scroll-aware nav (needs hook) |
| Navigation.Stepper | CSS-only stepper |
| Navigation.Steps | Stepper via custom element |
| Navigation.Tab | Tabbed content |
| Function | Module | Description |
|---|---|---|
| Layout.BottomSheet | Bottom sheet overlay |
| Layout.Divider | Horizontal/vertical divider |
| Layout.Drawer | Slide-out drawer panel |
| Layout.ThemeSwitcher | Theme toggle (needs hook) |
| Function | Module | Description |
|---|---|---|
| Icon.Icons | Material Design Icons (7000+ icons) |
| Icon.Icons | Bootstrap Icons (2000+ icons) |
idclassrestuse PhoenixDuskmoon.ArtComponent| Function | Module | Description |
|---|---|---|
| ArtComponent.Atom | Animated atom |
| ArtComponent.CatStargazer | Cat stargazer scene |
| ArtComponent.CircularGallery | Circular gallery |
| ArtComponent.ColorSpin | Color spin effect |
| ArtComponent.Eclipse | Animated eclipse |
| ArtComponent.FlowerAnimation | Flower animation |
| ArtComponent.GeminiInput | Gemini-style input (size, placeholder) |
| ArtComponent.Moon | Moon scene |
| ArtComponent.Mountain | Mountain landscape |
| ArtComponent.PlasmaBall | Interactive plasma ball |
| ArtComponent.Snow | Falling snowflakes (unicode, fall) |
| ArtComponent.Sun | Sun scene |
| ArtComponent.SynthwaveStarfield | Synthwave starfield |
<%!-- Button with variant --%>
<.dm_btn variant="primary" size="md">Save</.dm_btn>
<.dm_btn variant="error" shape="circle" loading={@saving}>X</.dm_btn>
<%!-- Button with confirmation dialog --%>
<.dm_btn confirm="Delete this item?" phx-click="delete" phx-value-id={@item.id}>
Delete
</.dm_btn>
<%!-- Card with slots --%>
<.dm_card variant="bordered">
<:title>Dashboard</:title>
Content here
<:action><.dm_btn variant="primary">View</.dm_btn></:action>
</.dm_card>
<%!-- Icons --%>
<.dm_mdi name="home" class="w-6 h-6" />
<.dm_bsi name="house" class="w-5 h-5" />
<%!-- Form with inputs --%>
<.dm_form for={@form} phx-submit="save">
<.dm_input field={@form[:name]} label="Name" />
<.dm_select field={@form[:role]} label="Role" options={[{"admin", "Admin"}, {"user", "User"}]} />
<.dm_switch field={@form[:active]} label="Active" />
<:actions>
<.dm_btn variant="primary" type="submit">Save</.dm_btn>
</:actions>
</.dm_form>
<%!-- Navigation --%>
<.dm_appbar title="My App" title_to={~p"/"}>
<:menu to={~p"/dashboard"} active={@active == :dashboard}>Dashboard</:menu>
<:menu to={~p"/settings"}>Settings</:menu>
<:user_profile>
<.dm_avatar name={@current_user.name} size="sm" />
</:user_profile>
</.dm_appbar>
<%!-- Theme switcher (requires ThemeSwitcher hook) --%>
<.dm_theme_switcher id="theme-toggle" theme={@theme} />
<%!-- Tabs --%>
<.dm_tab id="my-tabs" active_tab_index={0}>
<:tab name="overview">Overview</:tab>
<:tab name="details">Details</:tab>
<:tab_content name="overview">Overview content</:tab_content>
<:tab_content name="details">Details content</:tab_content>
</.dm_tab>
<%!-- Modal --%>
<.dm_modal id="confirm-modal">
<:trigger><.dm_btn>Open</.dm_btn></:trigger>
<:title>Confirm</:title>
<:body>Are you sure?</:body>
<:footer><.dm_btn variant="primary" phx-click="confirm">Yes</.dm_btn></:footer>
</.dm_modal>
<%!-- Art components --%>
<.dm_art_snow id="snow-1" />
<.dm_art_eclipse id="eclipse-1" />
<.dm_art_gemini_input id="ai-input" size="lg" placeholder="Ask anything..." />| Import path | File |
|---|---|
| |
| |
| |
| |
| |