Check out BugBytes overview of labb

Button

<c-lb.button /> Markdown

Button component for Django: create accessible, styled buttons with variants, sizes, and icons. Built with django-cotton, Tailwind CSS, and daisyUI 5. Zero JavaScript by default.

Button for Django lets you create accessible, styled action triggers using a simple HTML-like syntax. Built on django-cotton, Tailwind CSS, and daisyUI 5, it supports colour variants, sizes, icons, and reactive states, all server-rendered with zero JavaScript by default. Use it to trigger form submissions, navigation actions, and modal dialogs in any Django template.

Basic Button

<c-lb.button>Click Me</c-lb.button>

Colour Variants

<div class="flex flex-wrap gap-2">
  <c-lb.button variant="neutral">Neutral</c-lb.button>
  <c-lb.button variant="primary">Primary</c-lb.button>
  <c-lb.button variant="secondary">Secondary</c-lb.button>
  <c-lb.button variant="accent">Accent</c-lb.button>
  <c-lb.button variant="info">Info</c-lb.button>
  <c-lb.button variant="success">Success</c-lb.button>
  <c-lb.button variant="warning">Warning</c-lb.button>
  <c-lb.button variant="error">Error</c-lb.button>
</div>

Different Styles

<div class="flex flex-wrap gap-2">
  <c-lb.button btnStyle="outline">Outline</c-lb.button>
  <c-lb.button btnStyle="dash">Dash</c-lb.button>
  <c-lb.button btnStyle="soft">Soft</c-lb.button>
  <c-lb.button btnStyle="ghost">Ghost</c-lb.button>
  <c-lb.button btnStyle="link">Link</c-lb.button>
  <c-lb.button btnStyle="bare">Bare</c-lb.button>
</div>

Outline Button Variants

<div class="flex flex-wrap gap-2">
  <c-lb.button btnStyle="outline" variant="neutral">Neutral</c-lb.button>
  <c-lb.button btnStyle="outline" variant="primary">Primary</c-lb.button>
  <c-lb.button btnStyle="outline" variant="secondary">Secondary</c-lb.button>
  <c-lb.button btnStyle="outline" variant="accent">Accent</c-lb.button>
  <c-lb.button btnStyle="outline" variant="info">Info</c-lb.button>
  <c-lb.button btnStyle="outline" variant="success">Success</c-lb.button>
  <c-lb.button btnStyle="outline" variant="warning">Warning</c-lb.button>
  <c-lb.button btnStyle="outline" variant="error">Error</c-lb.button>
</div>

Different Sizes

<div class="flex flex-wrap gap-2 items-center">
  <c-lb.button size="xs">Extra Small</c-lb.button>
  <c-lb.button size="sm">Small</c-lb.button>
  <c-lb.button size="md">Medium</c-lb.button>
  <c-lb.button size="lg">Large</c-lb.button>
  <c-lb.button size="xl">Extra Large</c-lb.button>
</div>

Button Behaviours

<div class="flex flex-wrap gap-2">
  <c-lb.button behavior="active">Active Button</c-lb.button>
  <c-lb.button behavior="disabled">Disabled Button</c-lb.button>
</div>

Button Modifiers

Wide Button

Block Button

Square Buttons

Circle Buttons

<div class="space-y-4 w-full">
  <div class="w-full">
    <h4 class="text-sm font-medium mb-2">Wide Button</h4>
    <div class="w-full">
      <c-lb.button modifier="wide">Wide Button</c-lb.button>
    </div>
  </div>

  <div class="w-full">
    <h4 class="text-sm font-medium mb-2">Block Button</h4>
    <div class="w-full">
      <c-lb.button modifier="block">Block Button</c-lb.button>
    </div>
  </div>

  <div>
    <h4 class="text-sm font-medium mb-2">Square Buttons</h4>
    <div class="flex flex-wrap gap-2">
      <c-lb.button modifier="square">+</c-lb.button>
      <c-lb.button modifier="square" variant="primary">×</c-lb.button>
      <c-lb.button modifier="square" variant="secondary">✓</c-lb.button>
    </div>
  </div>

  <div>
    <h4 class="text-sm font-medium mb-2">Circle Buttons</h4>
    <div class="flex flex-wrap gap-2">
      <c-lb.button modifier="circle">+</c-lb.button>
      <c-lb.button modifier="circle" variant="primary">×</c-lb.button>
      <c-lb.button modifier="circle" variant="secondary">✓</c-lb.button>
    </div>
  </div>
</div>

Custom Elements

Button Element (Default)

Anchor Element

Link Button

Input Element

Div Element

Div Button
<div class="space-y-4">
  <div>
    <h4 class="text-sm font-medium mb-2">Button Element (Default)</h4>
    <c-lb.button>Button Element</c-lb.button>
  </div>

  <div>
    <h4 class="text-sm font-medium mb-2">Anchor Element</h4>
    <c-lb.button as="a" href="#example">Link Button</c-lb.button>
  </div>

  <div>
    <h4 class="text-sm font-medium mb-2">Input Element</h4>
    <c-lb.button as="input" type="submit" value="Submit Input" />
  </div>

  <div>
    <h4 class="text-sm font-medium mb-2">Div Element</h4>
    <c-lb.button as="div">Div Button</c-lb.button>
  </div>
</div>

Button with Icons

<div class="flex flex-wrap gap-4 items-center">
    <!-- icon="name" — line icon at start -->
    <c-lb.button icon="rmx.home">
        Home
    </c-lb.button>

    <!-- icon.fill="name" — filled icon at start -->
    <c-lb.button icon.fill="rmx.heart" variant="error">
        Like
    </c-lb.button>

    <!-- icon.end="name" — line icon at end -->
    <c-lb.button icon.end="rmx.arrow-right" variant="primary">
        Continue
    </c-lb.button>

    <!-- icon.fill.end="name" — filled icon at end -->
    <c-lb.button icon.fill.end="rmx.arrow-right" variant="success">
        Submit
    </c-lb.button>

    <!-- icon.end.fill="name" — same as above, order doesn't matter -->
    <c-lb.button icon.end.fill="rmx.check" variant="accent">
        Done
    </c-lb.button>

    <!-- icon.class="..." — custom classes on the icon -->
    <c-lb.button icon.fill="rmx.star" icon.class="text-warning">
        Favorite
    </c-lb.button>

    <!-- Icon only buttons -->
    <c-lb.button modifier="square" icon="rmx.menu-4" variant="primary">
    </c-lb.button>

    <c-lb.button modifier="circle" icon.fill="rmx.add" variant="accent">
    </c-lb.button>
</div>

Reactive Button

<div x-data="{ btnProps: { variant: '', size: 'md', btnStyle: '' } }" class="flex flex-col gap-6 items-start w-full md:w-96">

    <c-lb.button.x x-model="btnProps" size="md">
        Click me — <span x-text="btnProps.variant || 'default'"></span>
    </c-lb.button.x>

    <c-lb.label floating class="w-full">
        <span>Variant</span>
        <select x-model="btnProps.variant" class="select select-sm">
            <option value="">Default</option>
            <option value="primary">Primary</option>
            <option value="secondary">Secondary</option>
            <option value="accent">Accent</option>
            <option value="success">Success</option>
            <option value="warning">Warning</option>
            <option value="error">Error</option>
        </select>
    </c-lb.label>

    <c-lb.label floating class="w-full">
        <span>Size</span>
        <select x-model="btnProps.size" class="select select-sm">
            <option value="xs">xs</option>
            <option value="sm">sm</option>
            <option value="md">md</option>
            <option value="lg">lg</option>
            <option value="xl">xl</option>
        </select>
    </c-lb.label>

    <c-lb.label floating class="w-full">
        <span>Style</span>
        <select x-model="btnProps.btnStyle" class="select select-sm">
            <option value="">Default</option>
            <option value="outline">Outline</option>
            <option value="soft">Soft</option>
            <option value="ghost">Ghost</option>
            <option value="link">Link</option>
        </select>
    </c-lb.label>

</div>

Extended Button Reactivity

<script>
document.addEventListener('alpine:init', () => {
    Alpine.data('saveBtnComp', lb.extendComponent('button', {
        state: "initial",
        async save() {
            this.lbProps.variant = "info";
            this.state = "saving";
            await new Promise(r => setTimeout(r, 2000));
            this.state = "saved";
            this.lbProps.variant = "success";
            await new Promise(r => setTimeout(r, 1000));
            this.state = "initial";
            this.lbProps.variant = "primary";
        },
    }));
});
</script>

<div class="w-full md:w-96">
    <c-lb.button.x
        x-data="saveBtnComp"
        variant="primary"
        @click="save()"
        class="w-full"
        x-cloak
    >
        <c-lb.text x-show="state === 'initial'" icon="rmx.save">
            Save changes
        </c-lb.text>
        <c-lb.text x-show="state === 'saving'">
            Saving <c-lb.loading type="dots" />
        </c-lb.text>
        <c-lb.text x-show="state === 'saved'" icon="rmx.checkbox-circle">
            Saved
        </c-lb.text>
    </c-lb.button.x>
</div>

API Reference

c-lb.button

Property Type Default Required Description
class string - No Additional CSS classes to apply
as
button a input div
button No HTML tag to use for the button element
variant
neutral primary secondary accent info success warning error
- No Button color variant
btnStyle
outline dash soft ghost link bare
- No Button style variant. Use "bare" for a plain button with no btn classes.
behavior
active disabled
- No Button behavior state
size
xs sm md lg xl
md No Button size
modifier
wide block square circle
- No Button layout modifier
icon string - No Icon name to display
↳ .fill modifier - No Render in filled (solid) style
↳ .end modifier - No Place at the end of the text
icon.class string - No Additional CSS classes for the icon