A labelled application destination tree with explicit body anatomy, current state, icons, badges, sections, and flexible spacing.
app/components/nitro_kit/app_navigation.rbNitroKit::AppNavigation.new(label:, id:) { |navigation| navigation.body { ... } }The required body keeps destinations explicit while optional chrome and ordered entries remain bounded.
Header, labelled sections, icons, badges, current state, divider, spacer, and footer appear in one tree.
test/dummy/app/components/gallery/components/app_navigation_page.rbrender 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
endThe smallest valid body and a sectioned body share the same public grammar.
test/dummy/app/components/gallery/components/app_navigation_page.rbsample("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
endLong labels, many destinations, state metadata, and ordinary Nitro children stay legible without opening the API.
Item labels truncate within the navigation boundary while numeric and text badges remain aligned.
test/dummy/app/components/gallery/components/app_navigation_page.rbrender 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
endA longer real-world inventory proves body scrolling, the single spacer, and one current destination.
test/dummy/app/components/gallery/components/app_navigation_page.rbrender_inventory_navigation