diff --git a/.changeset/button-changes.md b/.changeset/button-changes.md
index 06c7c06b90b..990cfe11512 100644
--- a/.changeset/button-changes.md
+++ b/.changeset/button-changes.md
@@ -2,25 +2,15 @@
"@salt-ds/core": minor
---
-Added `color` and `appearance` prop for Button.
+Added `color` and `appearance` props for Button. These props replace the `variant` prop.
```tsx
-
-
-
-
-
-
+
+
+
+
+
+
```
+
+_Note:_ Button's `variant` prop is now deprecated and will be removed in the next major version.
diff --git a/packages/core/src/button/Button.css b/packages/core/src/button/Button.css
index 69748a14681..8a92c6276e3 100644
--- a/packages/core/src/button/Button.css
+++ b/packages/core/src/button/Button.css
@@ -85,7 +85,7 @@
border-color: var(--saltButton-borderColor-disabled, var(--button-borderColor-disabled));
}
-.saltButton-solid-accent {
+.saltButton-accent.saltButton-solid {
--button-text-color: var(--salt-actionable-accent-bold-foreground);
--button-text-color-hover: var(--salt-actionable-accent-bold-foreground-hover);
--button-text-color-active: var(--salt-actionable-accent-bold-foreground-active);
@@ -100,7 +100,7 @@
--button-borderColor-disabled: var(--salt-actionable-accent-bold-borderColor-disabled);
}
-.saltButton-outline-accent {
+.saltButton-accent.saltButton-outline {
--button-text-color: var(--salt-actionable-accent-foreground);
--button-text-color-hover: var(--salt-actionable-accent-foreground-hover);
--button-text-color-active: var(--salt-actionable-accent-foreground-active);
@@ -115,7 +115,7 @@
--button-borderColor-disabled: var(--salt-actionable-accent-borderColor-disabled);
}
-.saltButton-transparent-accent {
+.saltButton-accent.saltButton-transparent {
--button-text-color: var(--salt-actionable-accent-subtle-foreground);
--button-text-color-hover: var(--salt-actionable-accent-subtle-foreground-hover);
--button-text-color-active: var(--salt-actionable-accent-subtle-foreground-active);
@@ -130,7 +130,7 @@
--button-borderColor-disabled: var(--salt-actionable-accent-subtle-borderColor-disabled);
}
-.saltButton-solid-neutral {
+.saltButton-neutral.saltButton-solid {
--button-text-color: var(--salt-actionable-bold-foreground);
--button-text-color-hover: var(--salt-actionable-bold-foreground-hover);
--button-text-color-active: var(--salt-actionable-bold-foreground-active);
@@ -145,7 +145,7 @@
--button-borderColor-disabled: var(--salt-actionable-bold-borderColor-disabled);
}
-.saltButton-outline-neutral {
+.saltButton-neutral.saltButton-outline {
--button-text-color: var(--salt-actionable-foreground);
--button-text-color-hover: var(--salt-actionable-foreground-hover);
--button-text-color-active: var(--salt-actionable-foreground-active);
@@ -160,7 +160,7 @@
--button-borderColor-disabled: var(--salt-actionable-borderColor-disabled);
}
-.saltButton-transparent-neutral {
+.saltButton-neutral.saltButton-transparent {
--button-text-color: var(--salt-actionable-subtle-foreground);
--button-text-color-hover: var(--salt-actionable-subtle-foreground-hover);
--button-text-color-active: var(--salt-actionable-subtle-foreground-active);
diff --git a/packages/core/src/button/Button.tsx b/packages/core/src/button/Button.tsx
index f60ae3beaa8..709e0c73b7d 100644
--- a/packages/core/src/button/Button.tsx
+++ b/packages/core/src/button/Button.tsx
@@ -32,6 +32,7 @@ export interface ButtonProps extends ComponentPropsWithoutRef<"button"> {
/**
* The variant to use. Options are 'primary', 'secondary' and 'cta'.
* 'primary' is the default value.
+ * @deprecated Use `appearance` and `color` instead.
*/
variant?: ButtonVariant;
/**
@@ -44,6 +45,17 @@ export interface ButtonProps extends ComponentPropsWithoutRef<"button"> {
color?: ButtonColor;
}
+function variantToAppearanceAndColor(variant: ButtonVariant) {
+ switch (variant) {
+ case "primary":
+ return { appearance: "solid", color: "neutral" };
+ case "secondary":
+ return { appearance: "transparent", color: "neutral" };
+ case "cta":
+ return { appearance: "solid", color: "accent" };
+ }
+}
+
export const Button = forwardRef(
function Button(
{
@@ -55,8 +67,8 @@ export const Button = forwardRef(
onKeyDown,
onBlur,
onClick,
- appearance,
- color,
+ appearance: appearanceProp,
+ color: colorProp,
type = "button",
variant = "primary",
...restProps
@@ -79,15 +91,9 @@ export const Button = forwardRef(
window: targetWindow,
});
- const variantStyles = {
- primary: { defaultAppearance: "solid", defaultColor: "neutral" },
- secondary: { defaultAppearance: "transparent", defaultColor: "neutral" },
- cta: { defaultAppearance: "solid", defaultColor: "accent" },
- };
-
- const { defaultAppearance, defaultColor } = variantStyles[variant];
- const resolvedAppearance = appearance ?? defaultAppearance;
- const resolvedColor = color ?? defaultColor;
+ const mapped = variantToAppearanceAndColor(variant);
+ const appearance = appearanceProp ?? mapped.appearance;
+ const color = colorProp ?? mapped.color;
// we do not want to spread tab index in this case because the button element
// does not require tabindex="0" attribute
@@ -101,8 +107,8 @@ export const Button = forwardRef(
{
[withBaseName("disabled")]: disabled,
[withBaseName("active")]: active,
- [withBaseName(`${resolvedAppearance}-${resolvedColor}`)]:
- resolvedAppearance,
+ [withBaseName(appearance)]: appearance,
+ [withBaseName(color)]: color,
},
className,
)}
diff --git a/packages/theme/css/characteristics/actionable.css b/packages/theme/css/characteristics/actionable.css
index 43e8001dbe7..5ab927144af 100644
--- a/packages/theme/css/characteristics/actionable.css
+++ b/packages/theme/css/characteristics/actionable.css
@@ -45,35 +45,7 @@
--salt-actionable-secondary-borderColor-active: transparent;
--salt-actionable-secondary-borderColor-disabled: transparent;
- /* saltButton-solid-neutral previous Primary */
- --salt-actionable-bold-foreground: var(--salt-palette-interact-primary-foreground);
- --salt-actionable-bold-foreground-hover: var(--salt-palette-interact-primary-foreground-hover);
- --salt-actionable-bold-foreground-active: var(--salt-palette-interact-primary-foreground-active);
- --salt-actionable-bold-foreground-disabled: var(--salt-palette-interact-primary-foreground-disabled);
- --salt-actionable-bold-background: var(--salt-palette-interact-primary-background);
- --salt-actionable-bold-background-hover: var(--salt-palette-interact-primary-background-hover);
- --salt-actionable-bold-background-active: var(--salt-palette-interact-primary-background-active);
- --salt-actionable-bold-background-disabled: var(--salt-palette-interact-primary-background-disabled);
- --salt-actionable-bold-borderColor: transparent;
- --salt-actionable-bold-borderColor-hover: transparent;
- --salt-actionable-bold-borderColor-active: transparent;
- --salt-actionable-bold-borderColor-disabled: transparent;
-
- /* saltButton-outline-neutral */
- --salt-actionable-foreground: var(--salt-palette-foreground-primary);
- --salt-actionable-foreground-hover: var(--salt-palette-interact-primary-foreground-hover);
- --salt-actionable-foreground-active: var(--salt-palette-interact-primary-foreground-active);
- --salt-actionable-foreground-disabled: var(--salt-palette-interact-primary-foreground-disabled);
- --salt-actionable-background: transparent;
- --salt-actionable-background-hover: var(--salt-palette-interact-primary-background-hover);
- --salt-actionable-background-active: var(--salt-palette-interact-primary-background-active);
- --salt-actionable-background-disabled: transparent;
- --salt-actionable-borderColor: var(--salt-palette-neutral-primary-border);
- --salt-actionable-borderColor-hover: var(--salt-palette-neutral-primary-border);
- --salt-actionable-borderColor-active: var(--salt-palette-neutral-primary-border);
- --salt-actionable-borderColor-disabled: var(--salt-palette-neutral-primary-border-disabled);
-
- /* saltButton-solid-accent previous CTA */
+ /* Accent bold */
--salt-actionable-accent-bold-foreground: var(--salt-palette-interact-cta-foreground);
--salt-actionable-accent-bold-foreground-hover: var(--salt-palette-interact-cta-foreground-hover);
--salt-actionable-accent-bold-foreground-active: var(--salt-palette-interact-cta-foreground-active);
@@ -87,7 +59,21 @@
--salt-actionable-accent-bold-borderColor-active: transparent;
--salt-actionable-accent-bold-borderColor-disabled: transparent;
- /* saltButton-outline-accent */
+ /* Neutral bold */
+ --salt-actionable-bold-foreground: var(--salt-palette-interact-primary-foreground);
+ --salt-actionable-bold-foreground-hover: var(--salt-palette-interact-primary-foreground-hover);
+ --salt-actionable-bold-foreground-active: var(--salt-palette-interact-primary-foreground-active);
+ --salt-actionable-bold-foreground-disabled: var(--salt-palette-interact-primary-foreground-disabled);
+ --salt-actionable-bold-background: var(--salt-palette-interact-primary-background);
+ --salt-actionable-bold-background-hover: var(--salt-palette-interact-primary-background-hover);
+ --salt-actionable-bold-background-active: var(--salt-palette-interact-primary-background-active);
+ --salt-actionable-bold-background-disabled: var(--salt-palette-interact-primary-background-disabled);
+ --salt-actionable-bold-borderColor: transparent;
+ --salt-actionable-bold-borderColor-hover: transparent;
+ --salt-actionable-bold-borderColor-active: transparent;
+ --salt-actionable-bold-borderColor-disabled: transparent;
+
+ /* Accent outline */
--salt-actionable-accent-foreground: var(--salt-palette-foreground-primary);
--salt-actionable-accent-foreground-hover: var(--salt-palette-interact-cta-foreground-hover);
--salt-actionable-accent-foreground-active: var(--salt-palette-interact-cta-foreground-active);
@@ -101,7 +87,21 @@
--salt-actionable-accent-borderColor-active: var(--salt-palette-accent-border);
--salt-actionable-accent-borderColor-disabled: var(--salt-palette-accent-border-disabled);
- /* saltButton-transparent-accent */
+ /* Neutral outline */
+ --salt-actionable-foreground: var(--salt-palette-foreground-primary);
+ --salt-actionable-foreground-hover: var(--salt-palette-interact-primary-foreground-hover);
+ --salt-actionable-foreground-active: var(--salt-palette-interact-primary-foreground-active);
+ --salt-actionable-foreground-disabled: var(--salt-palette-interact-primary-foreground-disabled);
+ --salt-actionable-background: transparent;
+ --salt-actionable-background-hover: var(--salt-palette-interact-primary-background-hover);
+ --salt-actionable-background-active: var(--salt-palette-interact-primary-background-active);
+ --salt-actionable-background-disabled: transparent;
+ --salt-actionable-borderColor: var(--salt-palette-neutral-primary-border);
+ --salt-actionable-borderColor-hover: var(--salt-palette-neutral-primary-border);
+ --salt-actionable-borderColor-active: var(--salt-palette-neutral-primary-border);
+ --salt-actionable-borderColor-disabled: var(--salt-palette-neutral-primary-border-disabled);
+
+ /* Accent transparent */
--salt-actionable-accent-subtle-foreground: var(--salt-palette-foreground-primary);
--salt-actionable-accent-subtle-foreground-hover: var(--salt-palette-interact-cta-foreground-hover);
--salt-actionable-accent-subtle-foreground-active: var(--salt-palette-interact-cta-foreground-active);
@@ -115,7 +115,7 @@
--salt-actionable-accent-subtle-borderColor-active: var(--salt-palette-accent-border);
--salt-actionable-accent-subtle-borderColor-disabled: var(--salt-palette-interact-border-none);
- /* saltButton-transparent-neutral previous Secondary */
+ /* Neutral transparent */
--salt-actionable-subtle-foreground: var(--salt-palette-interact-secondary-foreground);
--salt-actionable-subtle-foreground-hover: var(--salt-palette-interact-secondary-foreground-hover);
--salt-actionable-subtle-foreground-active: var(--salt-palette-interact-secondary-foreground-active);
diff --git a/site/docs/components/button/examples.mdx b/site/docs/components/button/examples.mdx
index 6436b63f888..f5df0744ae6 100644
--- a/site/docs/components/button/examples.mdx
+++ b/site/docs/components/button/examples.mdx
@@ -9,34 +9,21 @@ data:
---
-
+
-## CTA
-
-Use the CTA button for high-priority actions. For example, a CTA button may prompt a user to register, sign up, submit or buy.
+## Appearance
-### Best practices
-
-Use CTA buttons sparingly. They represent the default or expected action on the page.
+Button supports multiple visual styles; `"solid"`, `"outline"` and `"transparent"`. `"solid"` is the default appearance.
+
+
-
+## Color
-## Primary
-
-This is the default variant. Use the primary button for routine, nonurgent actions, for example, to move to the next page or complete a task.
+Button has a default color of `"neutral"`, it can be used for routine, nonurgent actions. You can use the `"accent"` color for high-priority actions or call-to-actions.
-
-
-
-## Secondary
-
-Use the secondary button for noncritical actions that support the user but don't impact a flow. They're typically the alternative option available alongside a primary action. For example, a secondary “back” button may support a primary “next” button.
-
-
-
## Icon and text
@@ -69,15 +56,60 @@ Display an icon-only button with no text when you have limited on-screen space,
Use the disabled state for a button that the user can’t press.
-A button with the prop `disabled={true}` will suppress all functionality. If you need to allow the user to place focus on a disabled button, you also need to pass `focusableWhenDisabled={true}`.
+A button with the prop `disabled={true}` will suppress all functionality.
+
+
+## Focusable when disabled
+
+If you need to allow the user to place focus on a disabled button, you also need to pass `focusableWhenDisabled={true}`.
+
+This is useful when you want to show a tooltip or a popover when the user hovers over the button.
+
+
+
+
## Full width
Use full width buttons on mobile devices or smaller viewports, the button will take up the full width of its container.
+
+
+
+
+## CTA
+
+_Note:_ The `variant` prop is deprecated. Use `appearance="solid"` and `color="accent"` instead.
+
+Use the CTA button for high-priority actions. For example, a CTA button may prompt a user to register, sign up, submit or buy.
+
+### Best practices
+
+Use CTA buttons sparingly. They represent the default or expected action on the page.
+
+
+
+
+
+## Primary
+
+_Note:_ The `variant` prop is deprecated. Use `appearance="solid"` and `color="neutral"` instead.
+
+This is the default variant. Use the primary button for routine, nonurgent actions, for example, to move to the next page or complete a task.
+
+
+
+
+
+## Secondary
+
+_Note:_ The `variant` prop is deprecated. Use `appearance="transparent"` and `color="neutral"` instead.
+
+Use the secondary button for noncritical actions that support the user but don't impact a flow. They're typically the alternative option available alongside a primary action. For example, a secondary “back” button may support a primary “next” button.
+
diff --git a/site/src/examples/button/Appearance.tsx b/site/src/examples/button/Appearance.tsx
new file mode 100644
index 00000000000..c638a8f62fe
--- /dev/null
+++ b/site/src/examples/button/Appearance.tsx
@@ -0,0 +1,10 @@
+import { Button } from "@salt-ds/core";
+import type { ReactElement } from "react";
+
+export const Appearance = (): ReactElement => (
+ <>
+
+
+
+ >
+);
diff --git a/site/src/examples/button/Color.tsx b/site/src/examples/button/Color.tsx
new file mode 100644
index 00000000000..a9f0e970c92
--- /dev/null
+++ b/site/src/examples/button/Color.tsx
@@ -0,0 +1,25 @@
+import { Button, GridLayout } from "@salt-ds/core";
+import type { ReactElement } from "react";
+
+export const Color = (): ReactElement => (
+
+
+
+
+
+
+
+
+);
diff --git a/site/src/examples/button/Disabled.tsx b/site/src/examples/button/Disabled.tsx
index 7f69ba70008..3e7bc60d76b 100644
--- a/site/src/examples/button/Disabled.tsx
+++ b/site/src/examples/button/Disabled.tsx
@@ -1,17 +1,26 @@
-import { Button } from "@salt-ds/core";
+import { Button, GridLayout } from "@salt-ds/core";
import { SendIcon } from "@salt-ds/icons";
import type { ReactElement } from "react";
export const Disabled = (): ReactElement => (
- <>
-