diff --git a/.changeset/mean-pumpkins-scream.md b/.changeset/mean-pumpkins-scream.md new file mode 100644 index 000000000..2541d1e0c --- /dev/null +++ b/.changeset/mean-pumpkins-scream.md @@ -0,0 +1,5 @@ +--- +"@logto/console": minor +--- + +support Google One Tap configuration diff --git a/packages/console/src/components/ConnectorForm/GoogleOneTapCard/figure-dark.webp b/packages/console/src/components/ConnectorForm/GoogleOneTapCard/figure-dark.webp new file mode 100644 index 000000000..e3c006df4 Binary files /dev/null and b/packages/console/src/components/ConnectorForm/GoogleOneTapCard/figure-dark.webp differ diff --git a/packages/console/src/components/ConnectorForm/GoogleOneTapCard/figure-light.webp b/packages/console/src/components/ConnectorForm/GoogleOneTapCard/figure-light.webp new file mode 100644 index 000000000..9a99cfd8d Binary files /dev/null and b/packages/console/src/components/ConnectorForm/GoogleOneTapCard/figure-light.webp differ diff --git a/packages/console/src/components/ConnectorForm/GoogleOneTapCard/index.module.scss b/packages/console/src/components/ConnectorForm/GoogleOneTapCard/index.module.scss new file mode 100644 index 000000000..863074a4a --- /dev/null +++ b/packages/console/src/components/ConnectorForm/GoogleOneTapCard/index.module.scss @@ -0,0 +1,11 @@ +@use '@/scss/underscore' as _; + +.figure { + width: 200px; +} + +.oneTapConfig { + display: flex; + gap: _.unit(2); + flex-direction: column; +} diff --git a/packages/console/src/components/ConnectorForm/GoogleOneTapCard/index.tsx b/packages/console/src/components/ConnectorForm/GoogleOneTapCard/index.tsx new file mode 100644 index 000000000..60ea0d3e7 --- /dev/null +++ b/packages/console/src/components/ConnectorForm/GoogleOneTapCard/index.tsx @@ -0,0 +1,111 @@ +import { type GoogleConnectorConfig } from '@logto/connector-kit'; +import { Theme } from '@logto/schemas'; +import { Controller, useFormContext } from 'react-hook-form'; +import { Trans, useTranslation } from 'react-i18next'; + +import FormCard from '@/components/FormCard'; +import Checkbox from '@/ds-components/Checkbox'; +import FormField from '@/ds-components/FormField'; +import Switch from '@/ds-components/Switch'; +import TextLink from '@/ds-components/TextLink'; +import useTheme from '@/hooks/use-theme'; + +import figureDark from './figure-dark.webp'; +import figureLight from './figure-light.webp'; +import * as styles from './index.module.scss'; + +type FormContext = { rawConfig: { oneTap: GoogleConnectorConfig['oneTap'] } }; + +const themeToFigure = Object.freeze({ + [Theme.Light]: figureLight, + [Theme.Dark]: figureDark, +} satisfies Record); + +/** + * A card for configuring Google One Tap. It requires the `rawConfig.oneTap` field in the form + * context which can usually be obtained from the connector configuration context. + */ +function GoogleOneTapCard() { + const { t } = useTranslation(undefined, { + keyPrefix: 'admin_console.connector_details.google_one_tap', + }); + const { register, control, watch } = useFormContext(); + const isEnabled = watch('rawConfig.oneTap.isEnabled'); + const theme = useTheme(); + + return ( + + + + Google One Tap figure + {t('enable_google_one_tap_description')} + + } + {...register('rawConfig.oneTap.isEnabled')} + /> + + {isEnabled && ( + + ( + + )} + /> + ( + + )} + /> + ( + + ), + }} + i18nKey="admin_console.connector_details.google_one_tap.itp_support" + /> + } + checked={field.value} + onChange={field.onChange} + /> + )} + /> + + )} + + ); +} + +export default GoogleOneTapCard; diff --git a/packages/console/src/components/FormCard/index.module.scss b/packages/console/src/components/FormCard/index.module.scss index a8bbe6a5d..7e2f582be 100644 --- a/packages/console/src/components/FormCard/index.module.scss +++ b/packages/console/src/components/FormCard/index.module.scss @@ -6,6 +6,7 @@ display: flex; align-items: center; gap: _.unit(2); + word-break: break-word; } .description { diff --git a/packages/console/src/ds-components/Checkbox/Checkbox/index.tsx b/packages/console/src/ds-components/Checkbox/Checkbox/index.tsx index 337473518..954aa3634 100644 --- a/packages/console/src/ds-components/Checkbox/Checkbox/index.tsx +++ b/packages/console/src/ds-components/Checkbox/Checkbox/index.tsx @@ -9,7 +9,7 @@ import * as styles from './index.module.scss'; type Props = { /* eslint-disable react/boolean-prop-naming */ - readonly checked: boolean; + readonly checked?: boolean; readonly disabled?: boolean; readonly indeterminate?: boolean; /* eslint-enable react/boolean-prop-naming */ @@ -61,7 +61,7 @@ function Checkbox({ , 'label'> & { - readonly label?: ReactNode; - readonly hasError?: boolean; -}; +type Props = + | (Omit, 'label'> & { + /** @deprecated Use `description` instead */ + readonly label?: ReactNode; + readonly hasError?: boolean; + }) + | (HTMLProps & { + readonly description: AdminConsoleKey | ReactElement; + readonly hasError?: boolean; + }); + +function Switch(props: Props, ref?: Ref) { + const { label, hasError, ...rest } = props; -function Switch({ label, hasError, ...rest }: Props, ref?: Ref) { return (
-
{label}
+ {'description' in props && ( +
+ {typeof props.description === 'string' ? ( + + ) : ( + props.description + )} +
+ )} + {label &&
{label}
}