From eca1ec97838a6cf7d05f84655b11bc817c60dd61 Mon Sep 17 00:00:00 2001 From: Marcel Cruz <12413903+marcelscruz@users.noreply.github.com> Date: Mon, 27 Nov 2023 16:57:20 +0100 Subject: [PATCH] feat(clerk-js): Retheme OAuth buttons (#2139) * feat(clerk-js): Retheme OAuth buttons * fix(clerk-js): Add missing descriptors on OAuth block button * chore(clerk-js): Move ResizeObserver to its own hook * chore(clerk-js): Add descriptor to all * chore(clerk-js): Move `distributeStrategiesIntoRows` to separate utils file --------- Co-authored-by: Marcel <{ID}+{username}@users.noreply.github.com> --- .changeset/friendly-months-film.md | 2 + .changeset/nice-dingos-argue.md | 2 + .changeset/rotten-ways-do.md | 2 + .changeset/silly-emus-boil.md | 2 + .../ui.retheme/common/EmailLinkStatusCard.tsx | 1 + .../ui.retheme/common/InfiniteListSpinner.tsx | 3 +- .../OrganizationList/OrganizationListPage.tsx | 1 + .../components/OrganizationList/shared.tsx | 1 + .../OrganizationProfile/DomainList.tsx | 3 +- .../OrganizationProfile/MemberListTable.tsx | 1 + .../OrganizationProfile/RemoveDomainPage.tsx | 3 +- .../VerifiedDomainPage.tsx | 3 +- .../OrganizationProfile/VerifyDomainPage.tsx | 1 + .../SignIn/ResetPasswordSuccess.tsx | 5 +- .../customizables/elementDescriptors.ts | 1 + .../src/ui.retheme/elements/Actions.tsx | 7 +- .../src/ui.retheme/elements/CodeControl.tsx | 1 + .../ui.retheme/elements/FullHeightLoader.tsx | 3 +- .../src/ui.retheme/elements/LoadingCard.tsx | 1 + .../src/ui.retheme/elements/SocialButtons.tsx | 233 ++++++++++++------ .../clerk-js/src/ui.retheme/elements/utils.ts | 22 ++ .../src/ui.retheme/foundations/sizes.ts | 1 + .../clerk-js/src/ui.retheme/hooks/index.ts | 1 + .../src/ui.retheme/hooks/useResizeObserver.ts | 57 +++++ .../src/ui.retheme/primitives/Button.tsx | 27 +- 25 files changed, 285 insertions(+), 99 deletions(-) create mode 100644 .changeset/friendly-months-film.md create mode 100644 .changeset/nice-dingos-argue.md create mode 100644 .changeset/rotten-ways-do.md create mode 100644 .changeset/silly-emus-boil.md create mode 100644 packages/clerk-js/src/ui.retheme/elements/utils.ts create mode 100644 packages/clerk-js/src/ui.retheme/hooks/useResizeObserver.ts diff --git a/.changeset/friendly-months-film.md b/.changeset/friendly-months-film.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/friendly-months-film.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.changeset/nice-dingos-argue.md b/.changeset/nice-dingos-argue.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/nice-dingos-argue.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.changeset/rotten-ways-do.md b/.changeset/rotten-ways-do.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/rotten-ways-do.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.changeset/silly-emus-boil.md b/.changeset/silly-emus-boil.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/silly-emus-boil.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/clerk-js/src/ui.retheme/common/EmailLinkStatusCard.tsx b/packages/clerk-js/src/ui.retheme/common/EmailLinkStatusCard.tsx index 953a707026..06e2752ae6 100644 --- a/packages/clerk-js/src/ui.retheme/common/EmailLinkStatusCard.tsx +++ b/packages/clerk-js/src/ui.retheme/common/EmailLinkStatusCard.tsx @@ -61,6 +61,7 @@ const StatusRow = (props: { status: VerificationStatus }) => { size='xl' colorScheme='primary' sx={theme => ({ margin: `${theme.space.$12} 0` })} + elementDescriptor={descriptors.spinner} /> ) : ( <> diff --git a/packages/clerk-js/src/ui.retheme/common/InfiniteListSpinner.tsx b/packages/clerk-js/src/ui.retheme/common/InfiniteListSpinner.tsx index 1a359c4ebe..97ae637e73 100644 --- a/packages/clerk-js/src/ui.retheme/common/InfiniteListSpinner.tsx +++ b/packages/clerk-js/src/ui.retheme/common/InfiniteListSpinner.tsx @@ -1,6 +1,6 @@ import { forwardRef } from 'react'; -import { Box, Spinner } from '../customizables'; +import { Box, descriptors, Spinner } from '../customizables'; export const InfiniteListSpinner = forwardRef((_, ref) => { return ( @@ -24,6 +24,7 @@ export const InfiniteListSpinner = forwardRef((_, ref) => { diff --git a/packages/clerk-js/src/ui.retheme/components/OrganizationList/OrganizationListPage.tsx b/packages/clerk-js/src/ui.retheme/components/OrganizationList/OrganizationListPage.tsx index 509eb62abd..87dcd8a807 100644 --- a/packages/clerk-js/src/ui.retheme/components/OrganizationList/OrganizationListPage.tsx +++ b/packages/clerk-js/src/ui.retheme/components/OrganizationList/OrganizationListPage.tsx @@ -67,6 +67,7 @@ export const OrganizationListPage = withCardStateProvider(() => { )} diff --git a/packages/clerk-js/src/ui.retheme/components/OrganizationList/shared.tsx b/packages/clerk-js/src/ui.retheme/components/OrganizationList/shared.tsx index e3e0d7df8e..7467687a2c 100644 --- a/packages/clerk-js/src/ui.retheme/components/OrganizationList/shared.tsx +++ b/packages/clerk-js/src/ui.retheme/components/OrganizationList/shared.tsx @@ -85,6 +85,7 @@ export const PreviewListSpinner = forwardRef((_, ref) => { diff --git a/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/DomainList.tsx b/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/DomainList.tsx index b782829b78..b1178894ba 100644 --- a/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/DomainList.tsx +++ b/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/DomainList.tsx @@ -10,7 +10,7 @@ import { stripOrigin, toURL, trimLeadingSlash } from '../../../utils'; import { useGate, withGate } from '../../common'; import { useCoreOrganization } from '../../contexts'; import type { LocalizationKey } from '../../customizables'; -import { Box, Col, localizationKeys, Spinner } from '../../customizables'; +import { Box, Col, descriptors, localizationKeys, Spinner } from '../../customizables'; import { ArrowBlockButton, BlockWithTrailingComponent, ThreeDotsMenu } from '../../elements'; import { useInView } from '../../hooks'; import { useRouter } from '../../router'; @@ -193,6 +193,7 @@ export const DomainList = withGate( diff --git a/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/MemberListTable.tsx b/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/MemberListTable.tsx index efdd2d5207..98f33d6faa 100644 --- a/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/MemberListTable.tsx +++ b/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/MemberListTable.tsx @@ -60,6 +60,7 @@ export const DataTable = (props: MembersListTableProps) => { diff --git a/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/RemoveDomainPage.tsx b/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/RemoveDomainPage.tsx index 4da8c1a2c0..50f0aaec49 100644 --- a/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/RemoveDomainPage.tsx +++ b/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/RemoveDomainPage.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { RemoveResourcePage } from '../../common'; import { useCoreOrganization, useEnvironment } from '../../contexts'; -import { Flex, Spinner } from '../../customizables'; +import { descriptors, Flex, Spinner } from '../../customizables'; import { useFetch } from '../../hooks'; import { localizationKeys } from '../../localization'; import { useRouter } from '../../router'; @@ -51,6 +51,7 @@ export const RemoveDomainPage = () => { ); diff --git a/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/VerifiedDomainPage.tsx b/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/VerifiedDomainPage.tsx index c6283731d6..84e7119544 100644 --- a/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/VerifiedDomainPage.tsx +++ b/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/VerifiedDomainPage.tsx @@ -7,7 +7,7 @@ import type { import { CalloutWithAction, useGate } from '../../common'; import { useCoreOrganization, useEnvironment } from '../../contexts'; import type { LocalizationKey } from '../../customizables'; -import { Col, Flex, localizationKeys, Spinner, Text } from '../../customizables'; +import { Col, descriptors, Flex, localizationKeys, Spinner, Text } from '../../customizables'; import { ContentPage, Form, @@ -189,6 +189,7 @@ export const VerifiedDomainPage = withCardStateProvider(() => { ); diff --git a/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/VerifyDomainPage.tsx b/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/VerifyDomainPage.tsx index f94b205255..c68fba57a4 100644 --- a/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/VerifyDomainPage.tsx +++ b/packages/clerk-js/src/ui.retheme/components/OrganizationProfile/VerifyDomainPage.tsx @@ -114,6 +114,7 @@ export const VerifyDomainPage = withCardStateProvider(() => { ); diff --git a/packages/clerk-js/src/ui.retheme/components/SignIn/ResetPasswordSuccess.tsx b/packages/clerk-js/src/ui.retheme/components/SignIn/ResetPasswordSuccess.tsx index d34d2345b3..210b49bb7f 100644 --- a/packages/clerk-js/src/ui.retheme/components/SignIn/ResetPasswordSuccess.tsx +++ b/packages/clerk-js/src/ui.retheme/components/SignIn/ResetPasswordSuccess.tsx @@ -1,8 +1,8 @@ import { withRedirectToHomeSingleSessionGuard } from '../../common'; -import { Col, descriptors, localizationKeys, Text } from '../../customizables'; +import { Col, descriptors, localizationKeys, Spinner, Text } from '../../customizables'; import { Card, CardAlert, Header, useCardState, withCardStateProvider } from '../../elements'; import { useSetSessionWithTimeout } from '../../hooks/useSetSessionWithTimeout'; -import { Flex, Spinner } from '../../primitives'; +import { Flex } from '../../primitives'; export const _ResetPasswordSuccess = () => { const card = useCardState(); @@ -29,6 +29,7 @@ export const _ResetPasswordSuccess = () => { diff --git a/packages/clerk-js/src/ui.retheme/customizables/elementDescriptors.ts b/packages/clerk-js/src/ui.retheme/customizables/elementDescriptors.ts index 1434238073..0c35a94837 100644 --- a/packages/clerk-js/src/ui.retheme/customizables/elementDescriptors.ts +++ b/packages/clerk-js/src/ui.retheme/customizables/elementDescriptors.ts @@ -279,6 +279,7 @@ export const APPEARANCE_KEYS = containsAllElementsConfigKeys([ 'notificationBadge', 'button', 'providerIcon', + 'spinner', // Decide if we want to keep the keys as camel cased in HTML as well, // if yes, refactor and remove the .map(camelize) method ] as const).map(camelize) as (keyof ElementsConfig)[]; diff --git a/packages/clerk-js/src/ui.retheme/elements/Actions.tsx b/packages/clerk-js/src/ui.retheme/elements/Actions.tsx index 434b61f4fa..60f5aa7b2e 100644 --- a/packages/clerk-js/src/ui.retheme/elements/Actions.tsx +++ b/packages/clerk-js/src/ui.retheme/elements/Actions.tsx @@ -1,7 +1,7 @@ import React from 'react'; import type { LocalizationKey } from '../customizables'; -import { Button, Col, Flex, Icon, Spinner, Text } from '../customizables'; +import { Button, Col, descriptors, Flex, Icon, Spinner, Text } from '../customizables'; import type { ElementDescriptor, ElementId } from '../customizables/elementDescriptors'; import { useCardState } from '../elements/contexts'; import { useLoadingStatus } from '../hooks'; @@ -96,7 +96,10 @@ export const Action = (props: ActionProps) => { sx={theme => ({ flex: `0 0 ${theme.sizes.$11}` })} > {status.isLoading ? ( - + ) : ( ((_, ref) => { ({ marginLeft: theme.space.$2 })} + elementDescriptor={descriptors.spinner} /> )} diff --git a/packages/clerk-js/src/ui.retheme/elements/FullHeightLoader.tsx b/packages/clerk-js/src/ui.retheme/elements/FullHeightLoader.tsx index 0422a7f1cc..a40bda53ed 100644 --- a/packages/clerk-js/src/ui.retheme/elements/FullHeightLoader.tsx +++ b/packages/clerk-js/src/ui.retheme/elements/FullHeightLoader.tsx @@ -1,4 +1,4 @@ -import { Flex, Spinner } from '../customizables'; +import { descriptors, Flex, Spinner } from '../customizables'; export const FullHeightLoader = (): JSX.Element => { return ( @@ -9,6 +9,7 @@ export const FullHeightLoader = (): JSX.Element => { ); diff --git a/packages/clerk-js/src/ui.retheme/elements/LoadingCard.tsx b/packages/clerk-js/src/ui.retheme/elements/LoadingCard.tsx index b3f9af49f7..6282001487 100644 --- a/packages/clerk-js/src/ui.retheme/elements/LoadingCard.tsx +++ b/packages/clerk-js/src/ui.retheme/elements/LoadingCard.tsx @@ -21,6 +21,7 @@ export const LoadingCardContainer = ({ children }: PropsWithChildren) => { {children} diff --git a/packages/clerk-js/src/ui.retheme/elements/SocialButtons.tsx b/packages/clerk-js/src/ui.retheme/elements/SocialButtons.tsx index a267a383a1..a7e05e1a4e 100644 --- a/packages/clerk-js/src/ui.retheme/elements/SocialButtons.tsx +++ b/packages/clerk-js/src/ui.retheme/elements/SocialButtons.tsx @@ -1,14 +1,30 @@ import type { OAuthProvider, OAuthStrategy, Web3Provider, Web3Strategy } from '@clerk/types'; -import React from 'react'; - -import { Button, descriptors, Grid, Image, localizationKeys, useAppearance } from '../customizables'; -import { useEnabledThirdPartyProviders } from '../hooks'; +import type { Ref } from 'react'; +import React, { forwardRef, isValidElement } from 'react'; + +import type { LocalizationKey } from '../customizables'; +import { + Button, + descriptors, + Flex, + Grid, + Icon, + Image, + localizationKeys, + SimpleButton, + Spinner, + Text, + useAppearance, +} from '../customizables'; +import { useEnabledThirdPartyProviders, useResizeObserver } from '../hooks'; import type { PropsOfComponent } from '../styledSystem'; import { sleep } from '../utils'; -import { ArrowBlockButton } from './ArrowBlockButton'; import { useCardState } from './contexts'; +import { distributeStrategiesIntoRows } from './utils'; const SOCIAL_BUTTON_BLOCK_THRESHOLD = 2; +const SOCIAL_BUTTON_PRE_TEXT_THRESHOLD = 1; +const MAX_STRATEGIES_PER_ROW = 6; export type SocialButtonsProps = React.PropsWithChildren<{ enableOAuthProviders: boolean; @@ -29,6 +45,7 @@ export const SocialButtons = React.memo((props: SocialButtonsRootProps) => { const { web3Strategies, authenticatableOauthStrategies, strategyToDisplayData } = useEnabledThirdPartyProviders(); const card = useCardState(); const { socialButtonsVariant } = useAppearance().parsedLayout; + const [firstStrategyRef, firstElementRect] = useResizeObserver(); const strategies = [ ...(enableOAuthProviders ? authenticatableOauthStrategies : []), @@ -39,6 +56,8 @@ export const SocialButtons = React.memo((props: SocialButtonsRootProps) => { return null; } + const strategyRows = distributeStrategiesIntoRows([...strategies], MAX_STRATEGIES_PER_ROW); + const preferBlockButtons = socialButtonsVariant === 'blockButton' ? true @@ -63,112 +82,172 @@ export const SocialButtons = React.memo((props: SocialButtonsRootProps) => { }; const ButtonElement = preferBlockButtons ? SocialButtonBlock : SocialButtonIcon; - const WrapperElement = preferBlockButtons ? ButtonRows : ButtonGrid; - - return ( - - {strategies.map(strategy => ( - ({ width: theme.sizes.$5, height: 'auto', maxWidth: '100%' })} - /> - } - /> - ))} - - ); -}); - -const ButtonGrid = (props: React.PropsWithChildren) => { - return ( - ({ - gridTemplateColumns: `repeat(auto-fit, minmax(${t.sizes.$12}, 1fr))`, - gridAutoRows: t.sizes.$12, - })} - > - {props.children} - - ); -}; -const ButtonRows = (props: React.PropsWithChildren) => { return ( - - {props.children} - + {strategyRows.map((row, rowIndex) => ( + + {row.map((strategy, strategyIndex) => { + const label = + strategies.length === SOCIAL_BUTTON_PRE_TEXT_THRESHOLD + ? `Continue with ${strategyToDisplayData[strategy].name}` + : strategyToDisplayData[strategy].name; + + const localizedText = + strategies.length === SOCIAL_BUTTON_PRE_TEXT_THRESHOLD + ? localizationKeys('socialButtonsBlockButton', { + provider: strategyToDisplayData[strategy].name, + }) + : undefined; + + // When strategies break into 2 rows or more, use the first item of the first + // row as reference for the width of the buttons in the second row and beyond + const ref = + strategies.length > MAX_STRATEGIES_PER_ROW && rowIndex === 0 && strategyIndex === 0 + ? firstStrategyRef + : null; + + return ( + ({ width: theme.sizes.$4, height: 'auto', maxWidth: '100%' })} + /> + } + /> + ); + })} + + ))} + ); -}; +}); type SocialButtonProps = PropsOfComponent & { icon: React.ReactElement; id: OAuthProvider | Web3Provider; - providerName: string; + textLocalizationKey: LocalizationKey | undefined; label?: string; }; -const SocialButtonIcon = (props: SocialButtonProps): JSX.Element => { - const { icon, label, id, providerName, ...rest } = props; +const SocialButtonIcon = forwardRef((props: SocialButtonProps, ref: Ref | null): JSX.Element => { + const { icon, label, id, textLocalizationKey, ...rest } = props; + return ( ); -}; +}); const SocialButtonBlock = (props: SocialButtonProps): JSX.Element => { - const { label, id, providerName, sx, icon, ...rest } = props; + const { id, icon, isLoading, label, textLocalizationKey, ...rest } = props; + const isIconElement = isValidElement(icon); return ( - [ { - textOverflow: 'ellipsis', - overflow: 'hidden', + gap: theme.space.$4, + position: 'relative', + justifyContent: 'flex-start', + borderColor: theme.colors.$blackAlpha200, }, - sx, + props.sx, ]} - {...rest} > - {label} - + + {(isLoading || icon) && ( + ({ flex: `0 0 ${theme.space.$4}` })} + > + {isLoading ? ( + + ) : !isIconElement && icon ? ( + ({ + color: theme.colors.$blackAlpha600, + width: theme.sizes.$4, + position: 'absolute', + }), + ]} + /> + ) : ( + icon + )} + + )} + + {label} + + + ); }; diff --git a/packages/clerk-js/src/ui.retheme/elements/utils.ts b/packages/clerk-js/src/ui.retheme/elements/utils.ts new file mode 100644 index 0000000000..83a094095d --- /dev/null +++ b/packages/clerk-js/src/ui.retheme/elements/utils.ts @@ -0,0 +1,22 @@ +// This function evenly distributes the strategies into rows (the inner arrays). +// This is done by calculating the number of necessary rows, then the amount of strategies in each row, and then distributing the strategies into the rows. +// Example of 5 strategies with max 3 per row: [ [1, 2, 3], [4, 5] ] +export function distributeStrategiesIntoRows(strategies: T[], maxStrategiesPerRow: number): T[][] { + if (strategies.length <= maxStrategiesPerRow) return [strategies]; + + const numRows = Math.ceil(strategies.length / maxStrategiesPerRow); + const strategiesPerRow = Math.ceil(strategies.length / numRows); + const rows: T[][] = Array.from({ length: numRows }, () => []); + + let currentArrayIndex = 0; + + for (const strategy of strategies) { + rows[currentArrayIndex].push(strategy); + + if (rows[currentArrayIndex].length === strategiesPerRow) { + currentArrayIndex++; + } + } + + return rows; +} diff --git a/packages/clerk-js/src/ui.retheme/foundations/sizes.ts b/packages/clerk-js/src/ui.retheme/foundations/sizes.ts index 0bdaa9c2e8..27c4f7ae85 100644 --- a/packages/clerk-js/src/ui.retheme/foundations/sizes.ts +++ b/packages/clerk-js/src/ui.retheme/foundations/sizes.ts @@ -16,6 +16,7 @@ const dynamicSpaceUnits = Object.freeze({ '5': '1.25rem', '6': '1.5rem', '7': '1.75rem', + '7x5': '1.875rem', '8': '2rem', '9': '2.25rem', '9x5': '2.375rem', diff --git a/packages/clerk-js/src/ui.retheme/hooks/index.ts b/packages/clerk-js/src/ui.retheme/hooks/index.ts index d0527e8808..5679be23e3 100644 --- a/packages/clerk-js/src/ui.retheme/hooks/index.ts +++ b/packages/clerk-js/src/ui.retheme/hooks/index.ts @@ -12,6 +12,7 @@ export * from './usePasswordComplexity'; export * from './usePopover'; export * from './usePrefersReducedMotion'; export * from './useLocalStorage'; +export * from './useResizeObserver'; export * from './useSafeState'; export * from './useSearchInput'; export * from './useDebounce'; diff --git a/packages/clerk-js/src/ui.retheme/hooks/useResizeObserver.ts b/packages/clerk-js/src/ui.retheme/hooks/useResizeObserver.ts new file mode 100644 index 0000000000..f861ea78e5 --- /dev/null +++ b/packages/clerk-js/src/ui.retheme/hooks/useResizeObserver.ts @@ -0,0 +1,57 @@ +import { useEffect, useMemo, useRef, useState } from 'react'; + +type ObserverRect = Omit; + +export function useResizeObserver() { + const frameID = useRef(0); + const ref = useRef(null); + + const [rect, setRect] = useState({ + x: 0, + y: 0, + width: 0, + height: 0, + top: 0, + left: 0, + bottom: 0, + right: 0, + }); + + const observer = useMemo( + () => + typeof window !== 'undefined' + ? new ResizeObserver((entries: any) => { + const entry = entries[0]; + + if (entry) { + cancelAnimationFrame(frameID.current); + + frameID.current = requestAnimationFrame(() => { + if (ref.current) { + setRect(ref.current.getBoundingClientRect()); + } + }); + } + }) + : null, + [], + ); + + useEffect(() => { + if (ref.current) { + observer?.observe(ref.current); + } + + return () => { + observer?.disconnect(); + + if (frameID.current) { + cancelAnimationFrame(frameID.current); + } + }; + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ref.current]); + + return [ref, rect] as const; +} diff --git a/packages/clerk-js/src/ui.retheme/primitives/Button.tsx b/packages/clerk-js/src/ui.retheme/primitives/Button.tsx index fefb5e3b7b..feafa10a8a 100644 --- a/packages/clerk-js/src/ui.retheme/primitives/Button.tsx +++ b/packages/clerk-js/src/ui.retheme/primitives/Button.tsx @@ -1,13 +1,12 @@ import React from 'react'; -import { Icon } from '../customizables'; +import { descriptors, Icon, Spinner } from '../customizables'; import { ArrowRightButtonIcon } from '../icons'; import type { PrimitiveProps, StyleVariants } from '../styledSystem'; import { common, createCssVariables, createVariants } from '../styledSystem'; import { colors } from '../utils'; import { applyDataStateProps } from './applyDataStateProps'; import { Flex } from './Flex'; -import { Spinner } from './Spinner'; const vars = createCssVariables('accent', 'accentDark', 'accentDarker', 'accentLighter', 'accentLightest', 'border'); @@ -62,11 +61,11 @@ const { applyVariants, filterProps } = createVariants((theme, props: OwnProps) = }, neutral: { [vars.border]: theme.colors.$blackAlpha200, - [vars.accentLightest]: theme.colors.$blackAlpha50, - [vars.accentLighter]: theme.colors.$blackAlpha300, - [vars.accent]: theme.colors.$colorText, - [vars.accentDark]: theme.colors.$blackAlpha600, - [vars.accentDarker]: theme.colors.$blackAlpha700, + [vars.accentLightest]: theme.colors.$blackAlpha50, // TODO: once we have the new color palette and style for pseudo classes + [vars.accentLighter]: theme.colors.$blackAlpha300, // TODO: once we have the new color palette and style for pseudo classes + [vars.accent]: theme.colors.$primary800, // WIP reference: Updated to new color palette; previously `$colorText` + [vars.accentDark]: theme.colors.$blackAlpha600, // TODO: once we have the new color palette and style for pseudo classes + [vars.accentDarker]: theme.colors.$blackAlpha700, // TODO: once we have the new color palette and style for pseudo classes }, }, variant: { @@ -87,9 +86,9 @@ const { applyVariants, filterProps } = createVariants((theme, props: OwnProps) = }, }, outline: { - border: theme.borders.$normal, - borderColor: vars.accentLighter, color: vars.accent, + boxShadow: + '0px 2px 3px -1px rgba(0, 0, 0, 0.08), 0px 1px 0px 0px rgba(25, 28, 33, 0.02), 0px 0px 0px 1px rgba(25, 28, 33, 0.08)', // TODO: Move to theme once we have the shadows defined '&:hover': { backgroundColor: vars.accentLightest }, '&:focus': props.hoverAsFocus ? { backgroundColor: vars.accentLightest } : undefined, '&:active': { backgroundColor: vars.accentLighter }, @@ -102,9 +101,8 @@ const { applyVariants, filterProps } = createVariants((theme, props: OwnProps) = }, icon: { color: vars.accent, - border: theme.borders.$normal, - borderRadius: theme.radii.$lg, - borderColor: vars.border, + boxShadow: + '0px 2px 3px -1px rgba(0, 0, 0, 0.08), 0px 1px 0px 0px rgba(25, 28, 33, 0.02), 0px 0px 0px 1px rgba(25, 28, 33, 0.08)', // TODO: Move to theme once we have the shadows defined '&:hover': { backgroundColor: vars.accentLightest }, '&:focus': props.hoverAsFocus ? { backgroundColor: vars.accentLightest } : undefined, '&:active': { backgroundColor: vars.accentLighter }, @@ -201,8 +199,11 @@ const Button = React.forwardRef((props, ref) => }} > {loadingText || {children}}