Skip to content

Commit

Permalink
feat: New Theme Structure and Custom Style Integration (#1958)
Browse files Browse the repository at this point in the history
Co-authored-by: Jeeva Ramachandran <[email protected]>
  • Loading branch information
kanikabansal-juspay and JeevaRamu0104 authored Dec 24, 2024
1 parent 31bac54 commit e15d0a1
Show file tree
Hide file tree
Showing 16 changed files with 384 additions and 89 deletions.
1 change: 1 addition & 0 deletions config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ new_analytics=false
new_analytics_smart_retries=false
new_analytics_refunds=false
down_time=false
dev_theme_feature=false
tax_processor=true
x_feature_route=false
tenant_user=false
Expand Down
74 changes: 60 additions & 14 deletions public/hyperswitch/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,26 +213,72 @@ const getRGBColor = (hex, type) => {
return `--color-${type}: ${r}, ${g}, ${b};`;
};

function appendStyle(customStyle) {
let { primaryColor, primaryHover, sidebar } = customStyle;
let cssVariables = `
:root {
${getRGBColor(primaryColor, "primary")}
${getRGBColor(primaryHover, "hover")}
${getRGBColor(sidebar, "sidebar")}
const getRGBvalue = (hex) => {
let color = hex.replace(/#/g, "");
if (color.length !== 6) {
color = `${color}${color}`;
}
var r = parseInt(color.substr(0, 2), 16);
var g = parseInt(color.substr(2, 2), 16);
var b = parseInt(color.substr(4, 2), 16);

}
`;
let style;
return `${r}, ${g}, ${b};`;
};

const toSnakeCase = (str) => {
return str
.replace(/([A-Z])/g, "-$1")
.replace(/\s+/g, "-")
.replace(/^-/, "")
.toLowerCase();
};

const generateVariablesForSection = (sectionData, sectionName) => {
return (
Object.entries(sectionData)
.map(([key, value]) => {
const processedValue =
typeof value === "string" && value.startsWith("#")
? getRGBvalue(value)
: value;
return ` --${sectionName}-${toSnakeCase(key)}: ${processedValue};`;
})
.join("\n") + "\n"
);
};

const generateButtonVariables = (buttons) => {
return `
/* Primary Button */
${generateVariablesForSection(buttons.primary, "btn-primary")}
/* Secondary Button */
${generateVariablesForSection(buttons.secondary, "btn-secondary")}
`;
};

function appendStyle(themesConfig) {
const settings = themesConfig.settings;
let cssVariables = `:root{
/* Colors */
${generateVariablesForSection(settings.colors, "colors")}
/* Typography */
${generateVariablesForSection(settings.typography, "base")}
/* Buttons */
${generateButtonVariables(settings.buttons)}
/* Borders */
${generateVariablesForSection(settings.borders, "borders")}
/* Spacing */
${generateVariablesForSection(settings.spacing, "spacing")}
if (document.getElementById("custom-style")) {
style = document.getElementById("custom-style");
}`;
if (document.getElementById("custom-themes-style")) {
style = document.getElementById("custom-themes-style");
} else {
style = document.createElement("style");
}
// let style = document.createElement("style")
let text = document.createTextNode(cssVariables);
style.setAttribute("id", "custom-style");
style.setAttribute("id", "custom-themes-style");
style.appendChild(text);
document.head.appendChild(style);
}
46 changes: 31 additions & 15 deletions src/UIConifg/UIConfig.res
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ module ButtonConfig = {
default: string,
defaultPagination: string,
}
type textColor = {primaryOutline: string, primaryNormal: string, primaryDisabled: string}
type textColor = {
primaryOutline: string,
primaryNormal: string,
primaryDisabled: string,
secondaryNormal: string,
secondaryLoading: string,
secondaryDisabled: string,
secondaryNoBorder: string,
}
type bGcolor = {
primaryNormal: string,
primaryDisabled: string,
Expand All @@ -18,6 +26,7 @@ module ButtonConfig = {
secondaryNormal: string,
secondaryLoading: string,
secondaryNoHover: string,
secondaryNoBorder: string,
}

type border = {
Expand Down Expand Up @@ -71,7 +80,7 @@ module BorderConfig = {
}

module SidebarConfig = {
type backgroundColor = {primaryNormal: string}
type backgroundColor = {sidebarNormal: string}
type t = {backgroundColor: backgroundColor}
}

Expand All @@ -80,13 +89,14 @@ type t = {
font: FontConfig.t,
backgroundColor: string,
primaryColor: string,
secondaryColor: string,
shadow: ShadowConfig.t,
border: BorderConfig.t,
sidebarColor: SidebarConfig.t,
}

let defaultUIConfig: t = {
backgroundColor: "bg-primary",
backgroundColor: "bg-background",
button: {
height: {
medium: "h-fit",
Expand Down Expand Up @@ -114,33 +124,38 @@ let defaultUIConfig: t = {
borderSecondaryBorderStyleClass: "border-border_gray border-opacity-20 dark:border-jp-gray-960 dark:border-opacity-100",
},
backgroundColor: {
primaryNormal: "bg-primary hover:bg-primary-hover focus:outline-none",
primaryDisabled: "bg-primary opacity-60 dark:bg-jp-gray-950 dark:bg-opacity-50 border dark:border-jp-gray-disabled_border dark:border-opacity-50",
primaryNoHover: "bg-primary hover:bg-primary-hover focus:outline-none dark:text-opacity-50 text-opacity-50",
primaryLoading: "bg-primary",
primaryNormal: "bg-button-primary-bg hover:bg-button-primary-hoverbg focus:outline-none",
primaryDisabled: "bg-button-primary-bg opacity-60 dark:bg-jp-gray-950 dark:bg-opacity-50 border dark:border-jp-gray-disabled_border dark:border-opacity-50",
primaryNoHover: "bg-button-primary-bg hover:bg-button-primary-hoverbg focus:outline-none dark:text-opacity-50 text-opacity-50",
primaryLoading: "bg-button-primary-bg ",
primaryOutline: "mix-blend-normal",
paginationNormal: "border-left-1 opacity-80 border-right-1 font-normal border-left-1 text-jp-gray-900 text-opacity-50 hover:text-jp-gray-900 focus:outline-none",
paginationLoading: "border-left-1 border-right-1 font-normal border-left-1 bg-jp-gray-200 dark:bg-jp-gray-800 dark:bg-opacity-10",
paginationDisabled: "border-left-1 border-right-1 font-normal border-left-1 bg-jp-gray-300 dark:bg-jp-gray-950 dark:bg-opacity-50 border dark:border-jp-gray-disabled_border dark:border-opacity-50",
paginationNoHover: "bg-white border-left-1 border-right-1 font-normal text-jp-gray-900 text-opacity-75 hover:text-jp-gray-900 dark:text-jp-gray-text_darktheme dark:text-opacity-75",
dropdownDisabled: "bg-gray-200 dark:bg-jp-gray-950 dark:bg-opacity-50 border dark:border-jp-gray-disabled_border dark:border-opacity-50",
secondaryNormal: "bg-jp-gray-button_gray text-jp-gray-900 text-opacity-75 hover:bg-jp-gray-secondary_hover hover:text-jp-gray-890 dark:bg-jp-gray-darkgray_background dark:text-jp-gray-text_darktheme dark:text-opacity-50 focus:outline-none",
secondaryLoading: "bg-jp-gray-button_gray dark:bg-jp-gray-darkgray_background",
secondaryNoHover: "bg-jp-gray-button_gray text-jp-gray-900 text-opacity-50 hover:bg-jp-gray-secondary_hover hover:text-jp-gray-890 dark:bg-jp-gray-darkgray_background dark:text-jp-gray-text_darktheme focus:outline-none dark:text-opacity-50 ",
secondaryNormal: "bg-button-secondary-bg text-jp-gray-900 text-opacity-75 hover:bg-button-secondary-hoverbg hover:text-jp-gray-890 dark:bg-jp-gray-darkgray_background dark:text-jp-gray-text_darktheme dark:text-opacity-50 focus:outline-none",
secondaryNoBorder: "hover:bg-jp-gray-lightmode_steelgray hover:bg-opacity-40 dark:bg-jp-gray-darkgray_background dark:text-jp-gray-text_darktheme dark:text-opacity-50 dark:hover:bg-jp-gray-950 focus:outline-none",
secondaryLoading: "bg-button-secondary-bg dark:bg-jp-gray-darkgray_background",
secondaryNoHover: "bg-button-secondary-bg text-jp-gray-900 text-opacity-50 hover:bg-button-secondary-hoverbg hover:text-jp-gray-890 dark:bg-jp-gray-darkgray_background dark:text-jp-gray-text_darktheme focus:outline-none dark:text-opacity-50 ",
},
borderRadius: {
default: "rounded",
defaultPagination: "rounded-md",
},
textColor: {
primaryNormal: "text-white",
primaryOutline: "text-primary",
primaryOutline: "text-button-primary-text",
primaryDisabled: "text-jp-gray-600 dark:text-jp-gray-text_darktheme dark:text-opacity-25",
secondaryNormal: "text-button-secondary-text hover:text-black dark:text-jp-gray-text_darktheme dark:hover:text-jp-gray-text_darktheme dark:hover:text-opacity-75",
secondaryNoBorder: "text-jp-gray-900 ",
secondaryLoading: "text-button-secondary-text hover:text-black dark:text-jp-gray-text_darktheme dark:text-opacity-75",
secondaryDisabled: "text-jp-gray-600 dark:text-jp-gray-text_darktheme dark:text-opacity-25",
},
},
font: {
textColor: {
primaryNormal: "text-primary",
primaryNormal: "text-typography",
},
},
shadow: {
Expand All @@ -151,14 +166,15 @@ let defaultUIConfig: t = {
},
border: {
borderColor: {
primaryNormal: "border border-primary",
primaryFocused: "focus:border-primary",
primaryNormal: "border border-outline",
primaryFocused: "focus:border-outline",
},
},
primaryColor: "primary",
secondaryColor: "secondary",
sidebarColor: {
backgroundColor: {
primaryNormal: "bg-primary-sidebar",
sidebarNormal: "bg-sidebar",
},
},
}
17 changes: 6 additions & 11 deletions src/components/Button.res
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,10 @@ let useGetBgColor = (
switch buttonState {
| Focused
| Normal =>
showBorder
? "bg-jp-gray-button_gray text-jp-gray-900 text-opacity-75 hover:bg-jp-gray-secondary_hover hover:text-jp-gray-890 dark:bg-jp-gray-darkgray_background dark:text-jp-gray-text_darktheme dark:text-opacity-50 focus:outline-none"
: "text-jp-gray-900 hover:bg-jp-gray-lightmode_steelgray hover:bg-opacity-40 dark:bg-jp-gray-darkgray_background dark:text-jp-gray-text_darktheme dark:text-opacity-50 dark:hover:bg-jp-gray-950 focus:outline-none"
| Loading =>
showBorder
? "bg-jp-gray-button_gray dark:bg-jp-gray-darkgray_background"
: "bg-jp-gray-lightmode_steelgray bg-opacity-40 dark:bg-jp-gray-950 dark:bg-opacity-100"
showBorder ? buttonConfig.secondaryNormal : buttonConfig.secondaryNoBorder
| Loading => showBorder ? buttonConfig.secondaryLoading : buttonConfig.secondaryNoBorder
| Disabled => showBorder ? "bg-jp-gray-300 dark:bg-gray-800 dark:bg-opacity-10" : "px-4"
| NoHover => "bg-jp-gray-button_gray text-jp-gray-900 text-opacity-50 hover:bg-jp-gray-secondary_hover hover:text-jp-gray-890 dark:bg-jp-gray-darkgray_background dark:text-jp-gray-text_darktheme focus:outline-none dark:text-opacity-50 "
| NoHover => buttonConfig.secondaryNoHover
}
| Pill =>
switch buttonState {
Expand Down Expand Up @@ -218,9 +213,9 @@ let useGetTextColor = (
}
| Secondary =>
switch buttonState {
| Disabled => "text-jp-gray-600 dark:text-jp-gray-text_darktheme dark:text-opacity-25"
| Loading => "text-jp-gray-950 hover:text-black dark:text-jp-gray-text_darktheme dark:text-opacity-75"
| _ => "text-jp-gray-950 hover:text-black dark:text-jp-gray-text_darktheme dark:hover:text-jp-gray-text_darktheme dark:hover:text-opacity-75"
| Disabled => textConfig.secondaryDisabled
| Loading => textConfig.secondaryLoading
| _ => textConfig.secondaryNormal
}
| SecondaryFilled =>
switch buttonState {
Expand Down
133 changes: 117 additions & 16 deletions src/context/ThemeProvider.res
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,54 @@ type themeType = LightTheme

type x = {theme: string}

type customStyle = {
primaryColor: string,
primaryHover: string,
sidebar: string,
}

type customUIConfig = {
globalUIConfig: UIConfig.t,
theme: theme,
themeSetter: theme => unit,
configCustomDomainTheme: JSON.t => unit,
}

let defaultGlobalConfig: customStyle = {
primaryColor: "#006DF9",
primaryHover: "#005ED6",
sidebar: "#242F48",
let newDefaultConfig: HyperSwitchConfigTypes.customStylesTheme = {
settings: {
colors: {
primary: "#006DF9",
secondary: "#F7F7F7",
sidebar: "#242F48",
background: "#F7F8FB",
},
typography: {
fontFamily: "Roboto, sans-serif",
fontSize: "14px",
headingFontSize: "24px",
textColor: "#006DF9",
linkColor: "#3498db",
linkHoverColor: "#005ED6",
},
buttons: {
primary: {
backgroundColor: "#006DF9",
textColor: "#006df9",
hoverBackgroundColor: "#005ED6",
},
secondary: {
backgroundColor: "#F7F7F7",
textColor: "#202124",
hoverBackgroundColor: "#EEEEEE",
},
},
borders: {
defaultRadius: "4px",
borderColor: "#006DF9",
},
spacing: {
padding: "16px",
margin: "16px",
},
},
urls: {
faviconUrl: None,
logoUrl: None,
},
}

let themeContext = {
Expand Down Expand Up @@ -75,14 +106,84 @@ let make = (~children) => {
| Dark => "dark"
| Light => ""
}

let configCustomDomainTheme = React.useCallback((uiConfg: JSON.t) => {
open LogicUtils
let dict = uiConfg->getDictFromJsonObject->getDictfromDict("theme")
let {primaryColor, primaryHover, sidebar} = defaultGlobalConfig
let value: HyperSwitchConfigTypes.customStyle = {
primaryColor: dict->getString("primary_color", primaryColor),
primaryHover: dict->getString("primary_hover_color", primaryHover),
sidebar: dict->getString("sidebar_color", sidebar),
let dict = uiConfg->getDictFromJsonObject
let settings = dict->getDictfromDict("settings")
let url = dict->getDictfromDict("urls")
let colorsConfig = settings->getDictfromDict("colors")
let typography = settings->getDictfromDict("typography")
let borders = settings->getDictfromDict("borders")
let spacing = settings->getDictfromDict("spacing")
let colorsBtnPrimary = settings->getDictfromDict("buttons")->getDictfromDict("primary")
let colorsBtnSecondary = settings->getDictfromDict("buttons")->getDictfromDict("secondary")
let {settings: defaultSettings, _} = newDefaultConfig
let value: HyperSwitchConfigTypes.customStylesTheme = {
settings: {
colors: {
primary: colorsConfig->getString("primary", defaultSettings.colors.primary),
secondary: colorsConfig->getString("secondary", defaultSettings.colors.secondary),
sidebar: colorsConfig->getString("sidebar", defaultSettings.colors.sidebar),
background: colorsConfig->getString("background", defaultSettings.colors.background),
},
typography: {
fontFamily: typography->getString("fontFamily", defaultSettings.typography.fontFamily),
fontSize: typography->getString("fontSize", defaultSettings.typography.fontSize),
headingFontSize: typography->getString(
"headingFontSize",
defaultSettings.typography.headingFontSize,
),
textColor: typography->getString("textColor", defaultSettings.typography.textColor),
linkColor: typography->getString("linkColor", defaultSettings.typography.linkColor),
linkHoverColor: typography->getString(
"linkHoverColor",
defaultSettings.typography.linkHoverColor,
),
},
buttons: {
primary: {
backgroundColor: colorsBtnPrimary->getString(
"backgroundColor",
defaultSettings.buttons.primary.backgroundColor,
),
textColor: colorsBtnPrimary->getString(
"textColor",
defaultSettings.buttons.primary.textColor,
),
hoverBackgroundColor: colorsBtnPrimary->getString(
"hoverBackgroundColor",
defaultSettings.buttons.primary.hoverBackgroundColor,
),
},
secondary: {
backgroundColor: colorsBtnSecondary->getString(
"backgroundColor",
defaultSettings.buttons.secondary.backgroundColor,
),
textColor: colorsBtnSecondary->getString(
"textColor",
defaultSettings.buttons.secondary.textColor,
),
hoverBackgroundColor: colorsBtnSecondary->getString(
"hoverBackgroundColor",
defaultSettings.buttons.secondary.hoverBackgroundColor,
),
},
},
borders: {
defaultRadius: borders->getString("defaultRadius", defaultSettings.borders.defaultRadius),
borderColor: borders->getString("borderColor", defaultSettings.borders.borderColor),
},
spacing: {
padding: spacing->getString("padding", defaultSettings.spacing.padding),
margin: spacing->getString("margin", defaultSettings.spacing.margin),
},
},
urls: {
faviconUrl: url->getOptionString("faviconUrl"),
logoUrl: url->getOptionString("logoUrl"),
},
}
Window.appendStyle(value)
}, [])
Expand Down
Loading

0 comments on commit e15d0a1

Please sign in to comment.