tabs

Tabs can be used to show a list of links in a tabbed format.

Base Tabs

Exported source
tabs = SingleValueFactory("tabs", "Container of multiple tab items") # Base tabs component
tab = SingleValueFactory("tab", "A single tab button (can be button, link, div, radio input, etc)") # tab part
tab_content = SingleValueFactory("tab-content", "Tab content that comes immediately after a tab") # tab content part

Tabs Styles


source

LiftStyle

 LiftStyle (value, names=None, module=None, qualname=None, type=None,
            start=1, boundary=None)

*str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.*

Exported source
class BoxStyle(str, Enum):
    BOX = "box"
class LiftStyle(str, Enum):
    LIFT = "lift"

tabs_styles = enums_to_simple_factory(tabs, [BoxStyle, BorderStyle, LiftStyle]) # Tabs style variants

source

BoxStyle

 BoxStyle (value, names=None, module=None, qualname=None, type=None,
           start=1, boundary=None)

*str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.*

Tab Modifiers

Exported source
tab_modifiers = SimpleFactory(
    {
        "disabled": "tab-disabled",
        "active": "tab-active",
    },
    "Tab modifiers"
) # Tab modifiers

Tabs Placement

Exported source
tabs_placement = SimpleFactory(
    {
        "top": "tabs-top",
        "bottom": "tabs-bottom",
    },
    "tabs placement options"
) # tabs placement options

Tabs Sizes

Exported source
tabs_sizes = enums_to_simple_factory(tabs, [DaisyUINamedSize], "Tabs size variants from extra small to extra large") # Tabs size variants

Tabs Test Examples


source

test_tabs_basic_examples

 test_tabs_basic_examples ()

Test basic tabs utilities.

Exported source
def test_tabs_basic_examples():
    """Test basic tabs utilities."""
    # Basic tabs
    assert str(tabs) == "tabs"
    assert str(tab) == "tab"
    assert str(tab_content) == "tab-content"
    
    # tabs with modifiers
    assert str(tabs.hover) == "hover:tabs"
    assert str(tabs.md) == "md:tabs"
    assert str(tabs.dark) == "dark:tabs"

# Run the tests
test_tabs_basic_examples()

source

test_tab_modifiers_examples

 test_tab_modifiers_examples ()

Test tab modifier utilities.

Exported source
def test_tab_modifiers_examples():
    """Test tab modifier utilities."""
    assert str(tab_modifiers.disabled) == "tab-disabled"
    assert str(tab_modifiers.active) == "tab-active"

# Run the tests
test_tab_modifiers_examples()

source

test_tab_placement_examples

 test_tab_placement_examples ()

Test tab modifier utilities.

Exported source
def test_tab_placement_examples():
    """Test tab modifier utilities."""
    assert str(tabs_placement.top) == "tabs-top"
    assert str(tabs_placement.bottom) == "tabs-bottom"

# Run the tests
test_tab_placement_examples()

source

test_tabs_sizes_examples

 test_tabs_sizes_examples ()

Test tabs size variants.

Exported source
def test_tabs_sizes_examples():
    """Test tabs size variants."""
    assert str(tabs_sizes.xs) == "tabs-xs"
    assert str(tabs_sizes.sm) == "tabs-sm"
    assert str(tabs_sizes.md) == "tabs-md"
    assert str(tabs_sizes.lg) == "tabs-lg"
    assert str(tabs_sizes.xl) == "tabs-xl"
    
    # With responsive modifiers
    assert str(tabs_sizes.xs.sm) == "sm:tabs-xs"
    assert str(tabs_sizes.lg.md) == "md:tabs-lg"

# Run the tests
test_tabs_sizes_examples()

source

test_tabs_basic_fasthtml_examples

 test_tabs_basic_fasthtml_examples ()

Test basic tabs example from daisyUI v5 documentation.

Exported source
def test_tabs_basic_fasthtml_examples():
    """Test basic tabs example from daisyUI v5 documentation."""
    from fasthtml.common import Div, A
    
    # Basic tabs
    basic_tabs = Div(
        A("Tab 1", role="tab", cls=str(tab)),
        A("Tab 2", role="tab", cls=combine_classes(tab, tab_modifiers.active)),
        A("Tab 3", role="tab", cls=str(tab)),
        role="tablist",
        cls=str(tabs)
    )
    
    # Verify structure
    assert basic_tabs.tag == "div"
    assert basic_tabs.attrs['role'] == "tablist"
    assert basic_tabs.attrs['class'] == "tabs"
    
    # Verify tabs
    assert len(basic_tabs.children) == 3
    
    # First tab
    first_tab = basic_tabs.children[0]
    assert first_tab.tag == "a"
    assert first_tab.attrs['role'] == "tab"
    assert first_tab.attrs['class'] == "tab"
    assert first_tab.children[0] == "Tab 1"
    
    # Second tab (active)
    second_tab = basic_tabs.children[1]
    assert second_tab.tag == "a"
    assert second_tab.attrs['role'] == "tab"
    assert "tab" in second_tab.attrs['class']
    assert "tab-active" in second_tab.attrs['class']
    assert second_tab.children[0] == "Tab 2"
    
    # Third tab
    third_tab = basic_tabs.children[2]
    assert third_tab.tag == "a"
    assert third_tab.attrs['role'] == "tab"
    assert third_tab.attrs['class'] == "tab"
    assert third_tab.children[0] == "Tab 3"
    
    return basic_tabs

# Run the tests
test_tabs_basic_fasthtml_examples()
<div role="tablist" class="tabs">
<a href="#" role="tab" class="tab">Tab 1</a><a href="#" role="tab" class="tab tab-active">Tab 2</a><a href="#" role="tab" class="tab">Tab 3</a></div>
test_func = test_tabs_basic_fasthtml_examples
app, rt = create_test_app(theme=DaisyUITheme.LIGHT)

@rt
def index():
    return create_test_page(test_func.__doc__.title().replace('.', ''), test_func())
server = start_test_server(app)
display(HTMX())
server.stop()

source

test_tabs_styles_fasthtml_examples

 test_tabs_styles_fasthtml_examples ()

Test tabs style variations from daisyUI v5 documentation.

Exported source
def test_tabs_styles_fasthtml_examples():
    """Test tabs style variations from daisyUI v5 documentation."""
    from fasthtml.common import Div, A
    
    # Tabs with border style
    border_tabs = Div(
        A("Tab 1", role="tab", cls=str(tab)),
        A("Tab 2", role="tab", cls=combine_classes(tab, tab_modifiers.active)),
        A("Tab 3", role="tab", cls=str(tab)),
        role="tablist",
        cls=combine_classes(tabs, tabs_styles.border)
    )
    assert "tabs" in border_tabs.attrs['class']
    assert "tabs-border" in border_tabs.attrs['class']
    assert border_tabs.attrs['role'] == "tablist"
    
    # Tabs with lift style
    lift_tabs = Div(
        A("Tab 1", role="tab", cls=str(tab)),
        A("Tab 2", role="tab", cls=combine_classes(tab, tab_modifiers.active)),
        A("Tab 3", role="tab", cls=str(tab)),
        role="tablist",
        cls=combine_classes(tabs, tabs_styles.lift)
    )
    assert "tabs" in lift_tabs.attrs['class']
    assert "tabs-lift" in lift_tabs.attrs['class']
    assert lift_tabs.attrs['role'] == "tablist"
    
    # Tabs with box style
    box_tabs = Div(
        A("Tab 1", role="tab", cls=str(tab)),
        A("Tab 2", role="tab", cls=combine_classes(tab, tab_modifiers.active)),
        A("Tab 3", role="tab", cls=str(tab)),
        role="tablist",
        cls=combine_classes(tabs, tabs_styles.box)
    )
    assert "tabs" in box_tabs.attrs['class']
    assert "tabs-box" in box_tabs.attrs['class']
    assert box_tabs.attrs['role'] == "tablist"
    
    return Div(border_tabs, lift_tabs, box_tabs)

# Run the tests
test_tabs_styles_fasthtml_examples()
<div>
  <div role="tablist" class="tabs tabs-border">
<a href="#" role="tab" class="tab">Tab 1</a><a href="#" role="tab" class="tab tab-active">Tab 2</a><a href="#" role="tab" class="tab">Tab 3</a>  </div>
  <div role="tablist" class="tabs tabs-lift">
<a href="#" role="tab" class="tab">Tab 1</a><a href="#" role="tab" class="tab tab-active">Tab 2</a><a href="#" role="tab" class="tab">Tab 3</a>  </div>
  <div role="tablist" class="tabs tabs-box">
<a href="#" role="tab" class="tab">Tab 1</a><a href="#" role="tab" class="tab tab-active">Tab 2</a><a href="#" role="tab" class="tab">Tab 3</a>  </div>
</div>
test_func = test_tabs_styles_fasthtml_examples
app, rt = create_test_app(theme=DaisyUITheme.LIGHT)

@rt
def index():
    return create_test_page(test_func.__doc__.title().replace('.', ''), test_func())
server = start_test_server(app)
display(HTMX())
server.stop()

source

test_tabs_radio_inputs_fasthtml_examples

 test_tabs_radio_inputs_fasthtml_examples ()

Test tabs using radio inputs from daisyUI v5 documentation.

Exported source
def test_tabs_radio_inputs_fasthtml_examples():
    """Test tabs using radio inputs from daisyUI v5 documentation."""
    from fasthtml.common import Div, Input
    
    # Tabs-box using radio inputs
    radio_tabs = Div(
        Input(type="radio", name="my_tabs_1", aria_label="Tab 1", cls=str(tab)),
        Input(type="radio", name="my_tabs_1", aria_label="Tab 2", checked="checked", cls=str(tab)),
        Input(type="radio", name="my_tabs_1", aria_label="Tab 3", cls=str(tab)),
        cls=combine_classes(tabs, tabs_styles.box)
    )
    
    # Verify structure
    assert radio_tabs.tag == "div"
    assert "tabs" in radio_tabs.attrs['class']
    assert "tabs-box" in radio_tabs.attrs['class']
    
    # Verify radio inputs
    assert len(radio_tabs.children) == 3
    
    # First radio input
    first_input = radio_tabs.children[0]
    assert first_input.tag == "input"
    assert first_input.attrs['type'] == "radio"
    assert first_input.attrs['name'] == "my_tabs_1"
    assert first_input.attrs['aria-label'] == "Tab 1"
    assert first_input.attrs['class'] == "tab"
    assert 'checked' not in first_input.attrs
    
    # Second radio input (checked)
    second_input = radio_tabs.children[1]
    assert second_input.tag == "input"
    assert second_input.attrs['type'] == "radio"
    assert second_input.attrs['name'] == "my_tabs_1"
    assert second_input.attrs['aria-label'] == "Tab 2"
    assert second_input.attrs['class'] == "tab"
    assert second_input.attrs['checked'] == "checked"
    
    # Third radio input
    third_input = radio_tabs.children[2]
    assert third_input.tag == "input"
    assert third_input.attrs['type'] == "radio"
    assert third_input.attrs['name'] == "my_tabs_1"
    assert third_input.attrs['aria-label'] == "Tab 3"
    assert third_input.attrs['class'] == "tab"
    assert 'checked' not in third_input.attrs
    
    return radio_tabs

# Run the tests
test_tabs_radio_inputs_fasthtml_examples()
<div class="tabs tabs-box">
  <input type="radio" name="my_tabs_1" aria-label="Tab 1" class="tab">
  <input type="radio" name="my_tabs_1" aria-label="Tab 2" checked="checked" class="tab">
  <input type="radio" name="my_tabs_1" aria-label="Tab 3" class="tab">
</div>
test_func = test_tabs_radio_inputs_fasthtml_examples
app, rt = create_test_app(theme=DaisyUITheme.LIGHT)

@rt
def index():
    return create_test_page(test_func.__doc__.title().replace('.', ''), test_func())
server = start_test_server(app)
display(HTMX())
server.stop()

source

test_tabs_sizes_fasthtml_examples

 test_tabs_sizes_fasthtml_examples ()

Test tabs size variations from daisyUI v5 documentation.

Exported source
def test_tabs_sizes_fasthtml_examples():
    """Test tabs size variations from daisyUI v5 documentation."""
    from fasthtml.common import Div, A
    
    # Extra small tabs
    xs_tabs = Div(
        A("Xsmall", role="tab", cls=str(tab)),
        A("Xsmall", role="tab", cls=combine_classes(tab, tab_modifiers.active)),
        A("Xsmall", role="tab", cls=str(tab)),
        role="tablist",
        cls=combine_classes(tabs, tabs_styles.lift, tabs_sizes.xs)
    )
    assert "tabs" in xs_tabs.attrs['class']
    assert "tabs-lift" in xs_tabs.attrs['class']
    assert "tabs-xs" in xs_tabs.attrs['class']
    
    # Small tabs
    sm_tabs = Div(
        A("Small", role="tab", cls=str(tab)),
        A("Small", role="tab", cls=combine_classes(tab, tab_modifiers.active)),
        A("Small", role="tab", cls=str(tab)),
        role="tablist",
        cls=combine_classes(tabs, tabs_styles.lift, tabs_sizes.sm)
    )
    assert "tabs-sm" in sm_tabs.attrs['class']
    
    # Medium tabs (default size)
    md_tabs = Div(
        A("Medium", role="tab", cls=str(tab)),
        A("Medium", role="tab", cls=combine_classes(tab, tab_modifiers.active)),
        A("Medium", role="tab", cls=str(tab)),
        role="tablist",
        cls=combine_classes(tabs, tabs_styles.lift)
    )
    assert "tabs" in md_tabs.attrs['class']
    assert "tabs-lift" in md_tabs.attrs['class']
    # No size class for medium (default)
    
    # Large tabs
    lg_tabs = Div(
        A("Large", role="tab", cls=str(tab)),
        A("Large", role="tab", cls=combine_classes(tab, tab_modifiers.active)),
        A("Large", role="tab", cls=str(tab)),
        role="tablist",
        cls=combine_classes(tabs, tabs_styles.lift, tabs_sizes.lg)
    )
    assert "tabs-lg" in lg_tabs.attrs['class']
    
    # Extra large tabs
    xl_tabs = Div(
        A("Xlarge", role="tab", cls=str(tab)),
        A("Xlarge", role="tab", cls=combine_classes(tab, tab_modifiers.active)),
        A("Xlarge", role="tab", cls=str(tab)),
        role="tablist",
        cls=combine_classes(tabs, tabs_styles.lift, tabs_sizes.xl)
    )
    assert "tabs-xl" in xl_tabs.attrs['class']
    
    return Div(xs_tabs, sm_tabs, md_tabs, lg_tabs, xl_tabs)

# Run the tests
test_tabs_sizes_fasthtml_examples()
<div>
  <div role="tablist" class="tabs tabs-lift tabs-xs">
<a href="#" role="tab" class="tab">Xsmall</a><a href="#" role="tab" class="tab tab-active">Xsmall</a><a href="#" role="tab" class="tab">Xsmall</a>  </div>
  <div role="tablist" class="tabs tabs-lift tabs-sm">
<a href="#" role="tab" class="tab">Small</a><a href="#" role="tab" class="tab tab-active">Small</a><a href="#" role="tab" class="tab">Small</a>  </div>
  <div role="tablist" class="tabs tabs-lift">
<a href="#" role="tab" class="tab">Medium</a><a href="#" role="tab" class="tab tab-active">Medium</a><a href="#" role="tab" class="tab">Medium</a>  </div>
  <div role="tablist" class="tabs tabs-lift tabs-lg">
<a href="#" role="tab" class="tab">Large</a><a href="#" role="tab" class="tab tab-active">Large</a><a href="#" role="tab" class="tab">Large</a>  </div>
  <div role="tablist" class="tabs tabs-lift tabs-xl">
<a href="#" role="tab" class="tab">Xlarge</a><a href="#" role="tab" class="tab tab-active">Xlarge</a><a href="#" role="tab" class="tab">Xlarge</a>  </div>
</div>
test_func = test_tabs_sizes_fasthtml_examples
app, rt = create_test_app(theme=DaisyUITheme.LIGHT)

@rt
def index():
    return create_test_page(test_func.__doc__.title().replace('.', ''), test_func())
server = start_test_server(app)
display(HTMX())
server.stop()

source

test_tabs_with_content_fasthtml_examples

 test_tabs_with_content_fasthtml_examples ()

Test tabs with content panels from daisyUI v5 documentation.

Exported source
def test_tabs_with_content_fasthtml_examples():
    """Test tabs with content panels from daisyUI v5 documentation."""
    from fasthtml.common import Div, Input
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui, border_dui
    from cjm_fasthtml_tailwind.utilities.spacing import p
    
    # Radio tabs-border + tab content
    border_tabs_content = Div(
        Input(type="radio", name="my_tabs_2", aria_label="Tab 1", cls=str(tab)),
        Div(
            "Tab content 1",
            cls=combine_classes(tab_content, border_dui.base_300, bg_dui.base_100, p._10)
        ),
        Input(type="radio", name="my_tabs_2", aria_label="Tab 2", checked="checked", cls=str(tab)),
        Div(
            "Tab content 2",
            cls=combine_classes(tab_content, border_dui.base_300, bg_dui.base_100, p._10)
        ),
        Input(type="radio", name="my_tabs_2", aria_label="Tab 3", cls=str(tab)),
        Div(
            "Tab content 3",
            cls=combine_classes(tab_content, border_dui.base_300, bg_dui.base_100, p._10)
        ),
        cls=combine_classes(tabs, tabs_styles.border)
    )
    
    # Verify structure
    assert "tabs" in border_tabs_content.attrs['class']
    assert "tabs-border" in border_tabs_content.attrs['class']
    assert len(border_tabs_content.children) == 6  # 3 tabs + 3 content panels
    
    # Verify first tab and content
    assert border_tabs_content.children[0].tag == "input"
    assert border_tabs_content.children[0].attrs['type'] == "radio"
    assert border_tabs_content.children[1].tag == "div"
    assert "tab-content" in border_tabs_content.children[1].attrs['class']
    assert "border-base-300" in border_tabs_content.children[1].attrs['class']
    assert "bg-base-100" in border_tabs_content.children[1].attrs['class']
    assert "p-10" in border_tabs_content.children[1].attrs['class']
    assert border_tabs_content.children[1].children[0] == "Tab content 1"
    
    # Radio tabs-lift + tab content
    lift_tabs_content = Div(
        Input(type="radio", name="my_tabs_3", aria_label="Tab 1", cls=str(tab)),
        Div(
            "Tab content 1",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        Input(type="radio", name="my_tabs_3", aria_label="Tab 2", checked="checked", cls=str(tab)),
        Div(
            "Tab content 2",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        Input(type="radio", name="my_tabs_3", aria_label="Tab 3", cls=str(tab)),
        Div(
            "Tab content 3",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        cls=combine_classes(tabs, tabs_styles.lift)
    )
    
    # Verify lift tabs structure
    assert "tabs" in lift_tabs_content.attrs['class']
    assert "tabs-lift" in lift_tabs_content.attrs['class']
    assert "p-6" in lift_tabs_content.children[1].attrs['class']
    
    # Radio tabs-box + tab content
    box_tabs_content = Div(
        Input(type="radio", name="my_tabs_6", aria_label="Tab 1", cls=str(tab)),
        Div(
            "Tab content 1",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        Input(type="radio", name="my_tabs_6", aria_label="Tab 2", checked="checked", cls=str(tab)),
        Div(
            "Tab content 2",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        Input(type="radio", name="my_tabs_6", aria_label="Tab 3", cls=str(tab)),
        Div(
            "Tab content 3",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        cls=combine_classes(tabs, tabs_styles.box)
    )
    
    # Verify box tabs structure
    assert "tabs" in box_tabs_content.attrs['class']
    assert "tabs-box" in box_tabs_content.attrs['class']
    
    return Div(border_tabs_content, lift_tabs_content, box_tabs_content)

# Run the tests
test_tabs_with_content_fasthtml_examples()
<div>
  <div class="tabs tabs-border">
    <input type="radio" name="my_tabs_2" aria-label="Tab 1" class="tab">
    <div class="tab-content border-base-300 bg-base-100 p-10">Tab content 1</div>
    <input type="radio" name="my_tabs_2" aria-label="Tab 2" checked="checked" class="tab">
    <div class="tab-content border-base-300 bg-base-100 p-10">Tab content 2</div>
    <input type="radio" name="my_tabs_2" aria-label="Tab 3" class="tab">
    <div class="tab-content border-base-300 bg-base-100 p-10">Tab content 3</div>
  </div>
  <div class="tabs tabs-lift">
    <input type="radio" name="my_tabs_3" aria-label="Tab 1" class="tab">
    <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 1</div>
    <input type="radio" name="my_tabs_3" aria-label="Tab 2" checked="checked" class="tab">
    <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 2</div>
    <input type="radio" name="my_tabs_3" aria-label="Tab 3" class="tab">
    <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 3</div>
  </div>
  <div class="tabs tabs-box">
    <input type="radio" name="my_tabs_6" aria-label="Tab 1" class="tab">
    <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 1</div>
    <input type="radio" name="my_tabs_6" aria-label="Tab 2" checked="checked" class="tab">
    <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 2</div>
    <input type="radio" name="my_tabs_6" aria-label="Tab 3" class="tab">
    <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 3</div>
  </div>
</div>
test_func = test_tabs_with_content_fasthtml_examples
app, rt = create_test_app(theme=DaisyUITheme.LIGHT)

@rt
def index():
    return create_test_page(test_func.__doc__.title().replace('.', ''), test_func())
server = start_test_server(app)
display(HTMX())
server.stop()

source

test_tabs_with_icons_fasthtml_examples

 test_tabs_with_icons_fasthtml_examples ()

Test tabs with icons and content from daisyUI v5 documentation.

Exported source
def test_tabs_with_icons_fasthtml_examples():
    """Test tabs with icons and content from daisyUI v5 documentation."""
    from fasthtml.common import Div, Label, Input
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import size_util
    from cjm_fasthtml_tailwind.utilities.spacing import me, p
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui, border_dui
    
    # Create reusable icon SVGs
    play_icon = Svg(
        Path(
            stroke_linecap="round",
            stroke_linejoin="round",
            d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"
        ),
        xmlns="http://www.w3.org/2000/svg",
        fill="none",
        viewBox="0 0 24 24",
        stroke_width="1.5",
        stroke="currentColor",
        cls=combine_classes(size_util._4, me._2)
    )
    
    face_icon = Svg(
        Path(
            stroke_linecap="round",
            stroke_linejoin="round",
            d="M15.182 15.182a4.5 4.5 0 0 1-6.364 0M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0ZM9.75 9.75c0 .414-.168.75-.375.75S9 10.164 9 9.75 9.168 9 9.375 9s.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Zm5.625 0c0 .414-.168.75-.375.75s-.375-.336-.375-.75.168-.75.375-.75.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Z"
        ),
        xmlns="http://www.w3.org/2000/svg",
        fill="none",
        viewBox="0 0 24 24",
        stroke_width="1.5",
        stroke="currentColor",
        cls=combine_classes(size_util._4, me._2)
    )
    
    heart_icon = Svg(
        Path(
            stroke_linecap="round",
            stroke_linejoin="round",
            d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z"
        ),
        xmlns="http://www.w3.org/2000/svg",
        fill="none",
        viewBox="0 0 24 24",
        stroke_width="1.5",
        stroke="currentColor",
        cls=combine_classes(size_util._4, me._2)
    )
    
    # Radio tabs-lift with icons + tab content
    icon_tabs = Div(
        Label(
            Input(type="radio", name="my_tabs_4"),
            play_icon,
            "Live",
            cls=str(tab)
        ),
        Div(
            "Tab content 1",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        Label(
            Input(type="radio", name="my_tabs_4", checked="checked"),
            face_icon,
            "Laugh",
            cls=str(tab)
        ),
        Div(
            "Tab content 2",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        Label(
            Input(type="radio", name="my_tabs_4"),
            heart_icon,
            "Love",
            cls=str(tab)
        ),
        Div(
            "Tab content 3",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        cls=combine_classes(tabs, tabs_styles.lift)
    )
    
    # Verify structure
    assert "tabs" in icon_tabs.attrs['class']
    assert "tabs-lift" in icon_tabs.attrs['class']
    assert len(icon_tabs.children) == 6  # 3 labels + 3 content panels
    
    # Verify first tab with icon
    first_label = icon_tabs.children[0]
    assert first_label.tag == "label"
    assert first_label.attrs['class'] == "tab"
    assert first_label.children[0].tag == "input"
    assert first_label.children[0].attrs['type'] == "radio"
    assert first_label.children[0].attrs['name'] == "my_tabs_4"
    assert first_label.children[1].tag == "svg"  # Play icon
    assert first_label.children[2] == "Live"
    
    # Verify second tab (checked) with icon
    second_label = icon_tabs.children[2]
    assert second_label.tag == "label"
    assert second_label.children[0].attrs['checked'] == "checked"
    assert second_label.children[1].tag == "svg"  # Face icon
    assert second_label.children[2] == "Laugh"
    
    # Verify third tab with icon
    third_label = icon_tabs.children[4]
    assert third_label.tag == "label"
    assert third_label.children[1].tag == "svg"  # Heart icon
    assert third_label.children[2] == "Love"
    
    # Verify content panels
    assert icon_tabs.children[1].tag == "div"
    assert "tab-content" in icon_tabs.children[1].attrs['class']
    assert icon_tabs.children[1].children[0] == "Tab content 1"
    
    return icon_tabs

# Run the tests
test_tabs_with_icons_fasthtml_examples()
<div class="tabs tabs-lift">
<label class="tab">    <input type="radio" name="my_tabs_4">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="size-4 me-2"><path d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z" stroke-linecap="round" stroke-linejoin="round"></path></svg>Live</label>  <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 1</div>
<label class="tab">    <input type="radio" name="my_tabs_4" checked="checked">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="size-4 me-2"><path d="M15.182 15.182a4.5 4.5 0 0 1-6.364 0M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0ZM9.75 9.75c0 .414-.168.75-.375.75S9 10.164 9 9.75 9.168 9 9.375 9s.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Zm5.625 0c0 .414-.168.75-.375.75s-.375-.336-.375-.75.168-.75.375-.75.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Z" stroke-linecap="round" stroke-linejoin="round"></path></svg>Laugh</label>  <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 2</div>
<label class="tab">    <input type="radio" name="my_tabs_4">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="size-4 me-2"><path d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z" stroke-linecap="round" stroke-linejoin="round"></path></svg>Love</label>  <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 3</div>
</div>
test_func = test_tabs_with_icons_fasthtml_examples
app, rt = create_test_app(theme=DaisyUITheme.LIGHT)

@rt
def index():
    return create_test_page(test_func.__doc__.title().replace('.', ''), test_func())
server = start_test_server(app)
display(HTMX())
server.stop()

source

test_tabs_special_fasthtml_examples

 test_tabs_special_fasthtml_examples ()

Test special tabs variations from daisyUI v5 documentation.

Exported source
def test_tabs_special_fasthtml_examples():
    """Test special tabs variations from daisyUI v5 documentation."""
    from fasthtml.common import Div, Input, A
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui, border_dui, text_dui
    from cjm_fasthtml_tailwind.utilities.spacing import p
    from cjm_fasthtml_tailwind.utilities.sizing import max_w, min_w
    from cjm_fasthtml_tailwind.utilities.layout import overflow, position, z, start
    
    # Radio tabs-lift + tab content on bottom
    bottom_tabs = Div(
        Input(type="radio", name="my_tabs_5", aria_label="Tab 1", cls=str(tab)),
        Div(
            "Tab content 1",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        Input(type="radio", name="my_tabs_5", aria_label="Tab 2", checked="checked", cls=str(tab)),
        Div(
            "Tab content 2",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        Input(type="radio", name="my_tabs_5", aria_label="Tab 3", cls=str(tab)),
        Div(
            "Tab content 3",
            cls=combine_classes(tab_content, bg_dui.base_100, border_dui.base_300, p._6)
        ),
        cls=combine_classes(tabs, tabs_styles.lift, tabs_placement.bottom)
    )
    
    # Verify bottom tabs structure
    assert "tabs" in bottom_tabs.attrs['class']
    assert "tabs-lift" in bottom_tabs.attrs['class']
    assert "tabs-bottom" in bottom_tabs.attrs['class']
    
    # Tabs with horizontal scroll when there's no space
    scrollable_tabs = Div(
        Div(
            Input(type="radio", name="my_tabs_7", aria_label="Tab title 1", cls=combine_classes(tab, z(1))),
            Div(
                "Tab content 1",
                cls=combine_classes(position.sticky, start(0), tab_content, max_w._60, border_dui.base_300, bg_dui.base_100, p._6)
            ),
            Input(type="radio", name="my_tabs_7", aria_label="Tab title 2", checked="checked", cls=combine_classes(tab, z(1))),
            Div(
                "Tab content 2",
                cls=combine_classes(position.sticky, start(0), tab_content, max_w._60, border_dui.base_300, bg_dui.base_100, p._6)
            ),
            Input(type="radio", name="my_tabs_7", aria_label="Tab title 3", cls=combine_classes(tab, z(1))),
            Div(
                "Tab content 3",
                cls=combine_classes(position.sticky, start(0), tab_content, max_w._60, border_dui.base_300, bg_dui.base_100, p._6)
            ),
            Input(type="radio", name="my_tabs_7", aria_label="Tab title 4", cls=combine_classes(tab, z(1))),
            Div(
                "Tab content 4",
                cls=combine_classes(position.sticky, start(0), tab_content, max_w._60, border_dui.base_300, bg_dui.base_100, p._6)
            ),
            cls=combine_classes(tabs_styles.lift, tabs, min_w.max)
        ),
        cls=combine_classes(overflow.x.auto, max_w._60)
    )
    
    # Verify scrollable tabs structure
    assert "overflow-x-auto" in scrollable_tabs.attrs['class']
    assert "max-w-60" in scrollable_tabs.attrs['class']
    inner_div = scrollable_tabs.children[0]
    assert "tabs-lift" in inner_div.attrs['class']
    assert "tabs" in inner_div.attrs['class']
    assert "min-w-max" in inner_div.attrs['class']
    assert "z-1" in inner_div.children[0].attrs['class']
    assert "sticky" in inner_div.children[1].attrs['class']
    assert "start-0" in inner_div.children[1].attrs['class']
    
    # Tabs with custom color
    custom_color_tabs = Div(
        A("Tab 1", role="tab", cls=str(tab)),
        A(
            "Tab 2",
            role="tab",
            cls=combine_classes(tab, tab_modifiers.active, text_dui.primary),
            style="--tab-bg:orange; --tab-border-color:red"
        ),
        A("Tab 3", role="tab", cls=str(tab)),
        role="tablist",
        cls=combine_classes(tabs, tabs_styles.lift)
    )
    
    # Verify custom color tabs
    assert "tabs" in custom_color_tabs.attrs['class']
    assert "tabs-lift" in custom_color_tabs.attrs['class']
    second_tab = custom_color_tabs.children[1]
    assert "tab-active" in second_tab.attrs['class']
    assert "text-primary" in second_tab.attrs['class']
    assert second_tab.attrs['style'] == "--tab-bg:orange; --tab-border-color:red"
    
    return Div(bottom_tabs, scrollable_tabs, custom_color_tabs)

# Run the tests
test_tabs_special_fasthtml_examples()
<div>
  <div class="tabs tabs-lift tabs-bottom">
    <input type="radio" name="my_tabs_5" aria-label="Tab 1" class="tab">
    <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 1</div>
    <input type="radio" name="my_tabs_5" aria-label="Tab 2" checked="checked" class="tab">
    <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 2</div>
    <input type="radio" name="my_tabs_5" aria-label="Tab 3" class="tab">
    <div class="tab-content bg-base-100 border-base-300 p-6">Tab content 3</div>
  </div>
  <div class="overflow-x-auto max-w-60">
    <div class="tabs-lift tabs min-w-max">
      <input type="radio" name="my_tabs_7" aria-label="Tab title 1" class="tab z-1">
      <div class="sticky start-0 tab-content max-w-60 border-base-300 bg-base-100 p-6">Tab content 1</div>
      <input type="radio" name="my_tabs_7" aria-label="Tab title 2" checked="checked" class="tab z-1">
      <div class="sticky start-0 tab-content max-w-60 border-base-300 bg-base-100 p-6">Tab content 2</div>
      <input type="radio" name="my_tabs_7" aria-label="Tab title 3" class="tab z-1">
      <div class="sticky start-0 tab-content max-w-60 border-base-300 bg-base-100 p-6">Tab content 3</div>
      <input type="radio" name="my_tabs_7" aria-label="Tab title 4" class="tab z-1">
      <div class="sticky start-0 tab-content max-w-60 border-base-300 bg-base-100 p-6">Tab content 4</div>
    </div>
  </div>
  <div role="tablist" class="tabs tabs-lift">
<a href="#" role="tab" class="tab">Tab 1</a><a href="#" role="tab" class="tab tab-active text-primary" style="--tab-bg:orange; --tab-border-color:red">Tab 2</a><a href="#" role="tab" class="tab">Tab 3</a>  </div>
</div>
test_func = test_tabs_special_fasthtml_examples
app, rt = create_test_app(theme=DaisyUITheme.LIGHT)

@rt
def index():
    return create_test_page(test_func.__doc__.title().replace('.', ''), test_func())
server = start_test_server(app)
display(HTMX())
server.stop()