From e808be49cfbc282a45552dd3ea1d4be66298b0d8 Mon Sep 17 00:00:00 2001 From: Brion Date: Mon, 28 Jul 2025 12:18:54 +0530 Subject: [PATCH 1/3] feat(javascript): add button border radius overrides and update theme components --- packages/javascript/src/theme/createTheme.ts | 23 ++++++++ packages/javascript/src/theme/types.ts | 53 +++++++++++++++++++ .../transformBrandingPreferenceToTheme.ts | 25 ++++++--- .../primitives/Button/Button.styles.ts | 4 +- .../src/contexts/Theme/ThemeProvider.tsx | 5 ++ 5 files changed, 101 insertions(+), 9 deletions(-) diff --git a/packages/javascript/src/theme/createTheme.ts b/packages/javascript/src/theme/createTheme.ts index 323a3554..f42712e6 100644 --- a/packages/javascript/src/theme/createTheme.ts +++ b/packages/javascript/src/theme/createTheme.ts @@ -449,12 +449,31 @@ const toCssVariables = (theme: ThemeConfig): Record => { }); } + /* |---------------------------------------------------------------| */ + /* | Components | */ + /* |---------------------------------------------------------------| */ + + // Button Overrides + if (theme.components?.Button?.styleOverrides?.root?.borderRadius) { + cssVars[`--${prefix}-component-button-root-borderRadius`] = + theme.components.Button.styleOverrides.root.borderRadius; + } + return cssVars; }; const toThemeVars = (theme: ThemeConfig): ThemeVars => { const prefix = theme.cssVarPrefix || VendorConstants.VENDOR_PREFIX; + const componentVars: ThemeVars['components'] = {}; + if (theme.components?.Button?.styleOverrides?.root?.borderRadius) { + componentVars.Button = { + root: { + borderRadius: `var(--${prefix}-component-button-root-borderRadius)`, + }, + }; + } + const themeVars: ThemeVars = { colors: { action: { @@ -558,6 +577,10 @@ const toThemeVars = (theme: ThemeConfig): ThemeVars => { }); } + if (Object.keys(componentVars).length > 0) { + themeVars.components = componentVars; + } + return themeVars; }; diff --git a/packages/javascript/src/theme/types.ts b/packages/javascript/src/theme/types.ts index 19aea3a2..286a71cb 100644 --- a/packages/javascript/src/theme/types.ts +++ b/packages/javascript/src/theme/types.ts @@ -101,6 +101,36 @@ export interface ThemeColors { }; } +export interface ThemeComponentStyleOverrides { + /** + * Style overrides for the root element or slots. + * Example: { root: { borderRadius: '8px' } } + */ + root?: Record; + [slot: string]: Record | undefined; +} + +export interface ThemeComponents { + Button?: { + styleOverrides?: { + root?: { + borderRadius?: string; + [key: string]: any; + }; + [slot: string]: Record | undefined; + }; + defaultProps?: Record; + variants?: Array>; + }; + [componentName: string]: + | { + styleOverrides?: ThemeComponentStyleOverrides; + defaultProps?: Record; + variants?: Array>; + } + | undefined; +} + export interface ThemeConfig { borderRadius: { large: string; @@ -148,6 +178,25 @@ export interface ThemeConfig { * @default 'asgardeo' (from VendorConstants.VENDOR_PREFIX) */ cssVarPrefix?: string; + /** + * Component style overrides + */ + components?: ThemeComponents; +} + +export interface ThemeComponentVars { + Button?: { + root?: { + borderRadius?: string; + [key: string]: any; + }; + [slot: string]: Record | undefined; + }; + [componentName: string]: + | { + [slot: string]: Record | undefined; + } + | undefined; } export interface ThemeVars { @@ -266,6 +315,10 @@ export interface ThemeVars { } | undefined; }; + /** + * Component CSS variable references (e.g., for overrides) + */ + components?: ThemeComponentVars; } export interface Theme extends ThemeConfig { diff --git a/packages/javascript/src/utils/transformBrandingPreferenceToTheme.ts b/packages/javascript/src/utils/transformBrandingPreferenceToTheme.ts index 494c1a23..08ff49d0 100644 --- a/packages/javascript/src/utils/transformBrandingPreferenceToTheme.ts +++ b/packages/javascript/src/utils/transformBrandingPreferenceToTheme.ts @@ -49,7 +49,7 @@ const transformThemeVariant = (themeVariant: ThemeVariant, isDark = false): Part const inputs = themeVariant.inputs; const images = themeVariant.images; - return { + const config: Partial = { colors: { action: { active: isDark ? 'rgba(255, 255, 255, 0.70)' : 'rgba(0, 0, 0, 0.54)', @@ -111,13 +111,6 @@ const transformThemeVariant = (themeVariant: ThemeVariant, isDark = false): Part dark: (colors?.alerts?.warning as ColorVariant)?.dark || (colors?.alerts?.warning as ColorVariant)?.main, }, }, - // Extract border radius from buttons or inputs - borderRadius: { - small: buttons?.primary?.base?.border?.borderRadius || inputs?.base?.border?.borderRadius, - medium: buttons?.secondary?.base?.border?.borderRadius, - large: buttons?.externalConnection?.base?.border?.borderRadius, - }, - // Extract and transform images images: { favicon: images?.favicon ? { @@ -135,6 +128,22 @@ const transformThemeVariant = (themeVariant: ThemeVariant, isDark = false): Part : undefined, }, }; + + // --- COMPONENT OVERRIDES: Button borderRadius --- + const buttonBorderRadius = buttons?.primary?.base?.border?.borderRadius; + if (buttonBorderRadius) { + config.components = { + Button: { + styleOverrides: { + root: { + borderRadius: buttonBorderRadius, + }, + }, + }, + }; + } + + return config; }; /** diff --git a/packages/react/src/components/primitives/Button/Button.styles.ts b/packages/react/src/components/primitives/Button/Button.styles.ts index 025bf466..282d420d 100644 --- a/packages/react/src/components/primitives/Button/Button.styles.ts +++ b/packages/react/src/components/primitives/Button/Button.styles.ts @@ -53,7 +53,9 @@ const useStyles = ( align-items: center; justify-content: center; gap: calc(${theme.vars.spacing.unit} * 1); - border-radius: ${shape === 'round' ? '50%' : theme.vars.borderRadius.medium}; + border-radius: ${shape === 'round' + ? '50%' + : theme.vars.components?.Button?.root?.borderRadius || theme.vars.borderRadius.medium}; font-weight: 500; cursor: ${disabled || loading ? 'not-allowed' : 'pointer'}; outline: none; diff --git a/packages/react/src/contexts/Theme/ThemeProvider.tsx b/packages/react/src/contexts/Theme/ThemeProvider.tsx index 204801a8..8494dcc1 100644 --- a/packages/react/src/contexts/Theme/ThemeProvider.tsx +++ b/packages/react/src/contexts/Theme/ThemeProvider.tsx @@ -175,6 +175,7 @@ const ThemeProvider: FC> = ({ shadows: brandingTheme.shadows, spacing: brandingTheme.spacing, images: brandingTheme.images, + components: brandingTheme.components, }; // Merge branding theme with user-provided theme config @@ -202,6 +203,10 @@ const ThemeProvider: FC> = ({ ...brandingThemeConfig.images, ...themeConfig?.images, }, + components: { + ...brandingThemeConfig.components, + ...themeConfig?.components, + }, }; }, [inheritFromBranding, brandingTheme, themeConfig]); From 6ba5b4bed7e6d64fbedb7d9099ce8126c58de7eb Mon Sep 17 00:00:00 2001 From: Brion Date: Mon, 28 Jul 2025 12:25:55 +0530 Subject: [PATCH 2/3] =?UTF-8?q?chore:=20add=20changeset=20=F0=9F=A6=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/sweet-geese-guess.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/sweet-geese-guess.md diff --git a/.changeset/sweet-geese-guess.md b/.changeset/sweet-geese-guess.md new file mode 100644 index 00000000..6b98ab2b --- /dev/null +++ b/.changeset/sweet-geese-guess.md @@ -0,0 +1,6 @@ +--- +'@asgardeo/javascript': patch +'@asgardeo/react': patch +--- + +Add component-specific overrides. From 17380f7fb8aed8b3557ea178bb8a6a5fb0f97bf3 Mon Sep 17 00:00:00 2001 From: Brion Date: Mon, 28 Jul 2025 13:16:49 +0530 Subject: [PATCH 3/3] feat(javascript): add border radius overrides for Field component and update related styles --- packages/javascript/src/theme/createTheme.ts | 12 ++++++++ packages/javascript/src/theme/types.ts | 18 +++++++++++ .../transformBrandingPreferenceToTheme.ts | 30 ++++++++++++++----- .../DatePicker/DatePicker.styles.ts | 2 +- .../primitives/OtpField/OtpField.styles.ts | 2 +- .../primitives/Select/Select.styles.ts | 2 +- .../primitives/TextField/TextField.styles.ts | 2 +- 7 files changed, 57 insertions(+), 11 deletions(-) diff --git a/packages/javascript/src/theme/createTheme.ts b/packages/javascript/src/theme/createTheme.ts index f42712e6..6a80e030 100644 --- a/packages/javascript/src/theme/createTheme.ts +++ b/packages/javascript/src/theme/createTheme.ts @@ -459,6 +459,11 @@ const toCssVariables = (theme: ThemeConfig): Record => { theme.components.Button.styleOverrides.root.borderRadius; } + // Field Overrides (Parent of `TextField`, `DatePicker`, `OtpField`, `Select`, etc.) + if (theme.components?.Field?.styleOverrides?.root?.borderRadius) { + cssVars[`--${prefix}-component-field-root-borderRadius`] = theme.components.Field.styleOverrides.root.borderRadius; + } + return cssVars; }; @@ -473,6 +478,13 @@ const toThemeVars = (theme: ThemeConfig): ThemeVars => { }, }; } + if (theme.components?.Field?.styleOverrides?.root?.borderRadius) { + componentVars.Field = { + root: { + borderRadius: `var(--${prefix}-component-field-root-borderRadius)`, + }, + }; + } const themeVars: ThemeVars = { colors: { diff --git a/packages/javascript/src/theme/types.ts b/packages/javascript/src/theme/types.ts index 286a71cb..1dd5ae7e 100644 --- a/packages/javascript/src/theme/types.ts +++ b/packages/javascript/src/theme/types.ts @@ -122,6 +122,17 @@ export interface ThemeComponents { defaultProps?: Record; variants?: Array>; }; + Field?: { + styleOverrides?: { + root?: { + borderRadius?: string; + [key: string]: any; + }; + [slot: string]: Record | undefined; + }; + defaultProps?: Record; + variants?: Array>; + }; [componentName: string]: | { styleOverrides?: ThemeComponentStyleOverrides; @@ -192,6 +203,13 @@ export interface ThemeComponentVars { }; [slot: string]: Record | undefined; }; + Field?: { + root?: { + borderRadius?: string; + [key: string]: any; + }; + [slot: string]: Record | undefined; + }; [componentName: string]: | { [slot: string]: Record | undefined; diff --git a/packages/javascript/src/utils/transformBrandingPreferenceToTheme.ts b/packages/javascript/src/utils/transformBrandingPreferenceToTheme.ts index 08ff49d0..d11e709b 100644 --- a/packages/javascript/src/utils/transformBrandingPreferenceToTheme.ts +++ b/packages/javascript/src/utils/transformBrandingPreferenceToTheme.ts @@ -129,17 +129,33 @@ const transformThemeVariant = (themeVariant: ThemeVariant, isDark = false): Part }, }; - // --- COMPONENT OVERRIDES: Button borderRadius --- + /* |---------------------------------------------------------------| */ + /* | Components | */ + /* |---------------------------------------------------------------| */ + const buttonBorderRadius = buttons?.primary?.base?.border?.borderRadius; - if (buttonBorderRadius) { + const fieldBorderRadius = inputs?.base?.border?.borderRadius; + + if (buttonBorderRadius || fieldBorderRadius) { config.components = { - Button: { - styleOverrides: { - root: { - borderRadius: buttonBorderRadius, + ...(buttonBorderRadius && { + Button: { + styleOverrides: { + root: { + borderRadius: buttonBorderRadius, + }, }, }, - }, + }), + ...(fieldBorderRadius && { + Field: { + styleOverrides: { + root: { + borderRadius: fieldBorderRadius, + }, + }, + }, + }), }; } diff --git a/packages/react/src/components/primitives/DatePicker/DatePicker.styles.ts b/packages/react/src/components/primitives/DatePicker/DatePicker.styles.ts index 2adbdecf..214e51de 100644 --- a/packages/react/src/components/primitives/DatePicker/DatePicker.styles.ts +++ b/packages/react/src/components/primitives/DatePicker/DatePicker.styles.ts @@ -34,7 +34,7 @@ const useStyles = (theme: Theme, colorScheme: string, hasError: boolean, disable width: 100%; padding: ${theme.vars.spacing.unit} calc(${theme.vars.spacing.unit} * 1.5); border: 1px solid ${theme.vars.colors.border}; - border-radius: ${theme.vars.borderRadius.medium}; + border-radius: ${theme.vars.components?.Field?.root?.borderRadius || theme.vars.borderRadius.medium}; font-size: 1rem; color: ${theme.vars.colors.text.primary}; background-color: ${theme.vars.colors.background.surface}; diff --git a/packages/react/src/components/primitives/OtpField/OtpField.styles.ts b/packages/react/src/components/primitives/OtpField/OtpField.styles.ts index 011c5b1e..c43f4309 100644 --- a/packages/react/src/components/primitives/OtpField/OtpField.styles.ts +++ b/packages/react/src/components/primitives/OtpField/OtpField.styles.ts @@ -54,7 +54,7 @@ const useStyles = ( font-size: ${theme.vars.typography.fontSizes.xl}; font-weight: 500; border: 2px solid ${hasError ? theme.vars.colors.error.main : theme.vars.colors.border}; - border-radius: ${theme.vars.borderRadius.medium}; + border-radius: ${theme.vars.components?.Field?.root?.borderRadius || theme.vars.borderRadius.medium}; color: ${theme.vars.colors.text.primary}; background-color: ${disabled ? theme.vars.colors.background.disabled : theme.vars.colors.background.surface}; outline: none; diff --git a/packages/react/src/components/primitives/Select/Select.styles.ts b/packages/react/src/components/primitives/Select/Select.styles.ts index 6907f5cb..0a83576e 100644 --- a/packages/react/src/components/primitives/Select/Select.styles.ts +++ b/packages/react/src/components/primitives/Select/Select.styles.ts @@ -37,7 +37,7 @@ const useStyles = (theme: Theme, colorScheme: string, disabled: boolean, hasErro width: 100%; padding: ${theme.vars.spacing.unit} calc(${theme.vars.spacing.unit} * 1.5); border: 1px solid ${hasError ? theme.vars.colors.error.main : theme.vars.colors.border}; - border-radius: ${theme.vars.borderRadius.medium}; + border-radius: ${theme.vars.components?.Field?.root?.borderRadius || theme.vars.borderRadius.medium}; font-size: ${theme.vars.typography.fontSizes.md}; color: ${theme.vars.colors.text.primary}; background-color: ${disabled ? theme.vars.colors.background.disabled : theme.vars.colors.background.surface}; diff --git a/packages/react/src/components/primitives/TextField/TextField.styles.ts b/packages/react/src/components/primitives/TextField/TextField.styles.ts index 14b02e67..99225e0b 100644 --- a/packages/react/src/components/primitives/TextField/TextField.styles.ts +++ b/packages/react/src/components/primitives/TextField/TextField.styles.ts @@ -54,7 +54,7 @@ const useStyles = ( width: 100%; padding: ${theme.vars.spacing.unit} ${rightPadding} ${theme.vars.spacing.unit} ${leftPadding}; border: 1px solid ${hasError ? theme.vars.colors.error.main : theme.vars.colors.border}; - border-radius: ${theme.vars.borderRadius.medium}; + border-radius: ${theme.vars.components?.Field?.root?.borderRadius || theme.vars.borderRadius.medium}; font-size: ${theme.vars.typography.fontSizes.md}; color: ${theme.vars.colors.text.primary}; background-color: ${disabled ? theme.vars.colors.background.disabled : theme.vars.colors.background.surface};