Join

Join groups elements together with shared borders. Perfect for button groups, input groups, and pagination.

Basic Example

Button group and input group

await import('/components/layout/join.js');
await import('/components/actions/button.js');
await import('/components/data-input/input.js');

const { signal, tags, $ } = Lightview;
const { div, Join, Button, Input } = tags;

const email = signal('');

const demo = div({ style: 'display: flex; flex-direction: column; gap: 1rem' },
    // Button group
    Join({},
        Button({ class: 'join-item' }, 'Previous'),
        Button({ class: 'join-item', color: 'primary' }, 'Current'),
        Button({ class: 'join-item' }, 'Next')
    ),
    // Input with button
    Join({},
        Input({ 
            class: 'join-item',
            placeholder: 'Enter your email',
            value: () => email.value,
            oninput: (e) => { email.value = e.target.value; }
        }),
        Button({ class: 'join-item', color: 'primary' }, 'Subscribe')
    )
);

$('#example').content(demo);
await import('/components/layout/join.js');
await import('/components/actions/button.js');
await import('/components/data-input/input.js');
const { signal, $, tags } = Lightview;
const { Join, Button, Input, div } = tags;

const email = signal('');

const demo = {
    tag: div,
    attributes: { style: 'display: flex; flex-direction: column; gap: 1rem' },
    children: [
        {
            tag: Join,
            children: [
                { tag: Button, attributes: { class: 'join-item' }, children: ['Previous'] },
                { tag: Button, attributes: { class: 'join-item', color: 'primary' }, children: ['Current'] },
                { tag: Button, attributes: { class: 'join-item' }, children: ['Next'] }
            ]
        },
        {
            tag: Join,
            children: [
                {
                    tag: Input,
                    attributes: {
                        class: 'join-item',
                        placeholder: 'Enter your email',
                        value: () => email.value,
                        oninput: (e) => { email.value = e.target.value; }
                    }
                },
                { tag: Button, attributes: { class: 'join-item', color: 'primary' }, children: ['Subscribe'] }
            ]
        }
    ]
};

$('#example').content(demo);
await import('/components/layout/join.js');
await import('/components/actions/button.js');
await import('/components/data-input/input.js');
const { signal, $ } = Lightview;

const email = signal('');

const demo = {
    div: {
        style: 'display: flex; flex-direction: column; gap: 1rem',
        children: [
            {
                Join: {
                    children: [
                        { Button: { class: 'join-item', children: ['Previous'] } },
                        { Button: { class: 'join-item', color: 'primary', children: ['Current'] } },
                        { Button: { class: 'join-item', children: ['Next'] } }
                    ]
                }
            },
            {
                Join: {
                    children: [
                        {
                            Input: {
                                class: 'join-item',
                                placeholder: 'Enter your email',
                                value: () => email.value,
                                oninput: (e) => { email.value = e.target.value; }
                            }
                        },
                        { Button: { class: 'join-item', color: 'primary', children: ['Subscribe'] } }
                    ]
                }
            }
        ]
    }
};

$('#example').content(demo);

Props

Prop Type Default Description
vertical boolean false Stack items vertically

Vertical

Radio Group