# `LineaUI.Components.Tabs`
[🔗](https://github.com/devaction-labs/linea_ui/blob/v0.1.1/lib/linea_ui/components/tabs.ex#L1)

LineOne's tabs: underlined (`line`), on a gray track (`boxed`), rounded (`pill`) and plain text (`text`), laid out
horizontally or vertically, with or without icons.

    <.tabs id="profile-tabs" selected="home">
      <:tab name="home">Home</:tab>
      <:tab name="profile">Profile</:tab>
      <:panel name="home">…</:panel>
      <:panel name="profile">…</:panel>
    </.tabs>

    <.tabs id="boxed" variant="boxed">
      <:tab name="home"><svg class="size-4.5">…</svg><span>Home</span></:tab>
      <:panel name="home">…</:panel>
    </.tabs>

The selected tab comes from `selected` and switching happens in the browser (click, ←/→ or ↑/↓,
Home and End) without a round trip. A choice made in the browser survives patches; when the
server changes `selected`, the server wins.

`on_change` tells the server what was chosen:

    <.tabs id="server-tabs" selected={@tab} on_change="select_tab">…</.tabs>
    <.tabs id="period" variant="boxed" size="sm"><:tab name="month">Last month</:tab></.tabs>
    <.tabs id="range" variant="text"><:tab name="week">Last 7 days</:tab><:tab name="all">All time</:tab></.tabs>

    def handle_event("select_tab", %{"id" => "server-tabs", "value" => tab}, socket),
      do: {:noreply, assign(socket, tab: tab)}

Every selection also dispatches a bubbling `linea:change` DOM event with
`detail: %{id: id, value: name, tab: name}`.

# `tabs`

Renders a tab list and its panels. Each `:tab` is matched to the `:panel` with the same `name`.

    <.tabs id="settings" selected={@tab} variant="boxed" on_change="tab_changed">
      <:tab name="general">General</:tab>
      <:tab name="billing" disabled>Billing</:tab>
      <:panel name="general">…</:panel>
      <:panel name="billing">…</:panel>
    </.tabs>

Events: with `on_change="tab_changed"` the hook pushes `"tab_changed"` with
`%{"id" => "settings", "value" => "general", "tab" => "general"}` (to `target` or the closest LiveComponent)
after the browser switched; with `on_change={%JS{}}` the commands run on the tabs element.
Either way a bubbling `linea:change` DOM event carries `detail: %{id, value, tab}`; `tab` repeats `value`.

## Attributes

* `id` (`:string`) (required) - Needed by the hook and for the tab/panel ids.
* `selected` (`:string`) - The `name` of the selected tab; the first one when not given. Defaults to `nil`.
* `variant` (`:string`) - `line` underlines the selected tab, `boxed` lifts it off a gray track, `pill` fills a rounded tab, `text` is plain text that only changes color (no border or background; spacing comes from `list_class`, `space-x-4` by default). Defaults to `"line"`. Must be one of `"line"`, `"boxed"`, `"pill"`, or `"text"`.
* `size` (`:string`) - For `boxed`: `md` is `px-3 py-1.5`, `sm` is LineOne's compact `px-3 py-1 text-xs-plus`, `xs` is `px-2.5 py-0.5 text-xs`. Defaults to `"md"`. Must be one of `"xs"`, `"sm"`, or `"md"`.
* `color` (`:string`) - The fill of the selected `pill` tab and the text color of the selected `text` tab. Defaults to `"primary"`. Must be one of `"primary"`, or `"neutral"`.
* `orientation` (`:string`) - Defaults to `"horizontal"`. Must be one of `"horizontal"`, or `"vertical"`.
* `bordered` (`:boolean`) - For `line`: draws the gray rule the tabs sit on. Defaults to `false`.
* `overlap` (`:boolean`) - For a `bordered` line: the selected tab's line covers the gray rule instead of sitting on it. Defaults to `false`.
* `grow` (`:boolean`) - The tabs share the whole width of the list. Defaults to `false`.
* `transition` (`:string`) - The way a panel comes in: sliding from the right (`left`) or from below (`up`). Defaults to `"left"`. Must be one of `"left"`, `"up"`, or `"none"`.
* `on_change` (`:any`) - Run when a tab is chosen in the browser. An event name is pushed with
  `%{"id" => id, "value" => name, "tab" => name}`; a `%JS{}` is executed on the tabs element.

  Defaults to `nil`.
* `target` (`:any`) - The `phx-target` of `on_change`. Defaults to `nil`.
* `list_class` (`:any`) - Extra classes for the tab list. Defaults to `nil`.
* `panels_class` (`:any`) - Extra classes for the wrapper of the panels. Defaults to `nil`.
* `class` (`:any`) - Defaults to `nil`.
* Global attributes are accepted.
## Slots

* `tab` (required) - A tab button; its content is the label, icons included. Accepts attributes:

  * `name` (`:string`) (required) - Matches the `:panel` it shows and is the `on_change` value.
  * `disabled` (`:boolean`) - Skipped by clicks and the arrow keys.
  * `class` (`:any`)
* `panel` - The content shown while the tab with the same `name` is selected. Accepts attributes:

  * `name` (`:string`) (required) - The `name` of its tab.
  * `class` (`:any`)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
