Skip to content

Commit

Permalink
Bordered Buttons (#3648)
Browse files Browse the repository at this point in the history
Co-authored-by: Josh Wooding <[email protected]>
  • Loading branch information
Vineet119 and joshwooding authored Jul 31, 2024
1 parent 3913dbb commit 7d874bb
Show file tree
Hide file tree
Showing 22 changed files with 854 additions and 135 deletions.
16 changes: 16 additions & 0 deletions .changeset/button-changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"@salt-ds/core": minor
---

Added `color` and `appearance` props for Button. These props replace the `variant` prop.

```tsx
<Button color="accent" appearance="solid" />
<Button color="accent" appearance="outline" />
<Button color="accent" appearance="transparent" />
<Button color="neutral" appearance="solid" />
<Button color="neutral" appearance="outline" />
<Button color="neutral" appearance="transparent" />
```

_Note:_ Button's `variant` prop is now deprecated and will be removed in the next major version.
85 changes: 85 additions & 0 deletions .changeset/silent-beds-promise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
"@salt-ds/theme": minor
---

Added foreground, background and border-color tokens for actionable and actionable-next.css

```
--salt-actionable-bold-foreground
--salt-actionable-bold-foreground-hover
--salt-actionable-bold-foreground-active
--salt-actionable-bold-foreground-disabled
--salt-actionable-bold-background
--salt-actionable-bold-background-hover
--salt-actionable-bold-background-active
--salt-actionable-bold-background-disabled
--salt-actionable-bold-borderColor
--salt-actionable-bold-borderColor-hover
--salt-actionable-bold-borderColor-active
--salt-actionable-bold-borderColor-disabled
--salt-actionable-foreground
--salt-actionable-foreground-hover
--salt-actionable-foreground-active
--salt-actionable-foreground-disabled
--salt-actionable-background
--salt-actionable-background-hover
--salt-actionable-background-active
--salt-actionable-background-disabled
--salt-actionable-borderColor
--salt-actionable-borderColor-hover
--salt-actionable-borderColor-active
--salt-actionable-borderColor-disabled
--salt-actionable-accent-bold-foreground
--salt-actionable-accent-bold-foreground-hover
--salt-actionable-accent-bold-foreground-active
--salt-actionable-accent-bold-foreground-disabled
--salt-actionable-accent-bold-background
--salt-actionable-accent-bold-background-hover
--salt-actionable-accent-bold-background-active
--salt-actionable-accent-bold-background-disabled
--salt-actionable-accent-bold-borderColor
--salt-actionable-accent-bold-borderColor-hover
--salt-actionable-accent-bold-borderColor-active
--salt-actionable-accent-bold-borderColor-disabled
--salt-actionable-accent-foreground
--salt-actionable-accent-foreground-hover
--salt-actionable-accent-foreground-active
--salt-actionable-accent-foreground-disabled
--salt-actionable-accent-background
--salt-actionable-accent-background-hover
--salt-actionable-accent-background-active
--salt-actionable-accent-background-disabled
--salt-actionable-accent-borderColor
--salt-actionable-accent-borderColor-hover
--salt-actionable-accent-borderColor-active
--salt-actionable-accent-borderColor-disabled
--salt-actionable-accent-subtle-foreground
--salt-actionable-accent-subtle-foreground-hover
--salt-actionable-accent-subtle-foreground-active
--salt-actionable-accent-subtle-foreground-disabled
--salt-actionable-accent-subtle-background
--salt-actionable-accent-subtle-background-hover
--salt-actionable-accent-subtle-background-active
--salt-actionable-accent-subtle-background-disabled
--salt-actionable-accent-borderColor
--salt-actionable-accent-borderColor-hover
--salt-actionable-accent-borderColor-active
--salt-actionable-accent-borderColor-disabled
--salt-actionable-subtle-foreground
--salt-actionable-subtle-foreground-hover
--salt-actionable-subtle-foreground-active
--salt-actionable-subtle-foreground-disabled
--salt-actionable-subtle-background
--salt-actionable-subtle-background-hover
--salt-actionable-subtle-background-active
--salt-actionable-subtle-background-disabled
--salt-actionable-subtle-borderColor
--salt-actionable-subtle-borderColor-hover
--salt-actionable-subtle-borderColor-active
--salt-actionable-subtle-borderColor-disabled
```
138 changes: 90 additions & 48 deletions packages/core/src/button/Button.css
Original file line number Diff line number Diff line change
@@ -1,51 +1,3 @@
/* Styles applied to the root element if variant="cta" */
.saltButton-cta {
--button-background: var(--salt-actionable-cta-background);
--button-background-active: var(--salt-actionable-cta-background-active);
--button-background-disabled: var(--salt-actionable-cta-background-disabled);
--button-background-hover: var(--salt-actionable-cta-background-hover);
--button-text-color: var(--salt-actionable-cta-foreground);
--button-text-color-active: var(--salt-actionable-cta-foreground-active);
--button-text-color-disabled: var(--salt-actionable-cta-foreground-disabled);
--button-text-color-hover: var(--salt-actionable-cta-foreground-hover);
--button-borderColor: var(--salt-actionable-cta-borderColor);
--button-borderColor-hover: var(--salt-actionable-cta-borderColor-hover);
--button-borderColor-active: var(--salt-actionable-cta-borderColor-active);
--button-borderColor-disabled: var(--salt-actionable-cta-borderColor-disabled);
}

/* Styles applied to the root element if variant="primary" (or no variant specified) */
.saltButton-primary {
--button-background: var(--salt-actionable-primary-background);
--button-background-active: var(--salt-actionable-primary-background-active);
--button-background-disabled: var(--salt-actionable-primary-background-disabled);
--button-background-hover: var(--salt-actionable-primary-background-hover);
--button-text-color: var(--salt-actionable-primary-foreground);
--button-text-color-active: var(--salt-actionable-primary-foreground-active);
--button-text-color-disabled: var(--salt-actionable-primary-foreground-disabled);
--button-text-color-hover: var(--salt-actionable-primary-foreground-hover);
--button-borderColor: var(--salt-actionable-primary-borderColor);
--button-borderColor-hover: var(--salt-actionable-primary-borderColor-hover);
--button-borderColor-active: var(--salt-actionable-primary-borderColor-active);
--button-borderColor-disabled: var(--salt-actionable-primary-borderColor-disabled);
}

/* Styles applied to the root element if variant="secondary" */
.saltButton-secondary {
--button-background: var(--salt-actionable-secondary-background);
--button-background-active: var(--salt-actionable-secondary-background-active);
--button-background-disabled: var(--salt-actionable-secondary-background-disabled);
--button-background-hover: var(--salt-actionable-secondary-background-hover);
--button-text-color: var(--salt-actionable-secondary-foreground);
--button-text-color-active: var(--salt-actionable-secondary-foreground-active);
--button-text-color-disabled: var(--salt-actionable-secondary-foreground-disabled);
--button-text-color-hover: var(--salt-actionable-secondary-foreground-hover);
--button-borderColor: var(--salt-actionable-secondary-borderColor);
--button-borderColor-hover: var(--salt-actionable-secondary-borderColor-hover);
--button-borderColor-active: var(--salt-actionable-secondary-borderColor-active);
--button-borderColor-disabled: var(--salt-actionable-secondary-borderColor-disabled);
}

.saltButton {
align-items: var(--saltButton-alignItems, center);
appearance: none;
Expand Down Expand Up @@ -132,3 +84,93 @@
cursor: var(--saltButton-cursor-disabled, var(--salt-actionable-cursor-disabled));
border-color: var(--saltButton-borderColor-disabled, var(--button-borderColor-disabled));
}

.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);
--button-text-color-disabled: var(--salt-actionable-accent-bold-foreground-disabled);
--button-background: var(--salt-actionable-accent-bold-background);
--button-background-active: var(--salt-actionable-accent-bold-background-active);
--button-background-disabled: var(--salt-actionable-accent-bold-background-disabled);
--button-background-hover: var(--salt-actionable-accent-bold-background-hover);
--button-borderColor: var(--salt-actionable-accent-bold-borderColor);
--button-borderColor-hover: var(--salt-actionable-accent-bold-borderColor-hover);
--button-borderColor-active: var(--salt-actionable-accent-bold-borderColor-active);
--button-borderColor-disabled: var(--salt-actionable-accent-bold-borderColor-disabled);
}

.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);
--button-text-color-disabled: var(--salt-actionable-accent-foreground-disabled);
--button-background: var(--salt-actionable-accent-background);
--button-background-hover: var(--salt-actionable-accent-background-hover);
--button-background-active: var(--salt-actionable-accent-background-active);
--button-background-disabled: var(--salt-actionable-accent-background-disabled);
--button-borderColor: var(--salt-actionable-accent-borderColor);
--button-borderColor-hover: var(--salt-actionable-accent-borderColor-hover);
--button-borderColor-active: var(--salt-actionable-accent-borderColor-active);
--button-borderColor-disabled: var(--salt-actionable-accent-borderColor-disabled);
}

.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);
--button-text-color-disabled: var(--salt-actionable-accent-subtle-foreground-disabled);
--button-background: var(--salt-actionable-accent-subtle-background);
--button-background-hover: var(--salt-actionable-accent-subtle-background-hover);
--button-background-active: var(--salt-actionable-accent-subtle-background-active);
--button-background-disabled: var(--salt-actionable-accent-subtle-background-disabled);
--button-borderColor: var(--salt-actionable-accent-subtle-borderColor);
--button-borderColor-hover: var(--salt-actionable-accent-subtle-borderColor-hover);
--button-borderColor-active: var(--salt-actionable-accent-subtle-borderColor-active);
--button-borderColor-disabled: var(--salt-actionable-accent-subtle-borderColor-disabled);
}

.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);
--button-text-color-disabled: var(--salt-actionable-bold-foreground-disabled);
--button-background: var(--salt-actionable-bold-background);
--button-background-hover: var(--salt-actionable-bold-background-hover);
--button-background-active: var(--salt-actionable-bold-background-active);
--button-background-disabled: var(--salt-actionable-bold-background-disabled);
--button-borderColor: var(--salt-actionable-bold-borderColor);
--button-borderColor-hover: var(--salt-actionable-bold-borderColor-hover);
--button-borderColor-active: var(--salt-actionable-bold-borderColor-active);
--button-borderColor-disabled: var(--salt-actionable-bold-borderColor-disabled);
}

.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);
--button-text-color-disabled: var(--salt-actionable-foreground-disabled);
--button-background: var(--salt-actionable-background);
--button-background-hover: var(--salt-actionable-background-hover);
--button-background-active: var(--salt-actionable-background-active);
--button-background-disabled: var(--salt-actionable-background-disabled);
--button-borderColor: var(--salt-actionable-borderColor);
--button-borderColor-hover: var(--salt-actionable-borderColor-hover);
--button-borderColor-active: var(--salt-actionable-borderColor-active);
--button-borderColor-disabled: var(--salt-actionable-borderColor-disabled);
}

.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);
--button-text-color-disabled: var(--salt-actionable-subtle-foreground-disabled);
--button-background: var(--salt-actionable-subtle-background);
--button-background-hover: var(--salt-actionable-subtle-background-hover);
--button-background-active: var(--salt-actionable-subtle-background-active);
--button-background-disabled: var(--salt-actionable-subtle-background-disabled);
--button-borderColor: var(--salt-actionable-subtle-borderColor);
--button-borderColor-hover: var(--salt-actionable-subtle-borderColor-hover);
--button-borderColor-active: var(--salt-actionable-subtle-borderColor-active);
--button-borderColor-disabled: var(--salt-actionable-subtle-borderColor-disabled);
}
32 changes: 32 additions & 0 deletions packages/core/src/button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import { useButton } from "./useButton";
const withBaseName = makePrefixer("saltButton");

export const ButtonVariantValues = ["primary", "secondary", "cta"] as const;
export const AppearanceValues = ["solid", "outline", "transparent"] as const;
export const ButtonColorValues = ["accent", "neutral"] as const;
export type ButtonVariant = (typeof ButtonVariantValues)[number];
export type Appearance = (typeof AppearanceValues)[number];
export type ButtonColor = (typeof ButtonColorValues)[number];

export interface ButtonProps extends ComponentPropsWithoutRef<"button"> {
/**
Expand All @@ -28,8 +32,28 @@ 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;
/**
* The type of the button. Options are 'solid', 'outline', and 'transparent'.
*/
appearance?: Appearance;
/**
* The color of the button. Options are 'accent' and 'neutral'.
*/
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<HTMLButtonElement, ButtonProps>(
Expand All @@ -43,6 +67,8 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
onKeyDown,
onBlur,
onClick,
appearance: appearanceProp,
color: colorProp,
type = "button",
variant = "primary",
...restProps
Expand All @@ -65,6 +91,10 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
window: targetWindow,
});

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
const { tabIndex, ...restButtonProps } = buttonProps;
Expand All @@ -77,6 +107,8 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
{
[withBaseName("disabled")]: disabled,
[withBaseName("active")]: active,
[withBaseName(appearance)]: appearance,
[withBaseName(color)]: color,
},
className,
)}
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/file-drop-zone/FileDropZoneTrigger.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import {
type ChangeEvent,
type FocusEvent,
type HTMLAttributes,
type SyntheticEvent,
forwardRef,
useRef,
} from "react";
import { Button } from "../button";
import { Button, type ButtonProps } from "../button";
import { useForkRef } from "../utils";

export interface FileDropZoneTriggerProps
extends Omit<HTMLAttributes<HTMLButtonElement>, "onChange"> {
extends Omit<ButtonProps, "onChange"> {
/**
* `accept` attribute for HTML <input>.
*
Expand Down
Loading

0 comments on commit 7d874bb

Please sign in to comment.