diff --git a/packages/react/src/components/adapters/Consent.tsx b/packages/react/src/components/adapters/Consent.tsx index fbe14bae..bf44157c 100644 --- a/packages/react/src/components/adapters/Consent.tsx +++ b/packages/react/src/components/adapters/Consent.tsx @@ -1,12 +1,7 @@ // Copyright 2026 The ThunderID Authors // SPDX-License-Identifier: Apache-2.0 -import { - type ConsentPurposeData, - FlowMetadataResponse, - PromptElement, - resolveFlowTemplateLiterals, -} from '@thunderid/browser'; +import {type ConsentPurposeData, PromptElement} from '@thunderid/browser'; import {type ChangeEvent, FC, ReactNode} from 'react'; import ConsentCheckboxList, {getConsentOptionalKey} from './ConsentCheckboxList'; import Typography from '../primitives/Typography/Typography'; @@ -41,8 +36,10 @@ export interface ConsentRenderProps { export interface ConsentConfig { essential?: string; optional?: string; + permission?: string; essentialInfo?: string; optionalInfo?: string; + permissionInfo?: string; } /** @@ -78,15 +75,6 @@ export interface ConsentProps { * Callback invoked when a user toggles an optional attribute. */ onInputChange: (name: string, value: string) => void; - /** - * Config to modified detail in consent page - */ - config?: Record; - - /** - * Config of meta response - */ - meta?: FlowMetadataResponse | null; /** * translation data @@ -94,9 +82,14 @@ export interface ConsentProps { t?: UseTranslation['t']; } -const defaultConfig: Required> = { - essential: 'Essential Attributtes', - optional: 'Optional Attributes', +// default config for consent related translation keys +const defaultConfig: ConsentConfig = { + essential: 'essential_claims', + optional: 'optional_claims', + permission: 'authorize_scope', + essentialInfo: 'essential_claims_info', + optionalInfo: 'optional_claims_info', + permissionInfo: 'authorize_scope_info', }; /** @@ -104,15 +97,7 @@ const defaultConfig: Required> = { * based on the data provided by the backend. It allows users to toggle optional attributes while essential * attributes are displayed as read-only. */ -const Consent: FC = ({ - consentData, - formValues, - config: suppliedConfig = {}, - onInputChange, - children, - meta, - t, -}: ConsentProps) => { +const Consent: FC = ({consentData, formValues, onInputChange, children, t}: ConsentProps) => { // Computed per render (not at module scope): a CSP nonce configured on // isn't known until the provider renders, and Emotion needs it applied before any style // insertion happens. These are static, so Emotion's own cache dedupes the repeat calls to a @@ -135,19 +120,27 @@ const Consent: FC = ({ }); const optionalSectionLabelClass: string = css({alignItems: 'center', display: 'flex', gap: '4px'}); - /** Resolve any remaining {{t()}} or {{meta()}} template expressions in a string at render time. */ + /** Resolve i18n keys */ const resolve = (text: string | undefined): string => { - if (!text || (!t && !meta)) { + if (!text || !t) { return text || ''; } - return resolveFlowTemplateLiterals(text, {meta, t: t || ((k: string): string => k)}); + + const key: string = `consent.${text}`; + const translated: string = t(key); + return translated === key ? '' : translated; }; - const config: ConsentConfig = {...defaultConfig, ...suppliedConfig}; - const essentialInfo = typeof config.essentialInfo === 'string' ? resolve(config.essentialInfo.trim()) : ''; - const optionalInfo = typeof config.optionalInfo === 'string' ? resolve(config.optionalInfo.trim()) : ''; - const essentialLabel = resolve(config['essential']); - const optionalLabel = resolve(config['optional']); + const essentialInfo = resolve(defaultConfig['essentialInfo']); + const optionalInfo = resolve(defaultConfig['optionalInfo']); + const permissionInfo = resolve(defaultConfig['permissionInfo']); + /** + * Falls back to default config values if essential/optional + * keys cannot be resolved via translation files . + */ + const essentialLabel = resolve(defaultConfig['essential']) || 'Essential Attributes'; + const optionalLabel = resolve(defaultConfig['optional']) || 'Optional Attributes'; + const permissionLabel = resolve(defaultConfig['permission']) || 'Permissions'; /** * Method to check whether master toggle button is checked or not @@ -223,6 +216,7 @@ const Consent: FC = ({ purpose={purpose} formValues={formValues} onInputChange={onInputChange} + t={t} /> )} @@ -232,10 +226,11 @@ const Consent: FC = ({
- {purpose.type === 'permissions' ? 'Permissions' : optionalLabel} + {purpose.type === 'permissions' ? permissionLabel : optionalLabel} - {optionalInfo !== '' && ( - + {/* Show tooltip for optional claims/permissions according to their type */} + {Boolean(purpose.type === 'permissions' ? permissionInfo : optionalInfo) && ( + )} @@ -252,6 +247,7 @@ const Consent: FC = ({ purpose={purpose} formValues={formValues} onInputChange={onInputChange} + t={t} />
)} diff --git a/packages/react/src/components/adapters/ConsentCheckboxList.tsx b/packages/react/src/components/adapters/ConsentCheckboxList.tsx index 00d20040..1f837da8 100644 --- a/packages/react/src/components/adapters/ConsentCheckboxList.tsx +++ b/packages/react/src/components/adapters/ConsentCheckboxList.tsx @@ -8,6 +8,7 @@ import useTheme from '../../contexts/Theme/useTheme'; import {cx} from '../../styles/emotion'; import Toggle from '../primitives/Toggle/Toggle'; import Typography from '../primitives/Typography/Typography'; +import {UseTranslation} from '../../hooks/useTranslation'; /** * Computes the form value key for tracking an optional attribute's consent state. @@ -78,6 +79,10 @@ export interface ConsentCheckboxListProps { purpose: ConsentPurposeData; /** Whether to render essential (disabled) or optional (toggleable) attributes */ variant: ConsentInputVariant; + /** + * translation data + */ + t?: UseTranslation['t']; } /** @@ -93,10 +98,21 @@ const ConsentCheckboxList: FC = ({ formValues, onInputChange, children, + t, }: ConsentCheckboxListProps) => { const {theme, colorScheme}: ReturnType = useTheme(); const styles: Record = useStyles(theme, colorScheme); + const resolve = (text: string | undefined): string => { + if (!text || !t) { + return text || ''; + } + + const key: string = `consent.${text}`; + const translated: string = t(key); + return translated === key ? text : translated; + }; + const attributes: string[] = (variant === 'ESSENTIAL' ? purpose.essential : purpose.optional).map( (e): string => e.name, ); @@ -153,11 +169,11 @@ const ConsentCheckboxList: FC = ({ styles['typography'], )} > - {attr} + {resolve(attr)}
{isEssential ? ( - Required + {resolve('required')} ) : ( );