# UI Rules

## Purpose

This document explains how UI should be built in Acelle so contributors do not hand-roll inconsistent forms and layouts.

## Form controls

Preferred helper controls live in:

- `resources/views/helpers/form_control/text.blade.php`
- `resources/views/helpers/form_control/number.blade.php`
- `resources/views/helpers/form_control/textarea.blade.php`
- `resources/views/helpers/form_control/select.blade.php`
- `resources/views/helpers/form_control/switcher.blade.php`
- `resources/views/helpers/form_control/checkbox.blade.php`

### Usage rules

- Prefer helper controls over raw `<input>` and `<select>` markup.
- Pass labels through the helper when the helper supports it.
- Pass validation state through Laravel's default `$errors` bag.
- Use `attributes` for `required`, `min`, `max`, placeholders, and feature-specific data attributes.

### Common examples

Text input:

```blade
@include('helpers.form_control.text', [
    'name' => 'name',
    'label' => trans('warmup.fields.name').' *',
    'value' => old('name', $warmupStrategy->name),
    'attributes' => [
        'required' => true,
        'placeholder' => trans('warmup.fields.name'),
    ],
])
```

Number input:

```blade
@include('helpers.form_control.number', [
    'name' => 'starting_volume',
    'label' => trans('warmup.fields.starting_volume').' *',
    'value' => old('starting_volume', $warmupStrategy->starting_volume),
    'attributes' => [
        'required' => true,
        'min' => 1,
        'max' => 1000000,
    ],
])
```

Select:

```blade
@include('helpers.form_control.select', [
    'name' => 'preset',
    'label' => trans('warmup.fields.preset').' *',
    'value' => old('preset', $warmupStrategy->preset),
    'options' => Acelle\Model\WarmupStrategy::presetOptions(),
    'attributes' => [
        'required' => true,
    ],
])
```

Textarea:

```blade
@include('helpers.form_control.textarea', [
    'name' => 'description',
    'label' => trans('warmup.fields.description').' *',
    'value' => old('description', $warmupStrategy->description),
    'attributes' => [
        'required' => true,
        'rows' => 4,
    ],
])
```

Switcher:

```blade
@include('helpers.form_control.switcher', [
    'name' => 'send_on_weekends',
    'value' => old('send_on_weekends', $warmupStrategy->send_on_weekends) ? '1' : '0',
    'on_value' => '1',
    'off_value' => '0',
])
```

## Layout rules

- Bootstrap 5 is the primary layout system.
- Prefer cards, grid, spacing utilities, and button variants before adding custom CSS.
- Prefer Bootstrap utility classes for typography, muted text, borders, and spacing before creating feature-local presentation classes.
- New views must start from existing layout primitives already used by the app: `page-title`, breadcrumbs, cards, grid, tables, alerts, and helper controls.
- Do not create a new view with a large block of custom CSS just to control font size, muted text, border radius, border color, spacing, or row layout. Those should come from Bootstrap utilities first.
- Feature-specific CSS must use explicit prefixes, for example `warmup-*`.
- Put feature-specific CSS in `public/core/css/app.css` only when Bootstrap utilities are insufficient.
- Every new admin screen must include dark-mode support. Put dark overrides in `public/core/css/dark.css` and prefer `rgba(...)` surfaces and borders so new UI stays consistent with the existing dark theme.

## New view rules

- Every new admin view should define `@section('page_header')` with the same structure already used across admin screens: `div.page-title`, `ul.breadcrumb.breadcrumb-caret.position-right`, and a single page heading.
- Prefer a single clear primary action using `btn btn-primary` and a secondary action using an existing neutral variant such as `btn btn-light`, `btn btn-secondary`, or `btn btn-default`, depending on the surrounding screen style.
- For create/edit pages, prefer Bootstrap grid layout and card sections instead of custom wrappers for spacing or alignment.
- For read-only summaries, previews, and side panels, prefer `bg-light`, `border`, `rounded-*`, `small`, `text-muted`, and flex utilities before inventing feature-specific row classes.
- New list screens should follow the existing `listing-form` pattern when server-driven filters, pagination, and sorting are needed.
- New paginated list screens should reuse `resources/views/elements/_per_page_select.blade.php` instead of building custom pagination footers.
- Wrap admin tables in `div.table-responsive` so dense data screens stay usable on smaller widths.
- For empty states, prefer the existing `empty-list` pattern or a simple centered card/section rather than designing a new empty-state system per feature.

## Current app practices

The current app already repeats these patterns often enough that new UI should treat them as defaults:

- Admin pages usually place breadcrumbs inside `page-title` and keep the screen title in the same header block.
- CRUD forms usually end with a clear primary save button and a lighter cancel/back action.
- Filterable index screens often render content through a list partial plus a shared pagination footer.
- Status and metadata are often shown with compact badges or muted supporting text rather than separate custom components.
- Detailed tabular previews are usually rendered inside `table-responsive` and standard Bootstrap table markup.
- Informational or fallback states commonly use `alert alert-light border` or `empty-list`, not bespoke notice components.

Representative references in the current codebase:

- `resources/views/admin/email_verification_plans/create.blade.php`
- `resources/views/admin/plugins/_list.blade.php`
- `resources/views/admin/users/_form.blade.php`
- `resources/views/elements/_per_page_select.blade.php`
- `resources/views/admin/warmup_strategies/index.blade.php`

## Legacy screens

- Many older admin views still use legacy classes such as `sub_section`, `btn-default`, `label label-flat`, or bespoke spacing patterns.
- When editing an existing legacy screen, preserve its local visual language unless the task is explicitly a modernization/refactor.
- When building a new screen or substantially rewriting an existing one, prefer the newer Bootstrap-first pattern used by the warmup module instead of copying older custom CSS-heavy structures.

## Warmup strategy reference

The warmup strategy create/edit screens are the reference implementation for:

- right preview visual can use ECharts (loaded from `core/echarts/echarts.min.js` and `core/echarts/dark.js`) for trend lines while keeping surrounding layout in Bootstrap cards/utilities

Reference views:

