badges as indicators

This commit is contained in:
Zep Fietje
2023-07-18 17:15:13 +02:00
parent 31a69db163
commit 2d4aecd423
18 changed files with 157 additions and 150 deletions
+7 -7
View File
@@ -67,21 +67,21 @@ class ActionsDemo extends Component implements HasActions, HasForms
->iconPosition('after');
}
public function indicatorAction(): Action
public function badgeAction(): Action
{
return Action::make('indicator')
return Action::make('badge')
->iconButton()
->icon('heroicon-m-funnel')
->indicator(5);
->badge(5);
}
public function successIndicatorAction(): Action
public function successBadgeAction(): Action
{
return Action::make('successIndicator')
return Action::make('successBadge')
->iconButton()
->icon('heroicon-m-funnel')
->indicator(5)
->indicatorColor('success');
->badge(5)
->badgeColor('success');
}
public function outlinedAction(): Action
@@ -28,12 +28,12 @@
{{ $this->iconAfterAction }}
</div>
<div id="indicatorAction" class="p-16 flex items-center justify-center max-w-xl">
{{ $this->indicatorAction }}
<div id="badgeAction" class="p-16 flex items-center justify-center max-w-xl">
{{ $this->badgeAction }}
</div>
<div id="successIndicatorAction" class="p-16 flex items-center justify-center max-w-xl">
{{ $this->successIndicatorAction }}
<div id="successBadgeAction" class="p-16 flex items-center justify-center max-w-xl">
{{ $this->successBadgeAction }}
</div>
<div id="outlinedAction" class="p-16 flex items-center justify-center max-w-xl">
+6 -6
View File
@@ -65,28 +65,28 @@ export default {
deviceScaleFactor: 3,
},
},
'actions/trigger-button/indicator': {
'actions/trigger-button/badge': {
url: 'actions',
selector: '#indicatorAction',
selector: '#badgeAction',
viewport: {
width: 1920,
height: 640,
deviceScaleFactor: 3,
},
before: async (page) => {
await page.hover('#indicatorAction button')
await page.hover('#badgeAction button')
},
},
'actions/trigger-button/success-indicator': {
'actions/trigger-button/success-badge': {
url: 'actions',
selector: '#successIndicatorAction',
selector: '#successBadgeAction',
viewport: {
width: 1920,
height: 640,
deviceScaleFactor: 3,
},
before: async (page) => {
await page.hover('#successIndicatorAction button')
await page.hover('#successBadgeAction button')
},
},
'actions/trigger-button/outlined': {
+8 -8
View File
@@ -159,9 +159,9 @@ Action::make('save')
->keyBindings(['command+s', 'ctrl+s'])
```
## Adding an indicator in the corner of the button
## Adding a badge to the corner of the button
You can add an indicator to the corner of the button, to display whatever you want. It's useful for displaying a count of something, or a status indicator:
You can add a badge to the corner of the button, to display whatever you want. It's useful for displaying a count of something, or a status indicator:
```php
use Filament\Actions\Action;
@@ -169,12 +169,12 @@ use Filament\Actions\Action;
Action::make('filter')
->iconButton()
->icon('heroicon-m-funnel')
->indicator(5)
->badge(5)
```
<AutoScreenshot name="actions/trigger-button/indicator" alt="Trigger with indicator" version="3.x" />
<AutoScreenshot name="actions/trigger-button/badge" alt="Trigger with badge" version="3.x" />
You can also pass a color to be used for the indicator, which can be either `danger`, `gray`, `info`, `primary`, `success` and `warning`:
You can also pass a color to be used for the badge, which can be either `danger`, `gray`, `info`, `primary`, `success` and `warning`:
```php
use Filament\Actions\Action;
@@ -182,11 +182,11 @@ use Filament\Actions\Action;
Action::make('filter')
->iconButton()
->icon('heroicon-m-funnel')
->indicator(5)
->indicatorColor('success')
->badge(5)
->badgeColor('success')
```
<AutoScreenshot name="actions/trigger-button/success-indicator" alt="Trigger with green indicator" version="3.x" />
<AutoScreenshot name="actions/trigger-button/success-badge" alt="Trigger with green badge" version="3.x" />
## Outlined button style
@@ -10,6 +10,8 @@
@endphp
<x-dynamic-component
:badge="$action->getBadge()"
:badge-color="$action->getBadgeColor()"
:component="$dynamicComponent"
:form="$action->getFormToSubmit()"
:tag="$url ? 'a' : 'button'"
@@ -24,8 +26,6 @@
:disabled="$isDisabled"
:icon="$icon ?? $action->getIcon()"
:icon-size="$action->getIconSize()"
:indicator="$action->getIndicator()"
:indicator-color="$action->getIndicatorColor()"
:size="$action->getSize()"
:label-sr-only="$action->isLabelHidden()"
:attributes="\Filament\Support\prepare_inherited_attributes($attributes)->merge($action->getExtraAttributes(), escape: false)"
@@ -1,5 +1,7 @@
@props([
'actions' => [],
'badge' => null,
'badgeColor' => null,
'button' => false,
'color' => null,
'dropdownPlacement' => null,
@@ -7,8 +9,6 @@
'group' => null,
'icon' => null,
'iconButton' => false,
'indicator' => null,
'indicatorColor' => null,
'label' => null,
'link' => false,
'size' => null,
@@ -19,11 +19,11 @@
@if (! ($dynamicComponent && $group))
@php
$group = \Filament\Actions\ActionGroup::make($actions)
->badge($badge)
->badgeColor($badgeColor)
->color($color)
->dropdownPlacement($dropdownPlacement)
->icon($icon)
->indicator($indicator)
->indicatorColor($indicatorColor)
->label($label)
->size($size)
->tooltip($tooltip)
@@ -87,12 +87,12 @@
>
<x-slot name="trigger">
<x-dynamic-component
:badge="$group->getBadge()"
:badge-color="$group->getBadgeColor()"
:component="$dynamicComponent"
:color="$group->getColor()"
:tooltip="$group->getTooltip()"
:icon="$group->getIcon()"
:indicator="$group->getIndicator()"
:indicator-color="$group->getIndicatorColor()"
:size="$group->getSize()"
:label-sr-only="$group->isLabelHidden()"
:attributes="\Filament\Support\prepare_inherited_attributes($attributes)->merge($group->getExtraAttributes(), escape: false)"
+1 -1
View File
@@ -14,11 +14,11 @@ class ActionGroup extends ViewComponent implements HasLivewire
use Concerns\CanBeHidden {
isHidden as baseIsHidden;
}
use Concerns\HasBadge;
use Concerns\CanBeLabeledFrom;
use Concerns\CanBeOutlined;
use Concerns\HasDropdown;
use Concerns\HasGroupedIcon;
use Concerns\HasIndicator;
use Concerns\HasLabel;
use Concerns\HasSize;
use Concerns\HasTooltip;
@@ -0,0 +1,63 @@
<?php
namespace Filament\Actions\Concerns;
use Closure;
trait HasBadge
{
protected string | int | float | Closure | null $badge = null;
/**
* @var string | array{50: string, 100: string, 200: string, 300: string, 400: string, 500: string, 600: string, 700: string, 800: string, 900: string, 950: string} | Closure | null
*/
protected string | array | Closure | null $badgeColor = null;
public function badge(string | int | float | Closure | null $badge): static
{
$this->badge = $badge;
return $this;
}
/**
* @deprecated Use `badge()` instead.
*/
public function indicator(string | int | float | Closure | null $indicator): static
{
return $this->badge($indicator);
}
/**
* @param string | array{50: string, 100: string, 200: string, 300: string, 400: string, 500: string, 600: string, 700: string, 800: string, 900: string, 950: string} | Closure | null $color
*/
public function badgeColor(string | array | Closure | null $color): static
{
$this->badgeColor = $color;
return $this;
}
/**
* @deprecated Use `badgeColor()` instead.
*
* @param string | array{50: string, 100: string, 200: string, 300: string, 400: string, 500: string, 600: string, 700: string, 800: string, 900: string, 950: string} | Closure | null $color
*/
public function indicatorColor(string | array | Closure | null $color): static
{
return $this->badgeColor($color);
}
public function getBadge(): string | int | float | null
{
return $this->evaluate($this->badge);
}
/**
* @return string | array{50: string, 100: string, 200: string, 300: string, 400: string, 500: string, 600: string, 700: string, 800: string, 900: string, 950: string} | null
*/
public function getBadgeColor(): string | array | null
{
return $this->evaluate($this->badgeColor);
}
}
@@ -1,45 +0,0 @@
<?php
namespace Filament\Actions\Concerns;
use Closure;
trait HasIndicator
{
protected string | int | float | Closure | null $indicator = null;
/**
* @var string | array{50: string, 100: string, 200: string, 300: string, 400: string, 500: string, 600: string, 700: string, 800: string, 900: string, 950: string} | Closure | null
*/
protected string | array | Closure | null $indicatorColor = null;
public function indicator(string | int | float | Closure | null $indicator): static
{
$this->indicator = $indicator;
return $this;
}
/**
* @param string | array{50: string, 100: string, 200: string, 300: string, 400: string, 500: string, 600: string, 700: string, 800: string, 900: string, 950: string} | Closure | null $color
*/
public function indicatorColor(string | array | Closure | null $color): static
{
$this->indicatorColor = $color;
return $this;
}
public function getIndicator(): string | int | float | null
{
return $this->evaluate($this->indicator);
}
/**
* @return string | array{50: string, 100: string, 200: string, 300: string, 400: string, 500: string, 600: string, 700: string, 800: string, 900: string, 950: string} | null
*/
public function getIndicatorColor(): string | array | null
{
return $this->evaluate($this->indicatorColor);
}
}
+1 -1
View File
@@ -23,8 +23,8 @@ class StaticAction extends ViewComponent
use Concerns\CanSubmitForm;
use Concerns\HasAction;
use Concerns\HasArguments;
use Concerns\HasBadge;
use Concerns\HasGroupedIcon;
use Concerns\HasIndicator;
use Concerns\HasKeyBindings;
use Concerns\HasLabel;
use Concerns\HasName;
+1 -1
View File
File diff suppressed because one or more lines are too long
@@ -1,8 +1,8 @@
<x-filament::icon-button
:label="__('filament::layout.actions.open_database_notifications.label')"
icon="heroicon-o-bell"
:badge="$unreadNotificationsCount"
color="gray"
icon-alias="panels::topbar.open-database-notifications-button"
icon-size="lg"
color="gray"
:indicator="$unreadNotificationsCount"
icon="heroicon-o-bell"
:label="__('filament::layout.actions.open_database_notifications.label')"
/>
@@ -22,10 +22,11 @@
{{
$attributes
->class([
'fi-badge flex items-center gap-x-1 whitespace-nowrap rounded-md text-xs font-medium ring-1 ring-inset',
'fi-badge flex items-center justify-center gap-x-1 whitespace-nowrap rounded-md text-xs font-medium ring-1 ring-inset',
match ($size) {
'sm' => 'px-1.5 py-0.5 tracking-tighter',
'md' => 'px-2 py-1 tracking-tight',
'xs' => 'px-0.5 min-w-[theme(spacing.4)] tracking-tighter',
'sm' => 'px-1.5 min-w-[theme(spacing.5)] py-0.5 tracking-tight',
'md' => 'px-2 min-w-[theme(spacing.6)] py-1',
},
match ($color) {
'gray' => 'bg-gray-300/10 text-gray-600 ring-gray-600/10 dark:bg-gray-400/10 dark:text-gray-400 dark:ring-gray-400/20',
@@ -1,4 +1,6 @@
@props([
'badge' => null,
'badgeColor' => 'primary',
'color' => 'primary',
'disabled' => false,
'form' => null,
@@ -6,8 +8,6 @@
'iconAlias' => null,
'iconPosition' => 'before',
'iconSize' => null,
'indicator' => null,
'indicatorColor' => 'primary',
'keyBindings' => null,
'labeledFrom' => null,
'labelSrOnly' => false,
@@ -78,9 +78,7 @@
},
]);
$indicatorClasses = 'fi-btn-indicator absolute -end-1 -top-1 inline-flex h-4 w-4 items-center justify-center rounded-full bg-custom-600 text-xs font-medium tracking-tight text-white dark:bg-custom-500';
$indicatorStyles = \Filament\Support\get_color_css_variables($indicatorColor, shades: [500, 600]);
$badgeClasses = 'absolute -top-1 start-full -ms-1 -translate-x-1/2 rounded-md bg-white dark:bg-gray-900';
$labelClasses = \Illuminate\Support\Arr::toCssClasses([
'fi-btn-label',
@@ -99,14 +97,14 @@
@if ($labeledFrom)
<x-filament::icon-button
:badge="$badge"
:badge-color="$badgeColor"
:color="$color"
:disabled="$disabled"
:form="$form"
:icon="$icon"
:icon-alias="$iconAlias"
:icon-size="$iconSize"
:indicator="$indicator"
:indicator-color="$indicatorColor"
:key-bindings="$keyBindings"
:label="$slot"
:size="$size"
@@ -240,13 +238,12 @@
@endif
@endif
@if ($indicator)
<span
class="{{ $indicatorClasses }}"
style="{{ $indicatorStyles }}"
>
{{ $indicator }}
</span>
@if ($badge)
<div class="{{ $badgeClasses }}">
<x-filament::badge :color="$badgeColor" size="xs">
{{ $badge }}
</x-filament::badge>
</div>
@endif
</button>
@elseif ($tag === 'a')
@@ -286,13 +283,12 @@
/>
@endif
@if ($indicator)
<span
class="{{ $indicatorClasses }}"
style="{{ $indicatorStyles }}"
>
{{ $indicator }}
</span>
@if ($badge)
<div class="{{ $badgeClasses }}">
<x-filament::badge :color="$badgeColor" size="xs">
{{ $badge }}
</x-filament::badge>
</div>
@endif
</a>
@endif
@@ -1,12 +1,12 @@
@props([
'badge' => null,
'badgeColor' => 'primary',
'color' => 'primary',
'disabled' => false,
'form' => null,
'icon' => null,
'iconAlias' => null,
'iconSize' => null,
'indicator' => null,
'indicatorColor' => 'primary',
'keyBindings' => null,
'label' => null,
'size' => 'md',
@@ -50,9 +50,7 @@
},
]);
$indicatorClasses = 'fi-icon-btn-indicator absolute end-0 top-0 inline-flex h-4 w-4 items-center justify-center rounded-full bg-custom-600 text-xs font-medium tracking-tight text-white dark:bg-custom-500';
$indicatorStyles = \Filament\Support\get_color_css_variables($indicatorColor, shades: [500, 600]);
$badgeClasses = 'absolute start-full top-0 -translate-x-1/2 rounded-md bg-white dark:bg-gray-900';
$wireTarget = $attributes->whereStartsWith(['wire:target', 'wire:click'])->first();
@@ -107,13 +105,12 @@
/>
@endif
@if ($indicator)
<span
class="{{ $indicatorClasses }}"
style="{{ $indicatorStyles }}"
>
{{ $indicator }}
</span>
@if ($badge)
<div class="{{ $badgeClasses }}">
<x-filament::badge :color="$badgeColor" size="xs">
{{ $badge }}
</x-filament::badge>
</div>
@endif
</button>
@elseif ($tag === 'a')
@@ -148,13 +145,12 @@
:class="$iconClasses"
/>
@if ($indicator)
<span
class="{{ $indicatorClasses }}"
style="{{ $indicatorStyles }}"
>
{{ $indicator }}
</span>
@if ($badge)
<div class="{{ $badgeClasses }}">
<x-filament::badge :color="$badgeColor" size="xs">
{{ $badge }}
</x-filament::badge>
</div>
@endif
</a>
@endif
@@ -1,4 +1,6 @@
@props([
'badge' => null,
'badgeColor' => 'primary',
'color' => 'primary',
'disabled' => false,
'form' => null,
@@ -6,8 +8,6 @@
'iconAlias' => null,
'iconPosition' => 'before',
'iconSize' => null,
'indicator' => null,
'indicatorColor' => 'primary',
'keyBindings' => null,
'size' => 'md',
'tag' => 'a',
@@ -20,7 +20,7 @@
$linkClasses = \Illuminate\Support\Arr::toCssClasses([
"fi-link fi-link-size-{$size} relative inline-flex items-center justify-center font-medium outline-none transition duration-75 hover:underline focus:underline disabled:pointer-events-none disabled:opacity-70",
'pe-4' => $indicator,
'pe-4' => $badge,
'pointer-events-none opacity-70' => $disabled,
match ($size) {
'xs' => 'gap-1 text-xs',
@@ -62,9 +62,7 @@
\Filament\Support\get_color_css_variables($color, shades: [500]) => $color !== 'gray',
]);
$indicatorClasses = 'fi-link-indicator absolute -end-1 -top-1 inline-flex h-4 w-4 items-center justify-center rounded-full bg-custom-600 text-xs font-medium tracking-tight text-white dark:bg-custom-500';
$indicatorStyles = \Filament\Support\get_color_css_variables($indicatorColor, shades: [500, 600]);
$badgeClasses = 'absolute -top-1 start-full -ms-1 -translate-x-1/2 rounded-md bg-white dark:bg-gray-900';
$wireTarget = $attributes->whereStartsWith(['wire:target', 'wire:click'])->first();
@@ -112,13 +110,12 @@
/>
@endif
@if ($indicator)
<span
class="{{ $indicatorClasses }}"
style="{{ $indicatorStyles }}"
>
{{ $indicator }}
</span>
@if ($badge)
<div class="{{ $badgeClasses }}">
<x-filament::badge :color="$badgeColor" size="xs">
{{ $badge }}
</x-filament::badge>
</div>
@endif
</a>
@elseif ($tag === 'button')
@@ -188,13 +185,12 @@
@endif
@endif
@if ($indicator)
<span
class="{{ $indicatorClasses }}"
style="{{ $indicatorStyles }}"
>
{{ $indicator }}
</span>
@if ($badge)
<div class="{{ $badgeClasses }}">
<x-filament::badge :color="$badgeColor" size="xs">
{{ $badge }}
</x-filament::badge>
</div>
@endif
</button>
@endif
@@ -15,7 +15,7 @@
{{ $attributes->class(['fi-ta-filters']) }}
>
<x-slot name="trigger">
{{ $triggerAction->indicator($indicatorsCount) }}
{{ $triggerAction->badge($indicatorsCount) }}
</x-slot>
<x-filament-tables::filters :form="$form" class="p-4" />
@@ -259,7 +259,7 @@
x-on:click="areFiltersOpen = ! areFiltersOpen"
class="flex w-full justify-end"
>
{{ $getFiltersTriggerAction()->indicator(count(\Illuminate\Support\Arr::flatten($filterIndicators))) }}
{{ $getFiltersTriggerAction()->badge(count(\Illuminate\Support\Arr::flatten($filterIndicators))) }}
</div>
@endif