beartropy/ui
Beartropy UI is a small Laravel UI package providing ready-made components and helpers to speed up building admin and front-end screens. Drop in common layouts, forms, and UI utilities to get a consistent look fast with minimal setup.
<x-bt-tag />
Tag → extends BeartropyComponent (no intermediate base class)tag.blade.phpresources/views/presets/input.php (calls $getComponentPresets('input'))resources/views/presets/sizes.phpbeartropyTagInput Alpine component (resources/js/modules/tag-input.js)lang/en/ui.php key add_tag| Prop | PHP Type | Default | Blade Attribute |
|---|---|---|---|
| id | ?string |
auto 'beartropy-tag-'.uniqid() |
id="my-tags" |
| name | ?string |
falls back to $id |
name="tags" |
| label | ?string |
null |
label="Tags" |
| color | ?string |
null |
color="blue" or magic: blue |
| size | ?string |
null |
size="lg" or magic: lg |
| placeholder | string |
__('beartropy-ui::ui.add_tag') |
placeholder="Type..." |
| value | array |
[] |
:value="['a','b']" |
| separator | array|string |
',' |
separator=";" or :separator="[',',';']" |
| disabled | bool |
false |
:disabled="true" |
| unique | bool |
true |
:unique="false" |
| maxTags | ?int |
null |
:max-tags="5" |
| help | ?string |
null |
help="Help text" |
| hint | ?string |
null |
hint="Hint text" |
| customError | mixed |
null |
:custom-error="$error" |
primary via config)primary, beartropy, red, blue, green, yellow, purple, pink, gray, orange, amber, lime, emerald, teal, cyan, sky, indigo, violet, rose, fuchsia, slate, stone, zinc, neutral
md)xs, sm, md, lg, xl
fill — applies $colorPreset['bg'] tinted background. Without fill, uses bg-white dark:bg-gray-900.
| Slot | Description |
|---|---|
| start | Content before the chips/input area (chrome stripped, vertically stretched) |
| end | Content after the chips/input area (chrome stripped, vertically stretched) |
The template auto-detects binding mode:
wire:model present → uses [@entangle](https://github.com/entangle), no hidden inputs rendered<input type="hidden" name="name[]"> per tag via Alpine x-forbeartropyTagInputbeartropyTagInput({
initialTags: [], // array — initial tags
unique: true, // bool — prevent duplicates
maxTags: null, // int|null — limit
disabled: false, // bool
separator: ',' // string|array — split chars
})
tags — array of current tagsinput — current text input valuefocusInput() — focuses the text inputaddTag() — adds current input value (splits on separator)removeTag(i) — removes tag at indexclearAll() — removes all tags and clears inputremoveOnBackspace() — removes last tag when input is emptyaddTagOnTab(e) — adds tag on Tab keyhandlePaste(e) — splits pasted text on separator_tryAddTag(tag) — internal: adds tag with unique/max checks$errors bag using wire:model name:custom-error="$message" propcolors → {color} → {bg, border, border_error, ring, ring_error, text, placeholder, label, label_error, chip_bg, chip_text, chip_close}
Tag-specific keys: chip_bg, chip_text, chip_close — used for tag chip styling.
Without wire:model, the Blade template renders:
<template x-for="(tag, i) in tags" :key="'hidden-'+tag+i">
<input type="hidden" :name="`{{ $inputName }}[]`" :value="tag">
</template>
Server receives $request->input('name') as an array.
{{-- Basic --}}
<x-bt-tag label="Tags" name="tags" />
{{-- With initial values --}}
<x-bt-tag label="Skills" name="skills" :value="['PHP', 'Laravel']" />
{{-- Livewire --}}
<x-bt-tag wire:model.live="tags" label="Tags" />
{{-- Limited + unique --}}
<x-bt-tag label="Tags" :max-tags="5" :unique="true" />
{{-- Custom separator --}}
<x-bt-tag label="Tags" separator=";" />
{{-- Color + Size --}}
<x-bt-tag blue sm label="Small Blue Tags" />
{{-- Fill mode --}}
<x-bt-tag fill emerald label="Emerald Tags" />
{{-- Disabled --}}
<x-bt-tag label="Locked" :disabled="true" :value="['readonly']" />
{{-- With help --}}
<x-bt-tag label="Tags" help="Separate with commas" />
{{-- Custom error --}}
<x-bt-tag label="Tags" :custom-error="'At least one tag required'" />
{{-- With slots --}}
<x-bt-tag label="Tags">
<x-slot:start><x-bt-icon name="tag" class="w-5 h-5 ml-2" /></x-slot:start>
</x-bt-tag>
{{-- Clear all button in end slot --}}
<x-bt-tag label="Tags" :value="['one', 'two']">
<x-slot:end>
<x-bt-button color="gray" soft [@click](https://github.com/click).stop="clearAll()">Clear All</x-bt-button>
</x-slot:end>
</x-bt-tag>
{{-- Form submission --}}
<form method="POST">
[@csrf](https://github.com/csrf)
<x-bt-tag name="tags" label="Tags" :value="$existingTags" />
<x-bt-button type="submit">Save</x-bt-button>
</form>
Tag shares the input config defaults — no separate component_defaults.tag entry:
'input' => [
'color' => env('BEARTROPY_UI_INPUT_COLOR', 'primary'),
'size' => env('BEARTROPY_UI_INPUT_SIZE', 'md'),
'outline' => env('BEARTROPY_UI_INPUT_OUTLINE', true),
],
BeartropyComponent directly (unlike Input which uses InputBase)input preset — $getComponentPresets('input') — so color/size config from component_defaults.input appliesid auto-generates as 'beartropy-tag-' . uniqid() when not provided; name falls back to id__('beartropy-ui::ui.add_tag') → 'Add tag...'hint takes precedence over help in the field-help component{{ }} (not {!! !!})wire:model is NOT presentbeartropyTagInput (not tagInput)text-xs for xs/sm, text-sm for md/lg, text-base for xl)items-stretch so start/end slots fill the full height (unlike Input which uses fixed height + items-center)max-h-32 overflow-y-auto with thin scrollbar for many tagswire:ignore on the chips container prevents Livewire from interfering with Alpine DOMclearAll() is available in Alpine scope for slot buttons (e.g., [@click](https://github.com/click).stop="clearAll()")How can I help you explore Laravel packages today?