join

Join is a container for grouping multiple items, it can be used to group buttons, inputs, etc. Join applies border radius to the first and last item. Join can be used to create a horizontal or vertical list of items.

Base Join

Exported source
join = SingleValueFactory("join", "Base join component for grouping multiple items") # Base join component
join_item = SingleValueFactory("join-item", "Item inside join. Can be a button, input, etc.") # Join item component

Join Direction


source

JoinDirection

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

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

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

Exported source
class JoinDirection(str, Enum):
    VERTICAL = "vertical"
    HORIZONTAL = "horizontal"

join_directions = enums_to_simple_factory(join, [JoinDirection], "join directions (vertical, horizontal)") # join directions

Join Test Examples


source

test_join_basic_examples

 test_join_basic_examples ()

Test basic join utilities.

Exported source
def test_join_basic_examples():
    """Test basic join 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_join_basic_examples()

source

test_join_directions_examples

 test_join_directions_examples ()

Test join directions variants.

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

# Run the tests
test_join_directions_examples()

source

test_join_basic_fasthtml_examples

 test_join_basic_fasthtml_examples ()

Test basic join example from daisyUI v5 documentation.

Exported source
def test_join_basic_fasthtml_examples():
    """Test basic join example from daisyUI v5 documentation."""
    from fasthtml.common import Button, Div
    from cjm_fasthtml_daisyui.components.actions.button import btn
    
    # Basic join with buttons
    basic_join = Div(
        Button("Button", cls=combine_classes(btn, join_item)),
        Button("Button", cls=combine_classes(btn, join_item)),
        Button("Button", cls=combine_classes(btn, join_item)),
        cls=str(join)
    )
    
    # Verify structure
    assert basic_join.tag == "div"
    assert basic_join.attrs['class'] == "join"
    
    # Verify all buttons
    assert len(basic_join.children) == 3
    for i, button in enumerate(basic_join.children):
        assert button.tag == "button"
        assert "btn" in button.attrs['class']
        assert "join-item" in button.attrs['class']
        assert button.children[0] == "Button"
    
    return basic_join

# Run the tests
test_join_basic_fasthtml_examples()
<div class="join">
<button class="btn join-item">Button</button><button class="btn join-item">Button</button><button class="btn join-item">Button</button></div>
test_func = test_join_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_join_vertical_fasthtml_examples

 test_join_vertical_fasthtml_examples ()

Test vertical join example from daisyUI v5 documentation.

Exported source
def test_join_vertical_fasthtml_examples():
    """Test vertical join example from daisyUI v5 documentation."""
    from fasthtml.common import Button, Div
    from cjm_fasthtml_daisyui.components.actions.button import btn
    
    # Vertical join with buttons
    vertical_join = Div(
        Button("Button", cls=combine_classes(btn, join_item)),
        Button("Button", cls=combine_classes(btn, join_item)),
        Button("Button", cls=combine_classes(btn, join_item)),
        cls=combine_classes(join, join_directions.vertical)
    )
    
    # Verify structure
    assert vertical_join.tag == "div"
    assert "join" in vertical_join.attrs['class']
    assert "join-vertical" in vertical_join.attrs['class']
    
    # Verify all buttons
    assert len(vertical_join.children) == 3
    for button in vertical_join.children:
        assert button.tag == "button"
        assert "btn" in button.attrs['class']
        assert "join-item" in button.attrs['class']
        assert button.children[0] == "Button"
    
    return vertical_join

# Run the tests
test_join_vertical_fasthtml_examples()
<div class="join join-vertical">
<button class="btn join-item">Button</button><button class="btn join-item">Button</button><button class="btn join-item">Button</button></div>
test_func = test_join_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_join_responsive_fasthtml_examples

 test_join_responsive_fasthtml_examples ()

Test responsive join example from daisyUI v5 documentation.

Exported source
def test_join_responsive_fasthtml_examples():
    """Test responsive join example from daisyUI v5 documentation."""
    from fasthtml.common import Button, Div
    from cjm_fasthtml_daisyui.components.actions.button import btn
    
    # Responsive join - vertical on small screen, horizontal on large screen
    responsive_join = Div(
        Button("Button", cls=combine_classes(btn, join_item)),
        Button("Button", cls=combine_classes(btn, join_item)),
        Button("Button", cls=combine_classes(btn, join_item)),
        cls=combine_classes(join, join_directions.vertical, join_directions.horizontal.lg)
    )
    
    # Verify structure
    assert responsive_join.tag == "div"
    assert "join" in responsive_join.attrs['class']
    assert "join-vertical" in responsive_join.attrs['class']
    assert "lg:join-horizontal" in responsive_join.attrs['class']
    
    # Verify all buttons
    assert len(responsive_join.children) == 3
    for button in responsive_join.children:
        assert button.tag == "button"
        assert "btn" in button.attrs['class']
        assert "join-item" in button.attrs['class']
        assert button.children[0] == "Button"
    
    return responsive_join

# Run the tests
test_join_responsive_fasthtml_examples()
<div class="join join-vertical lg:join-horizontal">
<button class="btn join-item">Button</button><button class="btn join-item">Button</button><button class="btn join-item">Button</button></div>
test_func = test_join_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_join_with_extra_elements_fasthtml_examples

 test_join_with_extra_elements_fasthtml_examples ()

Test join with extra elements from daisyUI v5 documentation.

Exported source
def test_join_with_extra_elements_fasthtml_examples():
    """Test join with extra elements from daisyUI v5 documentation."""
    from fasthtml.common import Button, Div, Input, Select, Option, Span
    from cjm_fasthtml_daisyui.components.actions.button import btn
    from cjm_fasthtml_daisyui.components.data_input.text_input import text_input
    from cjm_fasthtml_daisyui.components.data_input.select import select
    from cjm_fasthtml_daisyui.components.layout.indicator import indicator, indicator_item
    from cjm_fasthtml_daisyui.components.data_display.badge import badge, badge_colors
    
    # Join with extra elements
    join_extra = Div(
        Div(
            Div(
                Input(placeholder="Search", cls=combine_classes(text_input, join_item))
            )
        ),
        Select(
            Option("Filter", disabled=True, selected=True),
            Option("Sci-fi"),
            Option("Drama"),
            Option("Action"),
            cls=combine_classes(select, join_item)
        ),
        Div(
            Span("new", cls=combine_classes(indicator_item, badge, badge_colors.secondary)),
            Button("Search", cls=combine_classes(btn, join_item)),
            cls=str(indicator)
        ),
        cls=str(join)
    )
    
    # Verify structure
    assert join_extra.tag == "div"
    assert join_extra.attrs['class'] == "join"
    assert len(join_extra.children) == 3
    
    # Verify first element (nested divs with input)
    first_element = join_extra.children[0]
    assert first_element.tag == "div"
    assert first_element.children[0].tag == "div"
    input_element = first_element.children[0].children[0]
    assert input_element.tag == "input"
    assert "input" in input_element.attrs['class']
    assert "join-item" in input_element.attrs['class']
    assert input_element.attrs['placeholder'] == "Search"
    
    # Verify select element
    select_element = join_extra.children[1]
    assert select_element.tag == "select"
    assert "select" in select_element.attrs['class']
    assert "join-item" in select_element.attrs['class']
    assert len(select_element.children) == 4
    assert select_element.children[0].tag == "option"
    assert select_element.children[0].attrs['disabled'] == True
    assert select_element.children[0].attrs['selected'] == True
    assert select_element.children[0].children[0] == "Filter"
    
    # Verify indicator with badge and button
    indicator_element = join_extra.children[2]
    assert indicator_element.tag == "div"
    assert indicator_element.attrs['class'] == "indicator"
    assert len(indicator_element.children) == 2
    
    # Verify badge
    badge_span = indicator_element.children[0]
    assert badge_span.tag == "span"
    assert "indicator-item" in badge_span.attrs['class']
    assert "badge" in badge_span.attrs['class']
    assert "badge-secondary" in badge_span.attrs['class']
    assert badge_span.children[0] == "new"
    
    # Verify button
    search_button = indicator_element.children[1]
    assert search_button.tag == "button"
    assert "btn" in search_button.attrs['class']
    assert "join-item" in search_button.attrs['class']
    assert search_button.children[0] == "Search"
    
    return join_extra

# Run the tests
test_join_with_extra_elements_fasthtml_examples()
<div class="join">
  <div>
    <div>
      <input placeholder="Search" class="input join-item">
    </div>
  </div>
<select class="select join-item"><option disabled selected>Filter</option><option>Sci-fi</option><option>Drama</option><option>Action</option></select>  <div class="indicator">
<span class="indicator-item badge badge-secondary">new</span><button class="btn join-item">Search</button>  </div>
</div>
test_func = test_join_with_extra_elements_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_join_custom_border_fasthtml_examples

 test_join_custom_border_fasthtml_examples ()

Test join with custom border radius from daisyUI v5 documentation.

Exported source
def test_join_custom_border_fasthtml_examples():
    """Test join with custom border radius from daisyUI v5 documentation."""
    from fasthtml.common import Button, Div, Input
    from cjm_fasthtml_tailwind.utilities.borders import rounded
    from cjm_fasthtml_daisyui.components.actions.button import btn
    from cjm_fasthtml_daisyui.components.data_input.text_input import text_input
    
    # Join with custom border radius
    custom_border_join = Div(
        Input(placeholder="Email", cls=combine_classes(text_input, join_item)),
        Button("Subscribe", cls=combine_classes(btn, join_item, rounded.r_full)),
        cls=str(join)
    )
    
    # Verify structure
    assert custom_border_join.tag == "div"
    assert custom_border_join.attrs['class'] == "join"
    assert len(custom_border_join.children) == 2
    
    # Verify input element
    input_element = custom_border_join.children[0]
    assert input_element.tag == "input"
    assert "input" in input_element.attrs['class']
    assert "join-item" in input_element.attrs['class']
    assert input_element.attrs['placeholder'] == "Email"
    
    # Verify button with custom border radius
    button_element = custom_border_join.children[1]
    assert button_element.tag == "button"
    assert "btn" in button_element.attrs['class']
    assert "join-item" in button_element.attrs['class']
    assert "rounded-r-full" in button_element.attrs['class']
    assert button_element.children[0] == "Subscribe"
    
    return custom_border_join

# Run the tests
test_join_custom_border_fasthtml_examples()
<div class="join">
  <input placeholder="Email" class="input join-item">
<button class="btn join-item rounded-r-full">Subscribe</button></div>
test_func = test_join_custom_border_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_join_radio_inputs_fasthtml_examples

 test_join_radio_inputs_fasthtml_examples ()

Test join with radio inputs styled as buttons from daisyUI v5 documentation.

Exported source
def test_join_radio_inputs_fasthtml_examples():
    """Test join with radio inputs styled as buttons from daisyUI v5 documentation."""
    from fasthtml.common import Div, Input
    from cjm_fasthtml_daisyui.components.actions.button import btn
    
    # Join with radio inputs styled as buttons
    radio_join = Div(
        Input(type="radio", name="options", aria_label="Radio 1", cls=combine_classes(join_item, btn)),
        Input(type="radio", name="options", aria_label="Radio 2", cls=combine_classes(join_item, btn)),
        Input(type="radio", name="options", aria_label="Radio 3", cls=combine_classes(join_item, btn)),
        cls=str(join)
    )
    
    # Verify structure
    assert radio_join.tag == "div"
    assert radio_join.attrs['class'] == "join"
    assert len(radio_join.children) == 3
    
    # Verify all radio inputs
    for i, radio in enumerate(radio_join.children, 1):
        assert radio.tag == "input"
        assert radio.attrs['type'] == "radio"
        assert radio.attrs['name'] == "options"
        assert radio.attrs['aria-label'] == f"Radio {i}"
        assert "join-item" in radio.attrs['class']
        assert "btn" in radio.attrs['class']
    
    return radio_join

# Run the tests
test_join_radio_inputs_fasthtml_examples()
<div class="join">
  <input type="radio" name="options" aria-label="Radio 1" class="join-item btn">
  <input type="radio" name="options" aria-label="Radio 2" class="join-item btn">
  <input type="radio" name="options" aria-label="Radio 3" class="join-item btn">
</div>
test_func = test_join_radio_inputs_fasthtml_examples
app, rt = create_test_app(theme=DaisyUITheme.LIGHT)

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