timeline

Timeline component shows a list of events in chronological order.

Base Timeline

The base timeline components:

Exported source
timeline = SingleValueFactory("timeline", "Timeline container component") # Timeline container
timeline_start = SingleValueFactory("timeline-start", "The content inside <li> that will be at the start direction") # Timeline start
timeline_middle = SingleValueFactory("timeline-middle", "The content inside <li> that will be at the middle") # Timeline middle
timeline_end = SingleValueFactory("timeline-end", "The content inside <li> that will be at the end direction") # Timeline end

Timeline Modifiers

Timeline modifier utilities:

Exported source
timeline_modifiers = SimpleFactory(
    {
        "snap_icon": "timeline-snap-icon",
        "box": "timeline-box",
        "compact": "timeline-compact"
    },
    "Timeline modifiers (snap icon to start, box style, compact layout)"
) # Timeline modifiers

Timeline Direction

Timeline direction layouts:

Exported source
timeline_direction = SimpleFactory(
    {
        "horizontal": "timeline-horizontal",
        "vertical": "timeline-vertical"
    },
    "Timeline direction layout (horizontal or vertical)"
) # Timeline direction

Timeline Test Examples


source

test_timeline_basic_examples

 test_timeline_basic_examples ()

Test basic timeline utilities.

Exported source
def test_timeline_basic_examples():
    """Test basic timeline utilities."""
    # Basic components
    assert str(timeline) == "timeline"
    assert str(timeline_start) == "timeline-start"
    assert str(timeline_middle) == "timeline-middle"
    assert str(timeline_end) == "timeline-end"
    
    # With modifiers
    assert str(timeline.hover) == "hover:timeline"
    assert str(timeline_start.md) == "md:timeline-start"
    assert str(timeline_middle.dark) == "dark:timeline-middle"
    assert str(timeline_end.lg) == "lg:timeline-end"

# Run the tests
test_timeline_basic_examples()

source

test_timeline_modifiers_examples

 test_timeline_modifiers_examples ()

Test timeline modifier utilities.

Exported source
def test_timeline_modifiers_examples():
    """Test timeline modifier utilities."""
    assert str(timeline_modifiers.snap_icon) == "timeline-snap-icon"
    assert str(timeline_modifiers.box) == "timeline-box"
    assert str(timeline_modifiers.compact) == "timeline-compact"
    
    # With responsive modifiers
    assert str(timeline_modifiers.snap_icon.hover) == "hover:timeline-snap-icon"
    assert str(timeline_modifiers.box.md) == "md:timeline-box"
    assert str(timeline_modifiers.compact.lg) == "lg:timeline-compact"

# Run the tests
test_timeline_modifiers_examples()

source

test_timeline_direction_examples

 test_timeline_direction_examples ()

Test timeline direction utilities.

Exported source
def test_timeline_direction_examples():
    """Test timeline direction utilities."""
    assert str(timeline_direction.horizontal) == "timeline-horizontal"
    assert str(timeline_direction.vertical) == "timeline-vertical"
    
    # With responsive modifiers
    assert str(timeline_direction.horizontal.md) == "md:timeline-horizontal"
    assert str(timeline_direction.vertical.lg) == "lg:timeline-vertical"

# Run the tests
test_timeline_direction_examples()

source

test_timeline_basic_fasthtml_examples

 test_timeline_basic_fasthtml_examples ()

Test timeline with text on both sides and icon from daisyUI v5 documentation.

Exported source
def test_timeline_basic_fasthtml_examples():
    """Test timeline with text on both sides and icon from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, Div, Hr
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import h, w
    from cjm_fasthtml_tailwind.core.base import combine_classes
    
    # Create checkmark SVG icon as reusable component
    checkmark_icon = Svg(
        Path(
            d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z",
            fill_rule="evenodd",
            clip_rule="evenodd"
        ),
        xmlns="http://www.w3.org/2000/svg",
        viewBox="0 0 20 20",
        fill="currentColor",
        cls=combine_classes(h._5, w._5)
    )
    
    # Timeline with text on both sides and icon
    timeline_both_sides = Ul(
        Li(
            Div("1984", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("First Macintosh computer", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("1998", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("2001", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPod", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("2007", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("2015", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("Apple Watch", cls=combine_classes(timeline_end, timeline_modifiers.box))
        ),
        cls=str(timeline)
    )
    
    # Verify structure
    assert timeline_both_sides.tag == "ul"
    assert "timeline" in timeline_both_sides.attrs['class']
    assert len(timeline_both_sides.children) == 5  # 5 timeline items
    
    # Verify first item structure
    first_item = timeline_both_sides.children[0]
    assert first_item.tag == "li"
    assert len(first_item.children) == 4  # start, middle, end, hr
    assert "timeline-start" in first_item.children[0].attrs['class']
    assert first_item.children[0].children[0] == "1984"
    assert "timeline-middle" in first_item.children[1].attrs['class']
    assert first_item.children[1].children[0].tag == "svg"
    assert "timeline-end" in first_item.children[2].attrs['class']
    assert "timeline-box" in first_item.children[2].attrs['class']
    assert first_item.children[2].children[0] == "First Macintosh computer"
    assert first_item.children[3].tag == "hr"
    
    # Verify second item has hr at beginning
    second_item = timeline_both_sides.children[1]
    assert second_item.children[0].tag == "hr"
    assert "timeline-start" in second_item.children[1].attrs['class']
    assert second_item.children[1].children[0] == "1998"
    
    # Verify last item doesn't have trailing hr
    last_item = timeline_both_sides.children[4]
    assert last_item.children[0].tag == "hr"
    assert len(last_item.children) == 4  # hr, start, middle, end (no trailing hr)
    assert last_item.children[3].children[0] == "Apple Watch"
    
    # Return elements in a Div
    return Div(timeline_both_sides)

# Run the test
test_timeline_basic_fasthtml_examples()
<div>
  <ul class="timeline">
    <li>
      <div class="timeline-start">1984</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">First Macintosh computer</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">1998</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iMac</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">2001</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPod</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">2007</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">2015</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">Apple Watch</div>
    </li>
  </ul>
</div>
test_func = test_timeline_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_timeline_single_side_fasthtml_examples

 test_timeline_single_side_fasthtml_examples ()

Test timeline with bottom side only and top side only from daisyUI v5 documentation.

Exported source
def test_timeline_single_side_fasthtml_examples():
    """Test timeline with bottom side only and top side only from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, Div, Hr
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import h, w
    from cjm_fasthtml_tailwind.core.base import combine_classes
    
    # Create checkmark SVG icon as reusable component
    checkmark_icon = Svg(
        Path(
            d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z",
            fill_rule="evenodd",
            clip_rule="evenodd"
        ),
        xmlns="http://www.w3.org/2000/svg",
        viewBox="0 0 20 20",
        fill="currentColor",
        cls=combine_classes(h._5, w._5)
    )
    
    # Timeline with bottom side only
    timeline_bottom_only = Ul(
        Li(
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("First Macintosh computer", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPod", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("Apple Watch", cls=combine_classes(timeline_end, timeline_modifiers.box))
        ),
        cls=str(timeline)
    )
    
    # Verify bottom only timeline
    assert timeline_bottom_only.tag == "ul"
    assert "timeline" in timeline_bottom_only.attrs['class']
    assert len(timeline_bottom_only.children) == 5
    
    # First item has no timeline-start
    first_item = timeline_bottom_only.children[0]
    assert len(first_item.children) == 3  # middle, end, hr
    assert "timeline-middle" in first_item.children[0].attrs['class']
    assert "timeline-end" in first_item.children[1].attrs['class']
    assert "timeline-box" in first_item.children[1].attrs['class']
    assert first_item.children[1].children[0] == "First Macintosh computer"
    assert first_item.children[2].tag == "hr"
    
    # Timeline with top side only
    timeline_top_only = Ul(
        Li(
            Div("First Macintosh computer", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iMac", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iPod", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iPhone", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div("Apple Watch", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle))
        ),
        cls=str(timeline)
    )
    
    # Verify top only timeline
    assert timeline_top_only.tag == "ul"
    assert "timeline" in timeline_top_only.attrs['class']
    assert len(timeline_top_only.children) == 5
    
    # First item has no starting hr
    first_item = timeline_top_only.children[0]
    assert len(first_item.children) == 3  # start, middle, hr
    assert "timeline-start" in first_item.children[0].attrs['class']
    assert "timeline-box" in first_item.children[0].attrs['class']
    assert first_item.children[0].children[0] == "First Macintosh computer"
    assert "timeline-middle" in first_item.children[1].attrs['class']
    assert first_item.children[2].tag == "hr"
    
    # Last item has no trailing hr
    last_item = timeline_top_only.children[4]
    assert last_item.children[0].tag == "hr"
    assert len(last_item.children) == 3  # hr, start, middle (no trailing hr)
    assert "timeline-start" in last_item.children[1].attrs['class']
    assert last_item.children[1].children[0] == "Apple Watch"
    
    # Return both elements in a Div
    return Div(timeline_bottom_only, timeline_top_only)

# Run the test
test_timeline_single_side_fasthtml_examples()
<div>
  <ul class="timeline">
    <li>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">First Macintosh computer</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iMac</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPod</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">Apple Watch</div>
    </li>
  </ul>
  <ul class="timeline">
    <li>
      <div class="timeline-start timeline-box">First Macintosh computer</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">iMac</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">iPod</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">iPhone</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">Apple Watch</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
    </li>
  </ul>
</div>
test_func = test_timeline_single_side_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_timeline_alternating_fasthtml_examples

 test_timeline_alternating_fasthtml_examples ()

Test timeline with different sides and colorful lines from daisyUI v5 documentation.

Exported source
def test_timeline_alternating_fasthtml_examples():
    """Test timeline with different sides and colorful lines from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, Div, Hr
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import h, w
    from cjm_fasthtml_tailwind.core.base import combine_classes
    from cjm_fasthtml_daisyui.utilities.semantic_colors import text_dui, bg_dui
    
    # Create checkmark SVG icon as reusable component
    checkmark_icon = Svg(
        Path(
            d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z",
            fill_rule="evenodd",
            clip_rule="evenodd"
        ),
        xmlns="http://www.w3.org/2000/svg",
        viewBox="0 0 20 20",
        fill="currentColor",
        cls=combine_classes(h._5, w._5)
    )
    
    # Timeline with different sides
    timeline_different_sides = Ul(
        Li(
            Div("First Macintosh computer", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iPod", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("Apple Watch", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle))
        ),
        cls=str(timeline)
    )
    
    # Verify different sides timeline
    assert timeline_different_sides.tag == "ul"
    assert "timeline" in timeline_different_sides.attrs['class']
    assert len(timeline_different_sides.children) == 5
    
    # First item - start side
    first_item = timeline_different_sides.children[0]
    assert "timeline-start" in first_item.children[0].attrs['class']
    assert "timeline-box" in first_item.children[0].attrs['class']
    assert first_item.children[0].children[0] == "First Macintosh computer"
    
    # Second item - end side
    second_item = timeline_different_sides.children[1]
    assert "timeline-middle" in second_item.children[1].attrs['class']
    assert "timeline-end" in second_item.children[2].attrs['class']
    assert second_item.children[2].children[0] == "iMac"
    
    # Third item - start side
    third_item = timeline_different_sides.children[2]
    assert "timeline-start" in third_item.children[1].attrs['class']
    assert third_item.children[1].children[0] == "iPod"
    
    # Timeline with colorful lines
    # Create colored checkmark icons
    checkmark_icon_primary = Svg(
        Path(
            d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z",
            fill_rule="evenodd",
            clip_rule="evenodd"
        ),
        xmlns="http://www.w3.org/2000/svg",
        viewBox="0 0 20 20",
        fill="currentColor",
        cls=combine_classes(text_dui.primary, h._5, w._5)
    )
    
    timeline_colorful = Ul(
        Li(
            Div("First Macintosh computer", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon_primary, cls=str(timeline_middle)),
            Hr(cls=str(bg_dui.primary))
        ),
        Li(
            Hr(cls=str(bg_dui.primary)),
            Div(checkmark_icon_primary, cls=str(timeline_middle)),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr(cls=str(bg_dui.primary))
        ),
        Li(
            Hr(cls=str(bg_dui.primary)),
            Div("iPod", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon_primary, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("Apple Watch", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle))
        ),
        cls=str(timeline)
    )
    
    # Verify colorful timeline
    assert timeline_colorful.tag == "ul"
    assert "timeline" in timeline_colorful.attrs['class']
    
    # First item has primary colored hr
    first_item = timeline_colorful.children[0]
    assert first_item.children[2].tag == "hr"
    assert "bg-primary" in first_item.children[2].attrs['class']
    
    # Check primary colored icon
    assert "text-primary" in first_item.children[1].children[0].attrs['class']
    
    # Third item switches from primary to default
    third_item = timeline_colorful.children[2]
    assert "bg-primary" in third_item.children[0].attrs['class']  # Incoming hr is primary
    assert 'class' not in third_item.children[3].attrs or "bg-primary" not in third_item.children[3].attrs.get('class', '')  # Outgoing hr is default
    
    # Return both elements in a Div
    return Div(timeline_different_sides, timeline_colorful)

# Run the test
test_timeline_alternating_fasthtml_examples()
<div>
  <ul class="timeline">
    <li>
      <div class="timeline-start timeline-box">First Macintosh computer</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iMac</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">iPod</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">Apple Watch</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
    </li>
  </ul>
  <ul class="timeline">
    <li>
      <div class="timeline-start timeline-box">First Macintosh computer</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="text-primary h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr class="bg-primary">    </li>
    <li>
<hr class="bg-primary">      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="text-primary h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iMac</div>
<hr class="bg-primary">    </li>
    <li>
<hr class="bg-primary">      <div class="timeline-start timeline-box">iPod</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="text-primary h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">Apple Watch</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
    </li>
  </ul>
</div>
test_func = test_timeline_alternating_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_timeline_without_icons_fasthtml_examples

 test_timeline_without_icons_fasthtml_examples ()

Test timeline without icons from daisyUI v5 documentation.

Exported source
def test_timeline_without_icons_fasthtml_examples():
    """Test timeline without icons from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, Div, Hr
    from cjm_fasthtml_tailwind.core.base import combine_classes
    
    # Timeline without icons
    timeline_no_icons = Ul(
        Li(
            Div("First Macintosh computer", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iPod", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("Apple Watch", cls=combine_classes(timeline_start, timeline_modifiers.box))
        ),
        cls=str(timeline)
    )
    
    # Verify timeline without icons
    assert timeline_no_icons.tag == "ul"
    assert "timeline" in timeline_no_icons.attrs['class']
    assert len(timeline_no_icons.children) == 5
    
    # First item - only start and hr, no middle
    first_item = timeline_no_icons.children[0]
    assert len(first_item.children) == 2  # start, hr
    assert "timeline-start" in first_item.children[0].attrs['class']
    assert "timeline-box" in first_item.children[0].attrs['class']
    assert first_item.children[0].children[0] == "First Macintosh computer"
    assert first_item.children[1].tag == "hr"
    
    # Second item - alternates to end side
    second_item = timeline_no_icons.children[1]
    assert len(second_item.children) == 3  # hr, end, hr
    assert second_item.children[0].tag == "hr"
    assert "timeline-end" in second_item.children[1].attrs['class']
    assert "timeline-box" in second_item.children[1].attrs['class']
    assert second_item.children[1].children[0] == "iMac"
    assert second_item.children[2].tag == "hr"
    
    # Third item - back to start side
    third_item = timeline_no_icons.children[2]
    assert "timeline-start" in third_item.children[1].attrs['class']
    assert third_item.children[1].children[0] == "iPod"
    
    # Fourth item - end side
    fourth_item = timeline_no_icons.children[3]
    assert "timeline-end" in fourth_item.children[1].attrs['class']
    assert fourth_item.children[1].children[0] == "iPhone"
    
    # Last item - no trailing hr
    last_item = timeline_no_icons.children[4]
    assert len(last_item.children) == 2  # hr, start (no trailing hr)
    assert last_item.children[0].tag == "hr"
    assert "timeline-start" in last_item.children[1].attrs['class']
    assert last_item.children[1].children[0] == "Apple Watch"
    
    # Return element in a Div
    return Div(timeline_no_icons)

# Run the test
test_timeline_without_icons_fasthtml_examples()
<div>
  <ul class="timeline">
    <li>
      <div class="timeline-start timeline-box">First Macintosh computer</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-end timeline-box">iMac</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">iPod</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">Apple Watch</div>
    </li>
  </ul>
</div>
test_func = test_timeline_without_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_timeline_vertical_fasthtml_examples

 test_timeline_vertical_fasthtml_examples ()

Test vertical timeline variations from daisyUI v5 documentation.

Exported source
def test_timeline_vertical_fasthtml_examples():
    """Test vertical timeline variations from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, Div, Hr
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import h, w
    from cjm_fasthtml_tailwind.core.base import combine_classes
    from cjm_fasthtml_daisyui.utilities.semantic_colors import text_dui, bg_dui
    
    # Create checkmark SVG icon as reusable component
    checkmark_icon = Svg(
        Path(
            d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z",
            fill_rule="evenodd",
            clip_rule="evenodd"
        ),
        xmlns="http://www.w3.org/2000/svg",
        viewBox="0 0 20 20",
        fill="currentColor",
        cls=combine_classes(h._5, w._5)
    )
    
    # Vertical timeline with text on both sides and icon
    vertical_timeline_both = Ul(
        Li(
            Div("1984", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("First Macintosh computer", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("1998", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("2001", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPod", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("2007", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("2015", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("Apple Watch", cls=combine_classes(timeline_end, timeline_modifiers.box))
        ),
        cls=combine_classes(timeline, timeline_direction.vertical)
    )
    
    # Verify vertical timeline with both sides
    assert vertical_timeline_both.tag == "ul"
    assert "timeline" in vertical_timeline_both.attrs['class']
    assert "timeline-vertical" in vertical_timeline_both.attrs['class']
    assert len(vertical_timeline_both.children) == 5
    
    # Vertical timeline with right side only
    vertical_timeline_right = Ul(
        Li(
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("First Macintosh computer", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPod", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("Apple Watch", cls=combine_classes(timeline_end, timeline_modifiers.box))
        ),
        cls=combine_classes(timeline, timeline_direction.vertical)
    )
    
    # Verify vertical timeline with right side only
    assert "timeline" in vertical_timeline_right.attrs['class']
    assert "timeline-vertical" in vertical_timeline_right.attrs['class']
    first_item = vertical_timeline_right.children[0]
    assert len(first_item.children) == 3  # middle, end, hr (no start)
    
    # Vertical timeline with left side only
    vertical_timeline_left = Ul(
        Li(
            Div("First Macintosh computer", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iMac", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iPod", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iPhone", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div("Apple Watch", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle))
        ),
        cls=combine_classes(timeline, timeline_direction.vertical)
    )
    
    # Verify vertical timeline with left side only
    assert "timeline" in vertical_timeline_left.attrs['class']
    assert "timeline-vertical" in vertical_timeline_left.attrs['class']
    first_item = vertical_timeline_left.children[0]
    assert len(first_item.children) == 3  # start, middle, hr (no end)
    assert "timeline-start" in first_item.children[0].attrs['class']
    
    # Return all elements in a Div
    return Div(vertical_timeline_both, vertical_timeline_right, vertical_timeline_left)

# Run the test
test_timeline_vertical_fasthtml_examples()
<div>
  <ul class="timeline timeline-vertical">
    <li>
      <div class="timeline-start">1984</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">First Macintosh computer</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">1998</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iMac</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">2001</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPod</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">2007</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">2015</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">Apple Watch</div>
    </li>
  </ul>
  <ul class="timeline timeline-vertical">
    <li>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">First Macintosh computer</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iMac</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPod</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">Apple Watch</div>
    </li>
  </ul>
  <ul class="timeline timeline-vertical">
    <li>
      <div class="timeline-start timeline-box">First Macintosh computer</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">iMac</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">iPod</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">iPhone</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">Apple Watch</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
    </li>
  </ul>
</div>
test_func = test_timeline_vertical_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_timeline_vertical_advanced_fasthtml_examples

 test_timeline_vertical_advanced_fasthtml_examples ()

Test vertical timeline with different sides, colorful lines, and without icons from daisyUI v5 documentation.

Exported source
def test_timeline_vertical_advanced_fasthtml_examples():
    """Test vertical timeline with different sides, colorful lines, and without icons from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, Div, Hr
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import h, w
    from cjm_fasthtml_tailwind.core.base import combine_classes
    from cjm_fasthtml_daisyui.utilities.semantic_colors import text_dui, bg_dui
    
    # Create checkmark SVG icon as reusable component
    checkmark_icon = Svg(
        Path(
            d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z",
            fill_rule="evenodd",
            clip_rule="evenodd"
        ),
        xmlns="http://www.w3.org/2000/svg",
        viewBox="0 0 20 20",
        fill="currentColor",
        cls=combine_classes(h._5, w._5)
    )
    
    # Vertical timeline with different sides
    vertical_timeline_alternating = Ul(
        Li(
            Div("First Macintosh computer", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iPod", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("Apple Watch", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle))
        ),
        cls=combine_classes(timeline, timeline_direction.vertical)
    )
    
    # Verify vertical timeline with alternating sides
    assert "timeline" in vertical_timeline_alternating.attrs['class']
    assert "timeline-vertical" in vertical_timeline_alternating.attrs['class']
    
    # First item - start side
    assert "timeline-start" in vertical_timeline_alternating.children[0].children[0].attrs['class']
    # Second item - end side
    assert "timeline-end" in vertical_timeline_alternating.children[1].children[2].attrs['class']
    # Third item - start side
    assert "timeline-start" in vertical_timeline_alternating.children[2].children[1].attrs['class']
    
    # Vertical timeline with colorful lines
    checkmark_icon_primary = Svg(
        Path(
            d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z",
            fill_rule="evenodd",
            clip_rule="evenodd"
        ),
        xmlns="http://www.w3.org/2000/svg",
        viewBox="0 0 20 20",
        fill="currentColor",
        cls=combine_classes(text_dui.primary, h._5, w._5)
    )
    
    vertical_timeline_colorful = Ul(
        Li(
            Div("First Macintosh computer", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon_primary, cls=str(timeline_middle)),
            Hr(cls=str(bg_dui.primary))
        ),
        Li(
            Hr(cls=str(bg_dui.primary)),
            Div(checkmark_icon_primary, cls=str(timeline_middle)),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr(cls=str(bg_dui.primary))
        ),
        Li(
            Hr(cls=str(bg_dui.primary)),
            Div("iPod", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon_primary, cls=str(timeline_middle)),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("Apple Watch", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Div(checkmark_icon, cls=str(timeline_middle))
        ),
        cls=combine_classes(timeline, timeline_direction.vertical)
    )
    
    # Verify vertical timeline with colorful lines
    assert "timeline" in vertical_timeline_colorful.attrs['class']
    assert "timeline-vertical" in vertical_timeline_colorful.attrs['class']
    # First three items have primary colored hrs
    assert "bg-primary" in vertical_timeline_colorful.children[0].children[2].attrs['class']
    assert "bg-primary" in vertical_timeline_colorful.children[1].children[0].attrs['class']
    assert "bg-primary" in vertical_timeline_colorful.children[2].children[0].attrs['class']
    # Primary colored icons
    assert "text-primary" in vertical_timeline_colorful.children[0].children[1].children[0].attrs['class']
    
    # Vertical timeline without icons
    vertical_timeline_no_icons = Ul(
        Li(
            Div("First Macintosh computer", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iPod", cls=combine_classes(timeline_start, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("Apple Watch", cls=combine_classes(timeline_start, timeline_modifiers.box))
        ),
        cls=combine_classes(timeline, timeline_direction.vertical)
    )
    
    # Verify vertical timeline without icons
    assert "timeline" in vertical_timeline_no_icons.attrs['class']
    assert "timeline-vertical" in vertical_timeline_no_icons.attrs['class']
    # Items have no middle section
    assert len(vertical_timeline_no_icons.children[0].children) == 2  # start, hr
    assert len(vertical_timeline_no_icons.children[1].children) == 3  # hr, end, hr
    # Items alternate between start and end
    assert "timeline-start" in vertical_timeline_no_icons.children[0].children[0].attrs['class']
    assert "timeline-end" in vertical_timeline_no_icons.children[1].children[1].attrs['class']
    assert "timeline-start" in vertical_timeline_no_icons.children[2].children[1].attrs['class']
    
    # Return all elements in a Div
    return Div(vertical_timeline_alternating, vertical_timeline_colorful, vertical_timeline_no_icons)

# Run the test
test_timeline_vertical_advanced_fasthtml_examples()
<div>
  <ul class="timeline timeline-vertical">
    <li>
      <div class="timeline-start timeline-box">First Macintosh computer</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iMac</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">iPod</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">Apple Watch</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
    </li>
  </ul>
  <ul class="timeline timeline-vertical">
    <li>
      <div class="timeline-start timeline-box">First Macintosh computer</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="text-primary h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr class="bg-primary">    </li>
    <li>
<hr class="bg-primary">      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="text-primary h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iMac</div>
<hr class="bg-primary">    </li>
    <li>
<hr class="bg-primary">      <div class="timeline-start timeline-box">iPod</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="text-primary h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">Apple Watch</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
    </li>
  </ul>
  <ul class="timeline timeline-vertical">
    <li>
      <div class="timeline-start timeline-box">First Macintosh computer</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-end timeline-box">iMac</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">iPod</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start timeline-box">Apple Watch</div>
    </li>
  </ul>
</div>
test_func = test_timeline_vertical_advanced_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_timeline_responsive_fasthtml_examples

 test_timeline_responsive_fasthtml_examples ()

Test responsive timeline (vertical by default, horizontal on large screen) from daisyUI v5 documentation.

Exported source
def test_timeline_responsive_fasthtml_examples():
    """Test responsive timeline (vertical by default, horizontal on large screen) from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, Div, Hr
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import h, w
    from cjm_fasthtml_tailwind.core.base import combine_classes
    
    # Create checkmark SVG icon as reusable component
    checkmark_icon = Svg(
        Path(
            d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z",
            fill_rule="evenodd",
            clip_rule="evenodd"
        ),
        xmlns="http://www.w3.org/2000/svg",
        viewBox="0 0 20 20",
        fill="currentColor",
        cls=combine_classes(h._5, w._5)
    )
    
    # Responsive: vertical by default, horizontal on large screen
    responsive_timeline = Ul(
        Li(
            Div("1984", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("First Macintosh computer", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("1998", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iMac", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("2001", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPod", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("2007", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("iPhone", cls=combine_classes(timeline_end, timeline_modifiers.box)),
            Hr()
        ),
        Li(
            Hr(),
            Div("2015", cls=str(timeline_start)),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div("Apple Watch", cls=combine_classes(timeline_end, timeline_modifiers.box))
        ),
        cls=combine_classes(timeline, timeline_direction.vertical, timeline_direction.horizontal.lg)
    )
    
    # Verify responsive timeline
    assert responsive_timeline.tag == "ul"
    assert "timeline" in responsive_timeline.attrs['class']
    assert "timeline-vertical" in responsive_timeline.attrs['class']
    assert "lg:timeline-horizontal" in responsive_timeline.attrs['class']
    assert len(responsive_timeline.children) == 5
    
    # Verify structure is same as basic timeline
    first_item = responsive_timeline.children[0]
    assert "timeline-start" in first_item.children[0].attrs['class']
    assert first_item.children[0].children[0] == "1984"
    assert "timeline-middle" in first_item.children[1].attrs['class']
    assert "timeline-end" in first_item.children[2].attrs['class']
    assert first_item.children[2].children[0] == "First Macintosh computer"
    
    # Return element in a Div
    return Div(responsive_timeline)

# Run the test
test_timeline_responsive_fasthtml_examples()
<div>
  <ul class="timeline timeline-vertical lg:timeline-horizontal">
    <li>
      <div class="timeline-start">1984</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">First Macintosh computer</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">1998</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iMac</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">2001</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPod</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">2007</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">iPhone</div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-start">2015</div>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end timeline-box">Apple Watch</div>
    </li>
  </ul>
</div>
test_func = test_timeline_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_timeline_snap_icon_fasthtml_examples

 test_timeline_snap_icon_fasthtml_examples ()

Test timeline with icon snapped to the start from daisyUI v5 documentation.

Exported source
def test_timeline_snap_icon_fasthtml_examples():
    """Test timeline with icon snapped to the start from daisyUI v5 documentation."""
    from fasthtml.common import Ul, Li, Div, Hr, Time
    from fasthtml.svg import Svg, Path
    from cjm_fasthtml_tailwind.utilities.sizing import h, w
    from cjm_fasthtml_tailwind.utilities.spacing import m
    from cjm_fasthtml_tailwind.utilities.typography import font_size, font_weight, font_family, text_color, italic, text_align
    from cjm_fasthtml_tailwind.core.base import combine_classes
    
    # Create checkmark SVG icon as reusable component
    checkmark_icon = Svg(
        Path(
            d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z",
            fill_rule="evenodd",
            clip_rule="evenodd"
        ),
        xmlns="http://www.w3.org/2000/svg",
        viewBox="0 0 20 20",
        fill="currentColor",
        cls=combine_classes(h._5, w._5)
    )
    
    # Timeline with icon snapped to the start
    timeline_snap_icon = Ul(
        Li(
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div(
                Time("1984", cls=combine_classes(font_family.mono, italic)),
                Div("First Macintosh computer", cls=combine_classes(font_size.lg, font_weight.black)),
                "The Apple Macintosh—later rebranded as the Macintosh 128K—is the original Apple Macintosh personal computer. It played a pivotal role in establishing desktop publishing as a general office function. The motherboard, a 9 in (23 cm) CRT monitor, and a floppy drive were housed in a beige case with integrated carrying handle; it came with a keyboard and single-button mouse.",
                cls=combine_classes(timeline_start, m.b._10, text_align.end.md)
            ),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div(
                Time("1998", cls=combine_classes(font_family.mono, italic)),
                Div("iMac", cls=combine_classes(font_size.lg, font_weight.black)),
                "iMac is a family of all-in-one Mac desktop computers designed and built by Apple Inc. It has been the primary part of Apple's consumer desktop offerings since its debut in August 1998, and has evolved through seven distinct forms",
                cls=combine_classes(timeline_end, m.b._10.md)
            ),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div(
                Time("2001", cls=combine_classes(font_family.mono, italic)),
                Div("iPod", cls=combine_classes(font_size.lg, font_weight.black)),
                "The iPod is a discontinued series of portable media players and multi-purpose mobile devices designed and marketed by Apple Inc. The first version was released on October 23, 2001, about 8+1⁄2 months after the Macintosh version of iTunes was released. Apple sold an estimated 450 million iPod products as of 2022. Apple discontinued the iPod product line on May 10, 2022. At over 20 years, the iPod brand is the oldest to be discontinued by Apple",
                cls=combine_classes(timeline_start, m.b._10, text_align.end.md)
            ),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div(
                Time("2007", cls=combine_classes(font_family.mono, italic)),
                Div("iPhone", cls=combine_classes(font_size.lg, font_weight.black)),
                "iPhone is a line of smartphones produced by Apple Inc. that use Apple's own iOS mobile operating system. The first-generation iPhone was announced by then-Apple CEO Steve Jobs on January 9, 2007. Since then, Apple has annually released new iPhone models and iOS updates. As of November 1, 2018, more than 2.2 billion iPhones had been sold. As of 2022, the iPhone accounts for 15.6% of global smartphone market share",
                cls=combine_classes(timeline_end, m.b._10.md)
            ),
            Hr()
        ),
        Li(
            Hr(),
            Div(checkmark_icon, cls=str(timeline_middle)),
            Div(
                Time("2015", cls=combine_classes(font_family.mono, italic)),
                Div("Apple Watch", cls=combine_classes(font_size.lg, font_weight.black)),
                "The Apple Watch is a line of smartwatches produced by Apple Inc. It incorporates fitness tracking, health-oriented capabilities, and wireless telecommunication, and integrates with iOS and other Apple products and services",
                cls=combine_classes(timeline_start, m.b._10, text_align.end.md)
            )
        ),
        cls=combine_classes(
            timeline,
            timeline_modifiers.snap_icon,
            timeline_modifiers.compact.max_md, 
            timeline_direction.vertical
        )
    )
    
    # Verify timeline with snap icon
    assert timeline_snap_icon.tag == "ul"
    assert "timeline" in timeline_snap_icon.attrs['class']
    assert "timeline-snap-icon" in timeline_snap_icon.attrs['class']
    assert "max-md:timeline-compact" in timeline_snap_icon.attrs['class']
    assert "timeline-vertical" in timeline_snap_icon.attrs['class']
    
    # Verify first item structure with detailed content
    first_item = timeline_snap_icon.children[0]
    assert len(first_item.children) == 3  # middle, start (with content), hr
    assert "timeline-middle" in first_item.children[0].attrs['class']
    
    start_content = first_item.children[1]
    assert "timeline-start" in start_content.attrs['class']
    assert "mb-10" in start_content.attrs['class']
    assert "md:text-end" in start_content.attrs['class']
    
    # Check Time element
    assert start_content.children[0].tag == "time"
    assert "font-mono" in start_content.children[0].attrs['class']
    assert "italic" in start_content.children[0].attrs['class']
    assert start_content.children[0].children[0] == "1984"
    
    # Check title
    assert start_content.children[1].tag == "div"
    assert "text-lg" in start_content.children[1].attrs['class']
    assert "font-black" in start_content.children[1].attrs['class']
    assert start_content.children[1].children[0] == "First Macintosh computer"
    
    # Check description text
    assert "The Apple Macintosh" in start_content.children[2]
    
    # Verify alternating pattern (start -> end -> start -> end -> start)
    assert "timeline-start" in timeline_snap_icon.children[0].children[1].attrs['class']
    assert "timeline-end" in timeline_snap_icon.children[1].children[2].attrs['class']
    assert "timeline-start" in timeline_snap_icon.children[2].children[2].attrs['class']
    assert "timeline-end" in timeline_snap_icon.children[3].children[2].attrs['class']
    assert "timeline-start" in timeline_snap_icon.children[4].children[2].attrs['class']
    
    # Return element in a Div
    return Div(timeline_snap_icon)

# Run the test
test_timeline_snap_icon_fasthtml_examples()
<div>
  <ul class="timeline timeline-snap-icon max-md:timeline-compact timeline-vertical">
    <li>
      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-start mb-10 md:text-end">
<time class="font-mono italic">1984</time>        <div class="text-lg font-black">First Macintosh computer</div>
The Apple Macintosh—later rebranded as the Macintosh 128K—is the original Apple Macintosh personal computer. It played a pivotal role in establishing desktop publishing as a general office function. The motherboard, a 9 in (23 cm) CRT monitor, and a floppy drive were housed in a beige case with integrated carrying handle; it came with a keyboard and single-button mouse.      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end md:mb-10">
<time class="font-mono italic">1998</time>        <div class="text-lg font-black">iMac</div>
iMac is a family of all-in-one Mac desktop computers designed and built by Apple Inc. It has been the primary part of Apple's consumer desktop offerings since its debut in August 1998, and has evolved through seven distinct forms      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-start mb-10 md:text-end">
<time class="font-mono italic">2001</time>        <div class="text-lg font-black">iPod</div>
The iPod is a discontinued series of portable media players and multi-purpose mobile devices designed and marketed by Apple Inc. The first version was released on October 23, 2001, about 8+1⁄2 months after the Macintosh version of iTunes was released. Apple sold an estimated 450 million iPod products as of 2022. Apple discontinued the iPod product line on May 10, 2022. At over 20 years, the iPod brand is the oldest to be discontinued by Apple      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-end md:mb-10">
<time class="font-mono italic">2007</time>        <div class="text-lg font-black">iPhone</div>
iPhone is a line of smartphones produced by Apple Inc. that use Apple's own iOS mobile operating system. The first-generation iPhone was announced by then-Apple CEO Steve Jobs on January 9, 2007. Since then, Apple has annually released new iPhone models and iOS updates. As of November 1, 2018, more than 2.2 billion iPhones had been sold. As of 2022, the iPhone accounts for 15.6% of global smartphone market share      </div>
<hr>    </li>
    <li>
<hr>      <div class="timeline-middle">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 20 20" fill="currentColor" class="h-5 w-5"><path d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" fill-rule="evenodd" clip-rule="evenodd"></path></svg>      </div>
      <div class="timeline-start mb-10 md:text-end">
<time class="font-mono italic">2015</time>        <div class="text-lg font-black">Apple Watch</div>
The Apple Watch is a line of smartwatches produced by Apple Inc. It incorporates fitness tracking, health-oriented capabilities, and wireless telecommunication, and integrates with iOS and other Apple products and services      </div>
    </li>
  </ul>
</div>
test_func = test_timeline_snap_icon_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()