diff --git a/.changeset/dull-pandas-build.md b/.changeset/dull-pandas-build.md
new file mode 100644
index 00000000..86c8ef73
--- /dev/null
+++ b/.changeset/dull-pandas-build.md
@@ -0,0 +1,7 @@
+---
+"@cambly/syntax-design-tokens": minor
+"@cambly/syntax-core": minor
+"@syntax/storybook": minor
+---
+
+Add ThemeProvider & styles for Button / IconButton & LinkButton
diff --git a/apps/storybook/.storybook/main.ts b/apps/storybook/.storybook/main.ts
index 1245ca57..01744161 100644
--- a/apps/storybook/.storybook/main.ts
+++ b/apps/storybook/.storybook/main.ts
@@ -13,9 +13,10 @@ const config: StorybookConfig = {
actions: false,
},
},
+ "@storybook/addon-a11y",
"@storybook/addon-actions",
+ "@storybook/addon-toolbars",
"storybook-addon-designs",
- "@storybook/addon-a11y",
"storybook-addon-rtl",
],
staticDirs: ["../public"],
diff --git a/apps/storybook/.storybook/preview.tsx b/apps/storybook/.storybook/preview.tsx
index 13d11eaf..1beacaff 100644
--- a/apps/storybook/.storybook/preview.tsx
+++ b/apps/storybook/.storybook/preview.tsx
@@ -1,7 +1,32 @@
import React from "react";
-import "@cambly/syntax-design-tokens/dist/css/variables.css";
-import { initializeRTL } from "storybook-addon-rtl";
+import { Preview } from "@storybook/react";
+import ThemeProvider from "../../../packages/syntax-core/src/ThemeProvider/ThemeProvider";
-initializeRTL();
+const preview: Preview = {
+ globalTypes: {
+ theme: {
+ description: "Global theme for components",
+ defaultValue: "classic",
+ toolbar: {
+ title: "Theme",
+ icon: "circlehollow",
+ items: ["classic", "cambio"],
+ dynamicTitle: true,
+ },
+ },
+ },
+ decorators: [
+ (Story, context) => {
+ const theme = context.globals.theme;
+ return (
+
+
+
+ );
+ },
+ ],
+};
+
+export default preview;
export const decorators = [(Story) => ];
diff --git a/apps/storybook/package.json b/apps/storybook/package.json
index 4209dccc..3b14fcd9 100644
--- a/apps/storybook/package.json
+++ b/apps/storybook/package.json
@@ -27,6 +27,7 @@
"@storybook/addon-docs": "7.0.7",
"@storybook/addon-essentials": "7.0.7",
"@storybook/addon-links": "7.0.7",
+ "@storybook/addon-toolbars": "^7.6.17",
"@storybook/addons": "7.0.7",
"@storybook/react": "7.0.7",
"@storybook/react-vite": "7.0.7",
@@ -36,6 +37,7 @@
"serve": "14.2.0",
"storybook": "7.0.7",
"storybook-addon-designs": "7.0.0-beta.2",
+ "storybook-addon-rtl": "^1.0.0",
"storybook-dark-mode": "3.0.0",
"typescript": "5.0.4",
"vite": "4.3.4"
diff --git a/apps/storybook/stories/Colors.tsx b/apps/storybook/stories/Colors.tsx
index 886c689b..42b4674b 100644
--- a/apps/storybook/stories/Colors.tsx
+++ b/apps/storybook/stories/Colors.tsx
@@ -4,7 +4,10 @@ import variables from "../../../packages/syntax-design-tokens/dist/json/variable
export default function Colors() {
const groupColors = Object.entries(variables).reduce(
(acc, [key, value]) => {
- if (
+ if (key.includes("cambio")) {
+ // @ts-expect-error
+ acc["Cambio"].push({ key, value });
+ } else if (
key.includes("black") ||
key.includes("white") ||
key.includes("gray")
@@ -25,6 +28,7 @@ export default function Colors() {
return acc;
},
{
+ Cambio: [],
Grayscale: [],
Primary: [],
Destructive: [],
@@ -46,8 +50,15 @@ export default function Colors() {
style={{
color:
[
+ "color-cambio-white",
+ "color-cambio-cream",
+ "color-cambio-pink",
+ "color-cambio-sky",
+ "color-cambio-yellow-700",
+ "color-cambio-transparent-full",
"color-base-gray-10",
"color-base-gray-30",
+ "color-base-yellow-700",
"color-base-white",
].includes(key) ||
(number && parseInt(number) < 400)
diff --git a/package.json b/package.json
index 871a6a0b..aeebc033 100755
--- a/package.json
+++ b/package.json
@@ -26,7 +26,6 @@
"glob": "10.3.10",
"jsdom": "22.0.0",
"prettier": "2.8.8",
- "storybook-addon-rtl": "^0.5.0",
"stylelint": "15.6.0",
"stylelint-config-css-modules": "4.2.0",
"stylelint-config-standard": "33.0.0",
diff --git a/packages/syntax-core/src/Button/Button.module.css b/packages/syntax-core/src/Button/Button.module.css
index 51bc9901..2ae0cd6a 100644
--- a/packages/syntax-core/src/Button/Button.module.css
+++ b/packages/syntax-core/src/Button/Button.module.css
@@ -72,6 +72,27 @@
border-radius: 16px;
}
+.smCambio {
+ min-width: 52px;
+ height: 32px;
+ padding: 0 16px;
+ border-radius: 100px;
+}
+
+.mdCambio {
+ min-width: 78px;
+ height: 48px;
+ padding: 0 24px;
+ border-radius: 100px;
+}
+
+.lgCambio {
+ min-width: 104px;
+ height: 64px;
+ padding: 0 32px;
+ border-radius: 100px;
+}
+
.icon {
color: inherit;
}
diff --git a/packages/syntax-core/src/Button/Button.stories.tsx b/packages/syntax-core/src/Button/Button.stories.tsx
index 74f5df43..aa75c506 100644
--- a/packages/syntax-core/src/Button/Button.stories.tsx
+++ b/packages/syntax-core/src/Button/Button.stories.tsx
@@ -21,6 +21,9 @@ export default {
"destructive-secondary",
"destructive-tertiary",
"success",
+ "success-primary",
+ "success-secondary",
+ "success-tertiary",
"branded",
"inverse",
],
diff --git a/packages/syntax-core/src/Button/Button.tsx b/packages/syntax-core/src/Button/Button.tsx
index 20a34d77..da7f3669 100644
--- a/packages/syntax-core/src/Button/Button.tsx
+++ b/packages/syntax-core/src/Button/Button.tsx
@@ -1,18 +1,23 @@
import React, { forwardRef } from "react";
import classNames from "classnames";
-
-import backgroundColor from "../colors//backgroundColor";
-import foregroundColor from "../colors/foregroundColor";
-import foregroundTypographyColor from "../colors/foregroundTypographyColor";
import { type Size } from "../constants";
import Typography from "../Typography/Typography";
import Box from "../Box/Box";
-
import iconSize from "./constants/iconSize";
import textVariant from "./constants/textVariant";
import loadingIconSize from "./constants/loadingIconSize";
import styles from "./Button.module.css";
import useIsHydrated from "../useIsHydrated";
+import { useTheme } from "../ThemeProvider/ThemeProvider";
+import { classicColor, cambioColor } from "./constants/color";
+import {
+ classicBackgroundColor,
+ cambioBackgroundColor,
+} from "../colors/backgroundColor";
+import {
+ classicForegroundColor,
+ cambioForegroundColor,
+} from "../colors/foregroundColor";
type ButtonProps = {
/**
@@ -30,6 +35,15 @@ type ButtonProps = {
/**
* The color of the button
*
+ * Classic only:
+ * * `inverse`
+ * * `success`
+ *
+ * Cambio only:
+ * * `success-primary`
+ * * `success-secondary`
+ * * `success-tertiary`
+ *
* @defaultValue "primary"
*/
color?:
@@ -41,14 +55,23 @@ type ButtonProps = {
| "destructive-tertiary"
| "branded"
| "success"
+ | "success-primary"
+ | "success-secondary"
+ | "success-tertiary"
| "inverse";
/**
* The size of the button
*
+ * Classic:
* * `sm`: 32px
* * `md`: 40px
* * `lg`: 48px
*
+ * Cambio:
+ * * `sm`: 32px
+ * * `md`: 48px
+ * * `lg`: 64px
+ *
* @defaultValue "md"
*/
size?: (typeof Size)[number];
@@ -76,10 +99,12 @@ type ButtonProps = {
fullWidth?: boolean;
/**
* The icon to be displayed at the start of the button. Please use a [Rounded Material Icon](https://material.io/resources/icons/?style=round)
+ * Note: startIcon is not supported in the Cambio theme
*/
startIcon?: React.ComponentType<{ className?: string }>;
/**
* The icon to be displayed at the end of the button. Please use a [Rounded Material Icon](https://material.io/resources/icons/?style=round)
+ * Note: endIcon is not supported in the Cambio theme
*/
endIcon?: React.ComponentType<{ className?: string }>;
/**
@@ -120,6 +145,17 @@ const Button = forwardRef(
ref,
) => {
const isHydrated = useIsHydrated();
+ const { themeName } = useTheme();
+
+ const foregroundColorClass =
+ themeName === "classic"
+ ? classicForegroundColor(classicColor(color))
+ : cambioForegroundColor(cambioColor(color));
+
+ const backgroundColorClass =
+ themeName === "classic"
+ ? classicBackgroundColor(classicColor(color))
+ : cambioBackgroundColor(cambioColor(color));
return (