diff --git a/.changeset/slow-berries-walk.md b/.changeset/slow-berries-walk.md
new file mode 100644
index 00000000000..1822560c279
--- /dev/null
+++ b/.changeset/slow-berries-walk.md
@@ -0,0 +1,5 @@
+---
+'@clerk/ui': minor
+---
+
+Extract `` component to ensure consistency is usage across the UI components.
diff --git a/packages/ui/src/common/ProviderIcon.tsx b/packages/ui/src/common/ProviderIcon.tsx
new file mode 100644
index 00000000000..95d3359f4e8
--- /dev/null
+++ b/packages/ui/src/common/ProviderIcon.tsx
@@ -0,0 +1,106 @@
+import type { OAuthProvider, PhoneCodeChannel, Web3Provider } from '@clerk/shared/types';
+
+import { descriptors, Span } from '../customizables';
+import type { ElementDescriptor, ElementId } from '../customizables/elementDescriptors';
+import type { InternalTheme, PropsOfComponent } from '../styledSystem';
+import { ProviderInitialIcon } from './ProviderInitialIcon';
+
+type ProviderId = OAuthProvider | Web3Provider | PhoneCodeChannel;
+
+const SUPPORTS_MASK_IMAGE = ['apple', 'github', 'okx_wallet', 'vercel'] as const;
+
+const supportsMaskImage = (id: ProviderId): boolean => {
+ return (SUPPORTS_MASK_IMAGE as readonly string[]).includes(id);
+};
+
+const getIconImageStyles = (theme: InternalTheme, id: ProviderId, iconUrl: string) => {
+ if (supportsMaskImage(id)) {
+ return {
+ '--cl-icon-fill': theme.colors.$colorForeground,
+ backgroundColor: 'var(--cl-icon-fill)',
+ maskImage: `url(${iconUrl})`,
+ maskSize: 'cover',
+ maskPosition: 'center',
+ maskRepeat: 'no-repeat',
+ };
+ }
+
+ return {
+ backgroundImage: `url(${iconUrl})`,
+ backgroundSize: 'cover',
+ backgroundPosition: 'center',
+ backgroundRepeat: 'no-repeat',
+ };
+};
+
+const getThemeSize = (theme: InternalTheme, size: string): string => {
+ return theme.sizes[size as keyof typeof theme.sizes] || size;
+};
+
+export type ProviderIconProps = Omit<
+ PropsOfComponent,
+ 'elementDescriptor' | 'elementId' | 'aria-label'
+> & {
+ id: ProviderId;
+ iconUrl?: string | null;
+ name: string;
+ size?: string;
+ isLoading?: boolean;
+ isDisabled?: boolean;
+ alt?: string;
+ elementDescriptor?: ElementDescriptor | Array;
+ elementId?: ElementId;
+};
+
+export const ProviderIcon = (props: ProviderIconProps) => {
+ const {
+ id,
+ iconUrl,
+ name,
+ size = '$4',
+ isLoading,
+ isDisabled,
+ alt,
+ elementDescriptor = descriptors.providerIcon,
+ elementId,
+ sx,
+ ...rest
+ } = props;
+
+ if (!iconUrl || iconUrl.trim() === '') {
+ const { ref, ...initialIconProps } = rest;
+ return (
+
+ );
+ }
+
+ return (
+ {
+ const iconSize = getThemeSize(theme, size);
+ return [
+ {
+ display: 'inline-block',
+ width: iconSize,
+ height: iconSize,
+ maxWidth: '100%',
+ opacity: isLoading || isDisabled ? 0.5 : 1,
+ ...getIconImageStyles(theme, id, iconUrl),
+ },
+ sx,
+ ];
+ }}
+ {...rest}
+ />
+ );
+};
diff --git a/packages/ui/src/common/__tests__/ProviderIcon.test.tsx b/packages/ui/src/common/__tests__/ProviderIcon.test.tsx
new file mode 100644
index 00000000000..48657e10a83
--- /dev/null
+++ b/packages/ui/src/common/__tests__/ProviderIcon.test.tsx
@@ -0,0 +1,432 @@
+import { describe, expect, it } from 'vitest';
+
+import { bindCreateFixtures } from '@/test/create-fixtures';
+import { render, screen } from '@/test/utils';
+
+import { ProviderIcon } from '../ProviderIcon';
+
+const { createFixtures } = bindCreateFixtures('SignIn');
+
+describe('ProviderIcon', () => {
+ describe('Rendering with iconUrl', () => {
+ it('renders Span with correct aria-label when iconUrl is provided', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ expect(icon).toBeInTheDocument();
+ expect(icon.tagName).toBe('SPAN');
+ });
+
+ it('uses custom alt text when provided', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Custom Google logo');
+ expect(icon).toBeInTheDocument();
+ });
+
+ it('applies mask-image styles for supported providers (apple)', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Apple icon');
+ const styles = window.getComputedStyle(icon);
+
+ // Check that mask-image is applied (via inline styles)
+ expect(icon).toHaveStyle({
+ display: 'inline-block',
+ });
+ });
+
+ it('applies mask-image styles for supported providers (github)', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('GitHub icon');
+ expect(icon).toBeInTheDocument();
+ });
+
+ it('applies mask-image styles for supported providers (okx_wallet)', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('OKX Wallet icon');
+ expect(icon).toBeInTheDocument();
+ });
+
+ it('applies mask-image styles for supported providers (vercel)', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Vercel icon');
+ expect(icon).toBeInTheDocument();
+ });
+
+ it('applies background-image styles for non-mask-image providers', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ expect(icon).toBeInTheDocument();
+ });
+ });
+
+ describe('Rendering without iconUrl', () => {
+ it('falls back to ProviderInitialIcon when iconUrl is null', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ // ProviderInitialIcon renders the first letter of the name
+ const initial = screen.getByText('G');
+ expect(initial).toBeInTheDocument();
+ });
+
+ it('falls back to ProviderInitialIcon when iconUrl is undefined', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const initial = screen.getByText('G');
+ expect(initial).toBeInTheDocument();
+ });
+
+ it('falls back to ProviderInitialIcon when iconUrl is empty string', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const initial = screen.getByText('A');
+ expect(initial).toBeInTheDocument();
+ });
+
+ it('falls back to ProviderInitialIcon when iconUrl is whitespace-only', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const initial = screen.getByText('G');
+ expect(initial).toBeInTheDocument();
+ });
+
+ it('passes isLoading prop to ProviderInitialIcon', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const initial = screen.getByText('G');
+ expect(initial).toBeInTheDocument();
+ });
+
+ it('passes isDisabled prop to ProviderInitialIcon', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const initial = screen.getByText('G');
+ expect(initial).toBeInTheDocument();
+ });
+ });
+
+ describe('Loading and disabled states', () => {
+ it('applies opacity 0.5 when isLoading is true', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ const styles = window.getComputedStyle(icon);
+ expect(styles.opacity).toBe('0.5');
+ });
+
+ it('applies opacity 0.5 when isDisabled is true', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ const styles = window.getComputedStyle(icon);
+ expect(styles.opacity).toBe('0.5');
+ });
+
+ it('applies opacity 1 when neither isLoading nor isDisabled is true', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ const styles = window.getComputedStyle(icon);
+ expect(styles.opacity).toBe('1');
+ });
+ });
+
+ describe('Size prop', () => {
+ it('uses default size $4 when not provided', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ expect(icon).toBeInTheDocument();
+ // Size is applied via theme, so we verify the element exists
+ // The actual size value depends on theme configuration
+ });
+
+ it('uses custom size when provided', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ expect(icon).toBeInTheDocument();
+ });
+ });
+
+ describe('Accessibility', () => {
+ it('sets aria-label from alt prop when provided', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google provider icon');
+ expect(icon).toHaveAttribute('aria-label', 'Google provider icon');
+ });
+
+ it('generates aria-label from name when alt is not provided', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ expect(icon).toHaveAttribute('aria-label', 'Google icon');
+ });
+
+ it('uses correct elementDescriptor', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ expect(icon).toBeInTheDocument();
+ // Element descriptor is applied via data attributes in the styled system
+ });
+ });
+
+ describe('Edge cases', () => {
+ it('handles providers with different casing', async () => {
+ const { wrapper } = await createFixtures();
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ expect(icon).toBeInTheDocument();
+ });
+
+ it('handles custom elementDescriptor', async () => {
+ const { wrapper } = await createFixtures();
+ const { descriptors } = await import('../../customizables');
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ expect(icon).toBeInTheDocument();
+ });
+
+ it('handles custom elementId', async () => {
+ const { wrapper } = await createFixtures();
+ const { descriptors } = await import('../../customizables');
+
+ render(
+ ,
+ { wrapper },
+ );
+
+ const icon = screen.getByLabelText('Google icon');
+ expect(icon).toBeInTheDocument();
+ });
+ });
+});
diff --git a/packages/ui/src/common/index.ts b/packages/ui/src/common/index.ts
index e1a892faa43..f859201d4b6 100644
--- a/packages/ui/src/common/index.ts
+++ b/packages/ui/src/common/index.ts
@@ -8,6 +8,7 @@ export * from './InfiniteListSpinner';
export * from './NotificationCountBadge';
export * from './PrintableComponent';
export * from './ProviderInitialIcon';
+export * from './ProviderIcon';
export * from './QRCode';
export * from './redirects';
export * from './RemoveResourceForm';
diff --git a/packages/ui/src/components/SignIn/SignInAlternativePhoneCodePhoneNumberCard.tsx b/packages/ui/src/components/SignIn/SignInAlternativePhoneCodePhoneNumberCard.tsx
index f8c3ec42d34..5c784ba612b 100644
--- a/packages/ui/src/components/SignIn/SignInAlternativePhoneCodePhoneNumberCard.tsx
+++ b/packages/ui/src/components/SignIn/SignInAlternativePhoneCodePhoneNumberCard.tsx
@@ -6,7 +6,8 @@ import { Form } from '@/ui/elements/Form';
import { Header } from '@/ui/elements/Header';
import type { FormControlState } from '@/ui/utils/useFormControl';
-import { Button, Col, descriptors, Flex, Image, localizationKeys } from '../../customizables';
+import { ProviderIcon } from '../../common';
+import { Button, Col, descriptors, Flex, localizationKeys } from '../../customizables';
import { CaptchaElement } from '../../elements/CaptchaElement';
import { useEnabledThirdPartyProviders } from '../../hooks';
@@ -23,6 +24,7 @@ export const SignInAlternativePhoneCodePhoneNumberCard = (props: SignUpAlternati
const provider = phoneCodeProvider.name;
const channel = phoneCodeProvider.channel;
const card = useCardState();
+ const strategyData = strategyToDisplayData[channel];
return (
@@ -32,16 +34,18 @@ export const SignInAlternativePhoneCodePhoneNumberCard = (props: SignUpAlternati
showDivider
>
- ({
- width: theme.sizes.$7,
- height: theme.sizes.$7,
- maxWidth: '100%',
- marginBottom: theme.sizes.$6,
- })}
- />
+ {providerToDisplayData[channel] && (
+ ({
+ marginBottom: theme.sizes.$6,
+ })}
+ />
+ )}
{
return !!fields[name] && fields[name]?.required;
@@ -39,16 +41,18 @@ export const SignUpStartAlternativePhoneCodePhoneNumberCard = (props: SignUpForm
showDivider
>
- ({
- width: theme.sizes.$7,
- height: theme.sizes.$7,
- maxWidth: '100%',
- marginBottom: theme.sizes.$6,
- })}
- />
+ {providerToDisplayData[phoneCodeProvider.channel] && (
+ ({
+ marginBottom: theme.sizes.$6,
+ })}
+ />
+ )}
voi
});
});
- const imageOrInitial = strategyToDisplayData[strategy].iconUrl ? (
- ({ width: theme.sizes.$4 })}
- />
- ) : (
-
- );
-
const connect = () => {
if (!user) {
return;
@@ -93,7 +74,18 @@ const ConnectMenuButton = (props: { strategy: OAuthStrategy; onClick?: () => voi
justifyContent: 'start',
gap: t.space.$2,
})}
- leftIcon={imageOrInitial}
+ leftIcon={
+
+ }
/>
);
};
diff --git a/packages/ui/src/components/UserProfile/ConnectedAccountsSection.tsx b/packages/ui/src/components/UserProfile/ConnectedAccountsSection.tsx
index eaa0e746ba4..ff00fdb0f25 100644
--- a/packages/ui/src/components/UserProfile/ConnectedAccountsSection.tsx
+++ b/packages/ui/src/components/UserProfile/ConnectedAccountsSection.tsx
@@ -9,9 +9,9 @@ import { ProfileSection } from '@/ui/elements/Section';
import { ThreeDotsMenu } from '@/ui/elements/ThreeDotsMenu';
import { handleError } from '@/ui/utils/errorHandler';
-import { ProviderInitialIcon } from '../../common';
+import { ProviderIcon } from '../../common';
import { useUserProfileContext } from '../../contexts';
-import { Box, Button, descriptors, Flex, Image, localizationKeys, Text } from '../../customizables';
+import { Box, Button, descriptors, Flex, localizationKeys, Text } from '../../customizables';
import { Action } from '../../elements/Action';
import { useActionContext } from '../../elements/Action/ActionRoot';
import { useEnabledThirdPartyProviders } from '../../hooks';
@@ -117,11 +117,11 @@ const ConnectedAccount = ({ account }: { account: ExternalAccountResource }) =>
}),
);
+ const { providerToDisplayData } = useEnabledThirdPartyProviders();
+
if (!user) {
return null;
}
-
- const { providerToDisplayData } = useEnabledThirdPartyProviders();
const label = account.username || account.emailAddress;
const fallbackErrorMessage = account.verification?.error?.longMessage;
const additionalScopes = findAdditionalScopes(account, additionalOAuthScopes);
@@ -153,34 +153,28 @@ const ConnectedAccount = ({ account }: { account: ExternalAccountResource }) =>
}
};
- const ImageOrInitial = () =>
- providerToDisplayData[account.provider].iconUrl ? (
- ({ width: theme.sizes.$4, flexShrink: 0 })}
- />
- ) : (
-
- );
+ const providerData = providerToDisplayData[account.provider];
return (
({ overflow: 'hidden', gap: t.space.$2 })}>
-
+
({ color: t.colors.$colorForeground })}>{`${
- providerToDisplayData[account.provider].name
+ providerData?.name || account.provider
}`}
{
const { user } = useUser();
@@ -86,25 +86,14 @@ const EnterpriseAccountProviderIcon = ({ account }: { account: EnterpriseAccount
const providerWithoutPrefix = provider.replace(/(oauth_|saml_)/, '').trim() as OAuthProvider;
const connectionName = enterpriseConnection?.name ?? providerWithoutPrefix;
- const commonImageProps = {
- elementDescriptor: [descriptors.providerIcon],
- alt: connectionName,
- sx: (theme: any) => ({ width: theme.sizes.$4 }),
- elementId: descriptors.enterpriseButtonsProviderIcon.setId(account.provider),
- };
-
- return enterpriseConnection?.logoPublicUrl ? (
-
- ) : (
-
);
};
diff --git a/packages/ui/src/components/UserProfile/Web3Form.tsx b/packages/ui/src/components/UserProfile/Web3Form.tsx
index a2765b22f44..19c4b320c7a 100644
--- a/packages/ui/src/components/UserProfile/Web3Form.tsx
+++ b/packages/ui/src/components/UserProfile/Web3Form.tsx
@@ -3,8 +3,9 @@ import { useReverification, useUser } from '@clerk/shared/react';
import type { Web3Provider, Web3Strategy } from '@clerk/shared/types';
import { useModuleManager } from '@/contexts';
-import { descriptors, Image, localizationKeys } from '@/customizables';
+import { descriptors, localizationKeys } from '@/customizables';
import { useEnabledThirdPartyProviders } from '@/hooks';
+import { ProviderIcon } from '@/ui/common';
import { Web3SelectSolanaWalletScreen } from '@/ui/components/UserProfile/Web3SelectSolanaWalletScreen';
import { Action } from '@/ui/elements/Action';
import { useActionContext } from '@/ui/elements/Action/ActionRoot';
@@ -91,14 +92,15 @@ export const AddWeb3WalletActionMenu = () => {
gap: t.space.$2,
})}
leftIcon={
- ({ width: theme.sizes.$5 })}
+ elementDescriptor={descriptors.providerIcon}
+ elementId={descriptors.providerIcon.setId(strategyToDisplayData[strategy].id)}
/>
}
/>
diff --git a/packages/ui/src/components/UserProfile/Web3Section.tsx b/packages/ui/src/components/UserProfile/Web3Section.tsx
index 525246c6bd0..9dd7938f939 100644
--- a/packages/ui/src/components/UserProfile/Web3Section.tsx
+++ b/packages/ui/src/components/UserProfile/Web3Section.tsx
@@ -7,7 +7,8 @@ import { ProfileSection } from '@/ui/elements/Section';
import { ThreeDotsMenu } from '@/ui/elements/ThreeDotsMenu';
import { handleError } from '@/ui/utils/errorHandler';
-import { Badge, Box, Flex, Image, localizationKeys, Text } from '../../customizables';
+import { ProviderIcon } from '../../common';
+import { Badge, Box, Flex, localizationKeys, Text } from '../../customizables';
import { Action } from '../../elements/Action';
import { useActionContext } from '../../elements/Action/ActionRoot';
import { useEnabledThirdPartyProviders } from '../../hooks';
@@ -72,10 +73,11 @@ export const Web3Section = withCardStateProvider(
>
({ alignItems: 'center', gap: t.space.$2, width: '100%' })}>
{strategyToDisplayData[strategy].iconUrl && (
- ({ width: theme.sizes.$4 })}
/>
)}
diff --git a/packages/ui/src/components/UserProfile/__tests__/EnterpriseAccountsSection.test.tsx b/packages/ui/src/components/UserProfile/__tests__/EnterpriseAccountsSection.test.tsx
index 9ee0ee40d0e..cabd738fa30 100644
--- a/packages/ui/src/components/UserProfile/__tests__/EnterpriseAccountsSection.test.tsx
+++ b/packages/ui/src/components/UserProfile/__tests__/EnterpriseAccountsSection.test.tsx
@@ -243,12 +243,12 @@ describe('EnterpriseAccountsSection ', () => {
it('renders connection', async () => {
const { wrapper } = await createFixtures(withOAuthBuiltInEnterpriseConnection);
- const { getByText, getByRole } = render(, { wrapper });
+ const { getByText, getByLabelText } = render(, { wrapper });
getByText(/^Enterprise accounts/i);
getByText(/google/i);
- const img = getByRole('img', { name: /google/i });
- expect(img.getAttribute('src')).toBe('https://img.clerk.com/static/google.svg?width=160');
+ const icon = getByLabelText(/google's icon/i);
+ expect(icon).toBeInTheDocument();
getByText(/test@clerk.com/i);
});
});
@@ -260,12 +260,12 @@ describe('EnterpriseAccountsSection ', () => {
const { wrapper } = await createFixtures(withOAuthCustomEnterpriseConnection(mockLogoUrl));
- const { getByText, getByRole } = render(, { wrapper });
+ const { getByText, getByLabelText } = render(, { wrapper });
getByText(/^Enterprise accounts/i);
getByText(/roblox/i);
- const img = getByRole('img', { name: /roblox/i });
- expect(img.getAttribute('src')).toContain(mockLogoUrl);
+ const icon = getByLabelText(/roblox's icon/i);
+ expect(icon).toBeInTheDocument();
getByText(/test@clerk.com/i);
});
});
@@ -288,12 +288,12 @@ describe('EnterpriseAccountsSection ', () => {
it('renders connection', async () => {
const { wrapper } = await createFixtures(withSamlEnterpriseConnection);
- const { getByText, getByRole } = render(, { wrapper });
+ const { getByText, getByLabelText } = render(, { wrapper });
getByText(/^Enterprise accounts/i);
getByText(/okta workforce/i);
- const img = getByRole('img', { name: /okta/i });
- expect(img.getAttribute('src')).toBe('https://img.clerk.com/static/okta.svg?width=160');
+ const icon = getByLabelText(/okta workforce's icon/i);
+ expect(icon).toBeInTheDocument();
getByText(/test@clerk.com/i);
});
});
diff --git a/packages/ui/src/elements/SocialButtons.tsx b/packages/ui/src/elements/SocialButtons.tsx
index a9578e4b6b9..7b3d8b76186 100644
--- a/packages/ui/src/elements/SocialButtons.tsx
+++ b/packages/ui/src/elements/SocialButtons.tsx
@@ -4,7 +4,7 @@ import type { OAuthProvider, OAuthStrategy, PhoneCodeChannel, Web3Provider, Web3
import type { Ref } from 'react';
import React, { forwardRef, isValidElement } from 'react';
-import { ProviderInitialIcon } from '../common';
+import { ProviderIcon } from '../common';
import type { LocalizationKey } from '../customizables';
import {
Button,
@@ -14,7 +14,6 @@ import {
Icon,
localizationKeys,
SimpleButton,
- Span,
Spinner,
Text,
useAppearance,
@@ -30,13 +29,6 @@ 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'] as const;
-
-type SupportsMaskImageProvider = (typeof SUPPORTS_MASK_IMAGE)[number];
-
-const supportsMaskImage = (id: OAuthProvider | Web3Provider | PhoneCodeChannel): id is SupportsMaskImageProvider => {
- return (SUPPORTS_MASK_IMAGE as readonly string[]).includes(id);
-};
export type SocialButtonsProps = React.PropsWithChildren<{
enableOAuthProviders: boolean;
@@ -195,39 +187,16 @@ export const SocialButtons = React.memo((props: SocialButtonsRootProps) => {
provider: strategyToDisplayData[strategy].name,
});
- const imageOrInitial = strategyToDisplayData[strategy].iconUrl ? (
- ({
- display: 'inline-block',
- width: theme.sizes.$4,
- height: theme.sizes.$4,
- maxWidth: '100%',
- ...(supportsMaskImage(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',
- }),
- })}
- />
- ) : (
-
);