Larastrap

Opinionated Bootstrap 5 components for Laravel

There are lots of Laravel packages pretending to wrap the widely popular Bootstrap CSS design system. Most of them are limited just to forms formatting (while Bootstrap provides so many different tools), and all of them have an elaborated syntax, so the code required to format your component is no so less verbose (nor more readable) then the actual resulting HTML.

Larastrap provides a conspicuous amount of (configurable) defaults and many out-of-the-box common behaviours. And, leveraging the Laravel's native Blade Components system, provides a few handy automatisms and the ability to define your own reusable Custom Elements. To reduce to the bare minimum the code you have to actually write (and read, and maintain...) to obtain your desidered layout.


Intro

To install it in your Laravel project, run
composer require madbob/larastrap
php artisan vendor:publish --tag=config

This will generate the config/larastrap.php file where you can find (and modify) the default behaviours. From here, you can define a default value for each property of each component, and define custom presets.

Each component can be included into your Blade template using
<x-larastrap::componentname>
and it is possible to inline overwrite all of his attributes using the common notation for Blade components
<x-larastrap::componentname id="a_static_string" :name="$a_php_variable">

Attributes can be also packed in a single indexed array and passed as :params. This is in particular useful when dynamically setting up and loading a component
<x-dynamic-component
    :component="sprintf('larastrap::%s', $a_component_type)"
    :params="['id' => 'a_static_string', 'name' => $a_php_variable]" />

Remeber to include the Bootstrap assets (both CSS and JS) in your page!

Larastrap is opensource, MIT licensed: grab the code and contribute on the Gitlab repository.

A navbar.
For each item you can specify just a label and an url, or a sub-array with more informations. Eventually even the children (for dropdowns).
If none of the items has the active attribute set to true, tries to guess the active item through the actual Laravel route. On the contrary, if a child is set to active, his parent is marked active as well
Bootstrap documentation
Code
<x-larastrap::navbar :options="[
    'Home' => '/',
    'Navbar' => ['url' => '#navbar', 'active' => true],
    'More' => ['children' => ['Forms' => '#forms', 'Modals' => '#modals', 'All' => '#props']]
]" />
<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <div class="container-fluid">
    <div class="collapse navbar-collapse position-relative" id="navbar-vThOfsjDM2">
      <ul class="navbar-nav">
        <li class="nav-item">
          <a class="nav-link" href="/">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link active" href="#navbar">Navbar</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">More</a>
          <ul class="dropdown-menu">
            <li>
              <a class="dropdown-item" href="#forms">Forms</a>
            </li>
            <li>
              <a class="dropdown-item" href="#modals">Modals</a>
            </li>
            <li>
              <a class="dropdown-item" href="#props">All</a>
            </li>
          </ul>
        </li>
      </ul>
    </div>
  </div>
</nav>

Forms

Open a form, specifying a reference obj and an action URL, them populate it with the preferred inputs.
For each of them you have to specify at least a label and a name (matching with an attribute of the reference object) or an explicit value.
By default the POST method is used, the CSRF token is properly added, Bootstrap validation is leveraged, label_width and input_width are applied from the configuration, and a submit button is appended (using the array buttons, containing details for all desired buttons).
Bootstrap documentation
Must be a valid email address
Code
<?php $obj = (object) ['id' => 1234, 'name' => 'Foo', 'bio' => 'A very smart guy!', 'email' => 'foo@bar.baz', 'country' => 'it', 'colors' => ['red', 'green']] ?>
<x-larastrap::form :obj="$obj" action="/user/save">
  <x-larastrap::hidden name="id" />
  <x-larastrap::number name="id" label="ID" disabled="true" />
  <x-larastrap::text name="name" label="Name" />
  <x-larastrap::text name="surname" label="Surname" value="Bar" />
  <x-larastrap::textarea name="bio" label="Bio" />
  <x-larastrap::email name="email" label="EMail" help="Must be a valid email address" />

  <?php $countries = ['fr' => 'France', 'de' => 'Germany', 'it' => 'Italy'] ?>
  <x-larastrap::select name="country" label="Country (as select)" :options="$countries" />
  <x-larastrap::radios name="country" label="Country (as radio)" :options="$countries" />

  <?php $colors = ['red' => 'Red', 'green' => 'Green', 'blue' => 'Blue'] ?>
  <x-larastrap::checks name="colors" label="Colors" :options="$colors" />
</x-larastrap::form>
<form id="form-UUk1apJzov" class="" method="post" action="/user/save" novalidate="" name="form-UUk1apJzov">
  <input type="hidden" name="_token" value="UmiJGcaHzXT7mU00GPTszD9Fq0gk7KaNwIaIo873"> <input id="hidden-lsj2cBMN6F" type="hidden" class="" name="id" value="1234">
  <div class="row mb-3">
    <label for="input-TivYK7VGqE" class="col-2 col-form-label">ID</label>
    <div class="col-10">
      <input id="input-TivYK7VGqE" type="number" class="form-control-plaintext" name="id" value="1234" step="1" min="-9223372036854775808" max="9223372036854775807" disabled>
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-m8luWwanOV" class="col-2 col-form-label">Name</label>
    <div class="col-10">
      <input id="input-m8luWwanOV" type="text" class="form-control" name="name" value="Foo">
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-GFXltE5uXY" class="col-2 col-form-label">Surname</label>
    <div class="col-10">
      <input id="input-GFXltE5uXY" type="text" class="form-control" name="surname" value="Bar">
    </div>
  </div>
  <div class="row mb-3">
    <label for="textarea-Zn9CTJ8khi" class="col-2 col-form-label">Bio</label>
    <div class="col-10">
      <textarea id="textarea-Zn9CTJ8khi" class="form-control" name="bio">A very smart guy!</textarea>
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-5hND4TDVPX" class="col-2 col-form-label">EMail</label>
    <div class="col-10">
      <input id="input-5hND4TDVPX" type="email" class="form-control" name="email" value="foo@bar.baz">
      <div class="form-text">
        Must be a valid email address
      </div>
    </div>
  </div>
  <div class="row mb-3">
    <label for="select-rLd6K0XcmH" class="col-2 col-form-label">Country (as select)</label>
    <div class="col-10">
      <select class="form-select" name="country">
        <option value="fr">
          France
        </option>
        <option value="de">
          Germany
        </option>
        <option value="it" selected>
          Italy
        </option>
      </select>
    </div>
  </div>
  <div class="row mb-3">
    <label for="radios-qZkYEbU392" class="col-2 col-form-label col-2 col-form-label">Country (as radio)</label>
    <div class="col-10">
      <div class="btn-group" role="group">
        <input type="radio" class="btn-check" name="country" id="radios-qZkYEbU392-3458320820966871310" autocomplete="off" value="fr"> <label class="btn btn-outline-primary" for="radios-qZkYEbU392-3458320820966871310">France</label> <input type="radio" class="btn-check" name="country" id="radios-qZkYEbU392-3750341178505595757" autocomplete="off" value="de"> <label class="btn btn-outline-primary" for="radios-qZkYEbU392-3750341178505595757">Germany</label> <input type="radio" class="btn-check" name="country" id="radios-qZkYEbU392-6026725091324543594" autocomplete="off" value="it" checked> <label class="btn btn-outline-primary" for="radios-qZkYEbU392-6026725091324543594">Italy</label>
      </div>
    </div>
  </div>
  <div class="row mb-3">
    <label for="checks-kZJNyVDzVj" class="col-2 col-form-label col-2 col-form-label">Colors</label>
    <div class="col-10">
      <div class="btn-group" role="group">
        <input type="checkbox" class="btn-check" name="colors[]" id="checks-kZJNyVDzVj-4854916943426033176" autocomplete="off" value="red"> <label class="btn btn-outline-primary" for="checks-kZJNyVDzVj-4854916943426033176">Red</label> <input type="checkbox" class="btn-check" name="colors[]" id="checks-kZJNyVDzVj-2056776045321078209" autocomplete="off" value="green"> <label class="btn btn-outline-primary" for="checks-kZJNyVDzVj-2056776045321078209">Green</label> <input type="checkbox" class="btn-check" name="colors[]" id="checks-kZJNyVDzVj-261077486203858887" autocomplete="off" value="blue"> <label class="btn btn-outline-primary" for="checks-kZJNyVDzVj-261077486203858887">Blue</label>
      </div>
    </div>
  </div>
  <div class="col-12 text-end">
    <button class="btn btn-primary" type="submit">Save</button>
  </div>
</form>
For a different layout, use the formview parameter. Or modify the default configuration in larastrap.elements.form.formview to change them all.
Code
<?php $obj = (object) ['id' => 1234, 'name' => 'Mario', 'email' => 'mario@mailinator.com'] ?>
<x-larastrap::form :obj="$obj" action="/user/save" formview="vertical">
  <x-larastrap::number name="id" label="ID" disabled="true" />
  <x-larastrap::text name="name" label="Name" />
  <x-larastrap::email name="email" label="EMail" />
</x-larastrap::form>
<form id="form-ImWRvCjPwf" class="" method="post" action="/user/save" novalidate="" name="form-ImWRvCjPwf">
  <input type="hidden" name="_token" value="UmiJGcaHzXT7mU00GPTszD9Fq0gk7KaNwIaIo873">
  <div class="mb-3">
    <label for="input-2CRdNXtU0h" class="form-label">ID</label> <input id="input-2CRdNXtU0h" type="number" class="form-control-plaintext" name="id" value="1234" step="1" min="-9223372036854775808" max="9223372036854775807" disabled>
  </div>
  <div class="mb-3">
    <label for="input-3YQRulKTnc" class="form-label">Name</label> <input id="input-3YQRulKTnc" type="text" class="form-control" name="name" value="Mario">
  </div>
  <div class="mb-3">
    <label for="input-HDQczlLH9N" class="form-label">EMail</label> <input id="input-HDQczlLH9N" type="email" class="form-control" name="email" value="mario@mailinator.com">
  </div>
  <div class="col-12 text-end">
    <button class="btn btn-primary" type="submit">Save</button>
  </div>
</form>
The formview: inline mode displays the form on a single row, with hidden labels.
Bootstrap documentation
Code
<?php $obj = (object) ['id' => 1234, 'name' => 'Mario', 'email' => 'mario@mailinator.com'] ?>
<x-larastrap::form :obj="$obj" action="/user/save" formview="inline">
  <x-larastrap::number name="id" label="ID" disabled="true" />
  <x-larastrap::text name="name" label="Name" />
  <x-larastrap::email name="email" label="EMail" />
</x-larastrap::form>
<form id="form-09jzd4r49i" class="row row-cols-lg-auto g-3 align-items-center" method="post" action="/user/save" novalidate="" name="form-09jzd4r49i">
  <input type="hidden" name="_token" value="UmiJGcaHzXT7mU00GPTszD9Fq0gk7KaNwIaIo873">
  <div class="col-12">
    <label for="input-V2fTuHBPAk" class="d-none">ID</label> <input id="input-V2fTuHBPAk" type="number" class="form-control-plaintext" name="id" value="1234" step="1" min="-9223372036854775808" max="9223372036854775807" disabled>
  </div>
  <div class="col-12">
    <label for="input-7PuVmxpMjG" class="d-none">Name</label> <input id="input-7PuVmxpMjG" type="text" class="form-control" name="name" value="Mario">
  </div>
  <div class="col-12">
    <label for="input-oel13hh6ZV" class="d-none">EMail</label> <input id="input-oel13hh6ZV" type="email" class="form-control" name="email" value="mario@mailinator.com">
  </div>
  <div class="col-12 text-end">
    <button class="btn btn-primary" type="submit">Save</button>
  </div>
</form>
When a file input is involved, the enctype is automatically added to the parent form.
Code
<x-larastrap::form action="/document/save">
  <x-larastrap::file name="document" label="Attach Document" />
</x-larastrap::form>
<form id="form-795PRsPDvn" class="" method="post" action="/document/save" enctype="multipart/form-data" novalidate="" name="form-795PRsPDvn">
  <input type="hidden" name="_token" value="UmiJGcaHzXT7mU00GPTszD9Fq0gk7KaNwIaIo873">
  <div class="row mb-3">
    <label for="input-RQIx2VNjqq" class="col-2 col-form-label">Attach Document</label>
    <div class="col-10">
      <input id="input-RQIx2VNjqq" type="file" class="form-control" name="document" value="">
    </div>
  </div>
  <div class="col-12 text-end">
    <button class="btn btn-primary" type="submit">Save</button>
  </div>
</form>
If you have some special HTML block to align into the form, just leverage the x-larastrap::field component to format whatever you want.
Code
<x-larastrap::form action="/do/nothing">
  <x-larastrap::field label="Image">
    <img src="https://picsum.photos/100" class="img-fluid">
  </x-larastrap::field>
</x-larastrap::form>
<form id="form-yVHjiW8duD" class="" method="post" action="/do/nothing" novalidate="" name="form-yVHjiW8duD">
  <input type="hidden" name="_token" value="UmiJGcaHzXT7mU00GPTszD9Fq0gk7KaNwIaIo873">
  <div class="row mb-3">
    <label for="field-lLL6255Gr9" class="col-2 col-form-label">Image</label>
    <div class="col-10">
      <img src="https://picsum.photos/100" class="img-fluid">
    </div>
  </div>
  <div class="col-12 text-end">
    <button class="btn btn-primary" type="submit">Save</button>
  </div>
</form>
There are a few bult-in utilities that can be used out-of-the-box, both to enrich the visualization and customize the behaviour of the fields. Those do not cover all combinations provided by Bootstrap, but still are handy in most cases.
@
Code
<?php $obj = (object) ['id' => 1234, 'name' => 'Foo', 'email' => 'foo@bar.baz', 'country' => 'it'] ?>
<x-larastrap::form :obj="$obj" action="/user/save">
  <x-larastrap::text name="name" label="Name" :classes="['is-invalid']" />
  <x-larastrap::text name="surname" label="Surname" pophelp="This is an extensive description text about the field, displayed only on hover. Requires initialization of Bootstrap's popovers" />
  <x-larastrap::email name="email" label="EMail" textappend="@" />

  <?php $countries = ['fr' => 'France', 'de' => 'Germany', 'it' => 'Italy'] ?>
  <x-larastrap::select name="country" npostfix="[]" label="Array of Countries" :options="$countries" />
  <x-larastrap::select name="country" npostfix="[]" label="Array of Countries" :options="$countries" />
</x-larastrap::form>
<form id="form-ArJRh2qmX1" class="" method="post" action="/user/save" novalidate="" name="form-ArJRh2qmX1">
  <input type="hidden" name="_token" value="UmiJGcaHzXT7mU00GPTszD9Fq0gk7KaNwIaIo873">
  <div class="row mb-3">
    <label for="input-GjcvqqHx0a" class="col-2 col-form-label">Name</label>
    <div class="col-10">
      <input id="input-GjcvqqHx0a" type="text" class="is-invalid form-control" name="name" value="Foo">
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-mCINSB5Rim" class="col-2 col-form-label">Surname <span class="badge rounded-pill bg-primary" data-bs-toggle="popover" data-bs-trigger="hover" data-bs-content="This is an extensive description text about the field, displayed only on hover. Requires initialization of Bootstrap's popovers">?</span></label>
    <div class="col-10">
      <input id="input-mCINSB5Rim" type="text" class="form-control" name="surname" value="">
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-6VtzNvOUns" class="col-2 col-form-label">EMail</label>
    <div class="col-10">
      <div class="input-group">
        <input id="input-6VtzNvOUns" type="email" class="form-control" name="email" value="foo@bar.baz"> <span class="input-group-text">@</span>
      </div>
    </div>
  </div>
  <div class="row mb-3">
    <label for="select-Gd1C9IfOYc" class="col-2 col-form-label">Array of Countries</label>
    <div class="col-10">
      <select class="form-select" name="country[]">
        <option value="fr">
          France
        </option>
        <option value="de">
          Germany
        </option>
        <option value="it" selected>
          Italy
        </option>
      </select>
    </div>
  </div>
  <div class="row mb-3">
    <label for="select-JAExlah6La" class="col-2 col-form-label">Array of Countries</label>
    <div class="col-10">
      <select class="form-select" name="country[]">
        <option value="fr">
          France
        </option>
        <option value="de">
          Germany
        </option>
        <option value="it" selected>
          Italy
        </option>
      </select>
    </div>
  </div>
  <div class="col-12 text-end">
    <button class="btn btn-primary" type="submit">Save</button>
  </div>
</form>

Modals

The classic Bootstrap modal. The x-larastrap::button component has a special triggers_modal property to rapidly setup a trigger.
Bootstrap documentation
Code
<x-larastrap::button label="Open Modal" triggers_modal="#test-modal" />

<x-larastrap::modal title="Test" id="test-modal">
  <p>Ciao</p>
</x-larastrap::modal>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#test-modal">Open Modal</button>
<div class="modal fade" id="test-modal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-none">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">
          Test
        </h5>
      </div>
      <div class="modal-body">
        <p>
          Ciao
        </p>
      </div>
      <div class="modal-footer">
        <button class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>
A form into a modal is a special (automatically managed) case, in which buttons for the form are merged into the modal's footer.
Code
<x-larastrap::button label="Open Modal with Form" triggers_modal="#save-modal" />

<x-larastrap::modal title="Test" id="save-modal">
  <?php $obj = (object) ['id' => 1234, 'name' => 'Foo', 'email' => 'foo@bar.baz'] ?>
  <x-larastrap::form :obj="$obj" action="/user/save">
    <x-larastrap::hidden name="id" />
    <x-larastrap::text name="name" label="Name" />
    <x-larastrap::email name="email" label="EMail" />
  </x-larastrap::form>
</x-larastrap::modal>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#save-modal">Open Modal with Form</button>
<div class="modal fade" id="save-modal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-none">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">
          Test
        </h5>
      </div>
      <div class="modal-body">
        <form id="form-aA6bDZgqUo" class="" method="post" action="/user/save" novalidate="" name="form-aA6bDZgqUo">
          <input type="hidden" name="_token" value="UmiJGcaHzXT7mU00GPTszD9Fq0gk7KaNwIaIo873"> <input id="hidden-lmZkIwObTD" type="hidden" class="" name="id" value="1234">
          <div class="row mb-3">
            <label for="input-LmQJXnvefw" class="col-2 col-form-label">Name</label>
            <div class="col-10">
              <input id="input-LmQJXnvefw" type="text" class="form-control" name="name" value="Foo">
            </div>
          </div>
          <div class="row mb-3">
            <label for="input-bnftCp5BTE" class="col-2 col-form-label">EMail</label>
            <div class="col-10">
              <input id="input-bnftCp5BTE" type="email" class="form-control" name="email" value="foo@bar.baz">
            </div>
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button class="btn btn-secondary" data-bs-dismiss="modal">Close</button> <button class="btn btn-primary" type="submit" form="form-aA6bDZgqUo">Save</button>
      </div>
    </div>
  </div>
</div>

Tabs

Tabs are managed as a hiearchy of elements: the options associative array permits to specify the contents of the tabs, and each x-larastrap::tabpane is a tab page. By default, the first tab is active.
Remember that you can alter the classes attribute (both inline or once in the configuration file) to pass formatting classes for the tab panes (useful for padding and margins).
Bootstrap documentation

This is the first tab!

This is the second tab!

Code
<x-larastrap::tabs>
  <x-larastrap::tabpane label="First">
    <p>This is the first tab!</p>
  </x-larastrap::tabpane>

  <x-larastrap::tabpane label="Second" active="true">
    <p>This is the second tab!</p>
  </x-larastrap::tabpane>
</x-larastrap::tabs>
<ul class="nav nav-tabs" id="tabs-MjFlt1Mdyd" role="tablist">
  <li class="nav-item" role="presentation">
    <button class="nav-link btn btn-primary" role="tab" data-bs-toggle="tab" data-bs-target="#tabpane-pMXVacNx4n">First</button>
  </li>
  <li class="nav-item" role="presentation">
    <button class="nav-link active btn btn-primary" role="tab" data-bs-toggle="tab" data-bs-target="#tabpane-btlSq93rkI">Second</button>
  </li>
</ul>
<div class="tab-content" id="tabs-MjFlt1Mdyd_contents">
  <div class="p-3 tab-pane fade" id="tabpane-pMXVacNx4n" role="tabpanel">
    <p>
      This is the first tab!
    </p>
  </div>
  <div class="p-3 tab-pane fade show active" id="tabpane-btlSq93rkI" role="tabpanel">
    <p>
      This is the second tab!
    </p>
  </div>
</div>
Different styles for the tabs are possibile.
Remember to always define as active one of the tabpanes!
Bootstrap documentation

This is the first tab!

This is the second tab!

Code
<x-larastrap::tabs tabview="pills">
  <x-larastrap::tabpane label="First" active="true">
    <p>This is the first tab!</p>
  </x-larastrap::tabpane>

  <x-larastrap::tabpane label="Second">
    <p>This is the second tab!</p>
  </x-larastrap::tabpane>
</x-larastrap::tabs>
<ul class="nav nav-pills" id="tabs-JnIO5AcZ0P" role="tablist">
  <li class="nav-item" role="presentation">
    <button class="nav-link active btn btn-primary" role="tab" data-bs-toggle="tab" data-bs-target="#tabpane-EPzfjnb9j6">First</button>
  </li>
  <li class="nav-item" role="presentation">
    <button class="nav-link btn btn-primary" role="tab" data-bs-toggle="tab" data-bs-target="#tabpane-EOZGbCJDHS">Second</button>
  </li>
</ul>
<div class="tab-content" id="tabs-JnIO5AcZ0P_contents">
  <div class="p-3 tab-pane fade show active" id="tabpane-EPzfjnb9j6" role="tabpanel">
    <p>
      This is the first tab!
    </p>
  </div>
  <div class="p-3 tab-pane fade" id="tabpane-EOZGbCJDHS" role="tabpanel">
    <p>
      This is the second tab!
    </p>
  </div>
</div>

Accordion

Accordions are not much different from tabs: there is a wrapper component and child components, one for panel. Each sub panel can be individually opened through the active attribute.
Bootstrap documentation

This is the first accordion!

This is the second accordion!

Code
<x-larastrap::accordion always_open="true">
  <x-larastrap::accordionitem label="First">
    <p>This is the first accordion!</p>
  </x-larastrap::accordionitem>

  <x-larastrap::accordionitem label="Second" active="true">
    <p>This is the second accordion!</p>
  </x-larastrap::accordionitem>
</x-larastrap::accordion>
<div class="accordion" id="accordion-hNUto6qgY3">
  <div class="accordion-item">
    <h2 class="accordion-header" id="head-accordionitem-E14OtR9gjY">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#accordionitem-E14OtR9gjY" aria-expanded="false" aria-controls="accordionitem-E14OtR9gjY">First</button>
    </h2>
    <div id="accordionitem-E14OtR9gjY" class="accordion-collapse collapse" aria-labelledby="head-accordionitem-E14OtR9gjY">
      <div class="accordion-body">
        <p>
          This is the first accordion!
        </p>
      </div>
    </div>
  </div>
  <div class="accordion-item">
    <h2 class="accordion-header" id="head-accordionitem-CdmbwAvgnk">
      <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#accordionitem-CdmbwAvgnk" aria-expanded="true" aria-controls="accordionitem-CdmbwAvgnk">Second</button>
    </h2>
    <div id="accordionitem-CdmbwAvgnk" class="accordion-collapse collapse show" aria-labelledby="head-accordionitem-CdmbwAvgnk">
      <div class="accordion-body">
        <p>
          This is the second accordion!
        </p>
      </div>
    </div>
  </div>
</div>

Miscellaneous

Code
<x-larastrap::button label="Yes, this is a button" color="warning" />
<button class="btn btn-warning">Yes, this is a button</button>
Button groups!
Bootstrap documentation
Code
<x-larastrap::btngroup>
  <x-larastrap::button label="First" />
  <x-larastrap::button label="Second" />
  <x-larastrap::button label="Third" />
</x-larastrap::btngroup>
<div class="btn-group" role="group">
  <button class="btn btn-primary">First</button> <button class="btn btn-primary">Second</button> <button class="btn btn-primary">Third</button>
</div>
More input fields!
Code
<x-larastrap::form>
  <x-larastrap::check label="Checkbox" />
  <x-larastrap::check label="Switch" switch />
  <x-larastrap::url label="URL" />
  <x-larastrap::range label="Range" min="0" max="100" step="5" />
  <x-larastrap::date label="Date" />
  <x-larastrap::time label="Time" />
  <x-larastrap::datetime label="Date and Time" />
  <x-larastrap::color label="Color" />
</x-larastrap::form>
<form id="form-6Fbs6dGkOJ" class="" method="post" novalidate="" name="form-6Fbs6dGkOJ">
  <input type="hidden" name="_token" value="UmiJGcaHzXT7mU00GPTszD9Fq0gk7KaNwIaIo873">
  <div class="row mb-3">
    <label for="check-aJqpDYWpbw" class="col-2 col-form-label">Checkbox</label>
    <div class="col-10">
      <div class="form-check mt-1">
        <input id="check-aJqpDYWpbw" type="checkbox" class="form-check-input" name="" value="">
      </div>
    </div>
  </div>
  <div class="row mb-3">
    <label for="check-oBTT6cUKb4" class="col-2 col-form-label">Switch</label>
    <div class="col-10">
      <div class="form-check form-switch mt-1">
        <input id="check-oBTT6cUKb4" type="checkbox" class="form-check-input" name="" value="">
      </div>
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-6Td8qRZhKq" class="col-2 col-form-label">URL</label>
    <div class="col-10">
      <input id="input-6Td8qRZhKq" type="url" class="form-control" name="" value="">
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-a72jEL0kRV" class="col-2 col-form-label">Range</label>
    <div class="col-10">
      <input id="input-a72jEL0kRV" type="range" class="form-range" name="" value="" step="5" min="0" max="100">
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-KcQsvwrLuo" class="col-2 col-form-label">Date</label>
    <div class="col-10">
      <input id="input-KcQsvwrLuo" type="date" class="form-control" name="" value="">
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-qf7gMImBnv" class="col-2 col-form-label">Time</label>
    <div class="col-10">
      <input id="input-qf7gMImBnv" type="time" class="form-control" name="" value="">
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-gdKOLDykle" class="col-2 col-form-label">Date and Time</label>
    <div class="col-10">
      <input id="input-gdKOLDykle" type="datetime-local" class="form-control" name="" value="">
    </div>
  </div>
  <div class="row mb-3">
    <label for="input-9APxBodUdb" class="col-2 col-form-label">Color</label>
    <div class="col-10">
      <input id="input-9APxBodUdb" type="color" class="form-control" name="" value="">
    </div>
  </div>
  <div class="col-12 text-end">
    <button class="btn btn-primary" type="submit">Save</button>
  </div>
</form>
Optgroups in selects!
Code
<?php

$options = [
    'first' => (object) [
        'label' => 'First Group',
        'children' => [
            'first_1' => 'First Item in First Group',
            'first_2' => 'Second Item in First Group',
        ],
    ],
    'second' => (object) [
        'label' => 'Second Group',
        'children' => [
            'second_1' => 'First Item in Second Group',
            'second_2' => (object) [
                'label' => 'Second Item in Second Group (disabled)',
                'disabled' => true,
            ],
            'second_3' => 'Third Item in Second Group',
        ],
    ],
];

?>

<x-larastrap::select label="Select in groups" :options="$options" />
<div class="row mb-3">
  <label for="select-GdruvBO916" class="col-2 col-form-label">Select in groups</label>
  <div class="col-10">
    <select class="form-select" name="">
      <optgroup label="First Group">
        <option value="first_1">
          First Item in First Group
        </option>
        <option value="first_2">
          Second Item in First Group
        </option>
      </optgroup>
      <optgroup label="Second Group">
        <option value="second_1">
          First Item in Second Group
        </option>
        <option value="second_2" disabled>
          Second Item in Second Group (disabled)
        </option>
        <option value="second_3">
          Third Item in Second Group
        </option>
      </optgroup>
    </select>
  </div>
</div>
Complex radio selections! The same applies for x-larastrap::checks, too!
Code
<?php

$options = [
    'first' => 'First',
    'second' => 'Second',
    'third' => (object) [
        'label' => 'Third (disabled)',
        'disabled' => true,
    ],
    'fourth' => (object) [
        'label' => 'Fourth (hidden)',
        'hidden' => true,
    ],
    'fifth' => (object) [
        'label' => 'Fifth (with data attributes)',
        'button_attributes' => ['data-example' => 'test'],
    ],
];

?>

<x-larastrap::radios name="choose" label="Choose one" :options="$options" value="second" />
<div class="row mb-3">
  <label for="radios-c7maGFZJ2Q" class="col-2 col-form-label col-2 col-form-label">Choose one</label>
  <div class="col-10">
    <div class="btn-group" role="group">
      <input type="radio" class="btn-check" name="choose" id="radios-c7maGFZJ2Q-8483762765692064104" autocomplete="off" value="first"> <label class="btn btn-outline-primary" for="radios-c7maGFZJ2Q-8483762765692064104">First</label> <input type="radio" class="btn-check" name="choose" id="radios-c7maGFZJ2Q-607822747034759195" autocomplete="off" value="second" checked> <label class="btn btn-outline-primary" for="radios-c7maGFZJ2Q-607822747034759195">Second</label> <input type="radio" class="btn-check" name="choose" id="radios-c7maGFZJ2Q-6216138664917403624" autocomplete="off" value="third"> <label class="btn btn-outline-primary disabled" for="radios-c7maGFZJ2Q-6216138664917403624">Third (disabled)</label> <input type="radio" class="btn-check" name="choose" id="radios-c7maGFZJ2Q-7808012056858176865" autocomplete="off" value="fourth"> <input type="radio" class="btn-check" name="choose" id="radios-c7maGFZJ2Q-377108482481663833" autocomplete="off" value="fifth"> <label class="btn btn-outline-primary" for="radios-c7maGFZJ2Q-377108482481663833" data-example="test">Fifth (with data attributes)</label>
    </div>
  </div>
</div>

Custom Elements

In the config/larastrap.php file is possible to define custom presets, to be reused across the application using a specific set of configurations. Those are defined by a Blade component name, the name of the extended element type, and your own parameters.

Are you sure you want to delete this element?

Code
<!--

You find this example in the default config/larastrap.php file

'customs' => [
  'deleteform' => [  \\ <--- This is the name of your custom component!
    'extends' => 'form',
    'params' => [
      'classes' => ['text-center'],
      'method' => 'DELETE',
      'form_buttons' => [['color' => 'danger', 'label' => 'Yes, delete it', 'attributes' => ['type' => 'submit']]]
    ],
  ],
],

-->

<x-larastrap::deleteform action="/user/delete">
  <x-larastrap::hidden name="id" value="123" />
  <p>Are you sure you want to delete this element?</p>
</x-larastrap::deleteform>
<form id="form-VHdggUBKQq" class="text-center" method="delete" action="/user/delete" novalidate="" name="form-VHdggUBKQq">
  <input type="hidden" name="_token" value="UmiJGcaHzXT7mU00GPTszD9Fq0gk7KaNwIaIo873"> <input type="hidden" name="_method" value="DELETE"> <input id="hidden-bnoI2kTahk" type="hidden" class="" name="id" value="123">
  <p>
    Are you sure you want to delete this element?
  </p>
  <div class="col-12 text-center">
    <button class="btn btn-danger" type="submit">Yes, delete it</button>
  </div>
</form>
It is possible to dinamically create custom elements at runtime, accessing the LarastrapStack singleton inited by the Larastrap Service Provider.
Code
<?php

/*
    Call this before Blade rendering, e.g. in the parent Controller or in a Service Provider
*/
app()->make('LarastrapStack')->addCustomElement('jerkbutton', [
    'extends' => 'button',
    'params' => [
        'color' => 'secondary',
        'postlabel' => ' (Click Here!)',
    ],
]);

?>

<x-larastrap::jerkbutton label="A Button" />
<button class="btn btn-secondary">A Button (Click Here!)</button>

All Elements and Properties

Your can include any component using the proper Blade directive, and passing attributes to it. All the attributes here listed are processed internally and may not appear in the final rendered node; those that are not managed (e.g. your own data attributes) are simply translated into the final HTML.

Some attributes are valid for every kind of component, such as:

  • id
    The ID of the HTML node. If not specified, a random one is generated so that all items are properly marked
  • attributes
    An associative array which is translated to an extra set of attributes to the node. Useful to attach your data attributes, custom attributes, hooks for your preferred Javascript framework and so on
  • classes
    An array of CSS classes to be added to the HTML node, including those automatically generated. Can be defined as an array or a space separated string
  • hidden
    A boolean attribute which hides the element
  • reviewCallback
    A function to be called for manually handle and transform the parameters of the node. This have to take two parameters (the first is the instance of the component, the second is the indexed array of parameters) and returns the (eventually modified) array of parameters. Mostly intended for Custom Elements

Some components are Containers, so have an opening and a closing tag. Their behaviour may be altered by child elements. Those always accept the following attributes:

  • obj
    A PHP object (eventually, an Eloquent model) used to automatically populate the value of inner input fields

Then there are Inputs, used (usually into form) to take user inputs. Those are automatically wrapped by a x-larastap::field to format them within the parent Container. Common attributes:

  • label
    The label to be displayed within the input field into the form, accordly to his formview
  • label_class
    CSS classes to be applied to the label, aside those automatically generated
  • label_width
    Width, in Bootstrap columns, of the label column. Can be a simple integer, to be used once for all Bootstrap's breakpoints, or an associative array containing the desired width for each target breackpoint, such as ["xs" => 4, "sm" => 3, "md" => 2]
  • input_width
    Width, in Bootstrap columns, of the input field column. Same rules as label_width
  • help
    An optional text to be displayed below the input field
  • pophelp
    An optional text to be displayed in a popover, aside the label. This is intended for long text, as an alternative to help. If you use this, remember to init Bootstrap's popovers
  • squeeze
    If true, the wrapping x-larastap::field is omitted and just the input field is rendered
  • name
    HTML name of the input field. If matches with a property of the obj set into the parent Container, the input field is inited with the same value
  • nprefix
    Optional text to prepend to the name
  • npostfix
    Optional text to append to the name
  • value
    Value of the input field. If defined, will override the same value got from the obj object set into the parent Container
  • required
    True or false, if the input field has to be marked as mandatory for the user
  • disabled
    True or false, if the input field has to be marked as disabled for the user
  • readonly
    True or false, if the input field has to be marked as read only for the user
  • placeholder
    Optional placeholder to display when the input field is empty
  • textappend
    If defined and not empty, will create a Bootstrap input group with this text appended to the input

Following, a complete list of components with their custom properties and notes about how common properties are managed in special cases.

x-larastrap::accordion Container
  • always_open
    Set to true if opening an inner panel will not close all others
x-larastrap::accordionitem Container
  • active
    Set to true to display the panel opened
  • label
    Text to be displayed into the opening header
  • label_html
    Use this attribute if you want to use HTML code in the header (plain label is escaped by Blade)
x-larastrap::btngroup Container
x-larastrap::button
  • color
    One of the colors described by Bootstrap. Of course you can define your own custom CSS classes and add more colors
  • label
    Text to be displayed into the button
  • postlabel
    A static text to be placed after the label
  • prelabel
    A static text to be placed before the label
  • triggers_modal
    If set, the button will be set up to trigger the modal identified by the selector here specified
x-larastrap::check Input
  • checked
    If set, overrides the content of value to determine if the checkbox must be flagged
  • switch
    True to render the checkbox as a switch
  • value
    The value of the checkbox. If it is a boolean, is it used to set the checkbox as flagged or not
x-larastrap::checks
  • color
    One of the colors described by Bootstrap. Of course you can define your own custom CSS classes and add more colors
  • npostfix
    If not defined, this is set to [] to enforce handling of submitted checked options as an array
  • options
    Indexed array of options. May be a simple [value => label] array, otherwise "label" may be replaced by an object including the properties:
    • label: for the actual label
    • disabled: if set to true, the option is disabled
    • hidden: if set to true, the label is not displayed (but an invisible input radio is still rendered in HTML)
    • button_attributes: indexed array of additional attributes for the label
x-larastrap::color Input
x-larastrap::date Input
x-larastrap::datetime Input
x-larastrap::email Input
x-larastrap::enclose Container
x-larastrap::field Container
x-larastrap::file Input
x-larastrap::form Container
  • action
    The action URL of the form
  • buttons
    An array of associative arrays for each buttons to display at the end of the form. Same properties as for the x-larastrap::button component. If you override the default buttons, remember to always add one having a ["type" => "submit"] attribute!
  • buttons_align
    Alignment of form buttons. Valid values: start, end, center
  • enctype
    The enctype of the form. Please note that file component already handles this transparently
  • formview
    Style to be applied to the form, determines layout of inner fields. Valid values: horizontal, vertical, inline, grid
  • gutter
    Used for fields spacing when formview is inline or grid
  • method
    The HTML method (GET, POST, DELETE, PUT...) of the form. If it is not GET, the @method and @csrf Blade directives are automatically managed
  • novalidate
    By default this is set to true, to leverage native Bootstrap validation
x-larastrap::hidden
x-larastrap::modal Container
  • buttons
    An array containing associative arrays for each buttons to display at the end of the modal. Same properties as for the button component. If you override the default buttons, keep in mind to have one button with a ["attributes" => ["data-bs-dismiss" => "modal"]] attribute to close the modal!
  • scrollable
    True if the modal has to be set as scrollable
  • size
    The size of the modal. Can be a string (sm, lg, xl...) or an array of Bootstrap classes, to include also fullscreen behaviours
  • title
    Title of the modal
x-larastrap::navbar
  • color
    One of the colors described by Bootstrap for navbars. Of course you can define your own custom CSS classes and add more colors
  • end_options
    Same as options, but buttons are displayed on the end side of the navbar
  • options
    Indexed array of menu items. May be a simple [label => url] array, otherwise "url" may be replaced by an object including the properties:
    • url: the actual URL to link
    • active: if the menu item has to be highlighted. Note that Larastrap already tries to determine the currently active menu item, accordly to the current Route
    • children: if a dropdown menu has be to generated, this must include another indexed array recursively handled
  • title
    Title of the navbar
  • title_link
    Optional URL to link in the navbar title
x-larastrap::number Input
  • max
    The maximum value for the input
  • min
    The minimum value for the input
  • step
    The step value for the input
x-larastrap::password Input
x-larastrap::pophelp
  • text
    Text to display into the popover
x-larastrap::radios
  • color
    One of the colors described by Bootstrap. Of course you can define your own custom CSS classes and add more colors
  • options
    Indexed array of options. May be a simple [value => label] array, otherwise "label" may be replaced by an object including the properties:
    • label: for the actual label
    • disabled: if set to true, the option is disabled
    • hidden: if set to true, the label is not displayed (but an invisible input radio is still rendered in HTML)
    • button_attributes: indexed array of additional attributes for the label
x-larastrap::range Input
  • max
    The maximum value for the input
  • min
    The minimum value for the input
  • step
    The step value for the input
x-larastrap::select Input
  • multiple
    True for a multiple selection
  • npostfix
    If not defined, and multiple is active, this is set to [] to enforce handling of submitted selected options as an array
  • options
    Indexed array of options. May be a simple [value => label] array, otherwise "label" may be replaced by an object including the properties:
    • label: for the actual label
    • disabled: if set to true, the option is disabled
    • children: if an optgroup has be to generated, this must include another indexed array recursively handled
  • readonly
    If set to true, this forces the select to display as a static text with the selected option's label
x-larastrap::tabpane Container
  • active
    Set to true to display the pane. Only one active pane is opened at once in tabs
  • button_attributes
    Additional indexed array of attributes for the tab
  • button_classes
    Additional array of CSS classes for the tab
x-larastrap::tabs Container
  • tabview
    Style to be applied to the tabs. Valid values: tabs, pills
x-larastrap::text Input
x-larastrap::textarea Input
x-larastrap::time Input
x-larastrap::url Input