{
  "name": "BottomNav",
  "category": "Navigation",
  "subcategory": null,
  "description": "Mobile-first bottom navigation bar with icon items.",
  "thumbnail": "/preview-cards/bottom-nav.png",
  "hasDocsPage": true,
  "nugetPackage": "Lumeo",
  "files": [
    "UI/BottomNav/BottomNav.razor",
    "UI/BottomNav/BottomNavFab.razor",
    "UI/BottomNav/BottomNavItem.razor"
  ],
  "dependencies": [],
  "packageDependencies": [],
  "cssVars": [
    "--color-background",
    "--color-border",
    "--color-card",
    "--color-foreground",
    "--color-muted",
    "--color-muted-foreground",
    "--color-primary",
    "--color-primary-foreground",
    "--color-ring",
    "--radius"
  ],
  "api": {
    "name": "BottomNav",
    "category": "Navigation",
    "subcategory": null,
    "description": "Mobile-first bottom navigation bar with icon items.",
    "nugetPackage": "Lumeo",
    "files": [
      "UI/BottomNav/BottomNav.razor",
      "UI/BottomNav/BottomNavFab.razor",
      "UI/BottomNav/BottomNavItem.razor"
    ],
    "namespace": "Lumeo",
    "inheritsFrom": null,
    "implements": [],
    "parameters": [
      {
        "name": "ChildContent",
        "type": "RenderFragment?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "AriaLabel",
        "type": "string",
        "default": "\"Bottom navigation\"",
        "description": "Accessible label for the nav landmark. Defaults to \"Bottom navigation\".",
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Fixed",
        "type": "bool",
        "default": "true",
        "description": "When true (default), pins to the bottom of the viewport with position: fixed. Set false to render inline.",
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Variant",
        "type": "BottomNavVariant",
        "default": "BottomNavVariant.Default",
        "description": "Visual variant. Default is a solid bar with a top border; Pill is a floating centered pill.",
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "AnimatedIndicator",
        "type": "bool",
        "default": null,
        "description": "When true, each BottomNavItem gets smooth background-color and color transitions, and the small active pill transitions its transform with a spring easing. Default is false.",
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Class",
        "type": "string?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "AdditionalAttributes",
        "type": "Dictionary<string, object>?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": true
      }
    ],
    "events": [],
    "enums": [
      {
        "name": "BottomNavVariant",
        "values": [
          "Default",
          "Pill"
        ],
        "description": null
      }
    ],
    "records": [],
    "cssVars": [
      "--color-background",
      "--color-border",
      "--color-card",
      "--color-foreground",
      "--color-muted",
      "--color-muted-foreground",
      "--color-primary",
      "--color-primary-foreground",
      "--color-ring",
      "--radius"
    ],
    "examples": [
      {
        "title": "Basic",
        "code": "<BottomNav>\n    <BottomNavItem Href=\"/\" Label=\"Home\">\n        <IconContent><Icon Name=\"House\" Size=\"Icon.IconSize.Sm\" /></IconContent>\n    </BottomNavItem>\n    <BottomNavItem Href=\"/search\" Label=\"Search\">\n        <IconContent><Icon Name=\"Search\" Size=\"Icon.IconSize.Sm\" /></IconContent>\n    </BottomNavItem>\n    <BottomNavItem Href=\"/inbox\" Label=\"Inbox\">\n        <IconContent><Icon Name=\"Inbox\" Size=\"Icon.IconSize.Sm\" /></IconContent>\n    </BottomNavItem>\n    <BottomNavItem Href=\"/profile\" Label=\"Profile\">\n        <IconContent><Icon Name=\"User\" Size=\"Icon.IconSize.Sm\" /></IconContent>\n    </BottomNavItem>\n</BottomNav>"
      },
      {
        "title": "With Badges",
        "code": "<BottomNavItem Href=\"/chat\" Label=\"Chat\">\n    <IconContent><Icon Name=\"MessageCircle\" Size=\"Icon.IconSize.Sm\" /></IconContent>\n    <Badge>3</Badge>\n</BottomNavItem>"
      },
      {
        "title": "With Center FAB",
        "code": "<BottomNav>\n    <BottomNavItem Href=\"/\" Label=\"Home\" />\n    <BottomNavItem Href=\"/search\" Label=\"Search\" />\n\n    <BottomNavFab AriaLabel=\"Create\" OnClick=\"HandleCreate\">\n        <Icon Name=\"Plus\" Size=\"Icon.IconSize.Md\" />\n    </BottomNavFab>\n\n    <BottomNavItem Href=\"/inbox\" Label=\"Inbox\" />\n    <BottomNavItem Href=\"/profile\" Label=\"Profile\" />\n</BottomNav>"
      },
      {
        "title": "Animated Transitions",
        "code": "<BottomNav AnimatedIndicator=\"true\">\n    <BottomNavItem Href=\"/\" Label=\"Home\" />\n    <BottomNavItem Href=\"/search\" Label=\"Search\" />\n    <BottomNavItem Href=\"/inbox\" Label=\"Inbox\" />\n    <BottomNavItem Href=\"/profile\" Label=\"Profile\" />\n</BottomNav>"
      }
    ],
    "subComponents": {
      "BottomNavFab": {
        "componentName": "BottomNavFab",
        "fileName": "BottomNavFab.razor",
        "namespace": "Lumeo",
        "inheritsFrom": null,
        "implements": [],
        "parameters": [
          {
            "name": "Href",
            "type": "string?",
            "default": null,
            "description": "Optional destination URL. When set, renders as an anchor; otherwise a button.",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "AriaLabel",
            "type": "string",
            "default": "\"Primary action\"",
            "description": "Accessible label. Required because FABs are usually icon-only.",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "OnClick",
            "type": "EventCallback",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "ChildContent",
            "type": "RenderFragment?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Class",
            "type": "string?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "AdditionalAttributes",
            "type": "Dictionary<string, object>?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": true
          }
        ],
        "events": [
          {
            "name": "OnClick",
            "type": "EventCallback",
            "description": null
          }
        ],
        "enums": [],
        "records": [],
        "parseFailed": false,
        "parseError": null
      },
      "BottomNavItem": {
        "componentName": "BottomNavItem",
        "fileName": "BottomNavItem.razor",
        "namespace": "Lumeo",
        "inheritsFrom": null,
        "implements": [
          "IDisposable"
        ],
        "parameters": [
          {
            "name": "Context",
            "type": "BottomNav.BottomNavContext?",
            "default": null,
            "description": null,
            "isCascading": true,
            "captureUnmatched": false
          },
          {
            "name": "Href",
            "type": "string?",
            "default": null,
            "description": "Destination URL. When set, item renders as an &lt;a&gt;; otherwise as a &lt;button&gt;.",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Label",
            "type": "string?",
            "default": null,
            "description": "Text label shown under the icon. Also used as the accessible name.",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "IconContent",
            "type": "RenderFragment?",
            "default": null,
            "description": "Icon slot (use Icon or Blazicon). The Content suffix avoids colliding with the &lt;Icon&gt; component.",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Badge",
            "type": "RenderFragment?",
            "default": null,
            "description": "Optional badge (count, dot, or any content) shown on the icon. Int, string, or RenderFragment.",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "IconSize",
            "type": "string",
            "default": "\"h-5 w-5\"",
            "description": "Size class applied to the icon container. Defaults to h-5 w-5 to match the original visual. Override to fit larger content like avatars (e.g. \"h-7 w-7\").",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "IsActive",
            "type": "bool?",
            "default": null,
            "description": "Manual active-state override. When null, active is inferred from the current route matching Href.",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "OnClick",
            "type": "EventCallback",
            "default": null,
            "description": "Click handler — fires for both &lt;a&gt; and &lt;button&gt; renderings (link navigation still proceeds).",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "PressEffect",
            "type": "Button.ButtonPressEffect",
            "default": "Button.ButtonPressEffect.None",
            "description": "Visual feedback when the item is pressed. Default is None. Scale is recommended for a tactile feel on mobile.",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Class",
            "type": "string?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "AdditionalAttributes",
            "type": "Dictionary<string, object>?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": true
          }
        ],
        "events": [
          {
            "name": "OnClick",
            "type": "EventCallback",
            "description": "Click handler — fires for both &lt;a&gt; and &lt;button&gt; renderings (link navigation still proceeds)."
          }
        ],
        "enums": [],
        "records": [],
        "parseFailed": false,
        "parseError": null
      }
    },
    "parseFailed": false,
    "parseError": null
  },
  "$schema": "https://lumeo.nativ.sh/registry-component-schema.json",
  "key": "bottom-nav",
  "docsUrl": "https://lumeo.nativ.sh/components/bottom-nav",
  "sourceUrl": [
    {
      "file": "UI/BottomNav/BottomNav.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/BottomNav/BottomNav.razor"
    },
    {
      "file": "UI/BottomNav/BottomNavFab.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/BottomNav/BottomNavFab.razor"
    },
    {
      "file": "UI/BottomNav/BottomNavItem.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/BottomNav/BottomNavItem.razor"
    }
  ],
  "source": [
    {
      "path": "UI/BottomNav/BottomNav.razor",
      "content": "@namespace Lumeo\n\n<nav class=\"@CssClass\"\n     role=\"navigation\"\n     aria-label=\"@AriaLabel\"\n     @attributes=\"AdditionalAttributes\"\n     style=\"padding-bottom: env(safe-area-inset-bottom, 0px);\">\n    <CascadingValue Value=\"_context\" IsFixed=\"false\">\n        <div class=\"@InnerCssClass\">\n            @ChildContent\n        </div>\n    </CascadingValue>\n</nav>\n\n@code {\n    [Parameter] public RenderFragment? ChildContent { get; set; }\n\n    /// <summary>Accessible label for the nav landmark. Defaults to \"Bottom navigation\".</summary>\n    [Parameter] public string AriaLabel { get; set; } = \"Bottom navigation\";\n\n    /// <summary>When true (default), pins to the bottom of the viewport with <c>position: fixed</c>. Set false to render inline.</summary>\n    [Parameter] public bool Fixed { get; set; } = true;\n\n    /// <summary>Visual variant. <c>Default</c> is a solid bar with a top border; <c>Pill</c> is a floating centered pill.</summary>\n    [Parameter] public BottomNavVariant Variant { get; set; } = BottomNavVariant.Default;\n\n    /// <summary>\n    /// When true, each <see cref=\"BottomNavItem\"/> gets smooth background-color\n    /// and color transitions, and the small active pill transitions its transform\n    /// with a spring easing. Default is <c>false</c>.\n    /// </summary>\n    [Parameter] public bool AnimatedIndicator { get; set; }\n\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private BottomNavContext? _context;\n\n    protected override void OnParametersSet()\n    {\n        if (_context is null || _context.AnimatedIndicator != AnimatedIndicator)\n        {\n            _context = new BottomNavContext(AnimatedIndicator);\n        }\n    }\n\n    private string CssClass => string.Join(\" \", new[] {\n        Fixed ? \"fixed bottom-0 left-0 right-0 z-40\" : \"w-full\",\n        Variant == BottomNavVariant.Pill\n            ? \"px-4 pb-3\"\n            : \"bg-background border-t border-border/40\",\n        Class\n    }.Where(s => !string.IsNullOrWhiteSpace(s)));\n\n    private string InnerCssClass => Variant == BottomNavVariant.Pill\n        ? \"mx-auto flex max-w-md items-center justify-around gap-1 rounded-full border border-border bg-card/95 shadow-lg backdrop-blur px-2 py-1.5\"\n        : \"flex items-stretch justify-around gap-1 px-2 pt-1.5 pb-1.5\";\n\n    public enum BottomNavVariant { Default, Pill }\n\n    public class BottomNavContext\n    {\n        public BottomNavContext(bool animatedIndicator = false)\n        {\n            AnimatedIndicator = animatedIndicator;\n        }\n\n        /// <summary>True when parent <see cref=\"BottomNav\"/> was configured with <c>AnimatedIndicator=\"true\"</c>.</summary>\n        public bool AnimatedIndicator { get; }\n    }\n}\n"
    },
    {
      "path": "UI/BottomNav/BottomNavFab.razor",
      "content": "@namespace Lumeo\n\n@if (string.IsNullOrEmpty(Href))\n{\n    <button type=\"button\" class=\"@CssClass\" aria-label=\"@AriaLabel\" @onclick=\"OnClick\" @attributes=\"AdditionalAttributes\">\n        @ChildContent\n    </button>\n}\nelse\n{\n    <a href=\"@Href\" class=\"@CssClass\" aria-label=\"@AriaLabel\" @attributes=\"AdditionalAttributes\">\n        @ChildContent\n    </a>\n}\n\n@code {\n    /// <summary>Optional destination URL. When set, renders as an anchor; otherwise a button.</summary>\n    [Parameter] public string? Href { get; set; }\n\n    /// <summary>Accessible label. Required because FABs are usually icon-only.</summary>\n    [Parameter, EditorRequired] public string AriaLabel { get; set; } = \"Primary action\";\n\n    [Parameter] public EventCallback OnClick { get; set; }\n    [Parameter] public RenderFragment? ChildContent { get; set; }\n\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    // Raised above the bar so it visually \"sits on top\" of the nav.\n    private string CssClass => string.Join(\" \", new[] {\n        \"flex h-12 w-12 -translate-y-3 cursor-pointer items-center justify-center rounded-full bg-primary text-primary-foreground shadow-lg\",\n        \"transition-transform hover:scale-105 active:scale-95 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ring-offset-2 ring-offset-background\",\n        Class\n    }.Where(s => !string.IsNullOrWhiteSpace(s)));\n}\n"
    },
    {
      "path": "UI/BottomNav/BottomNavItem.razor",
      "content": "@namespace Lumeo\n@implements IDisposable\n@inject NavigationManager Nav\n@inject Lumeo.Services.IComponentInteropService Interop\n\n@if (string.IsNullOrEmpty(Href))\n{\n    <button @ref=\"_el\" type=\"button\" class=\"@CssClass\"\n            aria-current=\"@(_active ? \"page\" : null)\"\n            aria-label=\"@Label\"\n            @onclick=\"HandleClick\"\n            @attributes=\"AdditionalAttributes\">\n        @RenderBody\n    </button>\n}\nelse\n{\n    <a @ref=\"_el\" href=\"@Href\" class=\"@CssClass\"\n       aria-current=\"@(_active ? \"page\" : null)\"\n       aria-label=\"@Label\"\n       @attributes=\"AdditionalAttributes\">\n        @RenderBody\n    </a>\n}\n\n@code {\n    [CascadingParameter] public BottomNav.BottomNavContext? Context { get; set; }\n\n    /// <summary>Destination URL. When set, item renders as an <c>&lt;a&gt;</c>; otherwise as a <c>&lt;button&gt;</c>.</summary>\n    [Parameter] public string? Href { get; set; }\n\n    /// <summary>Text label shown under the icon. Also used as the accessible name.</summary>\n    [Parameter] public string? Label { get; set; }\n\n    /// <summary>Icon slot (use <see cref=\"Lumeo.Icon\"/> or Blazicon). The <c>Content</c> suffix avoids colliding with the <c>&lt;Icon&gt;</c> component.</summary>\n    [Parameter] public RenderFragment? IconContent { get; set; }\n\n    /// <summary>Optional badge (count, dot, or any content) shown on the icon. Int, string, or RenderFragment.</summary>\n    [Parameter] public RenderFragment? Badge { get; set; }\n\n    /// <summary>\n    /// Size class applied to the icon container. Defaults to <c>h-5 w-5</c> to\n    /// match the original visual. Override to fit larger content like avatars\n    /// (e.g. <c>\"h-7 w-7\"</c>).\n    /// </summary>\n    [Parameter] public string IconSize { get; set; } = \"h-5 w-5\";\n\n    /// <summary>Manual active-state override. When null, active is inferred from the current route matching <see cref=\"Href\"/>.</summary>\n    [Parameter] public bool? IsActive { get; set; }\n\n    /// <summary>Click handler — fires for both <c>&lt;a&gt;</c> and <c>&lt;button&gt;</c> renderings (link navigation still proceeds).</summary>\n    [Parameter] public EventCallback OnClick { get; set; }\n\n    /// <summary>\n    /// Visual feedback when the item is pressed. Default is\n    /// <see cref=\"Button.ButtonPressEffect.None\"/>. <c>Scale</c> is recommended\n    /// for a tactile feel on mobile.\n    /// </summary>\n    [Parameter] public Button.ButtonPressEffect PressEffect { get; set; } = Button.ButtonPressEffect.None;\n\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private bool _active;\n    private Microsoft.AspNetCore.Components.ElementReference _el;\n\n    protected override void OnInitialized()\n    {\n        Nav.LocationChanged += HandleLocationChanged;\n        RecomputeActive();\n    }\n\n    protected override void OnParametersSet() => RecomputeActive();\n\n    public void Dispose() => Nav.LocationChanged -= HandleLocationChanged;\n\n    private void HandleLocationChanged(object? sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e)\n    {\n        RecomputeActive();\n        StateHasChanged();\n    }\n\n    private void RecomputeActive()\n    {\n        if (IsActive is not null) { _active = IsActive.Value; return; }\n        if (string.IsNullOrEmpty(Href)) { _active = false; return; }\n        var current = \"/\" + Nav.ToBaseRelativePath(Nav.Uri).TrimEnd('/');\n        var target = Href.StartsWith('/') ? Href.TrimEnd('/') : \"/\" + Href.TrimEnd('/');\n        _active = string.Equals(current, target, StringComparison.OrdinalIgnoreCase)\n                  || (target != \"/\" && current.StartsWith(target + \"/\", StringComparison.OrdinalIgnoreCase));\n    }\n\n    private async Task HandleClick()\n    {\n        if (OnClick.HasDelegate) await OnClick.InvokeAsync();\n    }\n\n    private bool IsActiveResolved => _active;\n\n    private bool IsAnimated => Context?.AnimatedIndicator == true;\n\n    private string? PressEffectClass => PressEffect switch\n    {\n        Button.ButtonPressEffect.Scale => \"lumeo-press-scale\",\n        Button.ButtonPressEffect.Brightness => \"lumeo-press-brightness\",\n        Button.ButtonPressEffect.Ripple => \"lumeo-press-ripple\",\n        _ => null\n    };\n\n    private string CssClass => string.Join(\" \", new[] {\n        \"group relative flex min-w-0 flex-1 basis-0 flex-col items-center justify-center gap-0.5 rounded-md px-2 py-1.5 text-xs cursor-pointer\",\n        \"transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n        IsActiveResolved ? \"text-foreground\" : \"text-muted-foreground hover:text-foreground\",\n        IsAnimated ? \"lumeo-bottom-nav-animated\" : null,\n        PressEffectClass,\n        Class\n    }.Where(s => !string.IsNullOrWhiteSpace(s)));\n\n    protected override async Task OnAfterRenderAsync(bool firstRender)\n    {\n        if (firstRender && PressEffect == Button.ButtonPressEffect.Ripple)\n        {\n            try\n            {\n                await Interop.RippleAttachAsync(_el);\n            }\n            catch (Microsoft.JSInterop.JSDisconnectedException) { }\n        }\n    }\n\n    private RenderFragment RenderBody => __builder =>\n    {\n        <span class=\"@($\"relative flex {IconSize} items-center justify-center\")\">\n            @if (IconContent is not null)\n            {\n                @IconContent\n            }\n            @if (Badge is not null)\n            {\n                <span class=\"absolute -right-2 -top-1 inline-flex min-w-4 items-center justify-center rounded-full bg-primary px-1 text-[10px] font-medium text-primary-foreground leading-none h-4\">\n                    @Badge\n                </span>\n            }\n        </span>\n        @if (!string.IsNullOrEmpty(Label))\n        {\n            <span class=\"truncate font-medium\">@Label</span>\n        }\n        @if (IsActiveResolved)\n        {\n            <span aria-hidden=\"true\" class=\"absolute left-1/2 top-0 h-0.5 w-8 -translate-x-1/2 rounded-full bg-primary\"></span>\n        }\n    };\n}\n"
    }
  ],
  "slots": [
    {
      "name": "ChildContent",
      "owner": "BottomNav",
      "type": "RenderFragment?",
      "description": null
    },
    {
      "name": "ChildContent",
      "owner": "BottomNavFab",
      "type": "RenderFragment?",
      "description": null
    },
    {
      "name": "IconContent",
      "owner": "BottomNavItem",
      "type": "RenderFragment?",
      "description": "Icon slot (use Icon or Blazicon). The Content suffix avoids colliding with the &lt;Icon&gt; component."
    },
    {
      "name": "Badge",
      "owner": "BottomNavItem",
      "type": "RenderFragment?",
      "description": "Optional badge (count, dot, or any content) shown on the icon. Int, string, or RenderFragment."
    }
  ],
  "serviceDependencies": [
    {
      "service": "NavigationManager",
      "namespace": ""
    },
    {
      "service": "IComponentInteropService",
      "namespace": "Lumeo.Services"
    }
  ],
  "cascadingDependencies": [
    {
      "name": "Context",
      "type": "BottomNav.BottomNavContext?",
      "required": false
    }
  ],
  "relatedComponents": [
    {
      "name": "BottomNavFab",
      "reason": "sub-component"
    },
    {
      "name": "BottomNavItem",
      "reason": "sub-component"
    }
  ],
  "keyboardInteractions": [],
  "tests": [
    "tests/Lumeo.Tests/Components/BottomNav/BottomNavAnimatedTests.cs",
    "tests/Lumeo.Tests/Components/BottomNav/BottomNavFabTests.cs",
    "tests/Lumeo.Tests/Components/BottomNav/BottomNavItemCursorTests.cs",
    "tests/Lumeo.Tests/Components/BottomNav/BottomNavItemTests.cs",
    "tests/Lumeo.Tests/Components/BottomNav/BottomNavTests.cs"
  ],
  "mdSummary": "# BottomNav\n\nMobile-first bottom navigation bar with icon items.\n\n**Package:** `Lumeo` · **Category:** Navigation\n**Docs:** https://lumeo.nativ.sh/components/bottom-nav\n\n## Parameters\n| Owner | Name | Type | Default | Description |\n|---|---|---|---|---|\n| BottomNav | ChildContent | `RenderFragment?` | `` |  |\n| BottomNav | AriaLabel | `string` | `\"Bottom navigation\"` | Accessible label for the nav landmark. Defaults to \"Bottom navigation\". |\n| BottomNav | Fixed | `bool` | `true` | When true (default), pins to the bottom of the viewport with position: fixed. Set false to render inline. |\n| BottomNav | Variant | `BottomNavVariant` | `BottomNavVariant.Default` | Visual variant. Default is a solid bar with a top border; Pill is a floating centered pill. |\n| BottomNav | AnimatedIndicator | `bool` | `` | When true, each BottomNavItem gets smooth background-color and color transitions, and the small active pill transitions its transform with a spring easing. Default is false. |\n| BottomNav | Class | `string?` | `` |  |\n| BottomNav | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n| BottomNavFab | Href | `string?` | `` | Optional destination URL. When set, renders as an anchor; otherwise a button. |\n| BottomNavFab | AriaLabel | `string` | `\"Primary action\"` | Accessible label. Required because FABs are usually icon-only. |\n| BottomNavFab | OnClick | `EventCallback` | `` |  |\n| BottomNavFab | ChildContent | `RenderFragment?` | `` |  |\n| BottomNavFab | Class | `string?` | `` |  |\n| BottomNavFab | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n| BottomNavItem | Context | `BottomNav.BottomNavContext?` | `` |  |\n| BottomNavItem | Href | `string?` | `` | Destination URL. When set, item renders as an &lt;a&gt;; otherwise as a &lt;button&gt;. |\n| BottomNavItem | Label | `string?` | `` | Text label shown under the icon. Also used as the accessible name. |\n| BottomNavItem | IconContent | `RenderFragment?` | `` | Icon slot (use Icon or Blazicon). The Content suffix avoids colliding with the &lt;Icon&gt; component. |\n| BottomNavItem | Badge | `RenderFragment?` | `` | Optional badge (count, dot, or any content) shown on the icon. Int, string, or RenderFragment. |\n| BottomNavItem | IconSize | `string` | `\"h-5 w-5\"` | Size class applied to the icon container. Defaults to h-5 w-5 to match the original visual. Override to fit larger content like avatars (e.g. \"h-7 w-7\"). |\n| BottomNavItem | IsActive | `bool?` | `` | Manual active-state override. When null, active is inferred from the current route matching Href. |\n| BottomNavItem | OnClick | `EventCallback` | `` | Click handler — fires for both &lt;a&gt; and &lt;button&gt; renderings (link navigation still proceeds). |\n| BottomNavItem | PressEffect | `Button.ButtonPressEffect` | `Button.ButtonPressEffect.None` | Visual feedback when the item is pressed. Default is None. Scale is recommended for a tactile feel on mobile. |\n| BottomNavItem | Class | `string?` | `` |  |\n| BottomNavItem | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n\n## Slots\n- `ChildContent` (BottomNav) — RenderFragment slot\n- `ChildContent` (BottomNavFab) — RenderFragment slot\n- `IconContent` (BottomNavItem) — Icon slot (use Icon or Blazicon). The Content suffix avoids colliding with the &lt;Icon&gt; component.\n- `Badge` (BottomNavItem) — Optional badge (count, dot, or any content) shown on the icon. Int, string, or RenderFragment.\n\n## Events\n- (none)\n\n## Sub-components\n- `BottomNavFab`, `BottomNavItem`\n\n## Cascading values it expects\n- `Context` (`BottomNav.BottomNavContext?`)\n\n## Services it injects\n- `NavigationManager` ()\n- `IComponentInteropService` (Lumeo.Services)\n\n## Keyboard\n—\n\n## Example\n```razor\n<BottomNav />\n```\n\n## CSS variables\n`--color-background`, `--color-border`, `--color-card`, `--color-foreground`, `--color-muted`, `--color-muted-foreground`, `--color-primary`, `--color-primary-foreground`, `--color-ring`, `--radius`\n\n## Files\n- `UI/BottomNav/BottomNav.razor`\n- `UI/BottomNav/BottomNavFab.razor`\n- `UI/BottomNav/BottomNavItem.razor`\n"
}