phoenix-duskmoon-ui

Original🇺🇸 English
Translated

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.

9installs
Added on

NPX Install

npx skill4agent add gsmlg-dev/code-agent phoenix-duskmoon-ui

Phoenix Duskmoon UI

Elixir component library providing 80+ LiveView HEEX components that render as HTML Custom Elements (
<el-dm-*>
) styled by
@duskmoon-dev/core
.
Version: 9.0.1

Installation

elixir
# mix.exs
{:phoenix_duskmoon, "~> 9.0"}
bash
bun add @duskmoon-dev/core @duskmoon-dev/elements @duskmoon-dev/css-art @duskmoon-dev/art-elements

Setup

1. Import components in
app_web.ex

elixir
defp html_helpers do
  quote do
    use PhoenixDuskmoon.Component    # all dm_* UI components
    use PhoenixDuskmoon.ArtComponent # all dm_art_* decorative components
  end
end

2. CSS (
assets/css/app.css
)

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";
For custom elements to inherit theme colors, include the element-theme-bridge (ships with the package or copy from the repo's
assets/css/element-theme-bridge.css
).
For CSS art effects, import each CSS art stylesheet you need:
css
@import "@duskmoon-dev/css-art/eclipse.css";
@import "@duskmoon-dev/css-art/snow.css";
/* ... etc */

3. JavaScript hooks (
assets/js/app.js
)

javascript
import { LiveSocket } from "phoenix_live_view";
import * as DuskmoonHooks from "phoenix_duskmoon/hooks";

let liveSocket = new LiveSocket("/live", Socket, {
  params: { _csrf_token: csrfToken },
  hooks: DuskmoonHooks
});
Merge with your own hooks:
hooks: { ...DuskmoonHooks, ...MyHooks }
.

4. Register custom elements

javascript
import "@duskmoon-dev/el-button/register";
import "@duskmoon-dev/el-card/register";
// ... register each el-* package you use
Without registration,
<el-dm-*>
content is invisible.

Architecture (v9)

HEEX Components (dm_btn, dm_card)
       |
Custom Elements (<el-dm-button>, <el-dm-card>)
       |
@duskmoon-dev/core (CSS variables, design tokens)
CSS class naming (BEM):
dm-component
,
dm-component--variant
,
dm-component__element
Color mapping:
"accent"
in component APIs maps to
"tertiary"
in CSS tokens.

Hooks Reference

HookUsed byPurpose
WebComponentHook
Any
el-dm-*
with
phx-*
events
Bridges custom element events to LiveView
FormElementHook
Form
el-dm-*
inputs
Adds
phx-feedback-for
support
ThemeSwitcher
dm_theme_switcher
Theme toggle + localStorage persistence
Spotlight
Spotlight search componentCmd/Ctrl+K keyboard shortcut
PageHeader
dm_page_header
IntersectionObserver for scroll-based nav

Component Quick Reference

All components use
dm_
prefix. Common attributes across most components:
  • id
    ,
    class
    — standard HTML
  • variant
    — visual style (values vary per component)
  • color
    — primary | secondary | tertiary | accent | info | success | warning | error
  • size
    — xs | sm | md | lg (varies per component)
  • disabled
    — boolean
  • rest
    — passes through global HTML attributes
For full component catalog with all attributes and slots, see references/components.md.

Action

FunctionModuleDescription
dm_btn
Action.ButtonButton with variants, confirm dialog, noise effect
dm_link
Action.LinkLiveView-aware link (navigate/patch/href)
dm_dropdown
Action.DropdownPopover-based dropdown with trigger + content slots
dm_menu
/
dm_menu_item
Action.MenuAnchored menu with placement control
dm_toggle_group
Action.ToggleToggle button group (segmented, chip, etc.)

Data Display

FunctionModuleDescription
dm_accordion
DataDisplay.AccordionMulti-panel expand/collapse
dm_avatar
DataDisplay.AvatarUser avatar with status indicators
dm_badge
DataDisplay.BadgeLabel badge with color variants
dm_card
/
dm_async_card
DataDisplay.CardContent card with title/action slots
dm_chip
DataDisplay.ChipDeletable chip/tag
dm_collapse
/
dm_collapse_group
DataDisplay.CollapseSingle collapsible panel
dm_flash
/
dm_flash_group
DataDisplay.FlashFlash messages
dm_list
DataDisplay.ListStructured list with icons and subtitles
dm_markdown
DataDisplay.MarkdownMarkdown renderer with syntax highlighting
dm_pagination
/
dm_pagination_thin
DataDisplay.PaginationPage navigation
dm_popover
DataDisplay.PopoverContextual overlay with trigger
dm_progress
DataDisplay.ProgressLinear/circular progress
dm_skeleton_*
DataDisplay.Skeleton8 skeleton variants (text, avatar, card, table, list, form, comment, base)
dm_stat
DataDisplay.StatStat display with icon slot
dm_table
DataDisplay.TableData table with streaming support
dm_timeline
DataDisplay.TimelineVertical/horizontal timeline
dm_tooltip
DataDisplay.TooltipTooltip wrapper

Data Entry

FunctionModuleDescription
dm_form
DataEntry.FormForm container + layout helpers (
dm_label
,
dm_error
,
dm_alert
,
dm_fieldset
,
dm_form_row
,
dm_form_grid
,
dm_form_section
,
dm_form_divider
,
dm_form_inline
,
dm_form_hint
,
dm_form_counter
)
dm_input
DataEntry.InputUniversal input (30+ types via
type
attr)
dm_compact_input
DataEntry.CompactInputCompact variant of input
dm_checkbox
DataEntry.CheckboxCheckbox with label
dm_radio
DataEntry.RadioRadio button with label
dm_select
DataEntry.SelectSelect dropdown
dm_switch
DataEntry.SwitchToggle switch
dm_slider
DataEntry.SliderRange slider
dm_textarea
DataEntry.TextareaMulti-line text input
dm_rating
DataEntry.RatingStar rating
dm_segment_control
DataEntry.SegmentControlSegmented control
dm_multi_select
DataEntry.MultiSelectMulti-select with tags
dm_autocomplete
DataEntry.AutocompleteAutocomplete input
dm_otp_input
DataEntry.OtpInputOTP code input
dm_pin_input
DataEntry.PinInputPIN input
dm_file_upload
DataEntry.FileUploadFile upload area
dm_time_input
DataEntry.TimeInputTime picker
dm_cascader
DataEntry.CascaderCascading select
dm_tree_select
DataEntry.TreeSelectTree-structured select
dm_markdown_input
DataEntry.MarkdownInputMarkdown editor with preview

Feedback

FunctionModuleDescription
dm_modal
Feedback.DialogModal dialog with trigger/title/body/footer slots
dm_loading_spinner
/
dm_loading_ex
Feedback.LoadingLoading indicators
dm_toast
/
dm_toast_container
Feedback.ToastToast notifications
dm_snackbar
/
dm_snackbar_container
Feedback.SnackbarSnackbar messages

Navigation

FunctionModuleDescription
dm_actionbar
Navigation.ActionbarAction toolbar with left/right slots
dm_appbar
/
dm_simple_appbar
Navigation.AppbarTop navigation bar
dm_bottom_nav
Navigation.BottomNavMobile bottom navigation
dm_breadcrumb
Navigation.BreadcrumbBreadcrumb trail
dm_left_menu
/
dm_left_menu_group
Navigation.LeftMenuSidebar menu
dm_navbar
Navigation.NavbarHorizontal navbar (start/center/end)
dm_nested_menu
/
dm_nested_menu_item
Navigation.NestedMenuNested collapsible menu
dm_page_footer
Navigation.PageFooterPage footer with sections
dm_page_header
Navigation.PageHeaderPage header with scroll-aware nav (needs hook)
dm_stepper
Navigation.StepperCSS-only stepper
dm_steps
Navigation.StepsStepper via custom element
dm_tab
Navigation.TabTabbed content

Layout

FunctionModuleDescription
dm_bottom_sheet
Layout.BottomSheetBottom sheet overlay
dm_divider
Layout.DividerHorizontal/vertical divider
dm_drawer
Layout.DrawerSlide-out drawer panel
dm_theme_switcher
Layout.ThemeSwitcherTheme toggle (needs hook)

Icon

FunctionModuleDescription
dm_mdi
Icon.IconsMaterial Design Icons (7000+ icons)
dm_bsi
Icon.IconsBootstrap Icons (2000+ icons)

CSS Art (decorative)

All art components require
id
(required string) and accept
class
+
rest
global attrs. Import via
use PhoenixDuskmoon.ArtComponent
.
FunctionModuleDescription
dm_art_atom
ArtComponent.AtomAnimated atom
dm_art_cat_stargazer
ArtComponent.CatStargazerCat stargazer scene
dm_art_circular_gallery
ArtComponent.CircularGalleryCircular gallery
dm_art_color_spin
ArtComponent.ColorSpinColor spin effect
dm_art_eclipse
ArtComponent.EclipseAnimated eclipse
dm_art_flower_animation
ArtComponent.FlowerAnimationFlower animation
dm_art_gemini_input
ArtComponent.GeminiInputGemini-style input (size, placeholder)
dm_art_moon
ArtComponent.MoonMoon scene
dm_art_mountain
ArtComponent.MountainMountain landscape
dm_art_plasma_ball
ArtComponent.PlasmaBallInteractive plasma ball
dm_art_snow
ArtComponent.SnowFalling snowflakes (unicode, fall)
dm_art_sun
ArtComponent.SunSun scene
dm_art_synthwave_starfield
ArtComponent.SynthwaveStarfieldSynthwave starfield

Usage Examples

heex
<%!-- 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..." />

Package Exports

Import pathFile
phoenix_duskmoon
priv/static/phoenix_duskmoon.js
phoenix_duskmoon/hooks
assets/js/hooks/index.js
phoenix_duskmoon/css
priv/static/phoenix_duskmoon.css
phoenix_duskmoon/svg/mdi/*.svg
priv/mdi/svg/*.svg
phoenix_duskmoon/svg/bsi/*.svg
priv/bsi/svg/*.svg