menu

Menu is used to display a list of links vertically or horizontally.

Base Menu

Exported source
menu = SingleValueFactory("menu", "Base menu component for displaying a <ul> list of links vertically or horizontally") # Base menu component
menu_title = SingleValueFactory("menu-title", "Menu title part for styling a <li> as a title") # Menu title part
menu_dropdown = SingleValueFactory("menu-dropdown", "Menu dropdown part for the collapsible <ul> if you want to show it using JS") # Menu dropdown part
menu_dropdown_toggle = SingleValueFactory("menu-dropdown-toggle", "Menu part for the toggle to show/hide the menu-dropdown using JS") # Menu dropdown toggle part

test_menu_basic_examples

 test_menu_basic_examples ()

Test basic menu utilities.

Exported source
def test_menu_basic_examples():
    """Test basic menu utilities."""
    # Basic menu
    assert str(menu) == "menu"
    assert str(menu_title) == "menu-title"
    assert str(menu_dropdown) == "menu-dropdown"
    assert str(menu_dropdown_toggle) == "menu-dropdown-toggle"
    
    # menu with modifiers
    assert str(menu.hover) == "hover:menu"
    assert str(menu.md) == "md:menu"
    assert str(menu.dark) == "dark:menu"

# Run the tests
test_menu_basic_examples()

source

test_menu_modifiers_examples

 test_menu_modifiers_examples ()

Test menu modifier utilities.

Exported source
def test_menu_modifiers_examples():
    """Test menu modifier utilities."""
    assert str(menu_modifiers.disabled) == "menu-disabled"
    assert str(menu_modifiers.active) == "menu-active"
    assert str(menu_modifiers.focus) == "menu-focus"
    assert str(menu_modifiers.dropdown_show) == "menu-dropdown-show"

# Run the tests
test_menu_modifiers_examples()

source

test_menu_sizes_examples

 test_menu_sizes_examples ()

Test menu size variants.

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

# Run the tests
test_menu_sizes_examples()

source

test_menu_directions_examples

 test_menu_directions_examples ()

Test menu direction utilities.

Exported source
def test_menu_directions_examples():
    """Test menu direction utilities."""
    assert str(menu_directions.vertical) == "menu-vertical"
    assert str(menu_directions.horizontal) == "menu-horizontal"

# Run the tests
test_menu_directions_examples()

source

test_menu_basic_fasthtml_examples

 test_menu_basic_fasthtml_examples ()

Test basic menu from daisyUI v5 documentation.

Exported source
def test_menu_basic_fasthtml_examples():
    """Test basic menu from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, A
    from cjm_fasthtml_tailwind.utilities.sizing import w
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
    
    # Basic menu
    basic_menu = Ul(
        Li(A("Item 1", href="#")),
        Li(A("Item 2", href="#")),
        Li(A("Item 3", href="#")),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify structure
    assert basic_menu.tag == "ul"
    assert "menu" in basic_menu.attrs['class']
    assert "bg-base-200" in basic_menu.attrs['class']
    assert "rounded-box" in basic_menu.attrs['class']
    assert "w-56" in basic_menu.attrs['class']
    
    # Verify li elements
    assert len(basic_menu.children) == 3
    for i in range(3):
        li = basic_menu.children[i]
        assert li.tag == "li"
        assert li.children[0].tag == "a"
        assert li.children[0].attrs['href'] == "#"
        assert li.children[0].children[0] == f"Item {i + 1}"
    
    return basic_menu

# Run the tests
test_menu_basic_fasthtml_examples()
<ul class="menu bg-base-200 rounded-box w-56">
  <li>
<a href="#">Item 1</a>  </li>
  <li>
<a href="#">Item 2</a>  </li>
  <li>
<a href="#">Item 3</a>  </li>
</ul>
test_func = test_menu_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_menu_responsive_fasthtml_examples

 test_menu_responsive_fasthtml_examples ()

Test responsive menu and horizontal menu from daisyUI v5 documentation.

Exported source
def test_menu_responsive_fasthtml_examples():
    """Test responsive menu and horizontal menu from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, A, Div
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
    
    # Responsive: vertical on small screen, horizontal on large screen
    responsive_menu = Ul(
        Li(A("Item 1", href="#")),
        Li(A("Item 2", href="#")),
        Li(A("Item 3", href="#")),
        cls=combine_classes(menu, menu_directions.vertical, menu_directions.horizontal.lg, bg_dui.base_200, rounded.box)
    )
    
    # Verify structure
    assert responsive_menu.tag == "ul"
    assert "menu" in responsive_menu.attrs['class']
    assert "menu-vertical" in responsive_menu.attrs['class']
    assert "lg:menu-horizontal" in responsive_menu.attrs['class']
    assert "bg-base-200" in responsive_menu.attrs['class']
    assert "rounded-box" in responsive_menu.attrs['class']
    
    # Horizontal menu
    horizontal_menu = Ul(
        Li(A("Item 1", href="#")),
        Li(A("Item 2", href="#")),
        Li(A("Item 3", href="#")),
        cls=combine_classes(menu, menu_directions.horizontal, bg_dui.base_200)
    )
    
    # Verify horizontal menu
    assert horizontal_menu.tag == "ul"
    assert "menu" in horizontal_menu.attrs['class']
    assert "menu-horizontal" in horizontal_menu.attrs['class']
    assert "bg-base-200" in horizontal_menu.attrs['class']
    
    return Div(responsive_menu, horizontal_menu)

# Run the tests
test_menu_responsive_fasthtml_examples()
<div>
  <ul class="menu menu-vertical lg:menu-horizontal bg-base-200 rounded-box">
    <li>
<a href="#">Item 1</a>    </li>
    <li>
<a href="#">Item 2</a>    </li>
    <li>
<a href="#">Item 3</a>    </li>
  </ul>
  <ul class="menu menu-horizontal bg-base-200">
    <li>
<a href="#">Item 1</a>    </li>
    <li>
<a href="#">Item 2</a>    </li>
    <li>
<a href="#">Item 3</a>    </li>
  </ul>
</div>
test_func = test_menu_responsive_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_menu_icons_fasthtml_examples

 test_menu_icons_fasthtml_examples ()

Test menu with icons from daisyUI v5 documentation.

Exported source
def test_menu_icons_fasthtml_examples():
    """Test menu with icons from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, A, Span, Div
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import h, w
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_tailwind.utilities.spacing import m
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
    from cjm_fasthtml_daisyui.components.data_display.badge import badge, badge_sizes, badge_colors
    from cjm_fasthtml_daisyui.components.feedback.tooltip import tooltip, tooltip_placement
    
    # Create reusable icons
    home_icon = Svg(
        Path(
            stroke_linecap="round",
            stroke_linejoin="round",
            stroke_width="2",
            d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
        ),
        xmlns="http://www.w3.org/2000/svg",
        cls=combine_classes(h._5, w._5),
        fill="none",
        viewBox="0 0 24 24",
        stroke="currentColor"
    )
    
    info_icon = Svg(
        Path(
            stroke_linecap="round",
            stroke_linejoin="round",
            stroke_width="2",
            d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
        ),
        xmlns="http://www.w3.org/2000/svg",
        cls=combine_classes(h._5, w._5),
        fill="none",
        viewBox="0 0 24 24",
        stroke="currentColor"
    )
    
    stats_icon = Svg(
        Path(
            stroke_linecap="round",
            stroke_linejoin="round",
            stroke_width="2",
            d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
        ),
        xmlns="http://www.w3.org/2000/svg",
        cls=combine_classes(h._5, w._5),
        fill="none",
        viewBox="0 0 24 24",
        stroke="currentColor"
    )
    
    # Menu with icon only (vertical)
    icon_only_menu = Ul(
        Li(A(home_icon, href="#")),
        Li(A(info_icon, href="#")),
        Li(A(stats_icon, href="#")),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box)
    )
    
    # Verify icon only menu
    assert icon_only_menu.tag == "ul"
    assert "menu" in icon_only_menu.attrs['class']
    assert len(icon_only_menu.children) == 3
    for i in range(3):
        li = icon_only_menu.children[i]
        assert li.tag == "li"
        assert li.children[0].tag == "a"
        assert li.children[0].children[0].tag == "svg"
    
    # Menu with icon only (horizontal)
    icon_only_horizontal = Ul(
        Li(A(home_icon, href="#")),
        Li(A(info_icon, href="#")),
        Li(A(stats_icon, href="#")),
        cls=combine_classes(menu, menu_directions.horizontal, bg_dui.base_200, rounded.box)
    )
    
    # Verify horizontal icon menu
    assert "menu-horizontal" in icon_only_horizontal.attrs['class']
    
    # Menu with icons and text
    icons_with_text = Ul(
        Li(A(home_icon, "Item 2", href="#")),
        Li(A(info_icon, "Item 1", href="#")),
        Li(A(stats_icon, "Item 3", href="#")),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify icons with text
    assert "w-56" in icons_with_text.attrs['class']
    assert icons_with_text.children[0].children[0].children[0].tag == "svg"
    assert icons_with_text.children[0].children[0].children[1] == "Item 2"
    
    # Menu with icons and badge (responsive)
    icons_with_badge = Ul(
        Li(
            A(
                home_icon,
                "Inbox",
                Span("99+", cls=combine_classes(badge, badge_sizes.xs)),
                href="#"
            )
        ),
        Li(
            A(
                info_icon,
                "Updates",
                Span("NEW", cls=combine_classes(badge, badge_sizes.xs, badge_colors.warning)),
                href="#"
            )
        ),
        Li(
            A(
                "Stats",
                Span(cls=combine_classes(badge, badge_sizes.xs, badge_colors.info)),
                href="#"
            )
        ),
        cls=combine_classes(menu, bg_dui.base_200, menu_directions.horizontal.lg, rounded.box)
    )
    
    # Verify menu with badges
    assert "lg:menu-horizontal" in icons_with_badge.attrs['class']
    first_li = icons_with_badge.children[0]
    assert first_li.children[0].children[0].tag == "svg"  # Icon
    assert first_li.children[0].children[1] == "Inbox"  # Text
    assert "badge" in first_li.children[0].children[2].attrs['class']  # Badge
    assert first_li.children[0].children[2].children[0] == "99+"
    
    # Menu with icon only with tooltip
    icon_with_tooltip = Ul(
        Li(
            A(
                home_icon,
                href="#",
                cls=combine_classes(tooltip, tooltip_placement.right),
                data_tip="Home"
            )
        ),
        Li(
            A(
                info_icon,
                href="#",
                cls=combine_classes(tooltip, tooltip_placement.right),
                data_tip="Details"
            )
        ),
        Li(
            A(
                stats_icon,
                href="#",
                cls=combine_classes(tooltip, tooltip_placement.right),
                data_tip="Stats"
            )
        ),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box)
    )
    
    # Verify tooltips
    assert icon_with_tooltip.children[0].children[0].attrs['data-tip'] == "Home"
    assert "tooltip" in icon_with_tooltip.children[0].children[0].attrs['class']
    assert "tooltip-right" in icon_with_tooltip.children[0].children[0].attrs['class']
    
    # Menu with icon only (horizontal) with tooltip
    icon_horizontal_tooltip = Ul(
        Li(
            A(
                home_icon,
                href="#",
                cls=str(tooltip),
                data_tip="Home"
            )
        ),
        Li(
            A(
                info_icon,
                href="#",
                cls=str(tooltip),
                data_tip="Details"
            )
        ),
        Li(
            A(
                stats_icon,
                href="#",
                cls=str(tooltip),
                data_tip="Stats"
            )
        ),
        cls=combine_classes(menu, menu_directions.horizontal, bg_dui.base_200, rounded.box, m.t._6)
    )
    
    # Verify horizontal with tooltips
    assert "menu-horizontal" in icon_horizontal_tooltip.attrs['class']
    assert "mt-6" in icon_horizontal_tooltip.attrs['class']
    assert icon_horizontal_tooltip.children[1].children[0].attrs['data-tip'] == "Details"
    
    return Div(
        icon_only_menu,
        icon_only_horizontal,
        icons_with_text,
        icons_with_badge,
        icon_with_tooltip,
        icon_horizontal_tooltip
    )

# Run the tests
test_menu_icons_fasthtml_examples()
<div>
  <ul class="menu bg-base-200 rounded-box">
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
  </ul>
  <ul class="menu menu-horizontal bg-base-200 rounded-box">
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
  </ul>
  <ul class="menu bg-base-200 rounded-box w-56">
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>Item 2</a>    </li>
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>Item 1</a>    </li>
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>Item 3</a>    </li>
  </ul>
  <ul class="menu bg-base-200 lg:menu-horizontal rounded-box">
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>Inbox<span class="badge badge-xs">99+</span></a>    </li>
    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>Updates<span class="badge badge-xs badge-warning">NEW</span></a>    </li>
    <li>
<a href="#">Stats<span class="badge badge-xs badge-info"></span></a>    </li>
  </ul>
  <ul class="menu bg-base-200 rounded-box">
    <li>
<a href="#" data-tip="Home" class="tooltip tooltip-right"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
    <li>
<a href="#" data-tip="Details" class="tooltip tooltip-right"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
    <li>
<a href="#" data-tip="Stats" class="tooltip tooltip-right"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
  </ul>
  <ul class="menu menu-horizontal bg-base-200 rounded-box mt-6">
    <li>
<a href="#" data-tip="Home" class="tooltip"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
    <li>
<a href="#" data-tip="Details" class="tooltip"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
    <li>
<a href="#" data-tip="Stats" class="tooltip"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke="currentColor" class="h-5 w-5"><path d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg></a>    </li>
  </ul>
</div>
test_func = test_menu_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_menu_sizes_fasthtml_examples

 test_menu_sizes_fasthtml_examples ()

Test menu sizes from daisyUI v5 documentation.

Exported source
def test_menu_sizes_fasthtml_examples():
    """Test menu sizes from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, A, Div
    from cjm_fasthtml_tailwind.utilities.sizing import w
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
    
    # Extra small menu
    xs_menu = Ul(
        Li(A("Xsmall 1", href="#")),
        Li(A("Xsmall 2", href="#")),
        cls=combine_classes(menu, menu_sizes.xs, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify xs menu
    assert xs_menu.tag == "ul"
    assert "menu" in xs_menu.attrs['class']
    assert "menu-xs" in xs_menu.attrs['class']
    assert "w-56" in xs_menu.attrs['class']
    assert xs_menu.children[0].children[0].children[0] == "Xsmall 1"
    
    # Small menu
    sm_menu = Ul(
        Li(A("Small 1", href="#")),
        Li(A("Small 2", href="#")),
        cls=combine_classes(menu, menu_sizes.sm, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify sm menu
    assert "menu-sm" in sm_menu.attrs['class']
    assert sm_menu.children[0].children[0].children[0] == "Small 1"
    
    # Medium menu
    md_menu = Ul(
        Li(A("Medium 1", href="#")),
        Li(A("Medium 2", href="#")),
        cls=combine_classes(menu, menu_sizes.md, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify md menu
    assert "menu-md" in md_menu.attrs['class']
    assert md_menu.children[0].children[0].children[0] == "Medium 1"
    
    # Large menu
    lg_menu = Ul(
        Li(A("Large 1", href="#")),
        Li(A("Large 2", href="#")),
        cls=combine_classes(menu, menu_sizes.lg, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify lg menu
    assert "menu-lg" in lg_menu.attrs['class']
    assert lg_menu.children[0].children[0].children[0] == "Large 1"
    
    # Extra large menu
    xl_menu = Ul(
        Li(A("Xlarge 1", href="#")),
        Li(A("Xlarge 2", href="#")),
        cls=combine_classes(menu, menu_sizes.xl, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify xl menu
    assert "menu-xl" in xl_menu.attrs['class']
    assert xl_menu.children[0].children[0].children[0] == "Xlarge 1"
    
    return Div(xs_menu, sm_menu, md_menu, lg_menu, xl_menu)

# Run the tests
test_menu_sizes_fasthtml_examples()
<div>
  <ul class="menu menu-xs bg-base-200 rounded-box w-56">
    <li>
<a href="#">Xsmall 1</a>    </li>
    <li>
<a href="#">Xsmall 2</a>    </li>
  </ul>
  <ul class="menu menu-sm bg-base-200 rounded-box w-56">
    <li>
<a href="#">Small 1</a>    </li>
    <li>
<a href="#">Small 2</a>    </li>
  </ul>
  <ul class="menu menu-md bg-base-200 rounded-box w-56">
    <li>
<a href="#">Medium 1</a>    </li>
    <li>
<a href="#">Medium 2</a>    </li>
  </ul>
  <ul class="menu menu-lg bg-base-200 rounded-box w-56">
    <li>
<a href="#">Large 1</a>    </li>
    <li>
<a href="#">Large 2</a>    </li>
  </ul>
  <ul class="menu menu-xl bg-base-200 rounded-box w-56">
    <li>
<a href="#">Xlarge 1</a>    </li>
    <li>
<a href="#">Xlarge 2</a>    </li>
  </ul>
</div>
test_func = test_menu_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_menu_with_title_fasthtml_examples

 test_menu_with_title_fasthtml_examples ()

Test menu with title from daisyUI v5 documentation.

Exported source
def test_menu_with_title_fasthtml_examples():
    """Test menu with title from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, A, H2, Div
    from cjm_fasthtml_tailwind.utilities.sizing import w
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
    
    # Menu with title
    menu_with_title = Ul(
        Li("Title", cls=str(menu_title)),
        Li(A("Item 1", href="#")),
        Li(A("Item 2", href="#")),
        Li(A("Item 3", href="#")),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify menu with title
    assert menu_with_title.tag == "ul"
    assert "menu" in menu_with_title.attrs['class']
    assert menu_with_title.children[0].tag == "li"
    assert "menu-title" in menu_with_title.children[0].attrs['class']
    assert menu_with_title.children[0].children[0] == "Title"
    assert menu_with_title.children[1].children[0].children[0] == "Item 1"
    
    # Menu with title as a parent
    menu_title_parent = Ul(
        Li(
            H2("Title", cls=str(menu_title)),
            Ul(
                Li(A("Item 1", href="#")),
                Li(A("Item 2", href="#")),
                Li(A("Item 3", href="#"))
            )
        ),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify menu with title as parent
    assert menu_title_parent.children[0].tag == "li"
    assert menu_title_parent.children[0].children[0].tag == "h2"
    assert "menu-title" in menu_title_parent.children[0].children[0].attrs['class']
    assert menu_title_parent.children[0].children[0].children[0] == "Title"
    assert menu_title_parent.children[0].children[1].tag == "ul"
    assert len(menu_title_parent.children[0].children[1].children) == 3
    
    return Div(menu_with_title, menu_title_parent)

# Run the tests
test_menu_with_title_fasthtml_examples()
<div>
  <ul class="menu bg-base-200 rounded-box w-56">
    <li class="menu-title">Title</li>
    <li>
<a href="#">Item 1</a>    </li>
    <li>
<a href="#">Item 2</a>    </li>
    <li>
<a href="#">Item 3</a>    </li>
  </ul>
  <ul class="menu bg-base-200 rounded-box w-56">
    <li>
      <h2 class="menu-title">Title</h2>
      <ul>
        <li>
<a href="#">Item 1</a>        </li>
        <li>
<a href="#">Item 2</a>        </li>
        <li>
<a href="#">Item 3</a>        </li>
      </ul>
    </li>
  </ul>
</div>
test_func = test_menu_with_title_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_menu_submenu_fasthtml_examples

 test_menu_submenu_fasthtml_examples ()

Test submenu examples from daisyUI v5 documentation.

Exported source
def test_menu_submenu_fasthtml_examples():
    """Test submenu examples from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, A, Details, Summary, Span, Div
    from cjm_fasthtml_tailwind.utilities.sizing import w
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
    
    # Basic submenu
    basic_submenu = Ul(
        Li(A("Item 1", href="#")),
        Li(
            A("Parent", href="#"),
            Ul(
                Li(A("Submenu 1", href="#")),
                Li(A("Submenu 2", href="#")),
                Li(
                    A("Parent", href="#"),
                    Ul(
                        Li(A("Submenu 1", href="#")),
                        Li(A("Submenu 2", href="#"))
                    )
                )
            )
        ),
        Li(A("Item 3", href="#")),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify basic submenu structure
    assert basic_submenu.tag == "ul"
    assert "menu" in basic_submenu.attrs['class']
    assert basic_submenu.children[1].children[0].children[0] == "Parent"
    assert basic_submenu.children[1].children[1].tag == "ul"
    assert len(basic_submenu.children[1].children[1].children) == 3
    # Nested submenu
    nested = basic_submenu.children[1].children[1].children[2]
    assert nested.children[0].children[0] == "Parent"
    assert nested.children[1].tag == "ul"
    
    # Collapsible submenu
    collapsible_submenu = Ul(
        Li(A("Item 1", href="#")),
        Li(
            Details(
                Summary("Parent"),
                Ul(
                    Li(A("Submenu 1", href="#")),
                    Li(A("Submenu 2", href="#")),
                    Li(
                        Details(
                            Summary("Parent"),
                            Ul(
                                Li(A("Submenu 1", href="#")),
                                Li(A("Submenu 2", href="#"))
                            ),
                            open=True
                        )
                    )
                ),
                open=True
            )
        ),
        Li(A("Item 3", href="#")),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify collapsible submenu
    assert collapsible_submenu.children[1].children[0].tag == "details"
    assert collapsible_submenu.children[1].children[0].attrs['open'] == True
    assert collapsible_submenu.children[1].children[0].children[0].tag == "summary"
    assert collapsible_submenu.children[1].children[0].children[0].children[0] == "Parent"
    
    # Collapsible submenu with class names
    dropdown_submenu = Ul(
        Li(A("Item 1", href="#")),
        Li(
            Span("Parent", cls=str(menu_dropdown_toggle)),
            Ul(
                Li(A("Submenu 1", href="#")),
                Li(A("Submenu 2", href="#")),
                cls=str(menu_dropdown)
            )
        ),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify dropdown submenu
    assert dropdown_submenu.children[1].children[0].tag == "span"
    assert "menu-dropdown-toggle" in dropdown_submenu.children[1].children[0].attrs['class']
    assert dropdown_submenu.children[1].children[1].tag == "ul"
    assert "menu-dropdown" in dropdown_submenu.children[1].children[1].attrs['class']
    
    # Collapsible submenu shown
    dropdown_shown = Ul(
        Li(A("Item 1", href="#")),
        Li(
            Span("Parent", cls=combine_classes(menu_dropdown_toggle, menu_modifiers.dropdown_show)),
            Ul(
                Li(A("Submenu 1", href="#")),
                Li(A("Submenu 2", href="#")),
                cls=combine_classes(menu_dropdown, menu_modifiers.dropdown_show)
            )
        ),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify shown dropdown
    assert "menu-dropdown-show" in dropdown_shown.children[1].children[0].attrs['class']
    assert "menu-dropdown-show" in dropdown_shown.children[1].children[1].attrs['class']
    
    # Horizontal submenu
    horizontal_submenu = Ul(
        Li(A("Item 1", href="#")),
        Li(
            A("Parent", href="#"),
            Ul(
                Li(A("Submenu 1", href="#")),
                Li(A("Submenu 2", href="#"))
            )
        ),
        Li(A("Item 3", href="#")),
        cls=combine_classes(menu, menu_directions.horizontal, bg_dui.base_200, rounded.box)
    )
    
    # Verify horizontal submenu
    assert "menu-horizontal" in horizontal_submenu.attrs['class']
    assert horizontal_submenu.children[1].children[0].children[0] == "Parent"
    assert horizontal_submenu.children[1].children[1].tag == "ul"
    
    return Div(
        basic_submenu,
        collapsible_submenu,
        dropdown_submenu,
        dropdown_shown,
        horizontal_submenu
    )

# Run the tests
test_menu_submenu_fasthtml_examples()
<div>
  <ul class="menu bg-base-200 rounded-box w-56">
    <li>
<a href="#">Item 1</a>    </li>
    <li>
<a href="#">Parent</a>      <ul>
        <li>
<a href="#">Submenu 1</a>        </li>
        <li>
<a href="#">Submenu 2</a>        </li>
        <li>
<a href="#">Parent</a>          <ul>
            <li>
<a href="#">Submenu 1</a>            </li>
            <li>
<a href="#">Submenu 2</a>            </li>
          </ul>
        </li>
      </ul>
    </li>
    <li>
<a href="#">Item 3</a>    </li>
  </ul>
  <ul class="menu bg-base-200 rounded-box w-56">
    <li>
<a href="#">Item 1</a>    </li>
    <li>
<details open><summary>Parent</summary>        <ul>
          <li>
<a href="#">Submenu 1</a>          </li>
          <li>
<a href="#">Submenu 2</a>          </li>
          <li>
<details open><summary>Parent</summary>              <ul>
                <li>
<a href="#">Submenu 1</a>                </li>
                <li>
<a href="#">Submenu 2</a>                </li>
              </ul>
</details>          </li>
        </ul>
</details>    </li>
    <li>
<a href="#">Item 3</a>    </li>
  </ul>
  <ul class="menu bg-base-200 rounded-box w-56">
    <li>
<a href="#">Item 1</a>    </li>
    <li>
<span class="menu-dropdown-toggle">Parent</span>      <ul class="menu-dropdown">
        <li>
<a href="#">Submenu 1</a>        </li>
        <li>
<a href="#">Submenu 2</a>        </li>
      </ul>
    </li>
  </ul>
  <ul class="menu bg-base-200 rounded-box w-56">
    <li>
<a href="#">Item 1</a>    </li>
    <li>
<span class="menu-dropdown-toggle menu-dropdown-show">Parent</span>      <ul class="menu-dropdown menu-dropdown-show">
        <li>
<a href="#">Submenu 1</a>        </li>
        <li>
<a href="#">Submenu 2</a>        </li>
      </ul>
    </li>
  </ul>
  <ul class="menu menu-horizontal bg-base-200 rounded-box">
    <li>
<a href="#">Item 1</a>    </li>
    <li>
<a href="#">Parent</a>      <ul>
        <li>
<a href="#">Submenu 1</a>        </li>
        <li>
<a href="#">Submenu 2</a>        </li>
      </ul>
    </li>
    <li>
<a href="#">Item 3</a>    </li>
  </ul>
</div>
test_func = test_menu_submenu_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_menu_states_fasthtml_examples

 test_menu_states_fasthtml_examples ()

Test menu states and modifiers from daisyUI v5 documentation.

Exported source
def test_menu_states_fasthtml_examples():
    """Test menu states and modifiers from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, A, Div
    from cjm_fasthtml_tailwind.utilities.sizing import w
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_tailwind.utilities.spacing import p
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
    
    # Menu with disabled items
    menu_with_disabled = Ul(
        Li(A("Enabled item", href="#")),
        Li(A("disabled item", href="#"), cls=str(menu_modifiers.disabled)),
        Li(A("disabled item", href="#"), cls=str(menu_modifiers.disabled)),
        cls=combine_classes(menu, bg_dui.base_200, rounded.box, w._56)
    )
    
    # Verify disabled items
    assert menu_with_disabled.tag == "ul"
    assert "menu" in menu_with_disabled.attrs['class']
    assert menu_with_disabled.children[0].children[0].children[0] == "Enabled item"
    assert "menu-disabled" in menu_with_disabled.children[1].attrs['class']
    assert "menu-disabled" in menu_with_disabled.children[2].attrs['class']
    
    # Menu with active item
    menu_with_active = Ul(
        Li(A("Item 1", href="#")),
        Li(A("Item 2", href="#", cls=str(menu_modifiers.active))),
        Li(A("Item 3", href="#")),
        cls=combine_classes(menu, bg_dui.base_200, w._56)
    )
    
    # Verify active item
    assert "menu" in menu_with_active.attrs['class']
    assert menu_with_active.children[1].children[0].tag == "a"
    assert "menu-active" in menu_with_active.children[1].children[0].attrs['class']
    assert menu_with_active.children[1].children[0].children[0] == "Item 2"
    
    # Menu without padding and border radius (using arbitrary selector)
    menu_no_padding = Ul(
        Li(A("Item 1", href="#")),
        Li(A("Item 2", href="#")),
        Li(A("Item 3", href="#")),
        cls=combine_classes(menu, bg_dui.base_200, w._56, "[&_li>*]:rounded-none", p._0)
    )
    
    # Verify no padding menu
    assert "p-0" in menu_no_padding.attrs['class']
    assert "[&_li>*]:rounded-none" in menu_no_padding.attrs['class']
    
    return Div(menu_with_disabled, menu_with_active, menu_no_padding)

# Run the tests
test_menu_states_fasthtml_examples()
<div>
  <ul class="menu bg-base-200 rounded-box w-56">
    <li>
<a href="#">Enabled item</a>    </li>
    <li class="menu-disabled">
<a href="#">disabled item</a>    </li>
    <li class="menu-disabled">
<a href="#">disabled item</a>    </li>
  </ul>
  <ul class="menu bg-base-200 w-56">
    <li>
<a href="#">Item 1</a>    </li>
    <li>
<a href="#" class="menu-active">Item 2</a>    </li>
    <li>
<a href="#">Item 3</a>    </li>
  </ul>
  <ul class="menu bg-base-200 w-56 [&amp;_li&gt;*]:rounded-none p-0">
    <li>
<a href="#">Item 1</a>    </li>
    <li>
<a href="#">Item 2</a>    </li>
    <li>
<a href="#">Item 3</a>    </li>
  </ul>
</div>
test_func = test_menu_states_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_menu_file_tree_fasthtml_examples

 test_menu_file_tree_fasthtml_examples ()

Test file tree menu from daisyUI v5 documentation.

Exported source
def test_menu_file_tree_fasthtml_examples():
    """Test file tree menu from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, A, Details, Summary
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import h, w, max_w
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
    
    # Create reusable icons
    file_icon = Svg(
        Path(
            stroke_linecap="round",
            stroke_linejoin="round",
            d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"
        ),
        xmlns="http://www.w3.org/2000/svg",
        cls=combine_classes(h._4, w._4),
        fill="none",
        viewBox="0 0 24 24",
        stroke_width="1.5",
        stroke="currentColor"
    )
    
    folder_icon = Svg(
        Path(
            stroke_linecap="round",
            stroke_linejoin="round",
            d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z"
        ),
        xmlns="http://www.w3.org/2000/svg",
        cls=combine_classes(h._4, w._4),
        fill="none",
        viewBox="0 0 24 24",
        stroke_width="1.5",
        stroke="currentColor"
    )
    
    image_icon = Svg(
        Path(
            stroke_linecap="round",
            stroke_linejoin="round",
            d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z"
        ),
        xmlns="http://www.w3.org/2000/svg",
        cls=combine_classes(h._4, w._4),
        fill="none",
        viewBox="0 0 24 24",
        stroke_width="1.5",
        stroke="currentColor"
    )
    
    # File tree menu
    file_tree = Ul(
        Li(A(file_icon, "resume.pdf", href="#")),
        Li(
            Details(
                Summary(folder_icon, "My Files"),
                Ul(
                    Li(A(file_icon, "Project-final.psd", href="#")),
                    Li(A(file_icon, "Project-final-2.psd", href="#")),
                    Li(
                        Details(
                            Summary(folder_icon, "Images"),
                            Ul(
                                Li(A(image_icon, "Screenshot1.png", href="#")),
                                Li(A(image_icon, "Screenshot2.png", href="#")),
                                Li(
                                    Details(
                                        Summary(folder_icon, "Others"),
                                        Ul(
                                            Li(A(image_icon, "Screenshot3.png", href="#"))
                                        ),
                                        open=True
                                    )
                                )
                            ),
                            open=True
                        )
                    )
                ),
                open=True
            )
        ),
        Li(A(file_icon, "reports-final-2.pdf", href="#")),
        cls=combine_classes(menu, menu_sizes.xs, bg_dui.base_200, rounded.box, max_w.xs, w.full)
    )
    
    # Verify structure
    assert file_tree.tag == "ul"
    assert "menu" in file_tree.attrs['class']
    assert "menu-xs" in file_tree.attrs['class']
    assert "max-w-xs" in file_tree.attrs['class']
    assert "w-full" in file_tree.attrs['class']
    
    # Verify top-level items
    assert len(file_tree.children) == 3
    assert file_tree.children[0].children[0].children[0].tag == "svg"  # file icon
    assert file_tree.children[0].children[0].children[1] == "resume.pdf"
    
    # Verify nested folder structure
    my_files = file_tree.children[1].children[0]
    assert my_files.tag == "details"
    assert my_files.attrs['open'] == True
    assert my_files.children[0].tag == "summary"
    assert my_files.children[0].children[0].tag == "svg"  # folder icon
    assert my_files.children[0].children[1] == "My Files"
    
    # Verify nested files
    my_files_list = my_files.children[1]
    assert my_files_list.tag == "ul"
    assert len(my_files_list.children) == 3
    assert my_files_list.children[0].children[0].children[1] == "Project-final.psd"
    assert my_files_list.children[1].children[0].children[1] == "Project-final-2.psd"
    
    # Verify images folder
    images_folder = my_files_list.children[2].children[0]
    assert images_folder.tag == "details"
    assert images_folder.attrs['open'] == True
    assert images_folder.children[0].children[1] == "Images"
    
    # Verify images list
    images_list = images_folder.children[1]
    assert images_list.tag == "ul"
    assert len(images_list.children) == 3
    assert images_list.children[0].children[0].children[1] == "Screenshot1.png"
    assert images_list.children[1].children[0].children[1] == "Screenshot2.png"
    
    # Verify Others subfolder
    others_folder = images_list.children[2].children[0]
    assert others_folder.tag == "details"
    assert others_folder.children[0].children[1] == "Others"
    others_list = others_folder.children[1]
    assert others_list.children[0].children[0].children[1] == "Screenshot3.png"
    
    # Verify last file
    assert file_tree.children[2].children[0].children[1] == "reports-final-2.pdf"
    
    return file_tree

# Run the tests
test_menu_file_tree_fasthtml_examples()
<ul class="menu menu-xs bg-base-200 rounded-box max-w-xs w-full">
  <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="h-4 w-4"><path d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" stroke-linecap="round" stroke-linejoin="round"></path></svg>resume.pdf</a>  </li>
  <li>
<details open><summary><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="h-4 w-4"><path d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z" stroke-linecap="round" stroke-linejoin="round"></path></svg>My Files</summary>      <ul>
        <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="h-4 w-4"><path d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" stroke-linecap="round" stroke-linejoin="round"></path></svg>Project-final.psd</a>        </li>
        <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="h-4 w-4"><path d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" stroke-linecap="round" stroke-linejoin="round"></path></svg>Project-final-2.psd</a>        </li>
        <li>
<details open><summary><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="h-4 w-4"><path d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z" stroke-linecap="round" stroke-linejoin="round"></path></svg>Images</summary>            <ul>
              <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="h-4 w-4"><path d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" stroke-linecap="round" stroke-linejoin="round"></path></svg>Screenshot1.png</a>              </li>
              <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="h-4 w-4"><path d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" stroke-linecap="round" stroke-linejoin="round"></path></svg>Screenshot2.png</a>              </li>
              <li>
<details open><summary><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="h-4 w-4"><path d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z" stroke-linecap="round" stroke-linejoin="round"></path></svg>Others</summary>                  <ul>
                    <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="h-4 w-4"><path d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z" stroke-linecap="round" stroke-linejoin="round"></path></svg>Screenshot3.png</a>                    </li>
                  </ul>
</details>              </li>
            </ul>
</details>        </li>
      </ul>
</details>  </li>
  <li>
<a href="#"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="h-4 w-4"><path d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" stroke-linecap="round" stroke-linejoin="round"></path></svg>reports-final-2.pdf</a>  </li>
</ul>
test_func = test_menu_file_tree_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_menu_mega_menu_fasthtml_examples

 test_menu_mega_menu_fasthtml_examples ()

Test mega menu with submenu (responsive) from daisyUI v5 documentation.

Exported source
def test_menu_mega_menu_fasthtml_examples():
    """Test mega menu with submenu (responsive) from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, A
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_tailwind.utilities.sizing import min_w
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
    
    # Mega menu with submenu (responsive)
    mega_menu = Ul(
        Li(
            A("Solutions", href="#"),
            Ul(
                Li(A("Design", href="#")),
                Li(A("Development", href="#")),
                Li(A("Hosting", href="#")),
                Li(A("Domain register", href="#"))
            )
        ),
        Li(
            A("Enterprise", href="#"),
            Ul(
                Li(A("CRM software", href="#")),
                Li(A("Marketing management", href="#")),
                Li(A("Security", href="#")),
                Li(A("Consulting", href="#"))
            )
        ),
        Li(
            A("Products", href="#"),
            Ul(
                Li(A("UI Kit", href="#")),
                Li(A("WordPress themes", href="#")),
                Li(A("WordPress plugins", href="#")),
                Li(
                    A("Open source", href="#"),
                    Ul(
                        Li(A("Auth management system", href="#")),
                        Li(A("VScode theme", href="#")),
                        Li(A("Color picker app", href="#"))
                    )
                )
            )
        ),
        Li(
            A("Company", href="#"),
            Ul(
                Li(A("About us", href="#")),
                Li(A("Contact us", href="#")),
                Li(A("Privacy policy", href="#")),
                Li(A("Press kit", href="#"))
            )
        ),
        cls=combine_classes(menu, menu_directions.horizontal.xl, bg_dui.base_200, rounded.box, min_w.max.lg)
    )
    
    # Verify structure
    assert mega_menu.tag == "ul"
    assert "menu" in mega_menu.attrs['class']
    assert "xl:menu-horizontal" in mega_menu.attrs['class']
    assert "lg:min-w-max" in mega_menu.attrs['class']
    assert "bg-base-200" in mega_menu.attrs['class']
    assert "rounded-box" in mega_menu.attrs['class']
    
    # Verify main menu items
    assert len(mega_menu.children) == 4
    assert mega_menu.children[0].children[0].children[0] == "Solutions"
    assert mega_menu.children[1].children[0].children[0] == "Enterprise"
    assert mega_menu.children[2].children[0].children[0] == "Products"
    assert mega_menu.children[3].children[0].children[0] == "Company"
    
    # Verify Solutions submenu
    solutions_submenu = mega_menu.children[0].children[1]
    assert solutions_submenu.tag == "ul"
    assert len(solutions_submenu.children) == 4
    assert solutions_submenu.children[0].children[0].children[0] == "Design"
    assert solutions_submenu.children[1].children[0].children[0] == "Development"
    assert solutions_submenu.children[2].children[0].children[0] == "Hosting"
    assert solutions_submenu.children[3].children[0].children[0] == "Domain register"
    
    # Verify Enterprise submenu
    enterprise_submenu = mega_menu.children[1].children[1]
    assert len(enterprise_submenu.children) == 4
    assert enterprise_submenu.children[0].children[0].children[0] == "CRM software"
    assert enterprise_submenu.children[1].children[0].children[0] == "Marketing management"
    
    # Verify Products submenu with nested submenu
    products_submenu = mega_menu.children[2].children[1]
    assert len(products_submenu.children) == 4
    assert products_submenu.children[0].children[0].children[0] == "UI Kit"
    assert products_submenu.children[3].children[0].children[0] == "Open source"
    
    # Verify nested Open source submenu
    open_source_submenu = products_submenu.children[3].children[1]
    assert open_source_submenu.tag == "ul"
    assert len(open_source_submenu.children) == 3
    assert open_source_submenu.children[0].children[0].children[0] == "Auth management system"
    assert open_source_submenu.children[1].children[0].children[0] == "VScode theme"
    assert open_source_submenu.children[2].children[0].children[0] == "Color picker app"
    
    # Verify Company submenu
    company_submenu = mega_menu.children[3].children[1]
    assert len(company_submenu.children) == 4
    assert company_submenu.children[0].children[0].children[0] == "About us"
    assert company_submenu.children[3].children[0].children[0] == "Press kit"
    
    return mega_menu

# Run the tests
test_menu_mega_menu_fasthtml_examples()
<ul class="menu xl:menu-horizontal bg-base-200 rounded-box lg:min-w-max">
  <li>
<a href="#">Solutions</a>    <ul>
      <li>
<a href="#">Design</a>      </li>
      <li>
<a href="#">Development</a>      </li>
      <li>
<a href="#">Hosting</a>      </li>
      <li>
<a href="#">Domain register</a>      </li>
    </ul>
  </li>
  <li>
<a href="#">Enterprise</a>    <ul>
      <li>
<a href="#">CRM software</a>      </li>
      <li>
<a href="#">Marketing management</a>      </li>
      <li>
<a href="#">Security</a>      </li>
      <li>
<a href="#">Consulting</a>      </li>
    </ul>
  </li>
  <li>
<a href="#">Products</a>    <ul>
      <li>
<a href="#">UI Kit</a>      </li>
      <li>
<a href="#">WordPress themes</a>      </li>
      <li>
<a href="#">WordPress plugins</a>      </li>
      <li>
<a href="#">Open source</a>        <ul>
          <li>
<a href="#">Auth management system</a>          </li>
          <li>
<a href="#">VScode theme</a>          </li>
          <li>
<a href="#">Color picker app</a>          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
<a href="#">Company</a>    <ul>
      <li>
<a href="#">About us</a>      </li>
      <li>
<a href="#">Contact us</a>      </li>
      <li>
<a href="#">Privacy policy</a>      </li>
      <li>
<a href="#">Press kit</a>      </li>
    </ul>
  </li>
</ul>
test_func = test_menu_mega_menu_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_menu_collapsible_responsive_fasthtml_examples

 test_menu_collapsible_responsive_fasthtml_examples ()

Test collapsible with submenu (responsive) from daisyUI v5 documentation.

Exported source
def test_menu_collapsible_responsive_fasthtml_examples():
    """Test collapsible with submenu (responsive) from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, A, Details, Summary
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_tailwind.utilities.spacing import m
    from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
    
    # Collapsible with submenu (responsive)
    collapsible_responsive = Ul(
        Li(A("Item 1", href="#")),
        Li(
            Details(
                Summary("Parent item"),
                Ul(
                    Li(A("Submenu 1", href="#")),
                    Li(A("Submenu 2", href="#")),
                    Li(
                        Details(
                            Summary("Parent"),
                            Ul(
                                Li(A("item 1", href="#")),
                                Li(A("item 2", href="#"))
                            ),
                            open=True
                        )
                    )
                ),
                open=True
            )
        ),
        Li(A("Item 3", href="#")),
        cls=combine_classes(menu, menu_directions.horizontal.lg, bg_dui.base_200, rounded.box, m.b._64.lg)
    )
    
    # Verify structure
    assert collapsible_responsive.tag == "ul"
    assert "menu" in collapsible_responsive.attrs['class']
    assert "lg:menu-horizontal" in collapsible_responsive.attrs['class']
    assert "bg-base-200" in collapsible_responsive.attrs['class']
    assert "rounded-box" in collapsible_responsive.attrs['class']
    assert "lg:mb-64" in collapsible_responsive.attrs['class']
    
    # Verify main items
    assert len(collapsible_responsive.children) == 3
    assert collapsible_responsive.children[0].children[0].children[0] == "Item 1"
    assert collapsible_responsive.children[2].children[0].children[0] == "Item 3"
    
    # Verify parent item with details
    parent_details = collapsible_responsive.children[1].children[0]
    assert parent_details.tag == "details"
    assert parent_details.attrs['open'] == True
    assert parent_details.children[0].tag == "summary"
    assert parent_details.children[0].children[0] == "Parent item"
    
    # Verify parent submenu
    parent_submenu = parent_details.children[1]
    assert parent_submenu.tag == "ul"
    assert len(parent_submenu.children) == 3
    assert parent_submenu.children[0].children[0].children[0] == "Submenu 1"
    assert parent_submenu.children[1].children[0].children[0] == "Submenu 2"
    
    # Verify nested parent details
    nested_parent = parent_submenu.children[2].children[0]
    assert nested_parent.tag == "details"
    assert nested_parent.attrs['open'] == True
    assert nested_parent.children[0].tag == "summary"
    assert nested_parent.children[0].children[0] == "Parent"
    
    # Verify nested submenu
    nested_submenu = nested_parent.children[1]
    assert nested_submenu.tag == "ul"
    assert len(nested_submenu.children) == 2
    assert nested_submenu.children[0].children[0].children[0] == "item 1"
    assert nested_submenu.children[1].children[0].children[0] == "item 2"
    
    return collapsible_responsive

# Run the tests
test_menu_collapsible_responsive_fasthtml_examples()
<ul class="menu lg:menu-horizontal bg-base-200 rounded-box lg:mb-64">
  <li>
<a href="#">Item 1</a>  </li>
  <li>
<details open><summary>Parent item</summary>      <ul>
        <li>
<a href="#">Submenu 1</a>        </li>
        <li>
<a href="#">Submenu 2</a>        </li>
        <li>
<details open><summary>Parent</summary>            <ul>
              <li>
<a href="#">item 1</a>              </li>
              <li>
<a href="#">item 2</a>              </li>
            </ul>
</details>        </li>
      </ul>
</details>  </li>
  <li>
<a href="#">Item 3</a>  </li>
</ul>
test_func = test_menu_collapsible_responsive_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()