Loading...

Checkbox

A control that allows the user to toggle between checked and not checked.

Default Checkbox

Checked Checkbox

Disabled Checkbox

Disabled Checked Checkbox

Checkbox without Label

package showcase

import "github.com/axzilla/goilerplate/pkg/components"

templ CheckboxShowcase() {
	<div class="flex justify-center items-center border rounded-md py-16 px-4">
		<div>
			<div class="mb-8">
				<h2 class="font-semibold mb-2">Default Checkbox</h2>
				@components.Checkbox(components.CheckboxProps{
					ID:    "default-checkbox",
					Name:  "default",
					Value: "default",
					Label: "Accept terms and conditions",
				})
			</div>
			<div class="mb-8">
				<h2 class="font-semibold mb-2">Checked Checkbox</h2>
				@components.Checkbox(components.CheckboxProps{
					ID:      "checked-checkbox",
					Name:    "newsletter",
					Value:   "subscribe",
					Label:   "Receive newsletter",
					Checked: "true",
				})
			</div>
			<div class="mb-8">
				<h2 class="font-semibold mb-2">Disabled Checkbox</h2>
				@components.Checkbox(components.CheckboxProps{
					ID:       "disabled-checkbox",
					Name:     "disabled",
					Value:    "disabled",
					Label:    "Disabled option",
					Disabled: "true",
				})
			</div>
			<div class="mb-8">
				<h2 class="font-semibold mb-2">Disabled Checked Checkbox</h2>
				@components.Checkbox(components.CheckboxProps{
					ID:       "disabled-checked-checkbox",
					Name:     "disabled-checked",
					Value:    "disabled-checked",
					Label:    "Disabled checked option",
					Checked:  "true",
					Disabled: "true",
				})
			</div>
			<div class="mb-8">
				<h2 class="font-semibold mb-2">Checkbox without Label</h2>
				@components.Checkbox(components.CheckboxProps{
					ID:    "no-label-checkbox",
					Name:  "no-label",
					Value: "no-label",
				})
			</div>
		</div>
	</div>
}
package components

import (
	"github.com/axzilla/goilerplate/pkg/icons"
	"github.com/axzilla/goilerplate/pkg/utils"
)

// CheckboxProps defines the properties for the Checkbox component.
type CheckboxProps struct {
	// ID is the unique identifier for the checkbox input.
	ID string

	// Name is the name attribute for the checkbox input.
	Name string

	// Value is the value attribute for the checkbox input.
	Value string

	// Label is the text label associated with the checkbox.
	// If empty, no label will be rendered.
	Label string

	// Checked is a JavaScript expression for the checked state
	// Example: "true", "isSubscribed", "5+5===10"
	Checked string

	// Disabled is a JavaScript expression for the disabled state
	// Example: "true", "isLoading", "!isEnabled"
	Disabled string

	// Class specifies additional CSS classes for the container
	Class string

	// Attributes allows passing additional HTML attributes
	Attributes templ.Attributes
}

// Checkbox renders a customizable checkbox component with an associated label.
//
// Usage:
//
//	@components.Checkbox(components.CheckboxProps{
//	  ID:      "terms",
//	  Name:    "accept_terms",
//	  Value:   "accepted",
//	  Label:   "I accept the terms and conditions",
//	  Checked: "true",
//	  Disabled: "isSubmitting",
//	  Class:   "mt-4",
//	  Attributes: templ.Attributes{"data-testid": "terms-checkbox"},
//	})
//
// Props:
//   - ID: The unique identifier for the checkbox input. Required.
//   - Name: The name attribute for the checkbox input. Required.
//   - Value: The value attribute for the checkbox input. Required.
//   - Label: The text label associated with the checkbox. Optional.
//   - Checked: Determines the checked state. Can be a bool or a string for dynamic binding. Optional.
//   - Disabled: Determines the disabled state. Can be a bool or a string for dynamic binding. Optional.
//   - Class: Additional CSS classes to apply to the checkbox container. Optional.
//   - Attributes: Additional HTML attributes to apply to the checkbox input element. Optional.
templ Checkbox(props CheckboxProps) {
	<div x-data="{ checked: false }" class={ utils.TwMerge("flex items-center space-x-2", props.Class) }>
		<div class="relative">
			<input
				type="checkbox"
				id={ props.ID }
				name={ props.Name }
				value={ props.Value }
				x-ref="checkbox"
				x-model="checked"
				if props.Checked != "" {
					x-init={ "checked = " + props.Checked }
				}
				if props.Disabled != "" {
					:disabled={ props.Disabled }
				}
				class="absolute w-full h-full opacity-0 z-10 cursor-pointer peer"
				{ props.Attributes... }
			/>
			<div
				class="h-4 w-4 rounded-sm border border-primary ring-offset-background 
                       peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2 
                       peer-disabled:cursor-not-allowed peer-disabled:opacity-50
                       flex items-center justify-center
                       bg-background peer-checked:bg-primary transition-colors"
			>
				<div x-show="checked" class="text-primary-foreground">
					@icons.Check(icons.IconProps{Size: "12"})
				</div>
			</div>
		</div>
		if props.Label != "" {
			<label
				for={ props.ID }
				class="text-sm font-medium leading-none cursor-pointer select-none"
				:class="{ 'text-muted-foreground': !checked, 'text-foreground': checked }"
			>
				{ props.Label }
			</label>
		}
	</div>
}