Merge pull request #15398 from filamentphp/dynamic-heading-levels

Dynamic heading levels
This commit is contained in:
Dan Harrin
2025-01-22 08:27:20 +00:00
committed by GitHub
17 changed files with 165 additions and 21 deletions
@@ -567,7 +567,8 @@ trait InteractsWithActions
->take($actionNestingIndex + 1)
->pluck('name')
->implode('.'),
),
)
->rootHeadingLevel(3),
);
}
@@ -33,6 +33,8 @@
$key = $getKey();
$statePath = $getStatePath();
$blockLabelHeadingTag = $getHeadingTag();
@endphp
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
@@ -157,7 +159,7 @@
@endif
@if ($hasBlockLabels)
<h4
<{{ $blockLabelHeadingTag }}
@class([
'text-sm font-medium text-gray-950 dark:text-white',
'truncate' => $isBlockLabelTruncated(),
@@ -168,7 +170,7 @@
@if ($hasBlockNumbers)
{{ $loop->iteration }}
@endif
</h4>
</{{ $blockLabelHeadingTag }}>
@endif
@if ($editActionIsVisible || $cloneActionIsVisible || $deleteActionIsVisible || $isCollapsible || $visibleExtraItemActions)
@@ -28,6 +28,8 @@
$key = $getKey();
$statePath = $getStatePath();
$itemLabelHeadingTag = $getHeadingTag();
@endphp
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
@@ -147,14 +149,14 @@
@endif
@if (filled($itemLabel))
<h4
<{{ $itemLabelHeadingTag }}
@class([
'text-sm font-medium text-gray-950 dark:text-white',
'truncate' => $isItemLabelTruncated(),
])
>
{{ $itemLabel }}
</h4>
</{{ $itemLabelHeadingTag }}>
@endif
@if ($cloneActionIsVisible || $deleteActionIsVisible || $isCollapsible || $visibleExtraItemActions)
@@ -1134,4 +1134,13 @@ class Builder extends Field implements CanConcealComponents, HasExtraItemActions
{
return $this->getChildComponentContainer($uuid)->getRawState();
}
public function getHeadingsCount(): int
{
if (! $this->hasBlockLabels()) {
return 0;
}
return 1;
}
}
@@ -1315,4 +1315,13 @@ class Repeater extends Field implements CanConcealComponents, HasExtraItemAction
{
return $this->getChildComponentContainer($uuid)->getRawState();
}
public function getHeadingsCount(): int
{
if (! $this->hasItemLabels()) {
return 0;
}
return 1;
}
}
@@ -36,6 +36,7 @@
:footer="$getChildComponentContainer($schemaComponent::FOOTER_CONTAINER)?->toHtmlString()"
:has-content-el="false"
:heading="$getHeading()"
:heading-tag="$getHeadingTag()"
:icon="$getIcon()"
:icon-color="$getIconColor()"
:icon-size="$getIconSize()"
@@ -16,6 +16,7 @@ use Filament\Schemas\Components\Concerns\HasActions;
use Filament\Schemas\Components\Concerns\HasChildComponents;
use Filament\Schemas\Components\Concerns\HasEntryWrapper;
use Filament\Schemas\Components\Concerns\HasFieldWrapper;
use Filament\Schemas\Components\Concerns\HasHeadings;
use Filament\Schemas\Components\Concerns\HasId;
use Filament\Schemas\Components\Concerns\HasInlineLabel;
use Filament\Schemas\Components\Concerns\HasKey;
@@ -55,6 +56,7 @@ class Component extends ViewComponent
use HasExtraAttributes;
use HasFieldWrapper;
use HasGap;
use HasHeadings;
use HasId;
use HasInlineLabel;
use HasKey;
@@ -0,0 +1,32 @@
<?php
namespace Filament\Schemas\Components\Concerns;
trait HasHeadings
{
public function getHeadingLevel(int $index = 0): int
{
return $this->getContainer()->getRootHeadingLevel() + $index;
}
public function getHeadingTag(int $index = 0): string
{
$level = $this->getHeadingLevel($index);
if ($level > 6) {
return 'p';
}
return "h{$level}";
}
public function getChildComponentContainerRootHeadingLevel(): int
{
return $this->getHeadingLevel() + $this->getHeadingsCount();
}
public function getHeadingsCount(): int
{
return 0;
}
}
@@ -245,4 +245,13 @@ class Section extends Component implements CanConcealComponents, CanEntangleWith
return $schema;
}
public function getHeadingsCount(): int
{
if (blank($this->getHeading())) {
return 0;
}
return 1;
}
}
@@ -0,0 +1,24 @@
<?php
namespace Filament\Schemas\Concerns;
trait HasHeadings
{
protected int $rootHeadingLevel = 2;
public function rootHeadingLevel(int $level): static
{
$this->rootHeadingLevel = $level;
return $this;
}
public function getRootHeadingLevel(): int
{
if ($parentComponent = $this->getParentComponent()) {
return $parentComponent->getChildComponentContainerRootHeadingLevel();
}
return $this->rootHeadingLevel;
}
}
+1
View File
@@ -29,6 +29,7 @@ class Schema extends ViewComponent
use Concerns\HasEntryWrapper;
use Concerns\HasFieldWrapper;
use Concerns\HasGap;
use Concerns\HasHeadings;
use Concerns\HasInlineLabels;
use Concerns\HasKey;
use Concerns\HasOperation;
@@ -1,5 +1,5 @@
<h3
<h2
{{ $attributes->class(['fi-section-header-heading']) }}
>
{{ $slot }}
</h3>
</h2>
@@ -18,6 +18,7 @@
'footer' => null,
'hasContentEl' => true,
'heading' => null,
'headingTag' => 'h2',
'icon' => null,
'iconColor' => 'gray',
'iconSize' => IconSize::Large,
@@ -88,9 +89,9 @@
@if ($hasHeading || $hasDescription)
<div class="fi-section-header-text-ctn">
@if ($hasHeading)
<h3 class="fi-section-header-heading">
<{{ $headingTag }} class="fi-section-header-heading">
{{ $heading }}
</h3>
</{{ $headingTag }}>
@endif
@if ($hasDescription)
@@ -1,13 +1,14 @@
@props([
'applyAction',
'form',
'headingTag' => 'h3',
])
<div {{ $attributes->class(['fi-ta-filters']) }}>
<div class="fi-ta-filters-header">
<h4 class="fi-ta-filters-heading">
<{{ $headingTag }} class="fi-ta-filters-heading">
{{ __('filament-tables::table.filters.heading') }}
</h4>
</{{ $headingTag }}>
<div>
<x-filament::link
+23 -10
View File
@@ -70,6 +70,8 @@
$hasColumnToggleDropdown = $hasToggleableColumns();
$hasHeader = $header || $heading || $description || ($headerActions && (! $isReordering)) || $isReorderable || $areGroupingSettingsVisible || $isGlobalSearchVisible || $hasFilters || count($filterIndicators) || $hasColumnToggleDropdown;
$hasHeaderToolbar = $isReorderable || $areGroupingSettingsVisible || $isGlobalSearchVisible || $hasFiltersDialog || $hasColumnToggleDropdown;
$headingTag = $getHeadingTag();
$secondLevelHeadingTag = $heading ? $getHeadingTag(1) : $headingTag;
$pluralModelLabel = $getPluralModelLabel();
$records = $isLoaded ? $getRecords() : null;
$searchDebounce = $getSearchDebounce();
@@ -135,9 +137,11 @@
@if ($heading || $description)
<div>
@if ($heading)
<h3 class="fi-ta-header-heading">
<{{ $headingTag }}
class="fi-ta-header-heading"
>
{{ $heading }}
</h3>
</{{ $headingTag }}>
@endif
@if ($description)
@@ -171,6 +175,7 @@
<x-filament-tables::filters
:apply-action="$getFiltersApplyAction()"
:form="$getFiltersForm()"
:heading-tag="$secondLevelHeadingTag"
x-cloak
x-show="areFiltersOpen"
/>
@@ -426,6 +431,7 @@
<x-filament-tables::filters
:apply-action="$getFiltersApplyAction()"
:form="$getFiltersForm()"
:heading-tag="$secondLevelHeadingTag"
/>
</x-filament::dropdown>
@endif
@@ -447,9 +453,11 @@
</x-slot>
<div class="fi-ta-col-toggle-form-ctn">
<h4 class="fi-ta-col-toggle-heading">
<{{ $secondLevelHeadingTag }}
class="fi-ta-col-toggle-heading"
>
{{ __('filament-tables::table.column_toggle.heading') }}
</h4>
</{{ $secondLevelHeadingTag }}>
{{ $getColumnToggleForm() }}
</div>
@@ -823,13 +831,15 @@
@endif
<div>
<h4 class="fi-ta-group-heading">
<{{ $secondLevelHeadingTag }}
class="fi-ta-group-heading"
>
@if (filled($recordGroupLabel = ($group->isTitlePrefixedWithLabel() ? $group->getLabel() : null)))
{{ $recordGroupLabel }}:
@endif
{{ $recordGroupTitle }}
</h4>
</{{ $secondLevelHeadingTag }}>
@if (filled($recordGroupDescription = $group->getDescription($record, $recordGroupTitle)))
<p
@@ -1471,7 +1481,7 @@
])
>
<div>
<h4
<{{ $secondLevelHeadingTag }}
class="fi-ta-group-heading"
>
@if (filled($recordGroupLabel = ($group->isTitlePrefixedWithLabel() ? $group->getLabel() : null)))
@@ -1479,7 +1489,7 @@
@endif
{{ $recordGroupTitle }}
</h4>
</{{ $secondLevelHeadingTag }}>
@if (filled($recordGroupDescription = $group->getDescription($record, $recordGroupTitle)))
<p
@@ -1817,9 +1827,11 @@
{{ \Filament\Support\generate_icon_html($getEmptyStateIcon()) }}
</div>
<h4 class="fi-ta-empty-state-heading">
<{{ $secondLevelHeadingTag }}
class="fi-ta-empty-state-heading"
>
{{ $getEmptyStateHeading() }}
</h4>
</{{ $secondLevelHeadingTag }}>
@if ($emptyStateDescription = $getEmptyStateDescription())
<p class="fi-ta-empty-state-description">
@@ -1857,6 +1869,7 @@
<x-filament-tables::filters
:apply-action="$getFiltersApplyAction()"
:form="$getFiltersForm()"
:heading-tag="$secondLevelHeadingTag"
class="fi-ta-filters-below-content"
/>
@endif
+1
View File
@@ -27,6 +27,7 @@ class Table extends ViewComponent
use Table\Concerns\HasFilters;
use Table\Concerns\HasHeader;
use Table\Concerns\HasHeaderActions;
use Table\Concerns\HasHeadings;
use Table\Concerns\HasQuery;
use Table\Concerns\HasQueryStringIdentifier;
use Table\Concerns\HasRecordAction;
@@ -0,0 +1,36 @@
<?php
namespace Filament\Tables\Table\Concerns;
trait HasHeadings
{
protected int $rootHeadingLevel = 2;
public function rootHeadingLevel(int $level): static
{
$this->rootHeadingLevel = $level;
return $this;
}
public function getRootHeadingLevel(): int
{
return $this->rootHeadingLevel;
}
public function getHeadingLevel(int $index = 0): int
{
return $this->getRootHeadingLevel() + $index;
}
public function getHeadingTag(int $index = 0): string
{
$level = $this->getHeadingLevel($index);
if ($level > 6) {
return 'p';
}
return "h{$level}";
}
}