From eee19b3b9343c7ac70b9efc3363a7f4eb8bc886e Mon Sep 17 00:00:00 2001 From: mulan xia Date: Fri, 26 Jan 2024 17:06:14 -0500 Subject: [PATCH] wip --- public/chart-bars-background.svg | 19 +++ public/chart-bars.svg | 20 +++ src/components/Panel.stories.tsx | 8 +- src/components/Panel.tsx | 8 +- src/constants/dialogs.ts | 1 + src/layout/DialogManager.tsx | 2 + src/views/dialogs/DisplaySettingsDialog.tsx | 171 ++++++++++++++++++++ src/views/menus/AccountMenu.tsx | 9 ++ 8 files changed, 232 insertions(+), 6 deletions(-) create mode 100644 public/chart-bars-background.svg create mode 100644 public/chart-bars.svg create mode 100644 src/views/dialogs/DisplaySettingsDialog.tsx diff --git a/public/chart-bars-background.svg b/public/chart-bars-background.svg new file mode 100644 index 0000000..a8df022 --- /dev/null +++ b/public/chart-bars-background.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/chart-bars.svg b/public/chart-bars.svg new file mode 100644 index 0000000..9a2e431 --- /dev/null +++ b/public/chart-bars.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/Panel.stories.tsx b/src/components/Panel.stories.tsx index ecdb993..1ef7d85 100644 --- a/src/components/Panel.stories.tsx +++ b/src/components/Panel.stories.tsx @@ -1,10 +1,10 @@ import type { Story } from '@ladle/react'; -import { Panel } from '@/components/Panel'; +import { Panel, PanelProps } from '@/components/Panel'; import { StoryWrapper } from '.ladle/components'; -export const PanelStory: Story<{ slotHeader: React.ReactNode, children?: React.ReactNode }> = (args) => { +export const PanelStory: Story = (args) => { return ( @@ -13,6 +13,8 @@ export const PanelStory: Story<{ slotHeader: React.ReactNode, children?: React.R }; PanelStory.args = { - slotHeader: 'Header', + slotHeaderContent: 'Header', children: 'Content', + slotRight: '1️⃣', + hasSeparator: true, }; diff --git a/src/components/Panel.tsx b/src/components/Panel.tsx index cebd1d7..1ea335f 100644 --- a/src/components/Panel.tsx +++ b/src/components/Panel.tsx @@ -6,7 +6,7 @@ import { Icon, IconName } from '@/components/Icon'; import { layoutMixins } from '@/styles/layoutMixins'; import { breakpoints } from '@/styles'; -type PanelProps = { +type ElementProps = { slotHeaderContent?: React.ReactNode; slotHeader?: React.ReactNode; slotRight?: React.ReactNode; @@ -16,11 +16,13 @@ type PanelProps = { onClick?: () => void; }; -type PanelStyleProps = { +type StyleProps = { className?: string; hasSeparator?: boolean; }; +export type PanelProps = ElementProps & StyleProps; + export const Panel = ({ slotHeaderContent, slotHeader, @@ -31,7 +33,7 @@ export const Panel = ({ onClick, hasSeparator, className, -}: PanelProps & PanelStyleProps) => ( +}: PanelProps) => ( {href ? ( diff --git a/src/constants/dialogs.ts b/src/constants/dialogs.ts index e5cf8fd..bad393c 100644 --- a/src/constants/dialogs.ts +++ b/src/constants/dialogs.ts @@ -2,6 +2,7 @@ export enum DialogTypes { ClosePosition = 'ClosePosition', Deposit = 'Deposit', DisconnectWallet = 'DisconnectWallet', + DisplaySettings = 'DisplaySettings', ExchangeOffline = 'ExchangeOffline', ExternalLink = 'ExternalLink', FillDetails = 'FillDetails', diff --git a/src/layout/DialogManager.tsx b/src/layout/DialogManager.tsx index d7145ae..04406cc 100644 --- a/src/layout/DialogManager.tsx +++ b/src/layout/DialogManager.tsx @@ -9,6 +9,7 @@ import { getActiveDialog } from '@/state/dialogsSelectors'; import { ClosePositionDialog } from '@/views/dialogs/ClosePositionDialog'; import { DepositDialog } from '@/views/dialogs/DepositDialog'; import { DisconnectDialog } from '@/views/dialogs/DisconnectDialog'; +import { DisplaySettingsDialog } from '@/views/dialogs/DisplaySettingsDialog'; import { ExchangeOfflineDialog } from '@/views/dialogs/ExchangeOfflineDialog'; import { HelpDialog } from '@/views/dialogs/HelpDialog'; import { ExternalLinkDialog } from '@/views/dialogs/ExternalLinkDialog'; @@ -51,6 +52,7 @@ export const DialogManager = () => { return { [DialogTypes.ClosePosition]: , [DialogTypes.Deposit]: , + [DialogTypes.DisplaySettings]: , [DialogTypes.DisconnectWallet]: , [DialogTypes.ExchangeOffline]: , [DialogTypes.FillDetails]: , diff --git a/src/views/dialogs/DisplaySettingsDialog.tsx b/src/views/dialogs/DisplaySettingsDialog.tsx new file mode 100644 index 0000000..67fdc83 --- /dev/null +++ b/src/views/dialogs/DisplaySettingsDialog.tsx @@ -0,0 +1,171 @@ +import { useDispatch, useSelector } from 'react-redux'; +import styled, { AnyStyledComponent, css } from 'styled-components'; + +import { Root, Item, Indicator } from '@radix-ui/react-radio-group'; + +import { AppTheme, setAppTheme } from '@/state/configs'; +import { getAppTheme } from '@/state/configsSelectors'; + +import { layoutMixins } from '@/styles/layoutMixins'; +import { Themes } from '@/styles/themes'; + +import { STRING_KEYS } from '@/constants/localization'; + +import { Icon, IconName } from '@/components/Icon'; + +import { Panel } from '@/components/Panel'; + +import { + useStringGetter, + } from '@/hooks'; + +import { Dialog } from '@/components/Dialog'; +import { HorizontalSeparatorFiller } from '@/components/Separator'; + +type ElementProps = { + setIsOpen: (open: boolean) => void; + }; + +export const DisplaySettingsDialog = ({ setIsOpen }: ElementProps) => { + const dispatch = useDispatch(); + const stringGetter = useStringGetter(); + + const currentTheme: AppTheme = useSelector(getAppTheme); + + const sectionHeader = (heading: string) => { + return ( + + { heading } + + + ); + }; + + const themePanels = () => { + return ( + + {[{ + theme: AppTheme.Classic, + label: STRING_KEYS.CLASSIC_DARK + }, { + theme: AppTheme.Dark, + label: STRING_KEYS.DARK + }, { + theme: AppTheme.Light, + label: STRING_KEYS.LIGHT + }].map(({theme, label}) => ( + + { + dispatch(setAppTheme(theme)); + }} + slotHeader={{stringGetter({ key: label })}} + > + + + + + + + ))} + + ) + } + + return ( + + + {sectionHeader(stringGetter({ key: STRING_KEYS.THEME }))} + {themePanels()} + + + ); +}; + +const Styled: Record = {}; + +Styled.Section = styled.div` + display: grid; + gap: 1.5rem; +`; + +Styled.Header = styled.header` + ${layoutMixins.inlineRow} +`; + +Styled.Root = styled(Root)` + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1.5rem; +`; + +Styled.Panel = styled(Panel)<{ backgroundColor: string, gridColor: string }>` + --panel-content-paddingY: 0.25rem; + --panel-content-paddingX: 0.25rem; + + ${({ backgroundColor, gridColor }) => css` + --themePanel-backgroundColor: ${backgroundColor}; + --themePanel-gridColor: ${gridColor}; + `} + + &:before { + content: ''; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + + background: radial-gradient(55% 35% at 50% 65%, transparent, var(--themePanel-backgroundColor) 100%); + background-color: var(--themePanel-gridColor); + mask-image: url('/chart-bars-background.svg'); + mask-size: cover; + } + + position: relative; + padding: 0.75rem; + + background-color: var(--themePanel-backgroundColor); + border: solid var(--border-width) var(--color-border); +`; + +Styled.PanelHeader = styled.h3<{ textColor: string }>` + ${({ textColor }) => css` + color: ${textColor}; + `} + + align-self: flex-start; +`; + +Styled.Image = styled.img` + width: 100%; + height: auto; +` + +Styled.Indicator = styled(Indicator)` + --indicator-size: 1.25rem; + + height: var(--indicator-size); + width: var(--indicator-size); + + position: absolute; + bottom: 0; + right: 0; + + display: flex; + align-items: center; + justify-content: center; + + background-color: var(--color-accent); + border-radius: 50%; + color: var(--color-text-2); +` + +Styled.CheckIcon = styled(Icon)` + --icon-size: 0.625rem; + + width: var(--icon-size); + height: var(--icon-size); +`; \ No newline at end of file diff --git a/src/views/menus/AccountMenu.tsx b/src/views/menus/AccountMenu.tsx index 2796a88..ac2ce49 100644 --- a/src/views/menus/AccountMenu.tsx +++ b/src/views/menus/AccountMenu.tsx @@ -32,9 +32,11 @@ import { Icon, IconName } from '@/components/Icon'; import { IconButton } from '@/components/IconButton'; import { WithTooltip } from '@/components/WithTooltip'; +import { AppTheme } from '@/state/configs'; import { openDialog } from '@/state/dialogs'; import { getOnboardingState, getSubaccount } from '@/state/accountSelectors'; +import { getAppTheme } from '@/state/configsSelectors'; import { isTruthy } from '@/lib/isTruthy'; import { truncateAddress } from '@/lib/wallet'; @@ -50,6 +52,7 @@ export const AccountMenu = () => { const { freeCollateral } = useSelector(getSubaccount, shallowEqual) || {}; const { nativeTokenBalance } = useAccountBalance(); const { usdcLabel, chainTokenLabel } = useTokenConfigs(); + const theme = useSelector(getAppTheme); const { evmAddress, walletType, dydxAddress, hdKey } = useAccounts(); @@ -177,6 +180,12 @@ export const AccountMenu = () => { label: stringGetter({ key: STRING_KEYS.PREFERENCES }), onSelect: () => dispatch(openDialog({ type: DialogTypes.Preferences })), }, + { + value: 'Display Settings', + icon: theme === AppTheme.Light ? : , + label: stringGetter({ key: STRING_KEYS.DISPLAY_SETTINGS }), + onSelect: () => dispatch(openDialog({ type: DialogTypes.DisplaySettings })), + }, ...(onboardingState === OnboardingState.AccountConnected && hdKey ? [ (!isMainnet || testFlags.showMobileSignInOption) && {