SuperAPI AI Directory

phoenix-duskmoon-ui

Frontend & websites

View repository

Updated 10-15 21:55

About this skill

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.4.0

Installation

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

Setup

1. Import components in app_web.ex

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)

@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:

@import "@duskmoon-dev/css-art/dist/art/eclipse.css";
@import "@duskmoon-dev/css-art/dist/art/snow.css";
/* ... etc */

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

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

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.

5. Register chat elements (if using chat components)

import "@duskmoon-dev/el-chat/register";

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

Hooks Reference

Hook Used by Purpose
WebComponentHook Any el-dm-* with phx-* events or chat event attrs 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 component Cmd/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

Function Module Description
dm_btn Action.Button Button with variants, confirm dialog, noise effect
dm_link Action.Link LiveView-aware link (navigate/patch/href)
dm_dropdown Action.Dropdown Popover-based dropdown with trigger + content slots
dm_menu / dm_menu_item Action.Menu Anchored menu with placement control
dm_toggle_group Action.Toggle Toggle button group (segmented, chip, etc.)

Data Display

Function Module Description
dm_accordion DataDisplay.Accordion Multi-panel expand/collapse
dm_avatar DataDisplay.Avatar User avatar with status indicators
dm_badge DataDisplay.Badge Label badge with color variants
dm_card / dm_async_card DataDisplay.Card Content card with title/action slots
dm_chat / dm_chat_bubble / dm_chat_input / dm_chat_reasoning / dm_chat_tool / dm_chat_typing DataDisplay.Chat LLM-oriented chat primitives (message, bubble, input, reasoning, tool, typing indicator)
dm_chip DataDisplay.Chip Deletable chip/tag
dm_collapse / dm_collapse_group DataDisplay.Collapse Single collapsible panel
dm_flash / dm_flash_group DataDisplay.Flash Flash messages
dm_list DataDisplay.List Structured list with icons and subtitles
dm_markdown DataDisplay.Markdown Markdown renderer with syntax highlighting
dm_pagination / dm_pagination_thin DataDisplay.Pagination Page navigation
dm_popover DataDisplay.Popover Contextual overlay with trigger
dm_progress DataDisplay.Progress Linear/circular progress
dm_skeleton_* DataDisplay.Skeleton 8 skeleton variants (text, avatar, card, table, list, form, comment, base)
dm_stat DataDisplay.Stat Stat display with icon slot
dm_table DataDisplay.Table Data table with streaming support
dm_timeline DataDisplay.Timeline Vertical/horizontal timeline
dm_tooltip DataDisplay.Tooltip Tooltip wrapper

Data Entry

Function Module Description
dm_form DataEntry.Form Form 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.Input Universal input (30+ types via type attr)
dm_compact_input DataEntry.CompactInput Compact variant of input
dm_checkbox DataEntry.Checkbox Checkbox with label
dm_radio DataEntry.Radio Radio button with label
dm_select DataEntry.Select Select dropdown
dm_switch DataEntry.Switch Toggle switch
dm_slider DataEntry.Slider Range slider
dm_textarea DataEntry.Textarea Multi-line text input
dm_rating DataEntry.Rating Star rating
dm_segment_control DataEntry.SegmentControl Segmented control
dm_multi_select DataEntry.MultiSelect Multi-select with tags
dm_autocomplete DataEntry.Autocomplete Autocomplete input
dm_otp_input DataEntry.OtpInput OTP code input
dm_pin_input DataEntry.PinInput PIN input
dm_file_upload DataEntry.FileUpload File upload area
dm_time_input DataEntry.TimeInput Time picker
dm_cascader DataEntry.Cascader Cascading select
dm_tree_select DataEntry.TreeSelect Tree-structured select
dm_markdown_input DataEntry.MarkdownInput Markdown editor with preview
dm_code_engine DataEntry.CodeEngine Code editor with 25+ language syntax highlighting

Feedback

Function Module Description
dm_modal Feedback.Dialog Modal dialog with trigger/title/body/footer slots
dm_loading_spinner / dm_loading_ex Feedback.Loading Loading indicators
dm_toast / dm_toast_container Feedback.Toast Toast notifications
dm_snackbar / dm_snackbar_container Feedback.Snackbar Snackbar messages

Navigation

Function Module Description
dm_actionbar Navigation.Actionbar Action toolbar with left/right slots
dm_appbar / dm_simple_appbar Navigation.Appbar Top navigation bar
dm_bottom_nav Navigation.BottomNav Mobile bottom navigation
dm_breadcrumb Navigation.Breadcrumb Breadcrumb trail
dm_left_menu / dm_left_menu_group Navigation.LeftMenu Sidebar menu
dm_navbar Navigation.Navbar Horizontal navbar (start/center/end)
dm_nested_menu / dm_nested_menu_item Navigation.NestedMenu Nested collapsible menu
dm_page_footer Navigation.PageFooter Page footer with sections
dm_page_header Navigation.PageHeader Page header with scroll-aware nav (needs hook)
dm_stepper Navigation.Stepper CSS-only stepper
dm_steps Navigation.Steps Stepper via custom element
dm_tab Navigation.Tab Tabbed content

Layout

Function Module Description
dm_bottom_sheet Layout.BottomSheet Bottom sheet overlay
dm_divider Layout.Divider Horizontal/vertical divider
dm_drawer Layout.Drawer Slide-out drawer panel
dm_theme_switcher Layout.ThemeSwitcher Theme toggle (needs hook)

Icon

Function Module Description
dm_mdi Icon.Icons Material Design Icons (7000+ icons)
dm_bsi Icon.Icons Bootstrap Icons (2000+ icons)

CSS Art (decorative)

All art components require id (required string) and accept class + rest global attrs. Import via use PhoenixDuskmoon.ArtComponent.

Function Module Description
dm_art_atom ArtComponent.Atom Animated atom
dm_art_cat_stargazer ArtComponent.CatStargazer Cat stargazer scene
dm_art_circular_gallery ArtComponent.CircularGallery Circular gallery
dm_art_color_spin ArtComponent.ColorSpin Color spin effect
dm_art_eclipse ArtComponent.Eclipse Animated eclipse
dm_art_flower_animation ArtComponent.FlowerAnimation Flower animation
dm_art_gemini_input ArtComponent.GeminiInput Gemini-style input (size, placeholder)
dm_art_moon ArtComponent.Moon Moon scene
dm_art_mountain ArtComponent.Mountain Mountain landscape
dm_art_plasma_ball ArtComponent.PlasmaBall Interactive plasma ball
dm_art_snow ArtComponent.Snow Falling snowflakes (unicode, fall)
dm_art_sun ArtComponent.Sun Sun scene
dm_art_synthwave_starfield ArtComponent.SynthwaveStarfield Synthwave starfield

Usage Examples

<%!-- 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>

<%!-- Chat message --%>
<.dm_chat author="Assistant" avatar="AI" color="primary" content="Hello! How can I help?" />
<.dm_chat align="end" author="You" avatar="JG" variant="filled">
  What's the weather like?
</.dm_chat>

<%!-- Chat input --%>
<.dm_chat_input id="chat-input" placeholder="Type a message..." send_label="Send" />

<%!-- Chat reasoning section --%>
<.dm_chat_reasoning summary="Thinking..." open={false}>
  Step-by-step reasoning here...
</.dm_chat_reasoning>

<%!-- Chat typing indicator --%>
<.dm_chat_typing id="typing-indicator" />

<%!-- Code editor --%>
<.dm_code_engine
  field={@form[:source]}
  language="elixir"
  theme="one-dark"
  show_topbar
  title="example.ex"
/>

<%!-- Markdown editor --%>
<.dm_markdown_input
  field={@form[:body]}
  placeholder="Write markdown here…"
  upload_url="/api/uploads"
/>

<%!-- 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 path File
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/components priv/static/phoenix_duskmoon.css
phoenix_duskmoon/svg/mdi/*.svg priv/mdi/svg/*.svg
phoenix_duskmoon/svg/bsi/*.svg priv/bsi/svg/*.svg