From 486b937c472231cf5dacbeb10cc027d8e74ff880 Mon Sep 17 00:00:00 2001 From: bzzz-coding <86077274+bzzz-coding@users.noreply.github.com> Date: Thu, 6 Feb 2025 14:15:10 -0800 Subject: [PATCH 1/5] Added Tailwind Button Components --- frontend/src/pages/Demo/DemoTailwind.tsx | 69 +++++++++++++++- frontend/src/tw-components/Buttons.tsx | 100 +++++++++++++++++++++++ frontend/tailwind.config.js | 1 + 3 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 frontend/src/tw-components/Buttons.tsx diff --git a/frontend/src/pages/Demo/DemoTailwind.tsx b/frontend/src/pages/Demo/DemoTailwind.tsx index 54759963..ad7fa78b 100644 --- a/frontend/src/pages/Demo/DemoTailwind.tsx +++ b/frontend/src/pages/Demo/DemoTailwind.tsx @@ -1,14 +1,79 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; import Typography from "tw-components/Typography"; +import { Button, IconButton } from "tw-components/Buttons"; const DemoTailwind = () => { + // Add a setDarkMode for testing dark mode styles + const [darkMode, setDarkMode] = useState(false); + + useEffect(() => { + if (darkMode) { + document.documentElement.classList.add("dark"); + } else { + document.documentElement.classList.remove("dark"); + } + }, [darkMode]); + return (
+
+ + Buttons + + + + + {/* Regular Buttons, active is the default state */} + + Active + +
+ + + {/* Medium is the default*/} + + + + +
+ + {/* Disabled Buttons */} + + Disabled + +
+ + +
+ + {/* Hover & Active/Focused States */} + + Hover, Focused and Active + +
+ + + +
+ + {/* Icon Buttons */} + + Search Icon + +
+ + +
+
+
Typography Demo (Title 1 - Roboto Bold 48/137% +0) - Title Styles (Title 2 - Roboto Bold 36/137% +0) diff --git a/frontend/src/tw-components/Buttons.tsx b/frontend/src/tw-components/Buttons.tsx new file mode 100644 index 00000000..eab0bd47 --- /dev/null +++ b/frontend/src/tw-components/Buttons.tsx @@ -0,0 +1,100 @@ +import React from "react"; +import Typography from "tw-components/Typography"; + +// size can only be one of: +// "small" | "small-long" | "medium" | "medium-long" | "large" | "large-long" | "icon-only" +type ButtonSize = keyof typeof buttonSizes; +// state can only be "enabled" or "disabled" +type ButtonState = keyof typeof buttonColors; + +type ButtonProps = { + size?: ButtonSize; + state?: ButtonState; + children?: React.ReactNode; + onClick?: () => void; +}; + +type IconButtonProps = { + state?: ButtonState; + onClick?: () => void; +}; + +const buttonSizes = { + small: "px-[24px] h-[32px] flex items-center justify-center leading-none", + "small-long": + "px-[40px] h-[32px] flex items-center justify-center leading-none", + medium: "px-[32px] h-[42px] flex items-center justify-center leading-none", + "medium-long": + "px-[48px] h-[42px] flex items-center justify-center leading-none", + large: "px-[40px] h-[51px] flex items-center justify-center leading-none", + "large-long": + "px-[56px] h-[51px] flex items-center justify-center leading-none", + "icon-only": "px-[24px] h-[42px] flex items-center justify-center", +}; + +const buttonColors = { + enabled: + "bg-blue-dark text-white dark:bg-white dark:text-blue-dark hover:bg-blue-dark-hover focus:bg-blue-dark-focused focus:outline-none active:bg-blue-dark-focused dark:hover:bg-grey-light dark:focus:bg-[#D9DBDF] dark:active:bg-[#D9DBDF]", + disabled: + "bg-grey text-white cursor-not-allowed dark:bg-grey dark:text-grey-light", +}; + +const buttonTypography: Record = { + small: Typography.Title7, + "small-long": Typography.Title7, + medium: Typography.Title6, + "medium-long": Typography.Title6, + large: Typography.Title5, + "large-long": Typography.Title5, + "icon-only": Typography.Title7, // Not sure about this one +}; + +const Button: React.FC = ({ + size = "medium", + state = "enabled", + children, + onClick, +}) => { + const TextComponent = buttonTypography[size]; + + return ( + + ); +}; + +const IconButton: React.FC = ({ + state = "enabled", + onClick, +}) => { + return ( + + ); +}; + +export { Button, IconButton }; diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index d6a6985e..7541c68e 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -1,5 +1,6 @@ /** @type {import('tailwindcss').Config} */ module.exports = { + darkMode: "class", // Enables dark mode with a class content: [ "./src/pages/Demo/DemoTailwind.tsx", "./src/pages/Authentication/*.tsx", From 11b1a124e590d8a12717a74defbe6776fbafc05b Mon Sep 17 00:00:00 2001 From: bzzz-coding <86077274+bzzz-coding@users.noreply.github.com> Date: Thu, 13 Feb 2025 15:23:29 -0800 Subject: [PATCH 2/5] Updated Buttons.tsx with clsx --- frontend/package-lock.json | 14 +++ frontend/package.json | 1 + frontend/src/pages/Demo/DemoTailwind.tsx | 18 ++-- frontend/src/tw-components/Buttons.tsx | 118 +++++++++++------------ 4 files changed, 82 insertions(+), 69 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a1d0cbf0..1ac3f2e4 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,6 +12,7 @@ "@popperjs/core": "^2.11.6", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", + "clsx": "^2.1.1", "react-hook-form": "^7.46.1", "react-popper": "^2.3.0", "vite-tsconfig-paths": "^4.3.1" @@ -3540,6 +3541,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -12930,6 +12939,11 @@ "wrap-ansi": "^7.0.0" } }, + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 73d8e4b2..a82f5797 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -70,6 +70,7 @@ "@popperjs/core": "^2.11.6", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", + "clsx": "^2.1.1", "react-hook-form": "^7.46.1", "react-popper": "^2.3.0", "vite-tsconfig-paths": "^4.3.1" diff --git a/frontend/src/pages/Demo/DemoTailwind.tsx b/frontend/src/pages/Demo/DemoTailwind.tsx index ad7fa78b..4894a97c 100644 --- a/frontend/src/pages/Demo/DemoTailwind.tsx +++ b/frontend/src/pages/Demo/DemoTailwind.tsx @@ -16,7 +16,7 @@ const DemoTailwind = () => { return (
-
+
Buttons @@ -24,10 +24,10 @@ const DemoTailwind = () => { {/* Regular Buttons, active is the default state */} - + Active -
+
{/* Medium is the default*/} @@ -41,11 +41,9 @@ const DemoTailwind = () => { Disabled -
- - +
@@ -54,7 +52,7 @@ const DemoTailwind = () => { Hover, Focused and Active -
+
@@ -66,7 +64,7 @@ const DemoTailwind = () => {
- +
diff --git a/frontend/src/tw-components/Buttons.tsx b/frontend/src/tw-components/Buttons.tsx index eab0bd47..17affc2e 100644 --- a/frontend/src/tw-components/Buttons.tsx +++ b/frontend/src/tw-components/Buttons.tsx @@ -1,100 +1,100 @@ import React from "react"; +import clsx from "clsx"; import Typography from "tw-components/Typography"; // size can only be one of: // "small" | "small-long" | "medium" | "medium-long" | "large" | "large-long" | "icon-only" type ButtonSize = keyof typeof buttonSizes; -// state can only be "enabled" or "disabled" -type ButtonState = keyof typeof buttonColors; +// Button props type ButtonProps = { size?: ButtonSize; - state?: ButtonState; + disabled?: boolean; children?: React.ReactNode; onClick?: () => void; + isIconButton?: boolean; }; -type IconButtonProps = { - state?: ButtonState; - onClick?: () => void; -}; - +// Button size styles const buttonSizes = { - small: "px-[24px] h-[32px] flex items-center justify-center leading-none", - "small-long": - "px-[40px] h-[32px] flex items-center justify-center leading-none", - medium: "px-[32px] h-[42px] flex items-center justify-center leading-none", - "medium-long": - "px-[48px] h-[42px] flex items-center justify-center leading-none", - large: "px-[40px] h-[51px] flex items-center justify-center leading-none", - "large-long": - "px-[56px] h-[51px] flex items-center justify-center leading-none", - "icon-only": "px-[24px] h-[42px] flex items-center justify-center", -}; - -const buttonColors = { - enabled: - "bg-blue-dark text-white dark:bg-white dark:text-blue-dark hover:bg-blue-dark-hover focus:bg-blue-dark-focused focus:outline-none active:bg-blue-dark-focused dark:hover:bg-grey-light dark:focus:bg-[#D9DBDF] dark:active:bg-[#D9DBDF]", - disabled: - "bg-grey text-white cursor-not-allowed dark:bg-grey dark:text-grey-light", + small: "px-[24px] h-[32px]", + "small-long": "px-[40px] h-[32px]", + medium: "px-[32px] h-[42px]", + "medium-long": "px-[48px] h-[42px]", + large: "px-[40px] h-[51px]", + "large-long": "px-[56px] h-[51px]", + "icon-only": "px-[24px] h-[42px]", }; -const buttonTypography: Record = { +const buttonTypography: Record< + keyof typeof buttonSizes, + React.ElementType | null +> = { small: Typography.Title7, "small-long": Typography.Title7, medium: Typography.Title6, "medium-long": Typography.Title6, large: Typography.Title5, "large-long": Typography.Title5, - "icon-only": Typography.Title7, // Not sure about this one + "icon-only": null, }; +// Shared base styles for all buttons +const baseButtonStyles = + "transition-all duration-200 flex items-center justify-center bg-blue-dark text-white hover:bg-blue-dark-hover focus:bg-blue-dark-focused focus:outline-none active:bg-blue-dark-focused"; + +const enabledDarkModeStyles = + "dark:bg-white dark:text-blue-dark dark:hover:bg-grey-light dark:focus:bg-[#D9DBDF] dark:active:bg-[#D9DBDF]"; + +const disabledStyles = "pointer-events-none bg-grey text-grey-light"; + +// Button component (handles both regular and icon buttons) const Button: React.FC = ({ size = "medium", - state = "enabled", + disabled = false, children, onClick, + isIconButton = false, }) => { const TextComponent = buttonTypography[size]; return ( ); }; -const IconButton: React.FC = ({ - state = "enabled", - onClick, -}) => { - return ( - - ); -}; +// Export separate IconButton +const IconButton: React.FC> = ( + props, +) => - +
@@ -64,7 +64,7 @@ const DemoTailwind = () => {
- +
diff --git a/frontend/src/tw-components/Buttons.tsx b/frontend/src/tw-components/Buttons.tsx index 17affc2e..8d0d3fc5 100644 --- a/frontend/src/tw-components/Buttons.tsx +++ b/frontend/src/tw-components/Buttons.tsx @@ -2,20 +2,6 @@ import React from "react"; import clsx from "clsx"; import Typography from "tw-components/Typography"; -// size can only be one of: -// "small" | "small-long" | "medium" | "medium-long" | "large" | "large-long" | "icon-only" -type ButtonSize = keyof typeof buttonSizes; - -// Button props -type ButtonProps = { - size?: ButtonSize; - disabled?: boolean; - children?: React.ReactNode; - onClick?: () => void; - isIconButton?: boolean; -}; - -// Button size styles const buttonSizes = { small: "px-[24px] h-[32px]", "small-long": "px-[40px] h-[32px]", @@ -26,75 +12,102 @@ const buttonSizes = { "icon-only": "px-[24px] h-[42px]", }; -const buttonTypography: Record< - keyof typeof buttonSizes, - React.ElementType | null -> = { - small: Typography.Title7, - "small-long": Typography.Title7, - medium: Typography.Title6, - "medium-long": Typography.Title6, - large: Typography.Title5, - "large-long": Typography.Title5, - "icon-only": null, +type ButtonSize = keyof typeof buttonSizes; + +type BaseButtonProps = { + size?: ButtonSize; + disabled?: boolean; + className?: string; + children?: React.ReactNode; + onClick?: () => void; }; -// Shared base styles for all buttons +// Shared styles const baseButtonStyles = - "transition-all duration-200 flex items-center justify-center bg-blue-dark text-white hover:bg-blue-dark-hover focus:bg-blue-dark-focused focus:outline-none active:bg-blue-dark-focused"; + "transition-all duration-200 flex items-center justify-center rounded-[64px] bg-blue-dark text-white hover:bg-blue-dark-hover focus:bg-blue-dark-focused focus:outline-none active:bg-blue-dark-focused disabled:bg-grey disabled:text-white disabled:cursor-not-allowed"; +// Dark mode styles for enabled buttons const enabledDarkModeStyles = - "dark:bg-white dark:text-blue-dark dark:hover:bg-grey-light dark:focus:bg-[#D9DBDF] dark:active:bg-[#D9DBDF]"; - -const disabledStyles = "pointer-events-none bg-grey text-grey-light"; + "dark:bg-white dark:text-blue-dark dark:hover:bg-grey-light dark:focus:bg-[#D9DBDF] dark:active:bg-[#D9DBDF] dark:disabled:bg-grey dark:disabled:text-grey-light"; -// Button component (handles both regular and icon buttons) -const Button: React.FC = ({ +// Base Button, no text, just styling +const BaseButton: React.FC = ({ size = "medium", disabled = false, + className, children, onClick, - isIconButton = false, }) => { - const TextComponent = buttonTypography[size]; - return ( ); }; -// Export separate IconButton -const IconButton: React.FC> = ( - props, -) =>