pagination

Pagination is a group of buttons that allow the user to navigate between a set of related content.

Note on Pagination Components

For pagination, we use join component to show multiple links or buttons next to each other.

All joing utilities are already defined in the cjm_fasthtml_daisyui.components.layout.join module.

Pagination Test Examples


source

test_pagination_basic_examples

 test_pagination_basic_examples ()

Test basic pagination utilities.

Exported source
def test_pagination_basic_examples():
    """Test basic pagination utilities."""
    # Basic join
    assert str(join) == "join"
    assert str(join_item) == "join-item"
    
    # Test with modifiers
    assert str(join.hover) == "hover:join"
    assert str(join.md) == "md:join"
    assert str(join.dark) == "dark:join"

    assert str(join_item.hover) == "hover:join-item"
    assert str(join_item.md) == "md:join-item"
    assert str(join_item.dark) == "dark:join-item"

# Run the tests
test_pagination_basic_examples()

source

test_pagination_directions_examples

 test_pagination_directions_examples ()

Test join directions variants.

Exported source
def test_pagination_directions_examples():
    """Test join directions variants."""
    assert str(join_directions.vertical) == "join-vertical"
    assert str(join_directions.horizontal) == "join-horizontal"

# Run the tests
test_pagination_directions_examples()

source

test_pagination_basic_fasthtml_examples

 test_pagination_basic_fasthtml_examples ()

Test pagination with an active button from daisyUI v5 documentation.

Exported source
def test_pagination_basic_fasthtml_examples():
    """Test pagination with an active button from daisyUI v5 documentation."""
    from fasthtml.common import Div, Button
    from cjm_fasthtml_tailwind.core.base import combine_classes
    from cjm_fasthtml_daisyui.components.actions.button import btn, btn_behaviors
    
    # Pagination with an active button
    pagination = Div(
        Button("1", cls=combine_classes(join_item, btn)),
        Button("2", cls=combine_classes(join_item, btn, btn_behaviors.active)),
        Button("3", cls=combine_classes(join_item, btn)),
        Button("4", cls=combine_classes(join_item, btn)),
        cls=str(join)
    )
    
    # Verify structure
    assert pagination.tag == "div"
    assert pagination.attrs['class'] == "join"
    
    # Verify buttons
    assert len(pagination.children) == 4
    
    # First button (inactive)
    first_button = pagination.children[0]
    assert first_button.tag == "button"
    assert "join-item" in first_button.attrs['class']
    assert "btn" in first_button.attrs['class']
    assert "btn-active" not in first_button.attrs['class']
    assert first_button.children[0] == "1"
    
    # Second button (active)
    second_button = pagination.children[1]
    assert second_button.tag == "button"
    assert "join-item" in second_button.attrs['class']
    assert "btn" in second_button.attrs['class']
    assert "btn-active" in second_button.attrs['class']
    assert second_button.children[0] == "2"
    
    # Third button (inactive)
    third_button = pagination.children[2]
    assert third_button.tag == "button"
    assert "join-item" in third_button.attrs['class']
    assert "btn" in third_button.attrs['class']
    assert "btn-active" not in third_button.attrs['class']
    assert third_button.children[0] == "3"
    
    # Fourth button (inactive)
    fourth_button = pagination.children[3]
    assert fourth_button.tag == "button"
    assert "join-item" in fourth_button.attrs['class']
    assert "btn" in fourth_button.attrs['class']
    assert "btn-active" not in fourth_button.attrs['class']
    assert fourth_button.children[0] == "4"
    
    return pagination

# Run the tests
test_pagination_basic_fasthtml_examples()
<div class="join">
<button class="join-item btn">1</button><button class="join-item btn btn-active">2</button><button class="join-item btn">3</button><button class="join-item btn">4</button></div>
test_func = test_pagination_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_pagination_sizes_fasthtml_examples

 test_pagination_sizes_fasthtml_examples ()

Test pagination with different button sizes from daisyUI v5 documentation.

Exported source
def test_pagination_sizes_fasthtml_examples():
    """Test pagination with different button sizes from daisyUI v5 documentation."""
    from fasthtml.common import Div, Button
    from cjm_fasthtml_tailwind.core.base import combine_classes
    from cjm_fasthtml_daisyui.components.actions.button import btn, btn_behaviors, btn_sizes
    
    # Extra small pagination
    pagination_xs = Div(
        Button("1", cls=combine_classes(join_item, btn, btn_sizes.xs)),
        Button("2", cls=combine_classes(join_item, btn, btn_sizes.xs, btn_behaviors.active)),
        Button("3", cls=combine_classes(join_item, btn, btn_sizes.xs)),
        Button("4", cls=combine_classes(join_item, btn, btn_sizes.xs)),
        cls=str(join)
    )
    assert pagination_xs.attrs['class'] == "join"
    assert "btn-xs" in pagination_xs.children[0].attrs['class']
    assert "btn-xs" in pagination_xs.children[1].attrs['class']
    assert "btn-active" in pagination_xs.children[1].attrs['class']
    
    # Small pagination
    pagination_sm = Div(
        Button("1", cls=combine_classes(join_item, btn, btn_sizes.sm)),
        Button("2", cls=combine_classes(join_item, btn, btn_sizes.sm, btn_behaviors.active)),
        Button("3", cls=combine_classes(join_item, btn, btn_sizes.sm)),
        Button("4", cls=combine_classes(join_item, btn, btn_sizes.sm)),
        cls=str(join)
    )
    assert pagination_sm.attrs['class'] == "join"
    assert "btn-sm" in pagination_sm.children[0].attrs['class']
    assert "btn-sm" in pagination_sm.children[1].attrs['class']
    assert "btn-active" in pagination_sm.children[1].attrs['class']
    
    # Medium pagination
    pagination_md = Div(
        Button("1", cls=combine_classes(join_item, btn, btn_sizes.md)),
        Button("2", cls=combine_classes(join_item, btn, btn_sizes.md, btn_behaviors.active)),
        Button("3", cls=combine_classes(join_item, btn, btn_sizes.md)),
        Button("4", cls=combine_classes(join_item, btn, btn_sizes.md)),
        cls=str(join)
    )
    assert pagination_md.attrs['class'] == "join"
    assert "btn-md" in pagination_md.children[0].attrs['class']
    assert "btn-md" in pagination_md.children[1].attrs['class']
    assert "btn-active" in pagination_md.children[1].attrs['class']
    
    # Large pagination
    pagination_lg = Div(
        Button("1", cls=combine_classes(join_item, btn, btn_sizes.lg)),
        Button("2", cls=combine_classes(join_item, btn, btn_sizes.lg, btn_behaviors.active)),
        Button("3", cls=combine_classes(join_item, btn, btn_sizes.lg)),
        Button("4", cls=combine_classes(join_item, btn, btn_sizes.lg)),
        cls=str(join)
    )
    assert pagination_lg.attrs['class'] == "join"
    assert "btn-lg" in pagination_lg.children[0].attrs['class']
    assert "btn-lg" in pagination_lg.children[1].attrs['class']
    assert "btn-active" in pagination_lg.children[1].attrs['class']
    
    # Extra large pagination
    pagination_xl = Div(
        Button("1", cls=combine_classes(join_item, btn, btn_sizes.xl)),
        Button("2", cls=combine_classes(join_item, btn, btn_sizes.xl, btn_behaviors.active)),
        Button("3", cls=combine_classes(join_item, btn, btn_sizes.xl)),
        Button("4", cls=combine_classes(join_item, btn, btn_sizes.xl)),
        cls=str(join)
    )
    assert pagination_xl.attrs['class'] == "join"
    assert "btn-xl" in pagination_xl.children[0].attrs['class']
    assert "btn-xl" in pagination_xl.children[1].attrs['class']
    assert "btn-active" in pagination_xl.children[1].attrs['class']
    
    # Return all size variations
    return Div(
        pagination_xs,
        pagination_sm,
        pagination_md,
        pagination_lg,
        pagination_xl
    )

# Run the tests
test_pagination_sizes_fasthtml_examples()
<div>
  <div class="join">
<button class="join-item btn btn-xs">1</button><button class="join-item btn btn-xs btn-active">2</button><button class="join-item btn btn-xs">3</button><button class="join-item btn btn-xs">4</button>  </div>
  <div class="join">
<button class="join-item btn btn-sm">1</button><button class="join-item btn btn-sm btn-active">2</button><button class="join-item btn btn-sm">3</button><button class="join-item btn btn-sm">4</button>  </div>
  <div class="join">
<button class="join-item btn btn-md">1</button><button class="join-item btn btn-md btn-active">2</button><button class="join-item btn btn-md">3</button><button class="join-item btn btn-md">4</button>  </div>
  <div class="join">
<button class="join-item btn btn-lg">1</button><button class="join-item btn btn-lg btn-active">2</button><button class="join-item btn btn-lg">3</button><button class="join-item btn btn-lg">4</button>  </div>
  <div class="join">
<button class="join-item btn btn-xl">1</button><button class="join-item btn btn-xl btn-active">2</button><button class="join-item btn btn-xl">3</button><button class="join-item btn btn-xl">4</button>  </div>
</div>
test_func = test_pagination_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_pagination_disabled_fasthtml_examples

 test_pagination_disabled_fasthtml_examples ()

Test pagination with a disabled button from daisyUI v5 documentation.

Exported source
def test_pagination_disabled_fasthtml_examples():
    """Test pagination with a disabled button from daisyUI v5 documentation."""
    from fasthtml.common import Div, Button
    from cjm_fasthtml_tailwind.core.base import combine_classes
    from cjm_fasthtml_daisyui.components.actions.button import btn, btn_behaviors
    
    # Pagination with a disabled button
    pagination_disabled = Div(
        Button("1", cls=combine_classes(join_item, btn)),
        Button("2", cls=combine_classes(join_item, btn)),
        Button("...", cls=combine_classes(join_item, btn, btn_behaviors.disabled)),
        Button("99", cls=combine_classes(join_item, btn)),
        Button("100", cls=combine_classes(join_item, btn)),
        cls=str(join)
    )
    
    # Verify structure
    assert pagination_disabled.tag == "div"
    assert pagination_disabled.attrs['class'] == "join"
    assert len(pagination_disabled.children) == 5
    
    # First button
    assert pagination_disabled.children[0].tag == "button"
    assert "join-item" in pagination_disabled.children[0].attrs['class']
    assert "btn" in pagination_disabled.children[0].attrs['class']
    assert pagination_disabled.children[0].children[0] == "1"
    
    # Second button
    assert pagination_disabled.children[1].tag == "button"
    assert "join-item" in pagination_disabled.children[1].attrs['class']
    assert "btn" in pagination_disabled.children[1].attrs['class']
    assert pagination_disabled.children[1].children[0] == "2"
    
    # Disabled button (...)
    disabled_button = pagination_disabled.children[2]
    assert disabled_button.tag == "button"
    assert "join-item" in disabled_button.attrs['class']
    assert "btn" in disabled_button.attrs['class']
    assert "btn-disabled" in disabled_button.attrs['class']
    assert disabled_button.children[0] == "..."
    
    # 99 button
    assert pagination_disabled.children[3].tag == "button"
    assert "join-item" in pagination_disabled.children[3].attrs['class']
    assert "btn" in pagination_disabled.children[3].attrs['class']
    assert pagination_disabled.children[3].children[0] == "99"
    
    # 100 button
    assert pagination_disabled.children[4].tag == "button"
    assert "join-item" in pagination_disabled.children[4].attrs['class']
    assert "btn" in pagination_disabled.children[4].attrs['class']
    assert pagination_disabled.children[4].children[0] == "100"
    
    return pagination_disabled

# Run the tests
test_pagination_disabled_fasthtml_examples()
<div class="join">
<button class="join-item btn">1</button><button class="join-item btn">2</button><button class="join-item btn btn-disabled">...</button><button class="join-item btn">99</button><button class="join-item btn">100</button></div>
test_func = test_pagination_disabled_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_pagination_extra_small_fasthtml_examples

 test_pagination_extra_small_fasthtml_examples ()

Test extra small buttons pagination from daisyUI v5 documentation.

Exported source
def test_pagination_extra_small_fasthtml_examples():
    """Test extra small buttons pagination from daisyUI v5 documentation."""
    from fasthtml.common import Div, Button
    from cjm_fasthtml_tailwind.core.base import combine_classes
    from cjm_fasthtml_daisyui.components.actions.button import btn
    
    # Extra small buttons pagination with text
    pagination_extra_small = Div(
        Button("«", cls=combine_classes(join_item, btn)),
        Button("Page 22", cls=combine_classes(join_item, btn)),
        Button("»", cls=combine_classes(join_item, btn)),
        cls=str(join)
    )
    
    # Verify structure
    assert pagination_extra_small.tag == "div"
    assert pagination_extra_small.attrs['class'] == "join"
    assert len(pagination_extra_small.children) == 3
    
    # Previous button («)
    prev_button = pagination_extra_small.children[0]
    assert prev_button.tag == "button"
    assert "join-item" in prev_button.attrs['class']
    assert "btn" in prev_button.attrs['class']
    assert prev_button.children[0] == "«"
    
    # Page button
    page_button = pagination_extra_small.children[1]
    assert page_button.tag == "button"
    assert "join-item" in page_button.attrs['class']
    assert "btn" in page_button.attrs['class']
    assert page_button.children[0] == "Page 22"
    
    # Next button (»)
    next_button = pagination_extra_small.children[2]
    assert next_button.tag == "button"
    assert "join-item" in next_button.attrs['class']
    assert "btn" in next_button.attrs['class']
    assert next_button.children[0] == "»"
    
    return pagination_extra_small

# Run the tests
test_pagination_extra_small_fasthtml_examples()
<div class="join">
<button class="join-item btn">«</button><button class="join-item btn">Page 22</button><button class="join-item btn">»</button></div>
test_func = test_pagination_extra_small_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_pagination_grid_fasthtml_examples

 test_pagination_grid_fasthtml_examples ()

Test next/prev outline buttons with equal width from daisyUI v5 documentation.

Exported source
def test_pagination_grid_fasthtml_examples():
    """Test next/prev outline buttons with equal width from daisyUI v5 documentation."""
    from fasthtml.common import Div, Button
    from cjm_fasthtml_tailwind.core.base import combine_classes
    from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import grid_cols, grid_display
    from cjm_fasthtml_tailwind.utilities.layout import display_tw
    from cjm_fasthtml_daisyui.components.actions.button import btn, btn_styles
    
    # Next/Prev outline buttons with equal width
    pagination_grid = Div(
        Button("Previous page", cls=combine_classes(join_item, btn, btn_styles.outline)),
        Button("Next", cls=combine_classes(join_item, btn, btn_styles.outline)),
        cls=combine_classes(join, grid_display, grid_cols._2)
    )
    
    # Verify structure
    assert pagination_grid.tag == "div"
    assert "join" in pagination_grid.attrs['class']
    assert "grid" in pagination_grid.attrs['class']
    assert "grid-cols-2" in pagination_grid.attrs['class']
    assert len(pagination_grid.children) == 2
    
    # Previous page button
    prev_button = pagination_grid.children[0]
    assert prev_button.tag == "button"
    assert "join-item" in prev_button.attrs['class']
    assert "btn" in prev_button.attrs['class']
    assert "btn-outline" in prev_button.attrs['class']
    assert prev_button.children[0] == "Previous page"
    
    # Next button
    next_button = pagination_grid.children[1]
    assert next_button.tag == "button"
    assert "join-item" in next_button.attrs['class']
    assert "btn" in next_button.attrs['class']
    assert "btn-outline" in next_button.attrs['class']
    assert next_button.children[0] == "Next"
    
    return pagination_grid

# Run the tests
test_pagination_grid_fasthtml_examples()
<div class="join grid grid-cols-2">
<button class="join-item btn btn-outline">Previous page</button><button class="join-item btn btn-outline">Next</button></div>
test_func = test_pagination_grid_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_pagination_radio_fasthtml_examples

 test_pagination_radio_fasthtml_examples ()

Test pagination using radio inputs from daisyUI v5 documentation.

Exported source
def test_pagination_radio_fasthtml_examples():
    """Test pagination using radio inputs from daisyUI v5 documentation."""
    from fasthtml.common import Div, Input
    from cjm_fasthtml_tailwind.core.base import combine_classes
    from cjm_fasthtml_daisyui.components.actions.button import btn, btn_modifiers
    
    # Pagination using radio inputs
    pagination_radio = Div(
        Input(
            type="radio",
            name="options",
            aria_label="1",
            checked="checked",
            cls=combine_classes(join_item, btn, btn_modifiers.square)
        ),
        Input(
            type="radio",
            name="options",
            aria_label="2",
            cls=combine_classes(join_item, btn, btn_modifiers.square)
        ),
        Input(
            type="radio",
            name="options",
            aria_label="3",
            cls=combine_classes(join_item, btn, btn_modifiers.square)
        ),
        Input(
            type="radio",
            name="options",
            aria_label="4",
            cls=combine_classes(join_item, btn, btn_modifiers.square)
        ),
        cls=str(join)
    )
    
    # Verify structure
    assert pagination_radio.tag == "div"
    assert pagination_radio.attrs['class'] == "join"
    assert len(pagination_radio.children) == 4
    
    # First radio input (checked)
    first_radio = pagination_radio.children[0]
    assert first_radio.tag == "input"
    assert first_radio.attrs['type'] == "radio"
    assert first_radio.attrs['name'] == "options"
    assert first_radio.attrs['aria-label'] == "1"
    assert first_radio.attrs['checked'] == "checked"
    assert "join-item" in first_radio.attrs['class']
    assert "btn" in first_radio.attrs['class']
    assert "btn-square" in first_radio.attrs['class']
    
    # Second radio input
    second_radio = pagination_radio.children[1]
    assert second_radio.tag == "input"
    assert second_radio.attrs['type'] == "radio"
    assert second_radio.attrs['name'] == "options"
    assert second_radio.attrs['aria-label'] == "2"
    assert 'checked' not in second_radio.attrs
    assert "join-item" in second_radio.attrs['class']
    assert "btn" in second_radio.attrs['class']
    assert "btn-square" in second_radio.attrs['class']
    
    # Third radio input
    third_radio = pagination_radio.children[2]
    assert third_radio.tag == "input"
    assert third_radio.attrs['type'] == "radio"
    assert third_radio.attrs['name'] == "options"
    assert third_radio.attrs['aria-label'] == "3"
    assert 'checked' not in third_radio.attrs
    assert "join-item" in third_radio.attrs['class']
    assert "btn" in third_radio.attrs['class']
    assert "btn-square" in third_radio.attrs['class']
    
    # Fourth radio input
    fourth_radio = pagination_radio.children[3]
    assert fourth_radio.tag == "input"
    assert fourth_radio.attrs['type'] == "radio"
    assert fourth_radio.attrs['name'] == "options"
    assert fourth_radio.attrs['aria-label'] == "4"
    assert 'checked' not in fourth_radio.attrs
    assert "join-item" in fourth_radio.attrs['class']
    assert "btn" in fourth_radio.attrs['class']
    assert "btn-square" in fourth_radio.attrs['class']
    
    return pagination_radio

# Run the tests
test_pagination_radio_fasthtml_examples()
<div class="join">
  <input type="radio" name="options" aria-label="1" checked="checked" class="join-item btn btn-square">
  <input type="radio" name="options" aria-label="2" class="join-item btn btn-square">
  <input type="radio" name="options" aria-label="3" class="join-item btn btn-square">
  <input type="radio" name="options" aria-label="4" class="join-item btn btn-square">
</div>
test_func = test_pagination_radio_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()