Skip to main content
Firstlight / NativePHP

Firstlight / Docs

Native controls, familiar Blade, and the implementation details in between.

View source
Pill Group

Pill Group

Pill Group presents compact, individually shaped options for selecting zero or one value, or zero or more values.

Complete examples

Single selection is the default:

public ?string $queue = 'mine';

public array $queueOptions = [
    ['value' => 'mine', 'label' => 'Mine'],
    ['value' => 'all', 'label' => 'All'],
    ['value' => 'archived', 'label' => 'Archived', 'disabled' => true],
];
<firstlight:pill-group
    :options="$queueOptions"
    native:model="queue"
    label="Queue"
    helper="Choose the queue to include."
/>

Use multiple with an array-valued property:

public array $queues = ['mine'];
<firstlight:pill-group
    :options="$queueOptions"
    native:model="queues"
    label="Queues"
    helper="Choose any that apply."
    multiple
/>

Props

API Accepted type Purpose
options array Simple strings, a value-to-label map, or rich option arrays.
value / native:model string, int, array, or null Stable selection. Use a scalar or null in single mode and a homogeneous list or null in multiple mode.
multiple bool Enables zero-or-more selection. Defaults to false.
label string Visible field label.
helper string Supporting text below the pills.
error string Error text and native error semantics.
required bool Communicates required state; PHP still owns validation.
disabled bool Disables the complete group.
a11y-label string Explicit accessibility label when a visible label is inappropriate.
a11y-hint string Additional VoiceOver and TalkBack guidance.
class string External EDGE layout utilities.

Options and values

Simple strings use the same value and label:

['Mine', 'All']

A map separates stable values from labels and may use all-string or all-integer keys:

['mine' => 'Mine', 'all' => 'All']

Rich options accept only value, label, and optional disabled fields:

[
    ['value' => 'mine', 'label' => 'Mine'],
    ['value' => 'all', 'label' => 'All', 'disabled' => true],
]

All values in one group must be unique and must all be strings or all be integers. In single mode, tapping the selected pill proposes null. In multiple mode, tapping toggles that stable value while preserving the order of the others. null and [] both mean no multiple selection.

Events and state timing

@change receives the complete proposed selection: a scalar or null in single mode and a list in multiple mode. native:model normally generates this callback for property synchronisation.

Pill Group is server-authoritative. A tap emits immediately, but selected visuals wait for PHP's next publication. Further taps are ignored while that proposal is in flight so a rapid second tap cannot be calculated from stale state. Programmatic updates and reconciliation do not emit.

Use plain native:model or native:model.live; deferred blur and debounce modes are rejected.

Disabled and required behaviour

disabled prevents every pill from emitting. A rich option's disabled: true affects only that pill. An empty option set becomes an inert disabled group.

required is metadata rather than client-side enforcement. It does not prevent clearing the final pill; validate the resulting value in PHP and publish error when needed.

Accessibility

Provide either a visible label or an explicit a11y-label. Firstlight warns during development when both are blank. Each pill exposes its label, selected state, and disabled state through native platform semantics. Selection also has a visible checkmark, so it does not depend on colour alone. Pills wrap at larger text sizes and retain at least a 44-point iOS or 48-dp Android interaction target.

Validation and failure behaviour

Firstlight throws an actionable exception for malformed options, mixed or duplicate option values, a selection with the wrong type or shape, duplicate or mixed multiple selections, unsupported presentation props, and deferred sync modes. A same-typed selected value absent from options remains unselected rather than selecting a fallback.

Platform behaviour

iOS uses native SwiftUI capsule buttons in a wrapping layout. Android uses Material 3 FilterChip controls in a wrapping FlowRow. Both inherit NativePHP semantic theme tokens and preserve native press, focus, selection, disabled, and accessibility behaviour without exposing platform-widget props.

Compatibility

Pill Group supports the versions listed in the current compatibility reference and requires both native renderers to be compiled into the host application.

Screenshots

Runtime screenshot evidence is deferred for this development build. The capture manifest reserves these output paths for the later visual review:

Platform Light Dark
iOS docs/screenshots/pill-group/ios-light.png docs/screenshots/pill-group/ios-dark.png
Android docs/screenshots/pill-group/android-light.png docs/screenshots/pill-group/android-dark.png

Served from firstlightui/nativephp and cached for a fast first read.