minor improvement in showing custom fields in product page and boboko-core sourced locally

This commit is contained in:
elvira
2026-09-25 22:39:14 +03:00
parent ab7e560a3d
commit 8e186fc231
4 changed files with 44 additions and 13 deletions
@@ -5,6 +5,10 @@
inside the add-to-cart <form> so their values travel with it as
custom_fields[key]. text → input, textarea → textarea, file → photo upload.
The label is styled like the product option labels (option-buttons /
color-swatch); the optional help_text shows under it. Help text is
product-page only; the cart/checkout line meta only snapshots the label.
A photo is uploaded as soon as it's picked (custom-field-upload-controller.js)
and only the resulting File row's id (boboko-core's Modules\Core\File\
Models\File) is submitted with the form — the file input itself has no
@@ -22,18 +26,25 @@
$id = 'custom-field-'.$field['key'];
$name = 'custom_fields['.$field['key'].']';
$required = (bool) ($field['required'] ?? false);
$hint = filled($field['help_text'] ?? null) ? $field['help_text'] : null;
// mb-1 on top of the field's gap-2 matches the option labels' mb-3;
// with a hint, the label + hint group carries that spacing instead.
$labelClass = 'font-bold text-sm uppercase tracking-wide'.($hint ? '' : ' mb-1');
$hintId = $hint ? $id.'-hint' : null;
@endphp
@switch($field['type'])
@case('textarea')
<x-ui.field :label="$field['label']" :for="$id" :required="$required">
<x-ui.textarea :id="$id" :name="$name" :required="$required" :rows="4" maxlength="2000" />
<x-ui.field :label="$field['label']" :label-class="$labelClass" :hint="$hint" :for="$id" :required="$required">
<x-ui.textarea :id="$id" :name="$name" :required="$required" :rows="4" maxlength="2000" :aria-describedby="$hintId" />
</x-ui.field>
@break
@case('file')
<x-ui.field
:label="$field['label']"
:label-class="$labelClass"
:hint="$hint"
:for="$id"
:required="$required"
:description="__('storefront.product.custom_field_photo_hint', ['size' => CustomFieldUploadController::MAX_KILOBYTES / 1024])"
@@ -49,7 +60,7 @@
:id="$id"
:accept="CustomFieldUploadController::accept()"
:required="$required"
aria-describedby="{{ $id }}-description {{ $id }}-error"
aria-describedby="{{ $hintId ? $hintId.' ' : '' }}{{ $id }}-description {{ $id }}-error"
data-custom-field-upload-target="file"
data-action="change->custom-field-upload#upload"
/>
@@ -69,8 +80,8 @@ class="w-24 h-24 object-cover border border-black"
@break
@default
<x-ui.field :label="$field['label']" :for="$id" :required="$required">
<x-ui.input :id="$id" :name="$name" :required="$required" maxlength="255" />
<x-ui.field :label="$field['label']" :label-class="$labelClass" :hint="$hint" :for="$id" :required="$required">
<x-ui.input :id="$id" :name="$name" :required="$required" maxlength="255" :aria-describedby="$hintId" />
</x-ui.field>
@endswitch
@endforeach
@@ -1,6 +1,8 @@
@props([
'label' => null,
'labelDescription' => null,
'labelClass' => null,
'hint' => null,
'for' => null,
'description' => null,
'error' => null,
@@ -10,9 +12,23 @@
<div {{ $attributes->merge(['class' => 'flex flex-col gap-2']) }}>
@if ($label)
{{-- With a hint, label + hint are grouped so the hint sits tight
under the label, with the usual gap before the input. The input
should reference {for}-hint in its aria-describedby. --}}
@if ($hint) <div class="flex flex-col gap-1"> @endif
<label
@if ($for) for="{{ $for }}" @endif
@if ($labelClass) class="{{ $labelClass }}" @endif
>{{ $label }}@if ($required)<span class="ml-1" aria-hidden="true">*</span>@endif @if ($labelDescription) <span class="text-sm text-neutral-500">({{ $labelDescription }})</span> @endif</label>
@if ($hint)
<p
@if ($for) id="{{ $for }}-hint" @endif
class="text-sm text-neutral-500"
>{{ $hint }}</p>
</div>
@endif
@endif
{{ $slot }}