Nav Link

v0.0.10

v0.0.10StableHeadlessStatelessAccessibleApache-2.0
Installation mix mishka.ui.gen.headless nav_link
Source View Source

Keeping a group open in a LiveView

default_opened opens a group on first render, which is enough on a static page. Inside a LiveView, pass opened instead. It is the server's truth for the group and overrides default_opened. on_toggle is a phx-click on the control row, so use it to flip the value you pass as opened.

heex
<.nav_link label="Projects" opened={@projects_open} on_toggle="toggle_projects">
  <:children>
    <.nav_link label="Active" navigate={~p"/projects/active"} />
    <.nav_link label="Archived" navigate={~p"/projects/archived"} />
  </:children>
</.nav_link>
elixir
def handle_event("toggle_projects", _params, socket) do
  {:noreply, update(socket, :projects_open, &(!&1))}
end

Parts & data attributes

Each part carries a stable data-part and a structural chelekom-nav-link__* class you can target, plus the state attributes below. The root of a leaf has data-part="link" and the root of a group has data-part="root".

Partdata-partState / ARIAPurpose
Link (leaf root)linkdata-active, aria-currentThe LiveView link of an item with no children.
Root (group)rootdata-active, openThe details element of an item with children.
Controlcontrol-The summary that toggles the group. on_toggle is attached here.
Iconicon-Wraps the icon slot. Rendered only when the slot is given.
Labellabel-The text of the item.
Trailingtrailing-Wraps the trailing slot, for example a chevron.
Childrenchildren-The container of the nested links.

Accessibility

There is no formal WAI-ARIA APG pattern for a navigation link. The active leaf carries aria-current="page". A group uses the native details and summary disclosure: the summary is focusable, Enter and Space toggle it, and browsers expose its open state to assistive technology. Put the links inside a <nav> with an aria-label of your own.