Accent colors

View on GitHub

Use the accent color in a component

The three variables

VariableTypical use
--accent-colorSolid accent surfaces/text: a primary button's background, a link, a selected tab's underline, a focused input's border
--accent-light-colorA lighter accent for things layered on top of an already-accented surface, or a subtler highlight
--accent-color-opacityA translucent accent wash — a selected list row's background, a selected card's tint (see AccountSettingsThemeCard.tsx's selected state: border-[var(--accent-color)] bg-[var(--accent-color-opacity)])

Reference them exactly like any theme colorTheme colors (dark / light)Use a theme color in a componentThe convention every component in this codebase follows, and the mistakes that only show up in one of the two themes. — a Tailwind arbitrary value, never copied out as a hardcoded hex:

<button className="rounded-lg bg-[var(--accent-color)] px-4 py-2 text-white hover:opacity-90">
    Save changes
</button>

This needs zero useAccent()/useTheme() awareness in the component itself — same reasoning as theme colors: AccentProvider writes the three variables as inline styles on <html> (see the READMEAccent colorsThe accent color is the one brand color used for buttons, links, selected states, and highlights across the whole interface — chosen once per user (Account…), and the browser resolves them at render time regardless of which component is asking.

When you do need useAccent() directly

Only when a component needs the current color's identity, not just its rendered value — the accent picker itself is the main case:

import ColorPicker from '@/Components/Molecules/ColorPicker/ColorPicker';
import { useAccent } from '@/context/AccentContext';
import {
    ACCENT_PALETTE,
    accentFromHex,
    getAccentSwatch,
} from '@/utils/accentColors';

const { accentColor, setAccentColor } = useAccent();

return (
    <ColorPicker
        value={getAccentSwatch(accentColor)}
        onChange={(hex) => setAccentColor(accentFromHex(hex))}
        palette={ACCENT_PALETTE}
    />
);

accentFromHex() turns a picked color back into the setting it stands for: 'default' or a preset name when the hex is exactly one of those (so they keep following the theme), a custom #rrggbb otherwise.

getAccentSwatch() returns a hex string for any AccentColor, including a custom one, suitable for inline style=, not a CSS variable — deliberately, since this swatch needs to show every option's real color simultaneously (including options that aren't the active accent, which have no CSS variable to read from). Compare this to AccountSettingsThemeCard.tsx's theme previews, which use literal hex values for the same reason (see that component's own doc comment) — both pickers need to render every choice's true appearance at once, which var(--accent-color) alone can't do since it only ever holds the currently active one.

Accent color vs. a project's badge color

Both start from the same ten names (the accent can also be a custom hex, which a project color never is) (ProjectColors — see the READMEAccent colorsThe accent color is the one brand color used for buttons, links, selected states, and highlights across the whole interface — chosen once per user (Account…), but they are not interchangeable and pull from different code:

  • A project's badge/card color (project.color, rendered via getColorTheme() in resources/js/utils/colors.ts) is fixed data about that project, stored per-project, rendered with literal Tailwind classes (bg-red-500/10, …) that look identical regardless of the viewer's theme or their own accent preference. Use this for anything that's inherently "this project's color" — a project card, a project badge in a list.
  • The accent color (--accent-color and friends) is a per-viewer preference applied to generic interactive chrome — buttons, links, selected states — completely unrelated to which project (if any) is on screen. Use this for anything that should match whatever brand color the current user picked, not any particular project's identity.

Reaching for the wrong one is the most common mistake: a project badge built from var(--accent-color) would make every project look like whatever color the viewer happens to prefer, not the color the project was actually given; conversely, a generic "Save" button built from a hardcoded bg-purple-500 ignores the user's accent choice entirely.

Tests

Same guidance as theme colorsTheme colors (dark / light)Use a theme color in a componentThe convention every component in this codebase follows, and the mistakes that only show up in one of the two themes. — assert on the rendered className/inline style containing the expected var(--accent-...) reference or hex value, at the level of whatever component you're adding. No dedicated "accent variables exist" test is expected beyond that.