Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7b0ac73
Update static color palette
gcamacho079 May 4, 2026
aaf48a4
Merge branch '6.x' into a11y/static-color-palette
gcamacho079 May 4, 2026
03cd9e4
Start refactoring indicators, dev mode colors, and switch buttons to …
gcamacho079 May 5, 2026
a99bd7c
Build
gcamacho079 May 5, 2026
fda3be4
Start refactoring buttons to use static colors, update static color v…
gcamacho079 May 7, 2026
ed74ef3
Start updating buttons to use primary/secondary/tertiary variants wit…
gcamacho079 May 8, 2026
e42476b
Start migrating styles to use button color variables
gcamacho079 May 8, 2026
bd5deb4
Update color palette docs, more button modifications
gcamacho079 May 13, 2026
f1ea2af
Fix dev mode stripe
gcamacho079 May 13, 2026
593ef0e
Switch up token names again
gcamacho079 May 13, 2026
979fae0
Get hsl darkening working instead of setting additional variables
gcamacho079 May 15, 2026
e5daec2
More button styles fixes
gcamacho079 May 15, 2026
c6cb971
Reorder rules to simplify diff
gcamacho079 May 15, 2026
a743c95
Comment and remove space
gcamacho079 May 15, 2026
2f1a59a
Finalize button hover/active styles
gcamacho079 May 15, 2026
3353700
Add static color variants and incorporate into indicator colors
gcamacho079 May 15, 2026
83d469d
Finalize button docs and updates
gcamacho079 May 15, 2026
27a472a
Remove unused button color tokens, adjust switch checked bg color
gcamacho079 May 15, 2026
90b1126
Fix dev mode stripe color
gcamacho079 May 15, 2026
a40c2b9
Update all instances of buttons from primary to accent and default/se…
gcamacho079 May 15, 2026
80867d2
update default button to neutral'
gcamacho079 May 15, 2026
12d57e4
Bind loading arg
gcamacho079 May 15, 2026
5c9fb63
Update matrices in storybook docs
gcamacho079 May 15, 2026
27a809f
Streamline variant/appearance names
gcamacho079 May 17, 2026
8f33f53
Fix a couple parts of stories, update filled button
gcamacho079 May 17, 2026
7026370
A couple more references I missed
gcamacho079 May 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions packages/craftcms-cp/scripts/generate-color-palette.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import {writeFileSync} from 'fs';
import {dirname, resolve} from 'path';
import {fileURLToPath} from 'url';
import {stops, lightTheme, darkTheme} from '../src/styles/color-definitions.js';
import {
stops,
lightTheme,
darkTheme,
staticTheme,
} from '../src/styles/color-definitions.js';

const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = resolve(__dirname, '..');
Expand Down Expand Up @@ -35,7 +40,7 @@ function printStyles() {
const lightColors = colorsToCssVariables(lightTheme.contrastColors);
const darkColors = colorsToCssVariables(darkTheme.contrastColors);
const staticColors = colorsToCssVariables(
lightTheme.contrastColors,
staticTheme.contrastColors,
'color-static'
);

Expand Down
2 changes: 1 addition & 1 deletion packages/craftcms-cp/scripts/generate-colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const semanticColors = {
accent: 'blue',
info: 'blue',
success: 'emerald',
warning: 'orange',
warning: 'yellow',
danger: 'red',
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default class CraftActionItem extends LitElement {
@property() icon: string | null = null;
@property() href: string | null = null;
@property({type: Boolean}) disabled: boolean = false;
@property({reflect: true}) variant: VariantKey = Variant.Default;
@property({reflect: true}) variant: VariantKey = Variant.Neutral;
@property({type: Boolean}) checked: boolean = false;
@property({type: Boolean}) active: boolean = false;
@property() type: 'normal' | 'checkbox' = 'normal';
Expand Down
46 changes: 46 additions & 0 deletions packages/craftcms-cp/src/components/button/Docs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {Canvas, Meta} from '@storybook/addon-docs/blocks';
import * as ButtonStories from './button.stories';

<Meta of={ButtonStories} />

# Button

A button represents a clickable element that performs an action when activated.

<Canvas of={ButtonStories.Default} />

## Appearance

`appearance` controls how visually prominent the button is. Use it to signal importance relative to other buttons on the page.

- `solid` — Solid colored background. The highest-emphasis style. Use for the single most important action in a given context.
- `outline` — Transparent background with a colored border. Medium emphasis. Use for secondary actions alongside a solid button.
- `plain` — No background or border. Lowest emphasis. Use for tertiary or destructive actions that shouldn't draw attention on their own.

## Variant

`variant` controls the button's color, which communicates the _intent_ of the action — not how prominent it is. Appearance and variant are independent: any appearance can be combined with any variant.

- `accent` — Blue. Use for the primary action on a page, such as Save or Confirm.
- `neutral` — Gray. The default. Use for everyday actions that don't carry a strong positive or negative meaning.
- `danger` — Red. Use for actions that delete, remove, or permanently change data.

<Canvas of={ButtonStories.Accent} />

### Inherit

`variant="inherit"` is a special case for buttons placed inside [Colorable](?path=/docs/concepts-colorable--docs) containers. Instead of applying its own color, the button picks up the color from its parent container.

Avoid using the standard color variants (`accent`, `neutral`, `danger`) inside Colorable components — the two color systems can conflict and produce unexpected results.

## Sizes

<Canvas of={ButtonStories.Sizes} />

## Icon buttons

<Canvas of={ButtonStories.Icon} />

## Loading state

<Canvas of={ButtonStories.Loading} />
65 changes: 48 additions & 17 deletions packages/craftcms-cp/src/components/button/button.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import {html} from 'lit';
import './button.js';
import '../icon/icon.js';
import '../chip/chip.js';
import {ButtonAppearance, ButtonVariant} from '@src/types';

const buttonVariants = Object.values(ButtonVariant);
const appearance = Object.values(ButtonAppearance);

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const meta = {
Expand All @@ -13,20 +17,31 @@ const meta = {
parameters: {
layout: 'centered',
},
argTypes: {},
args: {
label: 'Button',
appearance: 'solid',
loading: false,
variant: 'neutral',
},
argTypes: {
appearance: {
control: {type: 'select'},
options: appearance,
},
loading: {
control: {type: 'boolean'},
},
},
render: (args) => html`
<div class="grid gap-4">
${['primary', 'default', 'danger'].map(
${buttonVariants.map(
(variant) => html`
<div class="flex gap-2">
<craft-button variant="${variant}"
>${variant ?? 'None'}</craft-button
>
<craft-button appearance="filled" variant="${variant}"
>${variant} filled</craft-button
>${variant ?? 'None'} solid</craft-button
>
<craft-button appearance="dashed" variant="${variant}"
>${variant} dashed</craft-button
<craft-button appearance="outline" variant="${variant}"
>${variant} outline</craft-button
>
<craft-button appearance="plain" variant="${variant}"
>${variant} plain</craft-button
Expand All @@ -37,15 +52,12 @@ const meta = {

<craft-chip data-color="violet">
<div class="flex gap-2">
<craft-button variant="inherit">Chip buttons</craft-button>
<craft-button appearance="filled" variant="inherit"
>Filled</craft-button
>
<craft-button appearance="dashed" variant="inherit"
>Dashed</craft-button
<craft-button variant="inherit">Chip Buttons</craft-button>
<craft-button appearance="outline" variant="inherit"
>Outline</craft-button
>
<craft-button appearance="plain" variant="inherit"
>plain</craft-button
>Plain</craft-button
>
</div>
</craft-chip>
Expand All @@ -61,6 +73,21 @@ export const Default: Story = {
args: {},
};

export const Accent: Story = {
args: {
variant: 'accent',
},
argTypes: {
variant: {
control: {type: 'select'},
options: buttonVariants,
},
},
render: (args) => html`
<craft-button variant="${args.variant}">${args.label}</craft-button>
`,
};

export const Sizes: Story = {
args: {},
render: (args) => html`
Expand All @@ -87,6 +114,10 @@ export const Icon: Story = {
};

export const Loading: Story = {
args: {},
render: (args) => html` <craft-button loading> Submit </craft-button> `,
args: {
loading: true,
},
render: (args) => html`
<craft-button ?loading="${args.loading}"> Submit </craft-button>
`,
};
134 changes: 55 additions & 79 deletions packages/craftcms-cp/src/components/button/button.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ export default css`
min-height: var(--c-button-height, var(--c-size-control-md));
min-width: var(--c-button-width, var(--c-size-control-md));
white-space: nowrap;
border-width: var(--c-button-border-width, 1px);
border-style: var(--c-button-border-style, solid);

/* Colorable styles */
color: var(--c-color-on-loud, var(--c-color-neutral-on-loud));
border-width: var(--c-button-border-width, 1px);
border-style: var(--c-button-border-style, solid);
border-color: var(
--c-color-border-loud,
var(--c-color-neutral-border-loud)
Expand All @@ -34,22 +34,17 @@ export default css`

@media (hover: hover) {
:host(:hover) {
background-color: color-mix(
in oklab,
var(--c-color-fill-loud, var(--c-button-default-fill)),
var(--c-color-mix-hover)
background-color: hsl(
from var(--c-color-fill-loud, var(--c-button-default-fill)) h s
calc(l - 5)
);
color: var(--c-color-on-loud);
}
}

:host(:not(:disabled):not(.loading):active) {
color: var(--c-color-on-loud);
background-color: color-mix(
in oklab,
var(--c-color-fill-loud, var(--c-color-neutral-fill-normal)),
var(--c-color-mix-active)
);
color: var(--_active-color);
background-color: var(--_active-background-color);
}

/*
Expand Down Expand Up @@ -113,101 +108,82 @@ export default css`
Appearances
*/

/* Plain */
:host([appearance~='plain']) {
/* Plain & Outline (Shared) */
:host([appearance~='plain']),
:host([appearance~='outline']) {
background-color: transparent;
border-color: transparent;
color: inherit;
color: var(--c-color-on-quiet);
}

:host([appearance~='plain']:hover) {
background-color: color-mix(
in oklab,
var(--c-color-fill-quiet, var(--c-button-default-fill)),
var(--c-color-mix-hover)
:host([appearance~='plain']:hover),
:host([appearance~='outline']:hover) {
background-color: hsl(
from var(--c-color-fill-quiet, var(--c-color-neutral-fill-quiet)) h s
calc(l - 5)
);
color: var(--c-color-on-quiet);
}

:host([appearance~='plain']:active) {
color: var(--c-color-on-quiet, var(--c-color-neutral-on-quiet));
background-color: color-mix(
in oklab,
var(--c-color-fill-quiet, var(--c-color-neutral-fill-quiet)),
var(--c-color-mix-active)
:host([appearance~='plain']:active),
:host([appearance~='outline']:active) {
--_active-background-color: hsl(
from var(--c-color-fill-quiet, var(--c-color-neutral-fill-quiet)) h s
calc(l - 8)
);
--_active-color: var(--c-color-on-quiet, var(--c-color-neutral-on-quiet));
}

/* Filled */
:host([appearance~='filled']) {
background-color: var(
--c-color-fill-normal,
var(--c-color-neutral-fill-normal)
);
/* Plain */
:host([appearance~='plain']) {
border-color: transparent;
color: var(--c-color-on-normal, var(--c-color-neutral-on-normal));
}

:host([appearance~='filled']:hover) {
background-color: color-mix(
in oklab,
var(--c-color-fill-normal, var(--c-color-neutral-fill-normal)),
var(--c-color-mix-hover)
/* Solid */
:host([appearance~='solid']) {
background-color: var(
--c-color-fill-loud,
var(--c-color-neutral-fill-loud)
);
color: var(--c-color-on-normal, var(--c-color-neutral-on-normal));
border-color: transparent;
color: var(--c-color-on-loud, var(--c-color-neutral-on-loud));
}

:host([appearance~='filled']:active) {
color: var(--c-color-on-quiet, var(--c-color-neutral-on-quiet));
background-color: color-mix(
in oklab,
var(--c-color-fill-quiet, var(--c-color-neutral-fill-quiet)),
var(--c-color-mix-active)
:host([appearance~='solid']:hover) {
background-color: hsl(
from var(--c-color-fill-loud, var(--c-color-neutral-fill-loud)) h s
calc(l - 5)
);
color: var(--c-color-on-loud, var(--c-color-neutral-on-loud));
}

/* Dashed */
:host([appearance~='dashed']) {
background-color: transparent;
border-color: var(--c-color-border-normal);
border-style: dashed;
color: var(--c-color-on-quiet);
}

:host([appearance~='dashed']:hover) {
background-color: color-mix(
in oklab,
var(--c-color-fill-quiet, var(--c-button-default-fill)),
var(--c-color-mix-hover)
:host([appearance~='solid']:active) {
--_active-background-color: hsl(
from var(--c-color-fill-loud, var(--c-color-neutral-fill-loud)) h s
calc(l - 10)
);
color: var(--c-color-on-quiet);
--_active-color: var(--c-color-on-loud, var(--c-color-neutral-on-loud));
}

:host([appearance~='dashed']:active) {
color: var(--c-color-on-quiet, var(--c-color-neutral-on-quiet));
background-color: color-mix(
in oklab,
var(--c-color-fill-quiet, var(--c-color-neutral-fill-quiet)),
var(--c-color-mix-active)
);
/* Outline */
:host([appearance~='outline']) {
border-color: var(--c-color-border-loud);
}

/*
Variants (aka fill colors)
*/
:host([variant~='primary']) {
--c-color-fill-loud: var(--c-color-brand-fill-loud);
--c-color-fill-normal: var(--c-color-brand-fill-normal);
--c-color-fill-quiet: var(--c-color-brand-fill-quiet);
--c-color-border-loud: var(--c-color-brand-border-loud);
--c-color-border-normal: var(--c-color-brand-border-normal);
--c-color-border-quiet: var(--c-color-brand-border-quiet);
--c-color-on-loud: var(--c-color-brand-on-loud);
--c-color-on-normal: var(--c-color-brand-on-normal);
--c-color-on-quiet: var(--c-color-brand-on-quiet);
:host([variant~='accent']) {
--c-color-fill-loud: var(--c-color-accent-fill-loud);
--c-color-fill-normal: var(--c-color-accent-fill-normal);
--c-color-fill-quiet: var(--c-color-accent-fill-quiet);
--c-color-border-loud: var(--c-color-accent-border-loud);
--c-color-border-normal: var(--c-color-accent-border-normal);
--c-color-border-quiet: var(--c-color-accent-border-quiet);
--c-color-on-loud: var(--c-color-accent-on-loud);
--c-color-on-normal: var(--c-color-accent-on-normal);
--c-color-on-quiet: var(--c-color-accent-on-quiet);
}

:host([variant='default']) {
:host([variant='neutral']) {
--c-color-fill-loud: var(--c-color-neutral-fill-loud);
--c-color-fill-normal: var(--c-color-neutral-fill-normal);
--c-color-fill-quiet: var(--c-color-neutral-fill-quiet);
Expand Down
Loading