diff --git a/.changeset/seven-grapes-lay.md b/.changeset/seven-grapes-lay.md new file mode 100644 index 00000000000..e3e8d9fe240 --- /dev/null +++ b/.changeset/seven-grapes-lay.md @@ -0,0 +1,27 @@ +--- +'@clerk/ui': major +--- + +Changes provider icon rendering from `` to `` elements to support customizable icon fills via CSS variables. + +Provider icons for Apple, GitHub, OKX Wallet, and Vercel now use CSS `mask-image` technique with a customizable `--cl-icon-fill` CSS variable, allowing themes to control icon colors. Other provider icons (like Google) continue to render as full-color images using `background-image`. + +You can customize the icon fill color in your theme: + +```tsx +import { createTheme } from '@clerk/ui/themes'; + +const myTheme = createTheme({ + name: 'myTheme', + elements: { + providerIcon__apple: { + '--cl-icon-fill': '#000000', // Custom fill color + }, + providerIcon__github: { + '--cl-icon-fill': 'light-dark(#000000, #ffffff)', // Theme-aware fill + }, + }, +}); +``` + +This change enables better theme customization for monochrome provider icons while maintaining full-color support for providers that require it. diff --git a/.changeset/slimy-vans-listen.md b/.changeset/slimy-vans-listen.md new file mode 100644 index 00000000000..19f1f3d6815 --- /dev/null +++ b/.changeset/slimy-vans-listen.md @@ -0,0 +1,44 @@ +--- +'@clerk/ui': minor +--- + +Adds new `lightDark` theme. + +This theme uses the `light-dark()` CSS function to automatically adapt colors based on the user's system color scheme preference, eliminating the need to manually switch between light and dark themes. + +To enable it, within your project, you can do the following: + +```tsx +import { lightDark } from '@clerk/ui/themes'; +import { ClerkProvider } from '@clerk/nextjs'; + +export default function MyApp({ Component, pageProps }: AppProps) { + return ( + + + + ); +} +``` + +and within your CSS file, add the following to enable automatic light/dark mode switching: + +```css +:root { + color-scheme: light dark; +} +``` + +This will automatically switch between light and dark modes based on the user's system preference. Alternatively, you can use a class-based approach: + +```css +:root { + color-scheme: light; +} + +.dark { + color-scheme: dark; +} +``` + +**Note:** The `light-dark()` CSS function requires modern browser support (Chrome 123+, Firefox 120+, Safari 17.4+). For older browsers, consider using the `dark` theme with manual switching. diff --git a/.changeset/tangy-melons-rescue.md b/.changeset/tangy-melons-rescue.md new file mode 100644 index 00000000000..571298c7408 --- /dev/null +++ b/.changeset/tangy-melons-rescue.md @@ -0,0 +1,5 @@ +--- +'@clerk/ui': patch +--- + +Removes provider icon filter invert from elements for both `dark` and `shadcn` themes. diff --git a/packages/ui/src/elements/SocialButtons.tsx b/packages/ui/src/elements/SocialButtons.tsx index 2435f6f5111..569cd5780ec 100644 --- a/packages/ui/src/elements/SocialButtons.tsx +++ b/packages/ui/src/elements/SocialButtons.tsx @@ -12,9 +12,9 @@ import { Flex, Grid, Icon, - Image, localizationKeys, SimpleButton, + Span, Spinner, Text, useAppearance, @@ -30,6 +30,7 @@ import { distributeStrategiesIntoRows } from './utils'; const SOCIAL_BUTTON_BLOCK_THRESHOLD = 2; const SOCIAL_BUTTON_PRE_TEXT_THRESHOLD = 1; const MAX_STRATEGIES_PER_ROW = 5; +const SUPPORTS_MASK_IMAGE = ['apple', 'github', 'okx_wallet', 'vercel']; export type SocialButtonsProps = React.PropsWithChildren<{ enableOAuthProviders: boolean; @@ -189,14 +190,31 @@ export const SocialButtons = React.memo((props: SocialButtonsRootProps) => { }); const imageOrInitial = strategyToDisplayData[strategy].iconUrl ? ( - {`Sign ({ width: theme.sizes.$4, height: 'auto', maxWidth: '100%' })} + aria-label={`Sign in with ${strategyToDisplayData[strategy].name}`} + sx={theme => ({ + display: 'inline-block', + width: theme.sizes.$4, + height: theme.sizes.$4, + maxWidth: '100%', + ...(SUPPORTS_MASK_IMAGE.includes(strategyToDisplayData[strategy].id) + ? { + '--cl-icon-fill': theme.colors.$colorForeground, + backgroundColor: 'var(--cl-icon-fill)', + maskImage: `url(${strategyToDisplayData[strategy].iconUrl})`, + maskSize: 'cover', + maskPosition: 'center', + maskRepeat: 'no-repeat', + } + : { + backgroundImage: `url(${strategyToDisplayData[strategy].iconUrl})`, + backgroundSize: 'cover', + backgroundPosition: 'center', + backgroundRepeat: 'no-repeat', + }), + })} /> ) : (