Zoeken...  ⌘K GitHub

IconNav icon

Horizontale of verticale navigatiebalk met icoon per item, actieve state en optionele badge. Secundaire nav of in-page tabbar.

/icon-nav
src/components/icon/IconNav.astro
---
/**
 * IconNav
 * Horizontale of verticale navigatiebalk met icoon per item en optionele badge.
 * Geschikt als secundaire nav, in-page tabbar of sidebar-menu.
 *
 * Props:
 * - items: { icon?: string; label: string; href: string; active?: boolean; badge?: string }[]
 * - orientation?: 'horizontal' | 'vertical'   default 'horizontal'
 * - ariaLabel?: string   default 'Navigatie'
 * - accentColor?: string   default '#6366f1'
 * - theme?: 'light' | 'dark'   default 'light'
 */
interface Props {
  items: { icon?: string; label: string; href: string; active?: boolean; badge?: string }[];
  orientation?: 'horizontal' | 'vertical';
  ariaLabel?: string;
  accentColor?: string;
  theme?: 'light' | 'dark';
}

const {
  items,
  orientation = 'horizontal',
  ariaLabel = 'Navigatie',
  accentColor = '#6366f1',
  theme = 'light',
} = Astro.props;
---

<section class:list={['bl-section', 'inav-section', `inav-section--${theme}`]}>
  <div class="bl-inner inav-inner" style={`--color-accent: ${accentColor}`}>
    <nav
      class:list={['inav', orientation === 'vertical' && 'inav--vertical']}
      aria-label={ariaLabel}
    >
      {items.map(item => (
        <a
          class:list={['inav__item', item.active && 'inav__item--active']}
          href={item.href}
          aria-current={item.active ? 'page' : undefined}
        >
          {item.icon && <span class="inav__icon" aria-hidden="true">{item.icon}</span>}
          <span class="inav__label">{item.label}</span>
          {item.badge && <span class="inav__badge">{item.badge}</span>}
        </a>
      ))}
    </nav>
  </div>
</section>

<style>
  .inav-section--light { background: var(--color-bg, #fff); }
  .inav-section--dark { background: #0a0a0a; }

  .inav {
    display: flex;
    gap: .25rem;
    flex-wrap: wrap;
  }
  .inav--vertical { flex-direction: column; }

  .inav__item {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .6rem 1rem;
    border-radius: 8px;
    text-decoration: none;
    color: #6b7280;
    font-size: .9375rem;
    font-weight: 500;
    transition: background .15s, color .15s;
    position: relative;
  }
  .inav__item:hover {
    background: #f5f5f5;
    color: var(--color-primary, #0a0a0a);
  }
  .inav-section--dark .inav__item { color: #aaa; }
  .inav-section--dark .inav__item:hover {
    background: #1a1a1a;
    color: #e8e8e8;
  }

  .inav__item--active {
    background: color-mix(in srgb, var(--color-accent) 10%, transparent);
    color: var(--color-accent);
    font-weight: 700;
  }

  .inav__icon { font-size: 1.1rem; }

  .inav__badge {
    position: absolute;
    top: .25rem;
    right: .25rem;
    background: var(--color-accent);
    color: #fff;
    font-size: .625rem;
    font-weight: 700;
    padding: .1rem .35rem;
    border-radius: 10px;
    text-transform: uppercase;
    letter-spacing: .04em;
  }
</style>

Props

Prop Type Default Beschrijving
items * { icon?: string; label: string; href: string; active?: boolean; badge?: string }[] - Navigatie-items
orientation 'horizontal' | 'vertical' 'horizontal' Richting van de navigatie
ariaLabel string 'Navigatie' Aria-label voor de nav
accentColor string '#6366f1' Kleur voor actieve items
theme 'light' | 'dark' 'light' Achtergrondmodus

* = verplicht