颜色
简介
Filament 使用 CSS 变量定义调色板。这些 CSS 变量在安装 Filament 时加载的 preset 文件中映射到 Tailwind 类。之所以使用 CSS 变量,是为了让框架能从 PHP 通过 <style> 元素传递调色板,该元素会作为 @filamentStyles Blade 指令的一部分被渲染。
默认情况下,Filament 的 Tailwind preset 文件附带 6 种颜色:
primary,默认对应 Tailwind 的amber色success,默认对应 Tailwind 的green色warning,默认对应 Tailwind 的amber色danger,默认对应 Tailwind 的red色info,默认对应 Tailwind 的blue色gray,默认对应 Tailwind 的zinc色
你可以了解如何更改这些颜色并注册新颜色。
如何向 Filament 传入颜色
在 Filament 中注册的「颜色」并非单一色阶,而是由 11 个色阶 组成的完整调色板:50、100、200、300、400、500、600、700、800、900 和 950。在 Filament 中使用颜色时,框架会根据上下文决定使用哪个色阶。例如,组件背景可能用 600,悬停时用 500,边框用 400。若用户开启了深色模式,则可能改用 700、800 或 900。
这意味着你可以在 Filament 中指定颜色,而不必操心具体用哪个色阶,也不必为组件的每个部分分别指定色阶。Filament 会尽可能选择能与其他元素形成可访问对比度的色阶。
要自定义 Filament 中某元素的颜色,可以使用颜色名称。例如,若要使用 success 颜色,可将其传给 PHP 组件的颜色方法,如下所示:
use Filament\Actions\Action;
use Filament\Forms\Components\Toggle;
Action::make('proceed')
->color('success')
Toggle::make('is_active')
->onColor('success')若要在 Blade 组件 中使用颜色,可将其作为属性传入:
<x-filament::badge color="success">
Active
</x-filament::badge>自定义默认颜色
可在服务提供者的 boot() 方法或中间件中调用 FilamentColor::register(),用于自定义 Filament 用于 UI 元素的颜色。
Filament 全局使用 6 种默认可自定义颜色:
use Filament\Support\Colors\Color;
use Filament\Support\Facades\FilamentColor;
FilamentColor::register([
'danger' => Color::Red,
'gray' => Color::Zinc,
'info' => Color::Blue,
'primary' => Color::Amber,
'success' => Color::Green,
'warning' => Color::Amber,
]);Color 类包含全部可供选择的 Tailwind CSS 颜色。


也可以向 register() 传入一个函数,该函数仅在应用渲染时才会被调用。若你从服务提供者中调用 register(),又想访问当前认证用户等稍后在中间件中才初始化的对象,这会很有用。
注册额外颜色
你可以通过向 FilamentColor::register() 传入新颜色(以名称为数组键)来注册,供任意 Filament 组件使用:
use Filament\Support\Colors\Color;
use Filament\Support\Facades\FilamentColor;
FilamentColor::register([
'secondary' => Color::Indigo,
]);现在可以在任意 Filament 组件中将 secondary 用作颜色。
使用非 Tailwind 颜色
你可以使用不在 Tailwind CSS 颜色 调色板中的自定义颜色,传入从 50 到 950 的 OKLCH 格式色阶数组即可:
use Filament\Support\Facades\FilamentColor;
FilamentColor::register([
'danger' => [
50 => 'oklch(0.969 0.015 12.422)',
100 => 'oklch(0.941 0.03 12.58)',
200 => 'oklch(0.892 0.058 10.001)',
300 => 'oklch(0.81 0.117 11.638)',
400 => 'oklch(0.712 0.194 13.428)',
500 => 'oklch(0.645 0.246 16.439)',
600 => 'oklch(0.586 0.253 17.585)',
700 => 'oklch(0.514 0.222 16.935)',
800 => 'oklch(0.455 0.188 13.697)',
900 => 'oklch(0.41 0.159 10.272)',
950 => 'oklch(0.271 0.105 12.094)',
],
]);生成自定义调色板
若希望我们根据单个十六进制或 RGB 值尝试生成调色板,可以直接传入该值:
use Filament\Support\Facades\FilamentColor;
FilamentColor::register([
'danger' => '#ff0000',
]);
FilamentColor::register([
'danger' => 'rgb(255, 0, 0)',
]);Filament 如何选择可访问的色阶
当你为 Filament 组件指定颜色(例如 ->color('primary'))时,Filament 会接收完整的 11 色阶调色板,并在运行时决定背景、文本、悬停状态、深色模式变体等应使用哪个色阶。选择由 WCAG 2.1 对比度 驱动:对每个 slot,Filament 会遍历调色板,选出相对于组件所在表面满足最低对比度的最浅(或最深,取决于上下文)色阶。
这种设计意味着:
- 每种颜色名称只需注册一个调色板。各组件的色阶选择是自动的。
- 同一颜色在不同组件上的呈现可能不同——`success` 按钮使用一种背景/文本组合,`success` 徽章则是另一种——因为每个组件会应用适合其视觉角色的对比规则。
- 若更换调色板(例如把 `primary` 从 amber 换成更深的色相),所有使用它的组件都会重新推导色阶以保持可访问性。
Filament 使用的对比度阈值来自 WCAG 2.1:
- **普通文本(`Color::WCAG_AA_TEXT`,4.5:1)** — 应用于按钮、徽章、链接、下拉项和文本列等含文本的组件。来自 [成功标准 1.4.3 Contrast (Minimum)](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html)。
- **用户界面组件与图形对象(`Color::WCAG_AA_NON_TEXT`,3:1)** — 应用于仅含图标的组件,如图标按钮、开关、图标列和图标条目。来自 [成功标准 1.4.11 Non-text Contrast](https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast.html)。
Filament\Support\Colors\Color 类将这些作为常量公开——WCAG_AA_TEXT、WCAG_AA_LARGE_TEXT、WCAG_AA_NON_TEXT、WCAG_AAA_TEXT、WCAG_AAA_LARGE_TEXT——自定义时可通过名称引用。
为何有些按钮渲染深色文本而非白色
对于实心按钮,Filament 会预先构建「每个背景色阶的最佳文本色阶」查找表,再通过检查哪些候选背景色阶最终会与浅色文本配对,来选定实际的按钮背景。
对于红、蓝、indigo 等鲜艳颜色,色阶 600 足够深,白色文本能通过 4.5:1 对比度阈值。解析器会选择 bg: 600、hover:bg: 500,并配白色文本——这是大多数颜色走的路径。
对于黄、amber、lime 等浅色,即使色阶 600 也足够亮,深色 文本的对比度优于白色。解析器会检测到这一点,并回退到更浅的背景——bg: 400——再配深色文本。结果是浅黄背景上带深色文本的黄色按钮,而不是难以阅读的白字配黄底。
这种行为是有意为之。若强迫每种颜色都使用相同的 bg: 600, text: white 模式,暖色或浅色调色板会产生不可访问的组合。双路径设计让 success 和 danger 看起来仍是实心彩色按钮,而 warning(通常为 amber)则以其较浅背景正确呈现。
自定义色阶选择
若需要覆盖某个组件如何选择色阶——例如在整个应用中强制 WCAG AAA 对比度,或让按钮偏向更深的色阶——可以扩展相应的视图组件,并通过 Laravel 容器重新绑定。
为此,Filament 提供了三个颜色映射类,均位于 Filament\Support\View\Components\ColorMaps 命名空间。它们遵循相同的流畅形态——以 make($palette) 开始,链式调用配置 setter,再以 get() 返回将 slot 名称(如 bg、text、dark:hover:bg)映射到色阶数字的 array<string, int>。
这三个类是:
ComponentColorMap— 用于按 slot 各选一个色阶的组件,如徽章、链接、文本列、图标、下拉菜单和开关。ButtonComponentColorMap— 用于实心按钮。选择背景色阶并配以匹配的文本色阶。IconButtonComponentColorMap— 用于仅含图标的按钮。选择单个图标色阶,并由此推导悬停变体。
可覆盖的组件
每个从调色板选择色阶的 Filament 组件都实现了 getColorMap()。要自定义某个组件,请扩展该类、覆盖 getColorMap(),并通过 Laravel 容器绑定你的子类。
| 组件类 | 用于 | 文档 |
|---|---|---|
Filament\Support\View\Components\BadgeComponent | 徽章 | 徽章 |
Filament\Support\View\Components\ButtonComponent | 按钮(实心与描边) | 按钮 |
Filament\Support\View\Components\IconButtonComponent | 仅含图标的按钮 | 图标按钮 |
Filament\Support\View\Components\LinkComponent | 链接 | 链接 |
Filament\Support\View\Components\ToggleComponent | 表单开关 | 开关 |
Filament\Support\View\Components\DropdownComponent\HeaderComponent | 下拉菜单标题 | 下拉菜单 |
Filament\Support\View\Components\DropdownComponent\ItemComponent | 下拉菜单项 | 下拉菜单 |
Filament\Schemas\View\Components\TextComponent | Schema 文本 prime | Prime 组件 |
Filament\Infolists\View\Components\TextEntryComponent\ItemComponent | Infolist 文本条目 | 文本条目 |
Filament\Infolists\View\Components\IconEntryComponent\IconComponent | Infolist 图标条目 | 图标条目 |
Filament\Tables\View\Components\Columns\TextColumnComponent\ItemComponent | 表格文本列 | 文本列 |
Filament\Tables\View\Components\Columns\IconColumnComponent\IconComponent | 表格图标列 | 图标列 |
Filament\Tables\View\Components\Columns\Summarizers\CountComponent\IconComponent | 表格计数汇总 | 汇总 |
Filament\Widgets\View\Components\StatsOverviewWidgetComponent\StatComponent\DescriptionComponent | 统计概览小部件描述 | 统计概览 |
TIP
编写自定义 getColorMap() 最快的方法,是从要覆盖的类中复制原始实现,再微调配置值。源文件与文档中的类位于 packages/<package>/src/View/Components/。每个实现都是几行流畅调用——学习该 API 最简单的方式是阅读默认实现再加以修改。
ComponentColorMap
逐条构建 slot 映射。为每个输出 slot 调用一次 slot(),然后调用 get()。
use Filament\Support\Colors\Color;
use Filament\Support\Facades\FilamentColor;
use Filament\Support\View\Components\ColorMaps\ComponentColorMap;
$gray = FilamentColor::getColor('gray');
ComponentColorMap::make($color)
->slot('text', surface: $gray[50], minRatio: Color::WCAG_AA_TEXT, fallback: 900)
->slot('dark:text', surface: $gray[700], maxShade: 500, shouldStartFromDarkest: true, fallback: 200)
->get();slot() 参数:
$name— 输出映射的键(text、bg、hover:text、dark:hover:bg等)。$surface— 所选色阶必须与之形成对比的颜色(通常为$gray[50]、$gray[700]或'oklch(1 0 0)')。$minRatio— 最低 WCAG 对比度。默认为Color::WCAG_AA_TEXT(4.5);图标可使用WCAG_AA_NON_TEXT(3.0),AAA 可使用WCAG_AAA_TEXT(7.0)。$maxShade— 可选,考虑的色阶数字上限。$minShade— 可选,下限。$shouldStartFromDarkest— 从最深到最浅遍历,而非默认的从最浅到最深。用于深色模式查找。$fallback— 没有候选符合时返回的色阶。浅色模式通常为900,深色模式通常为200。
ButtonComponentColorMap
一次 get() 调用即可返回实心按钮所需的全部八个 slot(bg、hover:bg、dark:bg、dark:hover:bg、text、hover:text、dark:text、dark:hover:text)。你配置要使用的背景色阶,每个背景对应的文本色阶会自动找出。至少需要一次 lightBackground() 和一次 darkBackground()。
use Filament\Support\Colors\Color;
use Filament\Support\View\Components\ColorMaps\ButtonComponentColorMap;
ButtonComponentColorMap::make($color)
->minContrastRatio(Color::WCAG_AA_TEXT)
->lightBackground(bg: 600, hover: 500)
->lightBackground(bg: 400, hover: 300, alternateHover: 500)
->darkBackground(bg: 600, hover: 500, alternateHover: 700)
->get();minContrastRatio() 设置背景与文本之间的最低 WCAG 对比度。默认为 Color::WCAG_AA_TEXT(4.5);AAA 可设为 WCAG_AAA_TEXT(7.0)。
lightBackground() 与 darkBackground() 使用相同的形态 (bg, hover, alternateHover?) 和相同的选择算法——区别仅在于配置哪种模式。每次调用都会向该模式的列表追加一个候选,按顺序分两轮评估:
- **首选** — 遍历列表,停在第一个其 `bg` 能产生浅色文本的候选。对该候选,若 `hover` 也能产生浅色文本则使用 `hover`;否则若 *`alternateHover`* 能产生浅色文本则使用它;否则跳过。
- **回退** — 若第一轮没有合格候选,则取*最后一个*候选。当 `hover` 的文本明度与 `bg` 一致时使用 `hover`,否则使用 `alternateHover`。一致性检查可避免悬停时文本颜色闪烁。
alternateHover 对任意候选(第一个、最后一个或中间)的处理方式相同。仅在主 hover 不合适时才会被考虑。
若要表达与颜色相关的级联——「若调色板撑得住就用 800,否则 700,再否则 600,对黄色则回退到更浅的背景配深色文本」——可链式添加候选,并以对浅色友好的回退结尾:
ButtonComponentColorMap::make($color)
->lightBackground(bg: 800, hover: 700)
->lightBackground(bg: 700, hover: 600)
->lightBackground(bg: 600, hover: 500)
->lightBackground(bg: 400, hover: 300, alternateHover: 500) // pale fallback
->darkBackground(bg: 600, hover: 500, alternateHover: 700)
->get();WARNING
当没有任何候选能在其 bg 上产生浅色文本时,最后一个候选会兼作回退。若你只配置了对鲜艳颜色友好的候选,而调色板本身偏浅,仍会使用最后一个候选——很可能得到深色文本配深色背景的按钮。请始终以对浅色友好的候选结尾(通常 bg 约为 400),以处理黄、amber 和 lime。
IconButtonComponentColorMap
返回仅含图标的按钮所需的四个图标 slot(text、hover:text、dark:text、dark:hover:text)。悬停变体由静止色阶加上固定的 100 色阶偏移推导,使图标更醒目。至少需要一次 lightSurface() 和一次 darkSurface()。
use Filament\Support\Colors\Color;
use Filament\Support\Facades\FilamentColor;
use Filament\Support\View\Components\ColorMaps\IconButtonComponentColorMap;
$gray = FilamentColor::getColor('gray');
IconButtonComponentColorMap::make($color)
->minContrastRatio(Color::WCAG_AA_NON_TEXT)
->lightSurface($gray[50])
->darkSurface($gray[700])
->darkMaxShade(500)
->get();minContrastRatio()— 图标与表面之间的最低对比度。默认为Color::WCAG_AA_NON_TEXT(3.0)。lightSurface()/darkSurface()— 各模式下图标必须与之形成对比的页面表面色。通常为$gray[50]和$gray[700]。darkMaxShade()— 深色模式图标颜色所考虑的色阶上限。默认为500;更浅的图标可设得更低。
完整示例:按钮的 AAA 对比度
下面是一个完整的子类,对实心按钮强制 WCAG AAA 对比度,并使背景选择偏向更深的色阶:
namespace App\View\Components;
use Filament\Support\Colors\Color;
use Filament\Support\Facades\FilamentColor;
use Filament\Support\View\Components\ButtonComponent as BaseButtonComponent;
use Filament\Support\View\Components\ColorMaps\ButtonComponentColorMap;
use Filament\Support\View\Components\ColorMaps\ComponentColorMap;
class ButtonComponent extends BaseButtonComponent
{
public function getColorMap(array $color): array
{
$gray = FilamentColor::getColor('gray');
if ($this->isOutlined) {
return ComponentColorMap::make($color)
->slot('text', surface: $gray[50], minRatio: Color::WCAG_AAA_TEXT, fallback: 900)
->slot('dark:text', surface: $gray[700], minRatio: Color::WCAG_AAA_TEXT, maxShade: 500, shouldStartFromDarkest: true, fallback: 200)
->get();
}
return ButtonComponentColorMap::make($color)
->minContrastRatio(Color::WCAG_AAA_TEXT)
->lightBackground(bg: 700, hover: 600)
->lightBackground(bg: 400, hover: 300, alternateHover: 500)
->darkBackground(bg: 600, hover: 500, alternateHover: 700)
->get();
}
}在服务提供者的 register() 方法中绑定你的子类:
use App\View\Components\ButtonComponent;
use Filament\Support\View\Components\ButtonComponent as BaseButtonComponent;
public function register(): void
{
$this->app->bind(BaseButtonComponent::class, ButtonComponent::class);
}上述列出的任意组件都可用同一模式——扩展、覆盖 getColorMap(),然后绑定。
TIP
默认值适用于绝大多数调色板。仅在有特定可访问性要求(如需符合 AAA)或设计系统强制不同色阶偏好时,才应覆盖这些类。