Skip to content

Instantly share code, notes, and snippets.

@bisonbrah
Last active December 3, 2025 16:40
Show Gist options
  • Select an option

  • Save bisonbrah/f9d24ff92753a9140bd0d68917bbce1d to your computer and use it in GitHub Desktop.

Select an option

Save bisonbrah/f9d24ff92753a9140bd0d68917bbce1d to your computer and use it in GitHub Desktop.
Block example w/ component
<?php
namespace App\Blocks;
use App\Fields\Partials\PaddingOptions;
use App\Traits\PaddingHelpers;
use Log1x\AcfComposer\Block;
use Log1x\AcfComposer\Builder;
class CardsGrid extends Block
{
use PaddingHelpers;
/**
* The block name.
*
* @var string
*/
public $name = 'Cards Grid';
/**
* The block description.
*
* @var string
*/
public $description = 'A beautiful Cards Grid block.';
/**
* The block category.
*
* @var string
*/
public $category = 'theme';
/**
* The block icon.
*
* @var string|array
*/
public $icon = 'editor-ul';
/**
* The block keywords.
*
* @var array
*/
public $keywords = [];
/**
* The block post type allow list.
*
* @var array
*/
public $post_types = ['page'];
/**
* The parent block type allow list.
*
* @var array
*/
public $parent = [];
/**
* The ancestor block type allow list.
*
* @var array
*/
public $ancestor = [];
/**
* The default block mode.
*
* @var string
*/
public $mode = 'preview';
/**
* The default block alignment.
*
* @var string
*/
public $align = '';
/**
* The default block text alignment.
*
* @var string
*/
public $align_text = '';
/**
* The default block content alignment.
*
* @var string
*/
public $align_content = '';
/**
* The default block spacing.
*
* @var array
*/
public $spacing = [];
/**
* The supported block features.
*
* @var array
*/
public $supports = [
'align' => true,
'align_text' => false,
'align_content' => false,
'full_height' => false,
'anchor' => false,
'mode' => true,
'multiple' => true,
'jsx' => true,
'color' => [
'background' => false,
'text' => false,
'gradients' => false,
],
'spacing' => [
'padding' => false,
'margin' => false,
],
];
/**
* The block styles.
*
* @var array
*/
public $styles = [];
/**
* The block preview example data.
*
* @var array
*/
public $example = [];
/**
* The block template.
*
* @var array
*/
public $template = [];
/**
* Data to be passed to the block before rendering.
*/
public function with(): array
{
return [
'featuredCards' => $this->featuredCards(),
'paddingClasses' => $this->paddingClasses(),
];
}
/**
* The block field group.
*/
public function fields(): array
{
$fields = Builder::make('cards_grid')
->addPartial(PaddingOptions::class);
$fields
->addAccordion('cards_grid', [
'label' => 'Block - Cards Grid',
])
->addRepeater('featured_cards', [
'label' => 'Featured Cards',
'collapsed' => 'title',
])
->addText('title', [
'label' => 'Title',
])
->addWysiwyg('content', [
'label' => 'Content',
'media_upload' => 0,
])
->addImage('featured_image', [
'label' => 'Featured Image',
'return_format' => 'ID',
])
// TODO: Convert this into Trait
->addSelect('ascent_color', [
'label' => 'Ascent Color Field',
'instructions' => 'Select an ascent color.',
'choices' => [
'border-lightBlue' => 'lightBlue',
'border-blue' => 'blue',
'border-darkBlue' => 'darkBlue',
'border-teal' => 'teal',
'border-orange' => 'orange',
'border-orangeYellow' => 'orangeYellow',
'border-green' => 'green',
'border-purple' => 'purple',
'border-red' => 'red',
'border-pink' => 'pink',
],
'allow_null' => 1,
'return_format' => 'value',
'placeholder' => 'Select an option',
'wrapper' => ['width' => '33%',],
])
->endRepeater();
return $fields->build();
}
/**
* Retrieve the featured_cards field.
*
* @return array|null
*/
public function featuredCards(): ?array
{
$cards = get_field('featured_cards');
if (empty($cards) || !is_array($cards)) {
return null;
}
$count = count($cards);
foreach ($cards as $i => &$card) {
$card['centered'] = ($count % 2 === 1) && ($i === $count - 1);
}
return $cards;
}
/**
* Retrieve the ascent color class.
*
* @return string|null
*/
public function ascentColor(): ?string
{
return get_field('ascent_color') ?: null;
}
/**
* Assets enqueued when rendering the block.
*/
public function assets(array $block): void
{
//
}
}
<x-block-wrapper :block="$block" additional_classes="not-prose {{ $paddingClasses }}">
<div class="container container-md max-w-container">
<div class="xl:w-4/5 grid grid-cols-1 md:grid-cols-2 md:gap-8 lg:gap-16 xl:gap-28 items-start mx-auto justify-items-center">
@if($featuredCards)
@foreach($featuredCards as $card)
<x-card
:title="$card['title']"
:content="$card['content']"
:borderColor="$card['ascent_color']"
:featuredImage="$card['featured_image']"
:centered="$card['centered'] ?? false"
/>
@endforeach
@endif
</div>
</div>
</x-block-wrapper>
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class Card extends Component
{
public string $title;
public string $content;
public string $borderColor;
public int $featuredImage;
public bool $centered;
/**
* Create a new component instance.
*/
public function __construct(string $title, string $content, string $borderColor, int $featuredImage, bool $centered = false)
{
$this->title = $title;
$this->content = $content;
$this->borderColor = $borderColor;
$this->featuredImage = $featuredImage;
$this->centered = $centered;
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.card');
}
}
<div {{ $attributes->merge([
'class' => 'not-prose relative text-center' . (!empty($centered) ? ' col-span-1 md:col-span-2 mx-auto max-w-md w-full md:max-w-[350px] lg:min-w-[465px] xl:min-w-[505px]' : '')
]) }}>
<div class="hidden lg:block absolute inset-0 -z-10 border-4 lg:h-[45px] xl:h-[75px] {{ $borderColor }} lg:-top-6 xl:-top-10 lg:-left-4 xl:-left-8 lg:-right-4 xl:-right-8"></div>
<div class="relative inline-block">
{!! wp_get_attachment_image($featuredImage, 'card', false, [
'class' => 'w-full h-auto object-cover shadow-lg my-0',
'alt' => get_post_meta($featuredImage, '_wp_attachment_image_alt', true),
]) !!}
</div>
<div class="mt-6 max-w-prose mx-auto">
@if($title)
<h3 class="font-bold text-darkBlue uppercase text-3xl mb-2">{{ $title }}</h3>
@endif
@if($content)
<div class="text-xl text-darkBlue font-thin [&_p]:leading-normal [&_a]:text-teal [&_a]:underline [&_a:hover]:text-darkBlue [&_a:hover]:no-underline [&_strong]:font-bold">
{!! $content !!}
</div>
@endif
</div>
</div>
<?php
namespace App\Fields\Partials;
use Log1x\AcfComposer\Builder;
use Log1x\AcfComposer\Partial;
class PaddingOptions extends Partial
{
/**
* The partial field group.
*/
public function fields(): Builder
{
$fields = Builder::make('padding_options');
$fields
->addAccordion('padding_options', [
'label' => 'Partial - Padding Options',
])
->addSelect('padding_top', [
'label' => 'Padding Top',
'choices' => [
'3em' => 'Default',
'1.5em' => 'Half',
'6em' => 'Double',
'none' => 'None'
],
'default_value' => ['Default'],
'wrapper' => ['width' => '33%',],
])
->addSelect('padding_bottom', [
'label' => 'Padding Bottom',
'choices' => [
'3em' => 'Default',
'1.5em' => 'Half',
'6em' => 'Double',
'none' => 'None'
],
'default_value' => ['Default'],
'wrapper' => ['width' => '33%',],
]);
return $fields;
}
}
<?php
namespace App\Traits;
/**
* Provides helper methods to manage and retrieve padding values and their corresponding
* Tailwind CSS classes for top and bottom padding configuration. Used within other ACF
* blocks.
*/
trait PaddingHelpers
{
/**
* Return the padding_top field value.
*
* @return string|null
*/
protected function paddingTop(): ?string
{
return get_field('padding_top');
}
/**
* Return the padding_bottom field value.
*
* @return string|null
*/
protected function paddingBottom(): ?string
{
return get_field('padding_bottom');
}
/**
* Determines and returns the Tailwind classes for the top and bottom padding
* based on the configured container padding values.
*
* @return string The combined classes representing the top and bottom padding.
*/
protected function paddingClasses(): string
{
$top = match ($this->paddingTop() ?? '') {
'1.5em' => 'pt-[1.5em] md:pt-[1.5em]',
'6em' => 'pt-[1.5em] md:pt-[3em] lg:pt-[6em]',
'none' => 'pt-0',
default => 'pt-[1.5em] md:pt-[3em]',
};
$bottom = match ($this->paddingBottom() ?? '') {
'1.5em' => 'pb-[1.5em] md:pb-[1.5em]',
'6em' => 'pb-[1.5em] md:pb-[3em] lg:pb-[6em]',
'none' => 'pb-0',
default => 'pb-[1.5em] md:pb-[3em]',
};
return "{$top} {$bottom}";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment