Skip to content

Layout & Structure ​

Spacing stores a layout value (four-sided padding/margin), while Group and Category add structure to a settings panel rather than storing a value — they organise the other inputs into readable, collapsible sections.

Spacing ​

A four-sided spacing control — top, right, bottom, left — with a link toggle that syncs every side at once. Compiled to FilamentCraft's SpacingField and rendered as a cross of numeric inputs around a central lock button, it's the right control for section padding or margin.

The Spacing control in the editor settings panel
The Spacing control — four per-side inputs around a central link toggle that syncs all sides.
php
use FilamentCraft\Settings\Types\Spacing;

Spacing::make('padding')
    ->label('Custom padding')
    ->min(0)->max(200)
    ->step(2)
    ->unit('px')
    ->default(['top' => 32, 'right' => 0, 'bottom' => 32, 'left' => 0]);
MethodEffect
min(int|float $min)Minimum value per side (default 0).
max(int|float $max)Maximum value per side (default 200).
step(int|float $step)Stepper increment (default 1).
unit(string $unit)CSS unit appended to each side (default px).
sides(array $sides)Restrict the editable sides, e.g. ->sides(['top', 'bottom']) for a vertical-only control.

The stored value is {top, right, bottom, left, linked}; a bare number (or ->default(16)) is accepted as a uniform shorthand. In a section's Blade view, read it through the value object's css() helper, which collapses to the shortest valid CSS shorthand (1 / 2 / 4 values):

blade
@php($pad = $section->settings->get('padding'))
<section @if ($pad) style="padding: {{ $pad->css() }}" @endif>
  …
</section>

$pad is a SpacingValue (or null when unset). Each side is also a raw float property ($pad->top, $pad->right, …) for hand-composed CSS, while the ->top() / ->right() methods return the unit-suffixed string. The object is Stringable, so {{ $pad }} emits the shorthand.

blade
{{-- raw per-side access, à la Bagisto --}}
style="padding: {{ $pad->top }}px {{ $pad->right }}px {{ $pad->bottom }}px {{ $pad->left }}px"

Margins & negative values. The control defaults min to 0, but negative values are fully supported — set a negative min for a margin control (Spacing::make('margin')->min(-80)->max(80)) and the field, value object, and css() output all handle them. The link toggle's state is stored when set and otherwise inferred from the data (all sides equal ⇒ linked), so importing a plain {top, right, bottom, left} map never silently re-syncs asymmetric values.

Group ​

A sub-heading that visually groups the inputs that follow it, compiled to a Filament section header. Used inside a single section's settings list to break a long form into labelled clusters.

php
use Filament\Forms\Components\Toggle;
use FilamentCraft\Settings\Types\Group;
use FilamentCraft\Settings\Types\Text;
use FilamentCraft\Settings\Types\Textarea;

return [
    Group::make('content_group')->label('Content'),
    Text::make('heading')->label('Heading'),
    Textarea::make('subheading')->label('Subheading'),

    Group::make('cta_group')->label('Call to action')->collapsed(),
    Toggle::make('cta_enabled')->label('Show button'),
    Text::make('cta_label')->label('Button label'),
];
MethodEffect
content(string $content)Optional descriptive text under the group heading (falls back to info()).
collapsed(bool $collapsed = true)Start the group collapsed.
icon(string $icon)An icon for the group heading.

A Group doesn't nest its fields as children — it acts as a divider/header, and every field listed after it (until the next Group) belongs to it visually. This is the pattern every built-in section uses (content_group, cta_group, layout_group, style_group).

An unlabeled Group renders its raw id as the heading (content_group, verbatim) — always give it a ->label().

Groups only group in section settings

This swallow-the-following-fields behaviour exists only when compiling a section'ssettings(). Inside a Category's settings([...]) each child compiles on its own, so a Group placed there renders as an empty collapsible header and does not absorb the fields after it. Structure theme panels with Category instead.

Category ​

Category panels in the theme settings panel
Each collapsible block here — Colors, Typography, Buttons, Inputs… — is one Category in the theme's settingsSchema().

A top-level collapsible panel for the theme template-settings panel. Unlike Group, Category contains its settings via settings(), and each category becomes a distinct collapsible block in the editor's theme panel.

php
use FilamentCraft\Settings\Types\Category;
use FilamentCraft\Settings\Types\Font;
use FilamentCraft\Settings\Types\Range;

Category::make('typography')
    ->label('Typography')
    ->icon('heroicon-o-language')
    ->collapsed(false)   // open by default; categories are collapsed otherwise
    ->settings([
        Font::make('default_font')->cssVar('--font-default')->default('inter'),
        Range::make('body_size')->cssVar('--font-body-size', 'px')
            ->unit('px')->min(12)->max(20)->default(16),
    ]);
MethodEffect
icon(string $icon)Icon shown next to the category title.
collapsed(bool $collapsed = true)Start collapsed. Categories are collapsed by default — pass ->collapsed(false) to open one.
settings(array $settings)The settings contained in this category.

info() renders as the panel's description text. An unlabeled Category falls back to a headlined version of its id (brand_colors → "Brand Colors").

Category is the backbone of a theme's settingsSchema() — see Theme Authoring for a complete multi-category theme class.

Group vs. Category ​

GroupCategory
WhereInside a section's settings()Top level of a theme schema
Holds children?No — acts as a divider/headerYes — via ->settings([...])
Default stateOpenCollapsed
Description textcontent(), falling back to info()info()
Unlabeled fallbackRaw idHeadlined id
Typical useCluster a section's fieldsA whole theme panel (Colors, Typography, Buttons…)