{
  "name": "Timeline",
  "category": "Data Display",
  "subcategory": "Lists & Trees",
  "description": "Vertical event timeline with icons and connectors.",
  "thumbnail": "/preview-cards/timeline.png",
  "hasDocsPage": true,
  "nugetPackage": "Lumeo",
  "files": [
    "UI/Timeline/Timeline.razor",
    "UI/Timeline/TimelineItem.razor"
  ],
  "dependencies": [],
  "packageDependencies": [],
  "cssVars": [
    "--color-background",
    "--color-border",
    "--color-foreground",
    "--color-muted",
    "--color-muted-foreground",
    "--color-primary",
    "--color-primary-foreground",
    "--radius"
  ],
  "api": {
    "name": "Timeline",
    "category": "Data Display",
    "subcategory": "Lists & Trees",
    "description": "Vertical event timeline with icons and connectors.",
    "nugetPackage": "Lumeo",
    "files": [
      "UI/Timeline/Timeline.razor",
      "UI/Timeline/TimelineItem.razor"
    ],
    "namespace": "Lumeo",
    "inheritsFrom": null,
    "implements": [],
    "parameters": [
      {
        "name": "ChildContent",
        "type": "RenderFragment?",
        "default": null,
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Orientation",
        "type": "TimelineOrientation",
        "default": "TimelineOrientation.Vertical",
        "description": null,
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "Animated",
        "type": "bool",
        "default": null,
        "description": "When true, each TimelineItem fades+translates in with a staggered delay, the active indicator pulses, and connector segments draw themselves as the active step advances. Default is false.",
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "ActiveIndex",
        "type": "int?",
        "default": null,
        "description": "When set AND Animated is true, drives the active-dot progression: items with index &lt; ActiveIndex render as \"completed\" (solid primary), the item at ActiveIndex pulses, later items are pending (muted). Connectors up to the active index draw themselves. Use together with ActiveIndexChanged for two-way binding.",
        "isCascading": false,
        "captureUnmatched": false
      },
      {
        "name": "ActiveIndexChanged",
        "type": "EventCallback<int>",
        "default": null,
        "description": "Two-way binding callback for ActiveIndex.",
        "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": "ActiveIndexChanged",
        "type": "EventCallback<int>",
        "description": "Two-way binding callback for ActiveIndex."
      }
    ],
    "enums": [
      {
        "name": "TimelineOrientation",
        "values": [
          "Vertical",
          "Horizontal"
        ],
        "description": null
      }
    ],
    "records": [
      {
        "name": "TimelineContext",
        "signature": "TimelineContext(TimelineOrientation Orientation, bool Animated, int? ActiveIndex, int? PreviousActiveIndex, int ReplayKey, Timeline Parent)",
        "description": null
      }
    ],
    "cssVars": [
      "--color-background",
      "--color-border",
      "--color-foreground",
      "--color-muted",
      "--color-muted-foreground",
      "--color-primary",
      "--color-primary-foreground",
      "--radius"
    ],
    "examples": [
      {
        "title": "Vertical Timeline",
        "code": "<Timeline>\n    <TimelineItem Title=\"Order placed\" Description=\"Your order has been placed.\" Time=\"Jan 1, 2025\" />\n    <TimelineItem Title=\"Processing\" Description=\"Being processed.\" Time=\"Jan 2, 2025\" />\n    <TimelineItem Title=\"Shipped\" Description=\"Shipped via express.\" Time=\"Jan 3, 2025\" />\n    <TimelineItem Title=\"Delivered\" Description=\"Has been delivered.\" Time=\"Jan 5, 2025\" />\n</Timeline>"
      },
      {
        "title": "With Icons",
        "code": "<Timeline>\n    <TimelineItem Title=\"Account created\" Time=\"9:00 AM\">\n        <IconContent><Blazicon Svg=\"Lucide.UserPlus\" class=\"h-4 w-4\" /></IconContent>\n    </TimelineItem>\n    <TimelineItem Title=\"Profile updated\" Time=\"10:30 AM\">\n        <IconContent><Blazicon Svg=\"Lucide.Pencil\" class=\"h-4 w-4\" /></IconContent>\n    </TimelineItem>\n</Timeline>"
      },
      {
        "title": "Horizontal Timeline",
        "code": "<Timeline Orientation=\"Timeline.TimelineOrientation.Horizontal\">\n    <TimelineItem Title=\"Step 1\" Description=\"Planning\" />\n    <TimelineItem Title=\"Step 2\" Description=\"Design\" />\n    <TimelineItem Title=\"Step 3\" Description=\"Development\" />\n    <TimelineItem Title=\"Step 4\" Description=\"Launch\" />\n</Timeline>"
      },
      {
        "title": "Orientation (interactive)",
        "code": "<Segmented @bind-Value=\"_orientation\">\n    <SegmentedItem Value=\"@Timeline.TimelineOrientation.Vertical\">Vertical</SegmentedItem>\n    <SegmentedItem Value=\"@Timeline.TimelineOrientation.Horizontal\">Horizontal</SegmentedItem>\n</Segmented>\n<Timeline Orientation=\"@_orientation\">\n    <TimelineItem Title=\"Planning\" Description=\"Scope defined\" Time=\"Jan 1\" />\n    <TimelineItem Title=\"Design\" Description=\"Wireframes approved\" Time=\"Jan 8\" />\n    <TimelineItem Title=\"Development\" Description=\"Sprint in progress\" Time=\"Jan 15\" />\n    <TimelineItem Title=\"Launch\" Description=\"Shipped to production\" Time=\"Feb 1\" />\n</Timeline>\n\n@code { private Timeline.TimelineOrientation _orientation = Timeline.TimelineOrientation.Vertical; }"
      }
    ],
    "subComponents": {
      "TimelineItem": {
        "componentName": "TimelineItem",
        "fileName": "TimelineItem.razor",
        "namespace": "Lumeo",
        "inheritsFrom": null,
        "implements": [],
        "parameters": [
          {
            "name": "Context",
            "type": "Timeline.TimelineContext?",
            "default": null,
            "description": null,
            "isCascading": true,
            "captureUnmatched": false
          },
          {
            "name": "IconContent",
            "type": "RenderFragment?",
            "default": null,
            "description": "Icon slot. Named IconContent to avoid shadowing the &lt;Icon&gt; component.",
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Title",
            "type": "string?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Description",
            "type": "string?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "Time",
            "type": "string?",
            "default": null,
            "description": null,
            "isCascading": false,
            "captureUnmatched": false
          },
          {
            "name": "IsActive",
            "type": "bool",
            "default": null,
            "description": "When set, marks this item as the \"active\" (current) item. When the parent Timeline has Animated=\"true\", this item's indicator pulses. If the parent also sets ActiveIndex, that value wins — use IsActive for static cases only.",
            "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": "ProgressState",
            "values": [
              "Pending",
              "Completed",
              "Active"
            ],
            "description": null
          }
        ],
        "records": [],
        "parseFailed": false,
        "parseError": null
      }
    },
    "parseFailed": false,
    "parseError": null
  },
  "$schema": "https://lumeo.nativ.sh/registry-component-schema.json",
  "key": "timeline",
  "docsUrl": "https://lumeo.nativ.sh/components/timeline",
  "sourceUrl": [
    {
      "file": "UI/Timeline/Timeline.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/Timeline/Timeline.razor"
    },
    {
      "file": "UI/Timeline/TimelineItem.razor",
      "url": "https://github.com/Brain2k-0005/Lumeo/tree/master/src/Lumeo/UI/Timeline/TimelineItem.razor"
    }
  ],
  "source": [
    {
      "path": "UI/Timeline/Timeline.razor",
      "content": "@namespace Lumeo\n\n@{\n    var context = new TimelineContext(Orientation, Animated, ActiveIndex, _lastActiveIndex, _replayKey, this);\n    _index = 0;\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 TimelineOrientation Orientation { get; set; } = TimelineOrientation.Vertical;\n\n    /// <summary>\n    /// When true, each <see cref=\"TimelineItem\"/> fades+translates in with a\n    /// staggered delay, the active indicator pulses, and connector segments\n    /// draw themselves as the active step advances. Default is <c>false</c>.\n    /// </summary>\n    [Parameter] public bool Animated { get; set; }\n\n    /// <summary>\n    /// When set AND <see cref=\"Animated\"/> is true, drives the active-dot\n    /// progression: items with index &lt; ActiveIndex render as \"completed\"\n    /// (solid primary), the item at ActiveIndex pulses, later items are\n    /// pending (muted). Connectors up to the active index draw themselves.\n    /// Use together with <see cref=\"ActiveIndexChanged\"/> for two-way binding.\n    /// </summary>\n    [Parameter] public int? ActiveIndex { get; set; }\n\n    /// <summary>Two-way binding callback for <see cref=\"ActiveIndex\"/>.</summary>\n    [Parameter] public EventCallback<int> ActiveIndexChanged { get; set; }\n\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private int _index;\n\n    // Track the previous ActiveIndex so children can tell whether THEIR\n    // connector should re-animate on this parameter change. `_replayKey`\n    // is bumped on every change so @key can force a re-render of affected\n    // connector elements.\n    private int? _lastActiveIndex;\n    private int _replayKey;\n\n    internal int GetNextIndex() => _index++;\n\n    protected override void OnParametersSet()\n    {\n        if (ActiveIndex != _lastActiveIndex)\n        {\n            _replayKey++;\n            _lastActiveIndex = ActiveIndex;\n        }\n    }\n\n    private string CssClass => Orientation switch\n    {\n        TimelineOrientation.Horizontal => $\"flex flex-row items-start {Class}\".Trim(),\n        _ => $\"flex flex-col {Class}\".Trim()\n    };\n\n    public enum TimelineOrientation { Vertical, Horizontal }\n\n    public record TimelineContext(TimelineOrientation Orientation, bool Animated, int? ActiveIndex, int? PreviousActiveIndex, int ReplayKey, Timeline Parent)\n    {\n        public TimelineContext(TimelineOrientation Orientation) : this(Orientation, false, null, null, 0, default!) { }\n    }\n}\n"
    },
    {
      "path": "UI/Timeline/TimelineItem.razor",
      "content": "@namespace Lumeo\n\n@if (Context?.Orientation == Timeline.TimelineOrientation.Horizontal)\n{\n    <div class=\"@HorizontalCssClass\" style=\"@AnimationStyle\" @attributes=\"AdditionalAttributes\">\n        <div class=\"flex flex-col items-center\">\n            <div class=\"@DotClasses\">\n                @if (IconContent is not null)\n                {\n                    @IconContent\n                }\n                else\n                {\n                    <div class=\"h-2.5 w-2.5 rounded-full @DotInnerFillClass\"></div>\n                }\n            </div>\n            <div class=\"mt-2 flex flex-col items-center text-center\">\n                @if (!string.IsNullOrEmpty(Title))\n                {\n                    <p class=\"text-sm font-medium text-foreground\">@Title</p>\n                }\n                @if (!string.IsNullOrEmpty(Description))\n                {\n                    <p class=\"text-xs text-muted-foreground\">@Description</p>\n                }\n                @if (!string.IsNullOrEmpty(Time))\n                {\n                    <p class=\"text-xs text-muted-foreground/70\">@Time</p>\n                }\n            </div>\n        </div>\n        <div class=\"@HorizontalConnectorClasses\" @key=\"@($\"tl-h-{_index}-{ConnectorState}\")\"></div>\n    </div>\n}\nelse\n{\n    <div class=\"@VerticalCssClass\" style=\"@AnimationStyle\" @attributes=\"AdditionalAttributes\">\n        <div class=\"flex flex-col items-center\">\n            <div class=\"@DotClasses\">\n                @if (IconContent is not null)\n                {\n                    @IconContent\n                }\n                else\n                {\n                    <div class=\"h-2.5 w-2.5 rounded-full @DotInnerFillClass\"></div>\n                }\n            </div>\n            <div class=\"@VerticalConnectorClasses\" @key=\"@($\"tl-v-{_index}-{ConnectorState}\")\"></div>\n        </div>\n        <div class=\"ml-3 pb-6\">\n            @if (!string.IsNullOrEmpty(Title))\n            {\n                <p class=\"text-sm font-medium text-foreground\">@Title</p>\n            }\n            @if (!string.IsNullOrEmpty(Description))\n            {\n                <p class=\"text-xs text-muted-foreground\">@Description</p>\n            }\n            @if (!string.IsNullOrEmpty(Time))\n            {\n                <p class=\"mt-1 text-xs text-muted-foreground/70\">@Time</p>\n            }\n        </div>\n    </div>\n}\n\n@code {\n    [CascadingParameter] public Timeline.TimelineContext? Context { get; set; }\n\n    /// <summary>Icon slot. Named <c>IconContent</c> to avoid shadowing the <c>&lt;Icon&gt;</c> component.</summary>\n    [Parameter] public RenderFragment? IconContent { get; set; }\n\n    [Parameter] public string? Title { get; set; }\n    [Parameter] public string? Description { get; set; }\n    [Parameter] public string? Time { get; set; }\n\n    /// <summary>\n    /// When set, marks this item as the \"active\" (current) item. When the\n    /// parent <see cref=\"Timeline\"/> has <c>Animated=\"true\"</c>, this item's\n    /// indicator pulses. If the parent also sets <c>ActiveIndex</c>, that\n    /// value wins — use <c>IsActive</c> for static cases only.\n    /// </summary>\n    [Parameter] public bool IsActive { get; set; }\n\n    [Parameter] public string? Class { get; set; }\n    [Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; }\n\n    private int _index;\n\n    protected override void OnParametersSet()\n    {\n        if (Context?.Parent is not null)\n        {\n            _index = Context.Parent.GetNextIndex();\n        }\n    }\n\n    private bool IsAnimated => Context?.Animated == true;\n    private bool IsHorizontal => Context?.Orientation == Timeline.TimelineOrientation.Horizontal;\n\n    // Derived state, preferring the parent's ActiveIndex if set — otherwise\n    // falling back to the legacy per-item IsActive flag.\n    private enum ProgressState { Pending, Completed, Active }\n\n    private ProgressState State\n    {\n        get\n        {\n            if (Context?.ActiveIndex is int idx)\n            {\n                if (_index < idx) return ProgressState.Completed;\n                if (_index == idx) return ProgressState.Active;\n                return ProgressState.Pending;\n            }\n            return IsActive ? ProgressState.Active : ProgressState.Pending;\n        }\n    }\n\n    private string DotClasses\n    {\n        get\n        {\n            // When ActiveIndex is driving, \"completed\" items get a filled\n            // primary background (like Steps completed), \"active\" uses the\n            // bordered ring (readable as \"you are here\"), pending items fall\n            // back to muted.\n            string visual;\n            if (Context?.ActiveIndex is not null)\n            {\n                visual = State switch\n                {\n                    ProgressState.Completed => \"border-2 border-primary bg-primary text-primary-foreground\",\n                    ProgressState.Active => \"border-2 border-primary bg-background text-primary\",\n                    _ => \"border-2 border-muted bg-background text-muted-foreground\"\n                };\n            }\n            else\n            {\n                visual = \"border-2 border-primary bg-background text-primary\";\n            }\n            var baseClasses = $\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full {visual}\";\n            return IsAnimated && State == ProgressState.Active ? $\"{baseClasses} lumeo-steps-pulse\" : baseClasses;\n        }\n    }\n\n    // The inner filled dot (used when no IconContent is supplied). When\n    // ActiveIndex drives progression we colour it to match the ring.\n    private string DotInnerFillClass\n    {\n        get\n        {\n            if (Context?.ActiveIndex is null) return \"bg-primary\";\n            return State switch\n            {\n                ProgressState.Completed => \"bg-primary-foreground\",\n                ProgressState.Active => \"bg-primary\",\n                _ => \"bg-muted-foreground/50\"\n            };\n        }\n    }\n\n    private string HorizontalConnectorClasses => BuildConnectorClasses(horizontal: true);\n    private string VerticalConnectorClasses => BuildConnectorClasses(horizontal: false);\n\n    // Three-state key used for @key so only the transitioning connector remounts.\n    // \"completed-drawing\" / \"completed-static\" / \"unwinding\" / \"pending\"\n    private string ConnectorState\n    {\n        get\n        {\n            if (Context?.ActiveIndex is not int current) return IsCompletedLegacy ? \"completed-static\" : \"pending\";\n\n            var prev = Context.PreviousActiveIndex ?? current;\n            var isBackward = current < prev;\n            var isCompleted = _index < current;\n\n            if (!isBackward && isCompleted && _index == current - 1) return \"completed-drawing\";\n            if (isCompleted) return \"completed-static\";\n            if (isBackward && _index == current) return \"unwinding\";\n            return \"pending\";\n        }\n    }\n\n    // Legacy completed state for the no-ActiveIndex path.\n    private bool IsCompletedLegacy => Context?.ActiveIndex is null && false;\n\n    private string BuildConnectorClasses(bool horizontal)\n    {\n        var baseLayout = horizontal ? \"mx-2 mt-4 h-px flex-1\" : \"my-1 w-px flex-1\";\n\n        if (!IsAnimated)\n        {\n            // Static: colour based on ActiveIndex completion state.\n            var staticColor = (Context?.ActiveIndex is int si && _index < si) ? \"bg-primary\" : \"bg-border\";\n            return $\"{baseLayout} {staticColor}\";\n        }\n\n        // Legacy no-ActiveIndex animated path — always draw in on mount.\n        if (Context?.ActiveIndex is null)\n        {\n            var drawClass = horizontal ? \"lumeo-steps-line-draw-x\" : \"lumeo-steps-line-draw-y\";\n            return $\"{baseLayout} bg-border {drawClass}\";\n        }\n\n        // ActiveIndex-driven: animate only the transitioning connector.\n        var state = ConnectorState;\n        return state switch\n        {\n            \"completed-drawing\" => $\"{baseLayout} bg-primary \" + (horizontal ? \"lumeo-steps-line-draw-x\" : \"lumeo-steps-line-draw-y\"),\n            \"completed-static\" => $\"{baseLayout} bg-primary\",\n            // Force bg-primary so the unwinding line is visible (otherwise the\n            // retracting line is bg-border grey — invisible on muted bg).\n            \"unwinding\" => $\"{baseLayout} bg-primary \" + (horizontal ? \"lumeo-steps-line-unwind-x\" : \"lumeo-steps-line-unwind-y\"),\n            _ => $\"{baseLayout} bg-border\"\n        };\n    }\n\n    private string VerticalCssClass\n    {\n        get\n        {\n            var baseClasses = $\"flex flex-row {Class}\".Trim();\n            return IsAnimated ? $\"{baseClasses} lumeo-timeline-enter-vertical\" : baseClasses;\n        }\n    }\n\n    private string HorizontalCssClass\n    {\n        get\n        {\n            var baseClasses = $\"flex flex-1 flex-row last:flex-initial {Class}\".Trim();\n            return IsAnimated ? $\"{baseClasses} lumeo-timeline-enter-horizontal\" : baseClasses;\n        }\n    }\n\n    private string? AnimationStyle =>\n        IsAnimated ? $\"animation-delay: {_index * 80}ms;\" : null;\n}\n"
    }
  ],
  "slots": [
    {
      "name": "ChildContent",
      "owner": "Timeline",
      "type": "RenderFragment?",
      "description": null
    },
    {
      "name": "IconContent",
      "owner": "TimelineItem",
      "type": "RenderFragment?",
      "description": "Icon slot. Named IconContent to avoid shadowing the &lt;Icon&gt; component."
    }
  ],
  "serviceDependencies": [],
  "cascadingDependencies": [
    {
      "name": "Context",
      "type": "Timeline.TimelineContext?",
      "required": false
    }
  ],
  "relatedComponents": [
    {
      "name": "TimelineItem",
      "reason": "sub-component"
    }
  ],
  "keyboardInteractions": [],
  "tests": [
    "tests/Lumeo.Tests/Components/Timeline/TimelineActiveIndexTests.cs",
    "tests/Lumeo.Tests/Components/Timeline/TimelineAnimatedTests.cs",
    "tests/Lumeo.Tests/Components/Timeline/TimelineTests.cs"
  ],
  "mdSummary": "# Timeline\n\nVertical event timeline with icons and connectors.\n\n**Package:** `Lumeo` · **Category:** Data Display/Lists & Trees\n**Docs:** https://lumeo.nativ.sh/components/timeline\n\n## Parameters\n| Owner | Name | Type | Default | Description |\n|---|---|---|---|---|\n| Timeline | ChildContent | `RenderFragment?` | `` |  |\n| Timeline | Orientation | `TimelineOrientation` | `TimelineOrientation.Vertical` |  |\n| Timeline | Animated | `bool` | `` | When true, each TimelineItem fades+translates in with a staggered delay, the active indicator pulses, and connector segments draw themselves as the active step advances. Default is false. |\n| Timeline | ActiveIndex | `int?` | `` | When set AND Animated is true, drives the active-dot progression: items with index &lt; ActiveIndex render as \"completed\" (solid primary), the item at ActiveIndex pulses, later items are pending (muted). Connectors up to the active index draw themselves. Use together with ActiveIndexChanged for two-way binding. |\n| Timeline | ActiveIndexChanged | `EventCallback<int>` | `` | Two-way binding callback for ActiveIndex. |\n| Timeline | Class | `string?` | `` |  |\n| Timeline | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n| TimelineItem | Context | `Timeline.TimelineContext?` | `` |  |\n| TimelineItem | IconContent | `RenderFragment?` | `` | Icon slot. Named IconContent to avoid shadowing the &lt;Icon&gt; component. |\n| TimelineItem | Title | `string?` | `` |  |\n| TimelineItem | Description | `string?` | `` |  |\n| TimelineItem | Time | `string?` | `` |  |\n| TimelineItem | IsActive | `bool` | `` | When set, marks this item as the \"active\" (current) item. When the parent Timeline has Animated=\"true\", this item's indicator pulses. If the parent also sets ActiveIndex, that value wins — use IsActive for static cases only. |\n| TimelineItem | Class | `string?` | `` |  |\n| TimelineItem | AdditionalAttributes | `Dictionary<string, object>?` | `` |  |\n\n## Slots\n- `ChildContent` (Timeline) — RenderFragment slot\n- `IconContent` (TimelineItem) — Icon slot. Named IconContent to avoid shadowing the &lt;Icon&gt; component.\n\n## Events\n- `ActiveIndexChanged` (`EventCallback<int>`) — Two-way binding callback for ActiveIndex.\n\n## Sub-components\n- `TimelineItem`\n\n## Cascading values it expects\n- `Context` (`Timeline.TimelineContext?`)\n\n## Services it injects\n- (none)\n\n## Keyboard\n—\n\n## Example\n```razor\n<Timeline />\n```\n\n## CSS variables\n`--color-background`, `--color-border`, `--color-foreground`, `--color-muted`, `--color-muted-foreground`, `--color-primary`, `--color-primary-foreground`, `--radius`\n\n## Files\n- `UI/Timeline/Timeline.razor`\n- `UI/Timeline/TimelineItem.razor`\n"
}