{
  "name": "Accordion",
  "category": "Navigation",
  "subcategory": null,
  "description": "Vertically stacked collapsible sections that expand to reveal content.",
  "thumbnail": "/preview-cards/accordion.png",
  "hasDocsPage": true,
  "nugetPackage": "Lumeo",
  "files": [
    "UI/Accordion/Accordion.razor",
    "UI/Accordion/AccordionContent.razor",
    "UI/Accordion/AccordionItem.razor",
    "UI/Accordion/AccordionTrigger.razor"
  ],
  "dependencies": [],
  "packageDependencies": [
    "Blazicons.Lucide"
  ],
  "cssVars": [
    "--color-border",
    "--color-muted",
    "--color-muted-foreground",
    "--color-ring",
    "--radius"
  ],
  "api": {
    "name": "Accordion",
    "category": "Navigation",
    "subcategory": null,
    "description": "Vertically stacked collapsible sections that expand to reveal content.",
    "nugetPackage": "Lumeo",
    "files": [
      "UI/Accordion/Accordion.razor",
      "UI/Accordion/AccordionContent.razor",
      "UI/Accordion/AccordionItem.razor",
      "UI/Accordion/AccordionTrigger.razor"
    ],
    "namespace": "Lumeo",
    "inheritsFrom": null,
    "implements": [],
    "parameters": [
      {
        "name": "ChildContent",
        "type": "RenderFragment?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Type",
        "type": "AccordionType",
        "default": "AccordionType.Single",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "DefaultValues",
        "type": "List<string>?",
        "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": [],
    "enums": [
      {
        "name": "AccordionType",
        "values": [
          "Single",
          "Multiple"
        ],
        "description": null
      }
    ],
    "records": [
      {
        "name": "AccordionContext",
        "signature": "AccordionContext(AccordionType Type, HashSet<string> OpenItems, EventCallback<string> Toggle)",
        "description": null
      }
    ],
    "cssVars": [
      "--color-border",
      "--color-muted",
      "--color-muted-foreground",
      "--color-ring",
      "--radius"
    ],
    "examples": [
      {
        "title": "Single (Default)",
        "code": "<Accordion Type=\"Accordion.AccordionType.Single\">\n    <AccordionItem Value=\"item-1\">\n        <AccordionTrigger>Is it accessible?</AccordionTrigger>\n        <AccordionContent>Yes. It adheres to the WAI-ARIA design pattern.</AccordionContent>\n    </AccordionItem>\n    <AccordionItem Value=\"item-2\">\n        <AccordionTrigger>Is it styled?</AccordionTrigger>\n        <AccordionContent>Yes. It comes with default styles that match the other components' aesthetic.</AccordionContent>\n    </AccordionItem>\n    <AccordionItem Value=\"item-3\">\n        <AccordionTrigger>Is it animated?</AccordionTrigger>\n        <AccordionContent>Yes. It's animated by default, but you can disable it if you prefer.</AccordionContent>\n    </AccordionItem>\n</Accordion>"
      },
      {
        "title": "FAQ",
        "code": "<Accordion Type=\"Accordion.AccordionType.Single\">\n    <AccordionItem Value=\"q1\">\n        <AccordionTrigger>What payment methods do you accept?</AccordionTrigger>\n        <AccordionContent>We accept all major credit cards, PayPal, and bank transfers.</AccordionContent>\n    </AccordionItem>\n    <AccordionItem Value=\"q2\">\n        <AccordionTrigger>Can I cancel my subscription at any time?</AccordionTrigger>\n        <AccordionContent>Yes, cancel anytime. Access continues until end of billing period.</AccordionContent>\n    </AccordionItem>\n    <AccordionItem Value=\"q3\">\n        <AccordionTrigger>Do you offer a free trial?</AccordionTrigger>\n        <AccordionContent>14-day free trial, no credit card required.</AccordionContent>\n    </AccordionItem>\n</Accordion>"
      },
      {
        "title": "Multiple",
        "code": "<Accordion Type=\"Accordion.AccordionType.Multiple\">\n    <AccordionItem Value=\"item-1\">\n        <AccordionTrigger>What is Lumeo?</AccordionTrigger>\n        <AccordionContent>Lumeo is a Blazor component library inspired by shadcn/ui, built with Tailwind CSS.</AccordionContent>\n    </AccordionItem>\n    <AccordionItem Value=\"item-2\">\n        <AccordionTrigger>Which .NET version?</AccordionTrigger>\n        <AccordionContent>Lumeo targets .NET 10 and uses Tailwind CSS v4 for styling.</AccordionContent>\n    </AccordionItem>\n    <AccordionItem Value=\"item-3\">\n        <AccordionTrigger>Can I customize it?</AccordionTrigger>\n        <AccordionContent>Absolutely. All components accept a Class parameter for additional CSS classes.</AccordionContent>\n    </AccordionItem>\n</Accordion>"
      },
      {
        "title": "Type — interactive",
        "code": "<Segmented @bind-Value=\"_accordionTypeSel\" Options=\"_accordionTypeOptions\" />\n<Accordion Type=\"@_activeAccordionType\">\n    <AccordionItem Value=\"a\">\n        <AccordionTrigger>Is it accessible?</AccordionTrigger>\n        <AccordionContent>Yes. It adheres to the WAI-ARIA design pattern.</AccordionContent>\n    </AccordionItem>\n    <AccordionItem Value=\"b\">\n        <AccordionTrigger>Is it styled?</AccordionTrigger>\n        <AccordionContent>Yes. It comes with default styles.</AccordionContent>\n    </AccordionItem>\n    <AccordionItem Value=\"c\">\n        <AccordionTrigger>Is it animated?</AccordionTrigger>\n        <AccordionContent>Yes. Animated by default.</AccordionContent>\n    </AccordionItem>\n</Accordion>\n\n@code {\n    private string _accordionTypeSel = \"Single\";\n    private Accordion.AccordionType _activeAccordionType => Enum.Parse<Accordion.AccordionType>(_accordionTypeSel);\n    private List<Segmented.SegmentedOption> _accordionTypeOptions = new()\n    {\n        new() { Label = \"Single\", Value = \"Single\" },\n        new() { Label = \"Multiple\", Value = \"Multiple\" },\n    };\n}"
      }
    ],
    "subComponents": {
      "AccordionContent": {
        "componentName": "AccordionContent",
        "fileName": "AccordionContent.razor",
        "namespace": "Lumeo",
        "inheritsFrom": null,
        "implements": [],
        "parameters": [
          {
            "name": "Context",
            "type": "Accordion.AccordionContext",
            "default": "default!",
            "description": null,
            "isCascading": true,
            "captureUnmatched": false
          },
          {
            "name": "ItemContext",
            "type": "AccordionItem.AccordionItemContext",
            "default": "default!",
            "description": null,
            "isCascading": true,
            "captureUnmatched": false
          },
          {
            "name": "ChildContent",
            "type": "RenderFragment?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "ForceMount",
            "type": "bool",
            "default": null,
            "description": "When true, this panel is always rendered into the DOM (with the hidden attribute when closed) instead of being unmounted. Use when child state (form inputs, scroll position, expensive component init) must survive closing the accordion item. Default false preserves the original unmount behaviour.",
            "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": [],
        "records": [],
        "parseFailed": false,
        "parseError": null
      },
      "AccordionItem": {
        "componentName": "AccordionItem",
        "fileName": "AccordionItem.razor",
        "namespace": "Lumeo",
        "inheritsFrom": null,
        "implements": [],
        "parameters": [
          {
            "name": "ChildContent",
            "type": "RenderFragment?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Value",
            "type": "string",
            "default": "\"\"",
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Disabled",
            "type": "bool",
            "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": [],
        "enums": [],
        "records": [
          {
            "name": "AccordionItemContext",
            "signature": "AccordionItemContext(string Value, bool Disabled)",
            "description": null
          }
        ],
        "parseFailed": false,
        "parseError": null
      },
      "AccordionTrigger": {
        "componentName": "AccordionTrigger",
        "fileName": "AccordionTrigger.razor",
        "namespace": "Lumeo",
        "inheritsFrom": null,
        "implements": [],
        "parameters": [
          {
            "name": "Context",
            "type": "Accordion.AccordionContext",
            "default": "default!",
            "description": null,
            "isCascading": true,
            "captureUnmatched": false
          },
          {
            "name": "ItemContext",
            "type": "AccordionItem.AccordionItemContext",
            "default": "default!",
            "description": null,
            "isCascading": true,
            "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": [],
        "enums": [],
        "records": [],
        "parseFailed": false,
        "parseError": null
      }
    },
    "parseFailed": false,
    "parseError": null
  },
  "$schema": "https://lumeo.nativ.sh/registry-component-schema.json",
  "key": "accordion",
  "docsUrl": "https://lumeo.nativ.sh/components/accordion",
  "sourceUrl": [
    {
      "file": "UI/Accordion/Accordion.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/Accordion/Accordion.razor"
    },
    {
      "file": "UI/Accordion/AccordionContent.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/Accordion/AccordionContent.razor"
    },
    {
      "file": "UI/Accordion/AccordionItem.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/Accordion/AccordionItem.razor"
    },
    {
      "file": "UI/Accordion/AccordionTrigger.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/Accordion/AccordionTrigger.razor"
    }
  ],
  "source": [
    {
      "path": "UI/Accordion/Accordion.razor",
      "content": "@namespace Lumeo\n\n@{\n    var context = new AccordionContext(Type, _openItems, EventCallback.Factory.Create<string>(this, ToggleItem));\n}\n\n<div class=\"@CssClass\" @attributes=\"AdditionalAttributes\">\n    <CascadingValue Value=\"context\" IsFixed=\"false\">\n        @ChildContent\n    </CascadingValue>\n</div>\n\n@code {\n    [Parameter] public RenderFragment? ChildContent { get; set; }\n    [Parameter] public AccordionType Type { get; set; } = AccordionType.Single;\n    [Parameter] public List<string>? DefaultValues { get; set; }\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private readonly HashSet<string> _openItems = new();\n    private bool _initialized;\n\n    private string CssClass => $\"{Class}\".Trim();\n\n    protected override void OnInitialized()\n    {\n        if (!_initialized && DefaultValues is { Count: > 0 })\n        {\n            foreach (var value in DefaultValues)\n            {\n                _openItems.Add(value);\n            }\n            _initialized = true;\n        }\n    }\n\n    private Task ToggleItem(string value)\n    {\n        if (_openItems.Contains(value))\n        {\n            _openItems.Remove(value);\n        }\n        else\n        {\n            if (Type == AccordionType.Single)\n            {\n                _openItems.Clear();\n            }\n            _openItems.Add(value);\n        }\n        StateHasChanged();\n        return Task.CompletedTask;\n    }\n\n    public enum AccordionType { Single, Multiple }\n\n    public record AccordionContext(AccordionType Type, HashSet<string> OpenItems, EventCallback<string> Toggle)\n    {\n        public bool IsOpen(string value) => OpenItems.Contains(value);\n    }\n}\n"
    },
    {
      "path": "UI/Accordion/AccordionContent.razor",
      "content": "@namespace Lumeo\n\n@if (ForceMount || IsOpen)\n{\n    <div class=\"@CssClass\" hidden=\"@(IsOpen ? null : \"hidden\")\" @attributes=\"AdditionalAttributes\">\n        <div class=\"pb-4 pt-0\">\n            @ChildContent\n        </div>\n    </div>\n}\n\n@code {\n    [CascadingParameter] public Accordion.AccordionContext Context { get; set; } = default!;\n    [CascadingParameter] public AccordionItem.AccordionItemContext ItemContext { get; set; } = default!;\n    [Parameter] public RenderFragment? ChildContent { get; set; }\n\n    /// <summary>\n    /// When true, this panel is always rendered into the DOM (with the\n    /// <c>hidden</c> attribute when closed) instead of being unmounted.\n    /// Use when child state (form inputs, scroll position, expensive\n    /// component init) must survive closing the accordion item.\n    /// Default <c>false</c> preserves the original unmount behaviour.\n    /// </summary>\n    [Parameter] public bool ForceMount { get; set; }\n\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private bool IsOpen => Context.IsOpen(ItemContext.Value);\n\n    private string CssClass => $\"overflow-hidden text-sm {(IsOpen ? \"animate-accordion-down\" : \"\")} {Class}\".Trim();\n}\n"
    },
    {
      "path": "UI/Accordion/AccordionItem.razor",
      "content": "@namespace Lumeo\n\n@{\n    var itemContext = new AccordionItemContext(Value, Disabled);\n}\n\n<CascadingValue Value=\"itemContext\" IsFixed=\"false\">\n    <div class=\"@CssClass\" @attributes=\"AdditionalAttributes\">\n        @ChildContent\n    </div>\n</CascadingValue>\n\n@code {\n    [Parameter] public RenderFragment? ChildContent { get; set; }\n    [Parameter, EditorRequired] public string Value { get; set; } = \"\";\n    [Parameter] public bool Disabled { get; set; }\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private string CssClass => string.Join(\" \", new[] { \"border-b border-border/40\", Disabled ? \"opacity-50\" : null, Class }.Where(s => !string.IsNullOrWhiteSpace(s)));\n\n    public record AccordionItemContext(string Value, bool Disabled);\n}\n"
    },
    {
      "path": "UI/Accordion/AccordionTrigger.razor",
      "content": "@namespace Lumeo\n\n<button type=\"button\" class=\"@CssClass\" aria-expanded=\"@IsOpen\" disabled=\"@IsDisabled\" @onclick=\"Toggle\" @attributes=\"AdditionalAttributes\">\n    @ChildContent\n    <Blazicon Svg=\"Lucide.ChevronDown\" class=\"@IconClasses\" />\n</button>\n\n@code {\n    [CascadingParameter] public Accordion.AccordionContext Context { get; set; } = default!;\n    [CascadingParameter] public AccordionItem.AccordionItemContext ItemContext { get; set; } = default!;\n    [Parameter] public RenderFragment? ChildContent { get; set; }\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private bool IsOpen => Context.IsOpen(ItemContext.Value);\n    private bool IsDisabled => ItemContext.Disabled;\n\n    private string CssClass => $\"flex flex-1 w-full items-center justify-between py-4 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm {(IsDisabled ? \"cursor-not-allowed\" : \"cursor-pointer hover:underline\")} {Class}\".Trim();\n\n    private string IconClasses => string.Join(\" \", new[] { \"h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200\", IsOpen ? \"rotate-180\" : null }.Where(s => !string.IsNullOrWhiteSpace(s)));\n\n    private async Task Toggle()\n    {\n        if (IsDisabled) return;\n        await Context.Toggle.InvokeAsync(ItemContext.Value);\n    }\n}\n"
    }
  ],
  "slots": [
    {
      "name": "ChildContent",
      "owner": "Accordion",
      "type": "RenderFragment?",
      "description": null
    },
    {
      "name": "ChildContent",
      "owner": "AccordionContent",
      "type": "RenderFragment?",
      "description": null
    },
    {
      "name": "ChildContent",
      "owner": "AccordionItem",
      "type": "RenderFragment?",
      "description": null
    },
    {
      "name": "ChildContent",
      "owner": "AccordionTrigger",
      "type": "RenderFragment?",
      "description": null
    }
  ],
  "serviceDependencies": [],
  "cascadingDependencies": [
    {
      "name": "Context",
      "type": "Accordion.AccordionContext",
      "required": true
    },
    {
      "name": "ItemContext",
      "type": "AccordionItem.AccordionItemContext",
      "required": true
    }
  ],
  "relatedComponents": [
    {
      "name": "AccordionContent",
      "reason": "sub-component"
    },
    {
      "name": "AccordionItem",
      "reason": "sub-component"
    },
    {
      "name": "AccordionTrigger",
      "reason": "sub-component"
    }
  ],
  "keyboardInteractions": [],
  "tests": [
    "tests/Lumeo.Tests/Contract/ComponentContractTests.cs"
  ],
  "mdSummary": "# Accordion\n\nVertically stacked collapsible sections that expand to reveal content.\n\n**Package:** `Lumeo` · **Category:** Navigation\n**Docs:** https://lumeo.nativ.sh/components/accordion\n\n## Parameters\n| Owner | Name | Type | Default | Description |\n|---|---|---|---|---|\n| Accordion | ChildContent | `RenderFragment?` | `` |  |\n| Accordion | Type | `AccordionType` | `AccordionType.Single` |  |\n| Accordion | DefaultValues | `List<string>?` | `` |  |\n| Accordion | Class | `string?` | `` |  |\n| Accordion | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n| AccordionContent | Context | `Accordion.AccordionContext` | `default!` |  |\n| AccordionContent | ItemContext | `AccordionItem.AccordionItemContext` | `default!` |  |\n| AccordionContent | ChildContent | `RenderFragment?` | `` |  |\n| AccordionContent | ForceMount | `bool` | `` | When true, this panel is always rendered into the DOM (with the hidden attribute when closed) instead of being unmounted. Use when child state (form inputs, scroll position, expensive component init) must survive closing the accordion item. Default false preserves the original unmount behaviour. |\n| AccordionContent | Class | `string?` | `` |  |\n| AccordionContent | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n| AccordionItem | ChildContent | `RenderFragment?` | `` |  |\n| AccordionItem | Value | `string` | `\"\"` |  |\n| AccordionItem | Disabled | `bool` | `` |  |\n| AccordionItem | Class | `string?` | `` |  |\n| AccordionItem | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n| AccordionTrigger | Context | `Accordion.AccordionContext` | `default!` |  |\n| AccordionTrigger | ItemContext | `AccordionItem.AccordionItemContext` | `default!` |  |\n| AccordionTrigger | ChildContent | `RenderFragment?` | `` |  |\n| AccordionTrigger | Class | `string?` | `` |  |\n| AccordionTrigger | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n\n## Slots\n- `ChildContent` (Accordion) — RenderFragment slot\n- `ChildContent` (AccordionContent) — RenderFragment slot\n- `ChildContent` (AccordionItem) — RenderFragment slot\n- `ChildContent` (AccordionTrigger) — RenderFragment slot\n\n## Events\n- (none)\n\n## Sub-components\n- `AccordionContent`, `AccordionItem`, `AccordionTrigger`\n\n## Cascading values it expects\n- `Context` (`Accordion.AccordionContext`)\n- `ItemContext` (`AccordionItem.AccordionItemContext`)\n\n## Services it injects\n- (none)\n\n## Keyboard\n—\n\n## Example\n```razor\n<Accordion />\n```\n\n## CSS variables\n`--color-border`, `--color-muted`, `--color-muted-foreground`, `--color-ring`, `--radius`\n\n## Files\n- `UI/Accordion/Accordion.razor`\n- `UI/Accordion/AccordionContent.razor`\n- `UI/Accordion/AccordionItem.razor`\n- `UI/Accordion/AccordionTrigger.razor`\n"
}