Current section
Files
Jump to
Current section
Files
lib/doggo/components/tabs.ex
defmodule Doggo.Components.Tabs do
@moduledoc false
@behaviour Doggo.Component
use Phoenix.Component
@impl true
def doc do
"""
Renders tab panels.
This component is meant for tabs that toggle content panels within the page.
If you want to link to a different view or live action, use
`tab_navigation/1` instead.
"""
end
@impl true
def usage do
"""
```heex
<.tabs id="dog-breed-profiles" label="Dog Breed Profiles">
<:panel label="Golden Retriever">
<p>
Friendly, intelligent, great with families. Origin: Scotland. Needs
regular exercise.
</p>
</:panel>
<:panel label="Siberian Husky">
<p>
Energetic, outgoing, distinctive appearance. Origin: Northeast Asia.
Loves cold climates.
</p>
</:panel>
<:panel label="Dachshund">
<p>
Playful, stubborn, small size. Origin: Germany. Enjoys sniffing games.
</p>
</:panel>
</.tabs>
```
"""
end
@impl true
def config do
[
type: :data,
since: "0.6.0",
maturity: :developing,
maturity_note: """
The necessary JavaScript for making this component fully functional and
accessible will be added in a future version.
**Missing features**
- Roving tabindex
- Move focus with arrow keys
""",
modifiers: []
]
end
@impl true
def nested_classes(_) do
[]
end
@impl true
def attrs_and_slots do
quote do
attr :id, :string, required: true
attr :label, :string,
default: nil,
doc: """
A accessibility label for the tabs. Set as `aria-label` attribute.
You should ensure that either the `label` or the `labelledby` attribute is
set.
Do not repeat the word `tab list` or similar in the label, since it is
already announced by screen readers.
"""
attr :labelledby, :string,
default: nil,
doc: """
The DOM ID of an element that labels the tabs.
Example:
```html
<h3 id="my-tabs-label">Dogs</h3>
<Doggo.tabs labelledby="my-tabs-label"></Doggo.tabs>
```
You should ensure that either the `label` or the `labelledby` attribute is
set.
"""
attr :rest, :global, doc: "Any additional HTML attributes."
slot :panel, required: true do
attr :label, :string
end
end
end
@impl true
def init_block(_opts, _extra) do
[]
end
@impl true
def render(assigns) do
Doggo.ensure_label!(assigns, ".tabs", "Dog Facts")
~H"""
<div id={@id} class={@class} {@data_attrs} {@rest}>
<div role="tablist" aria-label={@label} aria-labelledby={@labelledby}>
<button
:for={{panel, index} <- Enum.with_index(@panel, 1)}
type="button"
role="tab"
id={"#{@id}-tab-#{index}"}
aria-selected={to_string(index == 1)}
aria-controls={"#{@id}-panel-#{index}"}
tabindex={index != 1 && "-1"}
phx-click={Doggo.show_tab(@id, index)}
>
{panel.label}
</button>
</div>
<div
:for={{panel, index} <- Enum.with_index(@panel, 1)}
id={"#{@id}-panel-#{index}"}
role="tabpanel"
aria-labelledby={"#{@id}-tab-#{index}"}
hidden={index != 1}
>
{render_slot(panel)}
</div>
</div>
"""
end
end