# UI Elements Usage Instructions

> A reference guide for the reusable UI element components in the admin component library. Each element has a live demo page in the admin dashboard sidebar under **Components → UI Elements**. Use these Blade components instead of raw HTML to keep styling, dark mode, and interaction patterns consistent across modules.

---

## Table of Contents

1. [Overview](#1-overview)
2. [Live Demo Pages](#2-live-demo-pages)
3. [Buttons](#3-buttons)
4. [Badges & Tags](#4-badges--tags)
5. [Cards](#5-cards)
6. [Dropdowns](#6-dropdowns)
7. [Tooltips](#7-tooltips)
8. [Loaders & Spinners](#8-loaders--spinners)
9. [Modals](#9-modals)
10. [Best Practices](#10-best-practices)

---

## 1. Overview

All UI element components live in `resources/views/components/` and are auto-discovered by Laravel. Reference them with the `x-` prefix using dot-notation for subfolders:

| Category | Namespace | Example |
| :--- | :--- | :--- |
| Buttons | `<x-buttons.*>` | `<x-buttons.primary>` |
| Utility widgets | `<x-utility.*>` | `<x-utility.card>` |
| Feedback & overlays | `<x-feedback.*>` | `<x-feedback.modal>` |

Page registry and sidebar navigation are defined in `config/admin-nav.php`. Demo views live in `resources/views/pages/admin/components/ui-elements/`.

---

## 2. Live Demo Pages

After logging into the admin dashboard, open **Components → UI Elements** in the sidebar. Each page maps to a route under `/admin/components/ui-elements/{slug}`:

| Page | Route slug | Route name |
| :--- | :--- | :--- |
| Buttons | `buttons` | `admin.components.ui-elements.show` |
| Badges & Tags | `badges` | `admin.components.ui-elements.show` |
| Cards | `cards` | `admin.components.ui-elements.show` |
| Dropdowns | `dropdowns` | `admin.components.ui-elements.show` |
| Tooltips | `tooltips` | `admin.components.ui-elements.show` |
| Loaders & Spinners | `loaders` | `admin.components.ui-elements.show` |
| Modals | `modals` | `admin.components.ui-elements.show` |

Example link in a Blade view:

```blade
<a href="{{ route('admin.components.ui-elements.show', 'buttons') }}">View button demos</a>
```

---

## 3. Buttons

**Components:** `<x-buttons.primary>`, `<x-buttons.secondary>`, `<x-buttons.danger>`, `<x-buttons.icon>`, `<x-buttons.loading>`

**Shared props** (primary / secondary / danger):

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `type` | string | `button` | HTML button type (`button`, `submit`, `reset`) |
| `size` | string | `md` | `sm`, `md`, or `lg` |
| `href` | string\|null | `null` | When set, renders an `<a>` tag instead of `<button>` |
| `icon` | string\|null | `null` | Raw HTML/SVG icon markup |
| `loading` | bool | `false` | Shows a spinner and disables the button |

**Example — primary action with loading state:**

```blade
<x-buttons.primary type="submit" :loading="$isSaving">
    {{ __('buttons.save') }}
</x-buttons.primary>
```

**Example — secondary link button:**

```blade
<x-buttons.secondary href="{{ route('admin.dashboard') }}">
    {{ __('buttons.back') }}
</x-buttons.secondary>
```

**Icon button** (`<x-buttons.icon>`):

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `variant` | string | `default` | `primary`, `secondary`, `danger`, or `ghost` |
| `size` | string | `md` | `sm`, `md`, or `lg` |
| `title` | string | `''` | Accessible label (sets `title` and `aria-label`) |

```blade
<x-buttons.icon variant="ghost" :title="__('buttons.edit')">
    <x-heroicon-o-pencil class="h-5 w-5" />
</x-buttons.icon>
```

**Async loading button** (`<x-buttons.loading>`) — Alpine.js powered; toggles a spinner on click:

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `variant` | string | `primary` | `primary`, `secondary`, or `danger` |
| `type` | string | `submit` | HTML button type |
| `size` | string | `md` | `sm`, `md`, or `lg` |

```blade
<x-buttons.loading type="submit">{{ __('buttons.submit') }}</x-buttons.loading>
```

---

## 4. Badges & Tags

**Component:** `<x-utility.badge>`

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `variant` | string | `surface` | `surface`, `primary`, `success`, `warning`, or `danger` |
| `dot` | bool | `false` | Prepends a colored status dot |
| `size` | string | `md` | `md` or `sm` |

**Example — status badge with dot:**

```blade
<x-utility.badge variant="success" :dot="true">
    {{ __('statuses.active') }}
</x-utility.badge>
```

**Example — tag list:**

```blade
<div class="flex flex-wrap gap-2">
    <x-utility.badge variant="primary">Laravel</x-utility.badge>
    <x-utility.badge variant="primary">Tailwind</x-utility.badge>
    <x-utility.badge variant="surface">API</x-utility.badge>
</div>
```

---

## 5. Cards

**Component:** `<x-utility.card>`

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `title` | string | `''` | Card heading (renders header row when set) |
| `padding` | string | `p-6` | Tailwind padding class for the body |
| `shadow` | string | `''` | Custom shadow class (defaults to `shadow-card`) |
| `noBorder` | bool | `false` | Removes the border for a borderless card |

**Named slots:** `actions` (header-right buttons), `footer` (bottom action bar)

**Example — card with header actions and footer:**

```blade
<x-utility.card :title="__('pages/settings.title')">
    <x-slot:actions>
        <x-buttons.secondary size="sm">{{ __('buttons.export') }}</x-buttons.secondary>
        <x-buttons.primary size="sm">{{ __('buttons.add_new') }}</x-buttons.primary>
    </x-slot:actions>

    {{-- Card body content --}}
    <p class="text-sm text-muted-foreground">…</p>

    <x-slot:footer>
        <x-buttons.secondary>{{ __('buttons.cancel') }}</x-buttons.secondary>
        <x-buttons.primary>{{ __('buttons.save_changes') }}</x-buttons.primary>
    </x-slot:footer>
</x-utility.card>
```

---

## 6. Dropdowns

**Component:** `<x-utility.dropdown>`

Alpine.js powered. The menu is teleported and positioned via `resources/js/components/dropdown.js`.

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `align` | string | `left` | Menu alignment: `left` or `right` |
| `width` | string | `w-48` | Tailwind width class for the menu panel |

**Named slots:** `trigger` (the clickable element), `items` (menu links/actions)

```blade
<x-utility.dropdown align="right" width="w-52">
    <x-slot:trigger>
        <x-buttons.secondary>
            Options
            <x-heroicon-o-chevron-down class="h-4 w-4" />
        </x-buttons.secondary>
    </x-slot:trigger>
    <x-slot:items>
        <a href="#" class="block px-4 py-2 text-sm text-foreground transition-colors hover:bg-muted">
            {{ __('buttons.edit') }}
        </a>
        <hr class="my-1 border-border" />
        <a href="#" class="block px-4 py-2 text-sm text-destructive transition-colors hover:bg-destructive/10">
            {{ __('buttons.delete') }}
        </a>
    </x-slot:items>
</x-utility.dropdown>
```

---

## 7. Tooltips

**Component:** `<x-utility.tooltip>`

Wraps any trigger element. The tooltip is teleported to `<body>` and repositioned on scroll/resize.

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `text` | string | `''` | Tooltip label text |
| `position` | string | `top` | `top`, `bottom`, `left`, or `right` |

```blade
<x-utility.tooltip :text="__('buttons.delete')" position="top">
    <x-buttons.icon variant="ghost" :title="__('buttons.delete')">
        <x-heroicon-o-trash class="h-5 w-5 text-destructive" />
    </x-buttons.icon>
</x-utility.tooltip>
```

---

## 8. Loaders & Spinners

Two patterns are available: **skeleton placeholders** for content loading and **button spinners** for action feedback.

### Skeleton loader

**Component:** `<x-feedback.skeleton>`

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `lines` | int | `3` | Number of text placeholder lines |
| `avatar` | bool | `false` | Adds an avatar circle placeholder |
| `card` | bool | `true` | Wraps content in a card shell |
| `height` | string\|null | `null` | Custom block height (e.g. `h-24`); bypasses line layout |

```blade
<x-feedback.skeleton :lines="3" />
<x-feedback.skeleton :lines="2" :avatar="true" />
<x-feedback.skeleton height="h-24" :card="false" />
```

### Button loading spinners

Pass `:loading="true"` to any standard button component:

```blade
<x-buttons.primary :loading="true">{{ __('ui.state.saving') }}</x-buttons.primary>
<x-buttons.secondary :loading="true">{{ __('ui.state.processing') }}</x-buttons.secondary>
<x-buttons.danger :loading="true">{{ __('ui.state.deleting') }}</x-buttons.danger>
```

For form submissions that need client-side async feedback, use `<x-buttons.loading>` (see [Buttons](#3-buttons)).

---

## 9. Modals

**Component:** `<x-feedback.modal>`

Alpine.js event-driven. Open and close via `$dispatch` on the window.

| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `id` | string | `modal` | Unique identifier used in open/close events |
| `title` | string | `''` | Modal heading |
| `size` | string | `md` | `sm`, `md`, `lg`, `xl`, `2xl`, or `full` |

**Named slot:** `footer` (action buttons)

**Open a modal:**

```blade
<x-buttons.primary @click="$dispatch('open-modal', 'my-modal')">
    {{ __('pages/admin/components.modals.open') }}
</x-buttons.primary>
```

**Define the modal:**

```blade
<x-feedback.modal id="my-modal" :title="__('pages/admin/components.modals.headings.confirm_action')" size="lg">
    <p>{{ __('pages/admin/components.modals.descriptions.basic_body') }}</p>

    <x-slot:footer>
        <x-buttons.secondary @click="$dispatch('close-modal', 'my-modal')">
            {{ __('buttons.cancel') }}
        </x-buttons.secondary>
        <x-buttons.primary @click="$dispatch('close-modal', 'my-modal')">
            {{ __('buttons.confirm') }}
        </x-buttons.primary>
    </x-slot:footer>
</x-feedback.modal>
```

**Related:** For destructive confirmations (delete, archive), use `<x-alert-dialog>` which is driven by the Alpine `$store.confirmDialog` store. See the [Base Branch Usage Instructions](base-usage-instruction.md) for details.

---

## 10. Best Practices

1. **Always prefer components over raw HTML.** If you need a button, badge, or card, check `resources/views/components/` first.
2. **Use the live demo pages** as a visual reference before building new admin views.
3. **Keep modal IDs unique** per page. Duplicate IDs will cause open/close events to affect the wrong dialog.
4. **Pair icon buttons with tooltips** when the action is not obvious from the icon alone.
5. **Use skeleton loaders** for async content areas; use button `:loading` states for form submissions.
6. **Wrap demo pages** in `<x-layouts.admin.component-demo>` when adding new showcase pages — it provides consistent breadcrumbs and page layout.

> **Rule of Thumb:** When building a new admin feature, compose your views from `<x-utility.card>` containers, `<x-buttons.*>` actions, and `<x-feedback.*>` overlays. Match the patterns shown in the demo pages under **Components → UI Elements**.
