Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Button/IconButton/LinkButton: add 'on' lightBackground or darkBackground prop #333

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fluffy-files-press.md
@@ -0,0 +1,5 @@
---
"@cambly/syntax-core": minor
---

Button/Chip/IconButton/LinkButton: add 'on' lightBackground or darkBackground prop (Cambio only)
2 changes: 1 addition & 1 deletion packages/syntax-core/package.json
Expand Up @@ -14,7 +14,7 @@
"scripts": {
"build": "tsup",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
"dev": "NODE_OPTIONS=--max_old_space_size=4096 tsup --watch",
"dev": "NODE_OPTIONS=--max_old_space_size=8192 tsup --watch",
"lint": "TIMING=1 eslint \"src/**/*.ts*\" --max-warnings 0",
"stylelint": "stylelint \"**/*.css\"",
"stylelint:fix": "npm run stylelint --fix",
Expand Down
32 changes: 32 additions & 0 deletions packages/syntax-core/src/Button/Button.stories.tsx
@@ -1,6 +1,7 @@
import { type StoryObj, type Meta } from "@storybook/react";
import Button from "./Button";
import FavoriteBorder from "@mui/icons-material/FavoriteBorder";
import Box from "../Box/Box";

export default {
title: "Components/Button",
Expand All @@ -11,6 +12,20 @@ export default {
url: "https://www.figma.com/file/p7LKna9JMU0JEkcKamzs53/Cambly-Design-System-(Draft)?node-id=994%3A2346",
},
},
args: {
text: "Call to action",
color: "primary",
on: "lightBackground",
size: "md",
disabled: false,
loading: false,
fullWidth: false,
"data-testid": "",
loadingText: "",
accessibilityLabel: "",
tooltip: "",
type: "button",
},
argTypes: {
color: {
options: [
Expand All @@ -29,6 +44,10 @@ export default {
],
control: { type: "radio" },
},
on: {
options: ["lightBackground", "darkBackground"],
control: { type: "radio" },
},
size: {
options: ["sm", "md", "lg"],
control: { type: "radio" },
Expand All @@ -43,12 +62,25 @@ export default {
control: "boolean",
},
onClick: { action: "clicked" },
type: {
options: ["button", "submit", "reset"],
},
},
tags: ["autodocs"],
} as Meta<typeof Button>;

export const Default: StoryObj<typeof Button> = {
args: { text: "Call to action" },
render: (args) => {
return (
<Box
backgroundColor={args.on === "lightBackground" ? "white" : "black"}
padding={2}
>
<Button {...args} />
</Box>
);
},
};
export const Small: StoryObj<typeof Button> = {
args: { ...Default.args, size: "sm" },
Expand Down
13 changes: 10 additions & 3 deletions packages/syntax-core/src/Button/Button.tsx
Expand Up @@ -107,6 +107,12 @@ type ButtonProps = {
* Note: endIcon is not supported in the Cambio theme
*/
endIcon?: React.ComponentType<{ className?: string }>;
/**
* Indicate whether the button renders on a light or dark background. Changes the color of the button (Cambio only)
*
* @defaulValue `lightBackground`
*/
on?: "lightBackground" | "darkBackground";
/**
* The callback to be called when the button is clicked
*/
Expand All @@ -116,7 +122,7 @@ type ButtonProps = {
*/
tooltip?: string;
/**
* The type you want to set for the primitive <button/>
* The type you want to set for the primitive `<button/>`
*/
type?: "button" | "submit" | "reset";
};
Expand All @@ -138,6 +144,7 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
fullWidth = false,
startIcon: StartIcon,
endIcon: EndIcon,
on = "lightBackground",
onClick,
tooltip,
type = "button",
Expand All @@ -150,12 +157,12 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
const foregroundColorClass =
themeName === "classic"
? classicForegroundColor(classicColor(color))
: cambioForegroundColor(cambioColor(color));
: cambioForegroundColor(cambioColor(color), on);

const backgroundColorClass =
themeName === "classic"
? classicBackgroundColor(classicColor(color))
: cambioBackgroundColor(cambioColor(color));
: cambioBackgroundColor(cambioColor(color), on);

return (
<button
Expand Down
8 changes: 8 additions & 0 deletions packages/syntax-core/src/Chip/Chip.module.css
Expand Up @@ -35,10 +35,18 @@
background-color: var(--color-cambio-gray-370);
}

.deselectedChipCambioOnDarkBackground {
background-color: var(--color-cambio-gray-870);
}

.selectedChipCambio {
background-color: var(--color-cambio-gray-800);
}

.selectedChipCambioOnDarkBackground {
background-color: var(--color-cambio-gray-200);
}

.icon {
/* stylelint-disable-next-line declaration-no-important -- Need to use !important to override MUI icon sizes */
height: 24px !important;
Expand Down
22 changes: 20 additions & 2 deletions packages/syntax-core/src/Chip/Chip.stories.tsx
Expand Up @@ -13,7 +13,17 @@ export default {
url: "https://www.figma.com/file/p7LKna9JMU0JEkcKamzs53/%F0%9F%93%90-Syntax?type=design&node-id=6156%3A25032&mode=design&t=SSblm5y2vyrOKil1-1",
},
},
args: {
selected: false,
text: "text on chip",
size: "sm",
on: "lightBackground",
},
argTypes: {
on: {
options: ["lightBackground", "darkBackground"],
control: { type: "radio" },
},
selected: {
control: "boolean",
},
Expand All @@ -30,8 +40,16 @@ export const Default: StoryObj<typeof Chip> = {
text: "text on chip",
selected: false,
},
/* eslint-disable-next-line react/jsx-props-no-spreading */
render: ({ ...args }) => <Chip {...args} />,
render: (args) => {
return (
<Box
backgroundColor={args.on === "lightBackground" ? "white" : "black"}
padding={2}
>
<Chip {...args} />
</Box>
);
},
};

const ChipInteractive = () => {
Expand Down
54 changes: 50 additions & 4 deletions packages/syntax-core/src/Chip/Chip.tsx
@@ -1,11 +1,35 @@
import React, { forwardRef } from "react";
import React, { forwardRef, useMemo } from "react";
import classnames from "classnames";
import Typography from "../Typography/Typography";
import Box from "../Box/Box";
import styles from "./Chip.module.css";
import useIsHydrated from "../useIsHydrated";
import { useTheme } from "../ThemeProvider/ThemeProvider";

function typographyColor({
themeName,
selected,
on,
}: {
themeName: "cambio" | "classic";
selected: boolean;
on: "lightBackground" | "darkBackground";
}): "white" | "gray900" {
if (themeName === "cambio" && on === "darkBackground") {
if (selected) {
return "gray900";
} else {
return "white";
}
} else {
if (selected) {
return "white";
} else {
return "gray900";
}
}
}

type ChipProps = {
/**
* If true, the chip will be disabled.
Expand Down Expand Up @@ -40,6 +64,12 @@ type ChipProps = {
* The text to be displayed on the chip
*/
text: string;
/**
* Indicate whether the badge renders on a light or dark background. Changes the color of the chip (Cambio only)
*
* @defaulValue `lightBackground`
*/
on?: "lightBackground" | "darkBackground";
/**
* The callback to be called when the chip is clicked
*/
Expand All @@ -62,6 +92,7 @@ const Chip = forwardRef<HTMLButtonElement, ChipProps>(
"data-testid": dataTestId,
size = "sm",
text,
on = "lightBackground",
onChange,
icon: Icon,
dangerouslyForceFocusStyles,
Expand All @@ -73,17 +104,27 @@ const Chip = forwardRef<HTMLButtonElement, ChipProps>(
const isHydrated = useIsHydrated();
const disabled = !isHydrated || disabledProp;

const selectedChipCambioStyle =
on === "lightBackground"
? styles.selectedChipCambio
: styles.selectedChipCambioOnDarkBackground;

const deselectedChipCambioStyle =
on === "lightBackground"
? styles.deselectedChipCambio
: styles.deselectedChipCambioOnDarkBackground;

const chipStyles = classnames(
styles.chip,
themeName === "classic" ? styles.chipClassic : styles.chipCambio,
styles[transformedSize],
{
[themeName === "classic"
? styles.selectedChip
: styles.selectedChipCambio]: selected,
: selectedChipCambioStyle]: selected,
[themeName === "classic"
? styles.deselectedChip
: styles.deselectedChipCambio]: !selected,
: deselectedChipCambioStyle]: !selected,
[styles.disabled]: disabled,
[styles.forceFocus]: dangerouslyForceFocusStyles,
},
Expand All @@ -96,6 +137,11 @@ const Chip = forwardRef<HTMLButtonElement, ChipProps>(
["lg"]: 300,
} as const;

const color = useMemo(
() => typographyColor({ themeName, selected, on }),
[themeName, selected, on],
);

return (
<button
className={chipStyles}
Expand All @@ -112,7 +158,7 @@ const Chip = forwardRef<HTMLButtonElement, ChipProps>(
size={
themeName === "classic" ? typographySize[transformedSize] : 100
}
color={selected ? "white" : "gray900"}
color={color}
>
{text}
</Typography>
Expand Down
7 changes: 0 additions & 7 deletions packages/syntax-core/src/IconButton/IconButton.module.css
Expand Up @@ -117,10 +117,3 @@
/* stylelint-disable-next-line declaration-no-important -- Need to use !important to override MUI icon sizes */
width: 32px !important;
}

.xlIconCambio {
/* stylelint-disable-next-line declaration-no-important -- Need to use !important to override MUI icon sizes */
height: 40px !important;
/* stylelint-disable-next-line declaration-no-important -- Need to use !important to override MUI icon sizes */
width: 40px !important;
}
26 changes: 26 additions & 0 deletions packages/syntax-core/src/IconButton/IconButton.stories.tsx
Expand Up @@ -2,6 +2,7 @@ import { type StoryObj, type Meta } from "@storybook/react";
import IconButton from "./IconButton";
import FavoriteBorder from "@mui/icons-material/FavoriteBorder";
import Star from "@mui/icons-material/Star";
import Box from "../Box/Box";

export default {
title: "Components/IconButton",
Expand All @@ -12,6 +13,15 @@ export default {
url: "https://www.figma.com/file/p7LKna9JMU0JEkcKamzs53/Cambly-Design-System?node-id=1007%3A4105",
},
},
args: {
color: "primary",
on: "lightBackground",
size: "md",
disabled: false,
"data-testid": "",
accessibilityLabel: "",
tooltip: "",
},
argTypes: {
color: {
options: [
Expand All @@ -37,12 +47,28 @@ export default {
disabled: {
control: "boolean",
},
on: {
options: ["lightBackground", "darkBackground"],
control: { type: "radio" },
},
onClick: { action: "clicked" },
},
tags: ["autodocs"],
} as Meta<typeof IconButton>;

export const Default: StoryObj<typeof IconButton> = {
args: { accessibilityLabel: "Star", tooltip: "Demo title", icon: Star },

render: (args) => {
return (
<Box
backgroundColor={args.on === "lightBackground" ? "white" : "black"}
padding={2}
>
<IconButton {...args} />
</Box>
);
},
};
export const Small: StoryObj<typeof IconButton> = {
args: { ...Default.args, size: "sm" },
Expand Down
12 changes: 9 additions & 3 deletions packages/syntax-core/src/IconButton/IconButton.tsx
Expand Up @@ -25,7 +25,6 @@ const cambioIconSize = {
sm: styles.smIconCambio,
md: styles.mdIconCambio,
lg: styles.lgIconCambio,
xl: styles.xlIconCambio,
};

type IconButtonProps = {
Expand Down Expand Up @@ -90,6 +89,12 @@ type IconButtonProps = {
* @defaultValue false
*/
disabled?: boolean;
/**
* Indicate whether the button renders on a light or dark background. Changes the color of the button (Cambio only)
*
* @defaulValue `lightBackground`
*/
on?: "lightBackground" | "darkBackground";
/**
* The callback to be called when the button is clicked
*/
Expand All @@ -113,6 +118,7 @@ const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
icon: Icon,
size = "md",
tooltip,
on = "lightBackground",
onClick,
}: IconButtonProps,
ref,
Expand All @@ -123,12 +129,12 @@ const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
const foregroundColorClass =
themeName === "classic"
? classicForegroundColor(classicColor(color))
: cambioForegroundColor(cambioColor(color));
: cambioForegroundColor(cambioColor(color), on);

const backgroundColorClass =
themeName === "classic"
? classicBackgroundColor(classicColor(color))
: cambioBackgroundColor(cambioColor(color));
: cambioBackgroundColor(cambioColor(color), on);

return (
<button
Expand Down