Skip to content

Instantly share code, notes, and snippets.

@eightyfive
Created November 22, 2020 21:21
Show Gist options
  • Save eightyfive/b0ae559ac0557ddbaf955ebebbb76325 to your computer and use it in GitHub Desktop.
Save eightyfive/b0ae559ac0557ddbaf955ebebbb76325 to your computer and use it in GitHub Desktop.
Bulma Laravel Blade components
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\Support\HtmlString;
abstract class Bulma extends Component
{
protected $classes = [];
protected $name;
/**
* Create a new component instance.
*
* @return void
*/
public function __construct(
// Colors
$white = false,
$light = false,
$dark = false,
$black = false,
$text = false,
$ghost = false,
$primary = false,
$link = false,
$info = false,
$success = false,
$warning = false,
$danger = false,
// Sizes
$small = false,
$normal = false,
$medium = false,
$large = false,
// Displays
$fullwidth = false,
// Styles
$outlined = false,
$inverted = false,
$rounded = false,
// States
$hovered = false,
$focused = false,
$active = false,
$loading = false,
$static = false
) {
$this->classes = $this->is(
compact(
'white',
'light',
'dark',
'black',
'text',
'ghost',
'primary',
'link',
'info',
'success',
'warning',
'danger',
'small',
'normal',
'medium',
'large',
'fullwidth',
'outlined',
'inverted',
'rounded',
'hovered',
'focused',
'active',
'loading',
'static'
)
);
if ($name = $this->getName()) {
array_unshift($this->classes, $name);
}
}
protected function getName()
{
if (!isset($this->name)) {
$reflect = new \ReflectionClass($this);
$this->name = \strtolower($reflect->getShortName());
}
return $this->name;
}
protected function is(array $modifiers = [])
{
$classes = [];
foreach ($modifiers as $mod => $bool) {
if ($bool) {
$classes[] = 'is-' . $mod;
}
}
return $classes;
}
public function render()
{
return function (array $data) {
$attributes = $data['attributes']->merge([
'class' => \implode(' ', $this->classes),
]);
return $this->template($attributes, $data['slot']);
};
}
abstract protected function template(
ComponentAttributeBag $attributes,
HtmlString $slot
);
}
<?php
namespace App\View\Components;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\Support\HtmlString;
class Button extends Bulma
{
protected function template(
ComponentAttributeBag $attributes,
HtmlString $slot
) {
if ($attributes->get('href')) {
return "<a {$attributes}>{$slot}</a>";
}
$attributes = $attributes->merge(['type' => 'submit']);
return "<button {$attributes}>{$slot}</button>";
}
}
<?php
namespace App\View\Components;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\Support\HtmlString;
class Checkbox extends Bulma
{
protected $name = false;
protected function template(
ComponentAttributeBag $attributes,
HtmlString $slot
) {
$disabled = $attributes->get('disabled') ? 'disabled' : '';
$attributes = $attributes->merge(['type' => 'checkbox']);
return "<label class=\"checkbox\" {$disabled}><input {$attributes} />{$slot}</label>";
}
}
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Field extends Component
{
public $left;
public $right;
public $error;
public $errors;
public $help;
public $label;
public function __construct(
$left = '',
$right = '',
$error = '',
$errors = [],
$help = '',
$label = ''
) {
$this->left = $left;
$this->right = $right;
$this->error = $error;
$this->errors = $errors;
$this->help = $help;
$this->label = $label;
}
public function render()
{
return function (array $data) {
$addon = $data['left'] ?? ($data['right'] ?? null);
if ($addon) {
$addon = "<div class=\"control\">{$addon}</div>";
}
$content = "";
// Label
if ($data['label']) {
$content .= "<label class=\"label\">{$data['label']}</label>";
}
// Addon (left)
if ($data['left']) {
$content .= $addon;
}
// Control
$class = 'control' . ($addon ? ' is-expanded' : '');
$content .= "<div class=\"{$class}\">{$data['slot']}</div>";
// Addon (right)
if ($data['right']) {
$content .= $addon;
}
if ($data['error']) {
$content .= "<p class=\"help is-danger\">{$data['error']}</p>";
} elseif (count($data['errors'])) {
$errors = implode('<br />', $data['errors']);
$content .= "<p class=\"help is-danger\">{$errors}</p>";
} elseif ($data['help']) {
$content .= "<p class=\"help\">{$data['help']}</p>";
}
// Field (container)
$attributes = $data['attributes']->merge([
'class' => 'field' . ($addon ? ' has-addons' : ''),
]);
return "<div {$attributes}>{$content}</div>";
};
}
}
<?php
namespace App\View\Components;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\Support\HtmlString;
class Input extends Bulma
{
protected function template(
ComponentAttributeBag $attributes,
HtmlString $slot
) {
$attributes = $attributes->merge([
'id' => $attributes->get('name'),
'type' => 'text',
]);
return "<input {$attributes} />";
}
}
<?php
namespace App\View\Components;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\Support\HtmlString;
class Message extends Bulma
{
protected function template(
ComponentAttributeBag $attributes,
HtmlString $slot
) {
return "<div {$attributes}><div class=\"message-body\">{$slot}</div></div>";
}
}
<?php
namespace App\View\Components;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\Support\HtmlString;
class Notification extends Bulma
{
protected function template(
ComponentAttributeBag $attributes,
HtmlString $slot
) {
return "<div {$attributes}>{$slot}</div>";
}
}
<?php
namespace App\View\Components;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\Support\HtmlString;
class Radio extends Bulma
{
protected $name = false;
protected function template(
ComponentAttributeBag $attributes,
HtmlString $slot
) {
$disabled = $attributes->get('disabled') ? 'disabled' : '';
$attributes = $attributes->merge(['type' => 'radio']);
return "<label class=\"radio\" {$disabled}><input {$attributes} />{$slot}</label>";
}
}
<?php
namespace App\View\Components;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\Support\HtmlString;
class Tag extends Bulma
{
protected function template(
ComponentAttributeBag $attributes,
HtmlString $slot
) {
$as = $attributes->get('href') ? 'a' : 'span';
return "<{$as} {$attributes}>{$slot}</{$as}>";
}
}
<?php
namespace App\View\Components;
use Illuminate\View\ComponentAttributeBag;
use Illuminate\Support\HtmlString;
class Textarea extends Bulma
{
protected function template(
ComponentAttributeBag $attributes,
HtmlString $slot
) {
$attributes = $attributes->merge([
'id' => $attributes->get('name'),
'rows' => 6,
]);
return "<textarea {$attributes}>{$slot}</textarea>";
}
}
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Title extends Component
{
public $as;
public $size;
public $small;
public $spaced;
public function __construct($as, $size, $small = false, $spaced = false)
{
$this->as = $as;
$this->size = $size;
$this->small = $small;
$this->spaced = $spaced;
}
public function render()
{
return function (array $data) {
$classes = [];
$classes[] = $this->small ? 'subtitle' : 'title';
if ($this->size) {
$classes[] = 'is-' . $this->size;
}
if ($this->spaced) {
$classes[] = 'is-spaced';
}
$attributes = $data['attributes']->merge([
'class' => \implode(' ', $classes),
]);
if (isset($this->size)) {
$as = $this->as ?? 'h' . $this->size;
} else {
$as = $this->as ?? ($this->small ? 'h2' : 'h1');
}
return "<{$as} {$attributes}>{$data['slot']}</{$as}>";
};
}
}
<div {{ $attributes->merge([
'class' => 'container is-max-desktop'
]) }}>
{{ $slot }}
</div>
@props(['title', 'subtitle'])
<div {{ $attributes->merge(['class' => 'header']) }}>
<h1 class="title is-1">
{{ $title }}
</h1>
@if(isset($subtitle))
<h2 class="subtitle">{{ $subtitle }}</h2>
@endif
{{ $slot }}
</div>
@props(['name', 'small' => false, 'right' => false])
<span class="icon @if($small) is-small @endif @if($right) is-right @endif">
<i class="material-icons">{{ $name }}</i>
</span>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment