PhoenixPaper.Drawer (PhoenixPaper v0.1.0)

Copy Markdown View Source

A Material Design navigation drawer (pp_drawer/1) — a vertical panel, persistent on large screens (lg: and up, pinned via sticky so it stays in place as the page scrolls, with its own internal scroll if its content is taller than the viewport) and toggled by a mobile drawer below that breakpoint. Compose it with PhoenixPaper.List / PhoenixPaper.ListItem for its contents.

The mobile toggle is pure CSS, no JS/LiveView required: pp_drawer/1 renders a visually hidden checkbox, and both the drawer panel and its backdrop react to it via peer-checked:. pp_drawer_toggle/1 is just a <label for={...}> pointing at that same checkbox — clicking any label wired to a checkbox's id checks it natively, so the toggle button and the drawer don't need to be DOM siblings, unlike most of this library's other peer-*/has-[:checked]: tricks (see AGENTS.md).

<.pp_app_bar>
  <:leading><.pp_drawer_toggle for="app-drawer" /></:leading>
  My App
</.pp_app_bar>

<.pp_drawer id="app-drawer" color="primary">
  <:header>My App</:header>
  <.pp_list>
    <.pp_list_item navigate={~p"/"} active={@current_path == "/"}>
      <:leading><.pp_icon name="hero-home" /></:leading>
      Home
    </.pp_list_item>
    <.pp_list_item navigate={~p"/settings"} active={@current_path == "/settings"}>
      <:leading><.pp_icon name="hero-cog-6-tooth" /></:leading>
      Settings
    </.pp_list_item>
  </.pp_list>
</.pp_drawer>

pp_drawer_toggle/1 lives here rather than its own module because it only makes sense paired with a pp_drawer/1 (see AGENTS.md, "Component conventions").

color

Defaults to "surface" (the original plain white/dark-surface look, unchanged from before this attr existed). "primary"/"secondary"/ "tertiary" paint the whole panel that brand color — including its nested PhoenixPaper.List/PhoenixPaper.ListItem/ PhoenixPaper.ListSubheader/PhoenixPaper.Divider content, which are normally styled for a neutral surface background. There's no prop on those components for "the color of my container" (same "no cascading" limitation ButtonGroup/Tabs/AppBar already document), so instead pp_drawer/1 reaches into them with a handful of [&_[data-pp-component=...]] compound selectors — the same technique (and the same data-pp-component attribute) Tabs's variant="full_width" already uses to reach its child Tabs, just applied to more targets here. This is a real, intentional exception to "components don't reach into each other" for the one specific case where getting it wrong isn't a style mismatch but actual illegibility: ListItem's active-item highlight (bg-pp-primary/10) mixed with a color="primary" drawer background is the exact same color layered on itself, which is mathematically invisible, not just low-contrast — found and fixed by actually screenshotting a colored drawer with an active nav item, not by reasoning about it in the abstract. ListItem's active attr sets aria-current="page" specifically so this selector has something stable to target (see its moduledoc) — without that attribute there'd be no way to tell an active item from an inactive one from CSS alone.

Summary

Functions

Renders a navigation drawer. See the module doc.

A hamburger button that toggles the pp_drawer/1 with the given for id.

Functions

pp_drawer(assigns)

Renders a navigation drawer. See the module doc.

Attributes

  • id (:string) (required) - builds the mobile toggle checkbox's id as "#{id}-toggle".
  • color (:string) - surface (default) is the original plain look; the others also restyle nested List/ListItem content for contrast. Defaults to "surface". Must be one of "primary", "secondary", "tertiary", or "surface".
  • elevation (:integer) - resting elevation (0-24), see PhoenixPaper.Elevation -- 0 pairs well with a caller-added border instead. Defaults to 2.
  • paperize (:boolean) - Defaults to true.
  • class (:any) - Defaults to nil.
  • Global attributes are accepted.

Slots

  • header
  • inner_block (required)

pp_drawer_toggle(assigns)

A hamburger button that toggles the pp_drawer/1 with the given for id.

Attributes

  • for (:string) (required) - the target pp_drawer/1's id.
  • paperize (:boolean) - Defaults to true.
  • class (:any) - Defaults to nil.