Component: Dark mode

Getting started

Dark Mode

AvenUI includes built-in dark mode support using CSS variables. No JavaScript required for basic theming.

How it Works

Dark mode in AvenUI uses the class strategy. Add the "dark" class to your HTML element to enable dark mode:

html
<!-- Light mode -->
<html>

<!-- Dark mode -->
<html class="dark">

LiveView Implementation

Store the dark mode preference in your LiveView state and toggle it with an event:

elixir
def mount(_params, _session, socket) do
  {:ok, assign(socket, dark_mode: false)}
end

def handle_event("toggle_dark", _, socket) do
  {:noreply, update(socket, :dark_mode, &(!&1))}
end

In your root layout:

html
<html class={if @dark_mode, do: "dark", else: ""}>

Persisting with LocalStorage

To remember the user's preference across sessions, use JavaScript:

javascript
// app.js
const initDarkMode = () => {
  const isDark = localStorage.getItem('dark_mode') === 'true'
  if (isDark) {
    document.documentElement.classList.add('dark')
  }
}

// Toggle function
window.toggleDarkMode = () => {
  const isDark = document.documentElement.classList.toggle('dark')
  localStorage.setItem('dark_mode', isDark)
}

initDarkMode()

Respecting System Preference

Automatically use the user's system dark mode preference:

javascript
const initDarkMode = () => {
  const stored = localStorage.getItem('dark_mode')
  const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches

  if (stored === 'true' || (stored === null && systemDark)) {
    document.documentElement.classList.add('dark')
  }
}

// Listen for system changes
window.matchMedia('(prefers-color-scheme: dark)')
  .addEventListener('change', (e) => {
    if (localStorage.getItem('dark_mode') === null) {
      document.documentElement.classList.toggle('dark', e.matches)
    }
  })

Customizing Dark Mode Colors

Override the default dark mode colors in your CSS:

css
.dark {
  /* Darker background */
  --avn-background: 0 0 0;

  /* Custom card color */
  --avn-card: 17 24 39;

  /* Brighter text */
  --avn-foreground: 255 255 255;

  /* Custom border */
  --avn-border: 55 65 81;
}