Navigation and satellites

svelte
<script lang="ts">
  import {
    Navigation,
    ContentPage,
    SidebarNavigation,
    Section,
  } from '@page-sections/svelte';
  import { resolveNavigation, type MenuItem } from '@page-sections/core';
  const tree: MenuItem[] = [
    {
      id: 'guides',
      label: 'Guides',
      href: '/guides/',
      children: [
        {
          id: 'garden',
          label: 'Garden',
          href: '/guides/garden/',
          children: [
            { id: 'planting', label: 'Planting', href: '/guides/garden/planting/' },
          ],
        },
      ],
    },
  ];
  const navigation = resolveNavigation(tree, { currentId: 'planting' });
</script>

<Navigation items={navigation.items}>
  {#snippet brand()}<a href="/">Garden journal</a>{/snippet}
</Navigation>
<ContentPage
  page={{ title: 'Planting', breadcrumbs: navigation.breadcrumbs }}
  showContentMenu
>
  {#snippet leftSidebar()}<SidebarNavigation items={navigation.sidebarItems} />{/snippet}
  <Section section={{ id: 'soil', title: 'Soil' }}
    ><p>Start with healthy soil.</p></Section
  >
</ContentPage>

ButtonGroup

PropTypeDefault
itemsButtonGroupItem[]Required
labelstringRequired accessible group label
onselect(item: ButtonGroupItem) => voidOptional callback for button activation
ButtonGroupItem fieldTypeBehavior
idstring, requiredUnique group key
labelstring, requiredVisible text
hrefstringA non-disabled item with href becomes a native link
selectedbooleanButton aria-pressed or link aria-current=true; not updated internally
disabledbooleanRenders a disabled button, even if href exists

Button activation calls onselect; links navigate normally and do not call it. There is no radio-group selection algorithm or automatic state mutation. Buttons use type=button and normal keyboard focus; the wrapper has role=group and its label. Rendered buttons require JavaScript for their callbacks; links remain functional in SSR HTML.

ButtonGroup does not import full shared theme styles on its own. Navigation does, or import the stylesheet explicitly when using them elsewhere.

Site navigation, breadcrumbs and section navigation answer different questions: where can I go, where am I in the site, and what is on this page? Give each landmark a suitable label.

Navigation links use neutral --ps-ink; content links retain --ps-accent. Header and satellites share --ps-navigation-shadow. Set this token on a navigation ancestor to customize or disable elevation. If host button groups paint their own outline and radius, leave the satellite wrapper unpainted and apply the token to the actual group to avoid duplicate edges.

The current page and its ancestors retain a muted background in both menus. Only the current page is bold. The main menu marks the top-level ancestor with an accent line; the sidebar marks the actual page. Top-level menu backgrounds fill the menu height with square corners. Sidebar branches reopen along the current page path after navigation. Desktop submenus connect directly to their parent link and are centered beneath it. Selected ButtonGroup items use a muted background and accent text; icons that inherit the text color follow the same selection treatment.