Application navigation

A labelled application destination tree with explicit body anatomy, current state, icons, badges, sections, and flexible spacing.

Source
app/components/nitro_kit/app_navigation.rb
API
NitroKit::AppNavigation.new(label:, id:) { |navigation| navigation.body { ... } }

Anatomy

The required body keeps destinations explicit while optional chrome and ordered entries remain bounded.

Complete navigation

Header, labelled sections, icons, badges, current state, divider, spacer, and footer appear in one tree.

ViewportFull width
Rubytest/dummy/app/components/gallery/components/app_navigation_page.rb
render NitroKit::AppNavigation.new(
  id: "gallery-app-navigation-complete",
  label: "Workspace",
  data: { gallery_navigation_preview: "complete" }
) do |navigation|
  navigation.footer do
    render NitroKit::Button.new("Sign out", href: "#sign-out", variant: :ghost, size: :sm, icon: :log_out)
  end
  navigation.body do
    navigation.section(label: "Workspace") do
      navigation.item("Overview", href: "#overview", icon: :house, current: true)
      navigation.item("Projects", href: "#projects", icon: :folder, badge: 12)
      navigation.item("People", href: "#people", icon: :users)
    end
    navigation.divider
    navigation.section(label: "Manage") do
      navigation.item("Automations", href: "#automations", icon: :zap, badge: "New")
      navigation.item("Settings", href: "#settings", icon: :settings)
    end
    navigation.spacer
    navigation.item("Help and support", href: "#help", icon: :circle_help)
  end
  navigation.header do
    render NitroKit::Badge.new("Production", variant: :outline, size: :sm)
  end
end

Minimal and grouped

The smallest valid body and a sectioned body share the same public grammar.

One destination
Two labelled groups
ViewportFull width
Rubytest/dummy/app/components/gallery/components/app_navigation_page.rb
sample("One destination", slug: "app-navigation-minimal") do
  render_navigation(
    id: "gallery-app-navigation-minimal",
    label: "Minimal",
    destinations: [ [ "Home", "#minimal-home", :house ] ]
  )
end

sample("Two labelled groups", slug: "app-navigation-groups") do
  render NitroKit::AppNavigation.new(
    id: "gallery-app-navigation-groups",
    label: "Grouped destinations",
    data: { gallery_navigation_preview: "groups" }
  ) do |navigation|
    navigation.body do
      navigation.section(label: "Plan") do
        navigation.item("Roadmap", href: "#roadmap", icon: :map)
        navigation.item("Milestones", href: "#milestones", icon: :flag, current: true)
      end
      navigation.section(label: "Observe") do
        navigation.item("Activity", href: "#activity", icon: :activity)
        navigation.item("Reports", href: "#reports", icon: :chart_no_axes_column)
      end
    end
  end
end

Pressure and composition

Long labels, many destinations, state metadata, and ordinary Nitro children stay legible without opening the API.

Long labels and dense badges

Item labels truncate within the navigation boundary while numeric and text badges remain aligned.

ViewportFull width
Rubytest/dummy/app/components/gallery/components/app_navigation_page.rb
render NitroKit::AppNavigation.new(
  id: "gallery-app-navigation-pressure",
  label: "International research workspace",
  data: { gallery_navigation_preview: "pressure" }
) do |navigation|
  navigation.body do
    navigation.section(label: "International Research and Production") do
      navigation.item(
        "Analytical engine reliability and production readiness",
        href: "#reliability",
        icon: :gauge,
        badge: 128,
        current: true
      )
      navigation.item(
        "Cross-regional incident response and operational handoffs",
        href: "#incidents",
        icon: :siren,
        badge: "Urgent"
      )
      navigation.item(
        "Quarterly capacity forecasts and allocation planning",
        href: "#capacity",
        icon: :calendar_range
      )
    end
    navigation.spacer
    navigation.item("Workspace settings", href: "#workspace-settings", icon: :settings)
  end
  navigation.footer do
    render NitroKit::ButtonGroup.new(label: "Workspace help") do |group|
      group.button("Docs", href: "#docs", size: :sm)
      group.button("Support", href: "#support", size: :sm)
    end
  end
end

Destination inventory

A longer real-world inventory proves body scrolling, the single spacer, and one current destination.

ViewportFull width
Rubytest/dummy/app/components/gallery/components/app_navigation_page.rb
render_inventory_navigation