TRCL-3535 Add green/red preference to display modal (#261)

* add functionality, without user exposure yet

* fix commit history

* remove unnecessary change

* lint

* update css

* audit of pos/neg colors

* fix flipping of disconnect/export keys colors

* review comments

* clean up naming of icon

* fix icon sizing

* small edit to story example
This commit is contained in:
moo-onthelawn
2024-02-01 19:22:42 -05:00
committed by mulan xia
parent eacab6ae04
commit dd941a543e
23 changed files with 186 additions and 43 deletions
+3 -3
View File
@@ -102,13 +102,13 @@ const buttonActionVariants = {
[ButtonAction.Create]: css`
--button-textColor: var(--color-text-2);
--button-backgroundColor: var(--color-positive);
--button-backgroundColor: var(--color-success);
--button-border: solid var(--border-width) var(--color-border-white);
`,
[ButtonAction.Destroy]: css`
--button-textColor: var(--color-text-2);
--button-backgroundColor: var(--color-negative);
--button-backgroundColor: var(--color-error);
--button-border: solid var(--border-width) var(--color-border-white);
`,
@@ -119,7 +119,7 @@ const buttonActionVariants = {
`,
[ButtonAction.Reset]: css`
--button-textColor: var(--color-negative);
--button-textColor: var(--color-error);
--button-backgroundColor: var(--color-layer-3);
--button-border: solid var(--border-width) var(--color-border-red);
`,
+2 -2
View File
@@ -87,7 +87,7 @@ Styled.Icon = styled(Icon)<{ copied: boolean }>`
${({ copied }) =>
copied &&
css`
color: var(--color-positive);
color: var(--color-success);
`}
`;
@@ -96,7 +96,7 @@ Styled.IconButton = styled(IconButton)<{ copied: boolean }>`
copied &&
css`
svg {
color: var(--color-positive);
color: var(--color-success);
}
`}
`;
+1 -1
View File
@@ -62,6 +62,6 @@ Styled.DiffArrowContainer = styled.span<DiffArrowProps>`
`,
down: css`
transform: rotate(90deg);
`
`,
}[direction || 'right'])}
`;
+1 -1
View File
@@ -75,7 +75,7 @@ Styled.DiffValue = styled.div<{ hasInvalidNewValue?: boolean }>`
${({ hasInvalidNewValue }) =>
hasInvalidNewValue &&
css`
color: var(--color-negative);
color: var(--color-error);
`}
`;
+12 -7
View File
@@ -6,29 +6,34 @@ import { StoryWrapper } from '.ladle/components';
export const DropdownMenuStory: Story<Parameters<typeof DropdownMenu>> = (args) => {
const exampleItems = [
{
value: '0',
label: 'Item 0',
onSelect: () => alert('Item 0 action'),
},
{
value: '1',
label: 'Item 1',
label: 'Item 1 (accent)',
onSelect: () => alert('Item 1 action'),
highlightColor: 'accent',
},
{
value: '2',
label: 'Item 2',
label: 'Item 2 (create)',
onSelect: () => alert('Item 2 action'),
highlightColor: 'create',
},
{
value: '3',
label: 'Item 3',
label: 'Item 3 (destroy)',
onSelect: () => alert('Item 3 action'),
highlightColor: 'destroy',
},
];
return (
<StoryWrapper>
<DropdownMenu
{...args}
items={exampleItems}
>
<DropdownMenu {...args} items={exampleItems}>
<span>Menu</span>
</DropdownMenu>
</StoryWrapper>
+6 -6
View File
@@ -13,7 +13,7 @@ export type DropdownMenuItem<T> = {
label: React.ReactNode;
onSelect?: () => void;
separator?: boolean;
highlightColor?: 'accent' | 'positive' | 'negative';
highlightColor?: 'accent' | 'create' | 'destroy';
};
type StyleProps = {
@@ -82,7 +82,7 @@ Styled.Separator = styled(Separator)`
margin: 0.25rem 1rem;
`;
Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'positive' | 'negative' }>`
Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'create' | 'destroy' }>`
${popoverMixins.item}
--item-font-size: var(--dropdownMenu-item-font-size);
${({ $highlightColor }) =>
@@ -90,11 +90,11 @@ Styled.Item = styled(Item)<{ $highlightColor: 'accent' | 'positive' | 'negative'
['accent']: `
--item-highlighted-textColor: var(--color-accent);
`,
['positive']: `
--item-highlighted-textColor: var(--color-positive);
['create']: `
--item-highlighted-textColor: var(--color-success);
`,
['negative']: `
--item-highlighted-textColor: var(--color-negative);
['destroy']: `
--item-highlighted-textColor: var(--color-error);
`,
}[$highlightColor])}
+2 -2
View File
@@ -117,7 +117,7 @@ Styled.ConfirmButton = styled(Styled.IconButton)`
--button-backgroundColor: hsla(203, 25%, 19%, 1);
svg {
color: var(--color-positive);
color: var(--color-success);
}
`;
@@ -125,7 +125,7 @@ Styled.CancelButton = styled(Styled.IconButton)`
--button-backgroundColor: hsla(296, 16%, 18%, 1);
svg {
color: var(--color-negative);
color: var(--color-error);
width: 0.8em;
height: 0.8em;
+3
View File
@@ -54,6 +54,9 @@ type StatusColors = {
success: string;
warning: string;
error: string;
successFaded: string;
warningFaded: string;
errorFaded: string;
};
/** ##InvertDirectionalColors
+1 -1
View File
@@ -127,7 +127,7 @@ Styled.StatusDot = styled.div<{ exchangeStatus: ExchangeStatus }>`
background-color: ${({ exchangeStatus }) =>
({
[ExchangeStatus.Degraded]: css`var(--color-warning)`,
[ExchangeStatus.Operational]: css`var(--color-positive)`,
[ExchangeStatus.Operational]: css`var(--color-success)`,
}[exchangeStatus])};
`;
+3 -3
View File
@@ -43,19 +43,19 @@ export const getStatusIconInfo = ({
case AbacusOrderStatus.filled: {
return {
statusIcon: IconName.OrderFilled,
statusIconColor: `var(--color-positive)`,
statusIconColor: `var(--color-success)`,
};
}
case AbacusOrderStatus.cancelled: {
return {
statusIcon: IconName.OrderCanceled,
statusIconColor: `var(--color-negative)`,
statusIconColor: `var(--color-error)`,
};
}
case AbacusOrderStatus.canceling: {
return {
statusIcon: IconName.OrderPending,
statusIconColor: `var(--color-negative)`,
statusIconColor: `var(--color-error)`,
};
}
case AbacusOrderStatus.untriggered: {
+3 -3
View File
@@ -286,10 +286,10 @@ Styled.ConnectedIcon = styled.div`
height: 0.5rem;
width: 0.5rem;
margin-right: 0.25rem;
background: var(--color-positive);
background: var(--color-success);
border-radius: 50%;
box-shadow: 0 0 0 0.2rem var(--color-gradient-positive);
box-shadow: 0 0 0 0.2rem var(--color-gradient-success);
`;
Styled.Address = styled.h1`
@@ -318,7 +318,7 @@ Styled.ActionButton = styled(IconButton)<{ iconName?: IconName }>`
${({ iconName }) =>
iconName === IconName.Close
? css`
--button-textColor: var(--color-negative);
--button-textColor: var(--color-error);
--button-icon-size: 0.75em;
`
: iconName === IconName.Transfer &&
+3
View File
@@ -29,6 +29,9 @@ export const GlobalStyle = createGlobalStyle`
--color-success: ${({ theme }) => theme.success};
--color-warning: ${({ theme }) => theme.warning};
--color-error: ${({ theme }) => theme.error};
--color-gradient-success: ${({ theme }) => theme.successFaded};
--color-gradient-warning: ${({ theme }) => theme.warningFaded};
--color-gradient-error: ${({ theme }) => theme.errorFaded};
--color-positive: ${({ theme }) => theme.positive};
--color-negative: ${({ theme }) => theme.negative};
+9
View File
@@ -31,6 +31,9 @@ const ClassicThemeBase: ThemeColorBase = {
success: ColorToken.Green1,
warning: ColorToken.Yellow0,
error: ColorToken.Red2,
successFaded: generateFadedColorVariant(ColorToken.Green1, OpacityToken.Opacity16),
warningFaded: generateFadedColorVariant(ColorToken.Yellow0, OpacityToken.Opacity16),
errorFaded: generateFadedColorVariant(ColorToken.Red2, OpacityToken.Opacity16),
positive: ColorToken.Green1,
negative: ColorToken.Red2,
@@ -80,6 +83,9 @@ const DarkThemeBase: ThemeColorBase = {
success: ColorToken.Green0,
warning: ColorToken.Yellow0,
error: ColorToken.Red0,
successFaded: generateFadedColorVariant(ColorToken.Green0, OpacityToken.Opacity16),
warningFaded: generateFadedColorVariant(ColorToken.Yellow0, OpacityToken.Opacity16),
errorFaded: generateFadedColorVariant(ColorToken.Red0, OpacityToken.Opacity16),
positive: ColorToken.Green0,
negative: ColorToken.Red0,
@@ -129,6 +135,9 @@ const LightThemeBase: ThemeColorBase = {
success: ColorToken.Green2,
warning: ColorToken.Yellow0,
error: ColorToken.Red1,
successFaded: generateFadedColorVariant(ColorToken.Green2, OpacityToken.Opacity16),
warningFaded: generateFadedColorVariant(ColorToken.Yellow0, OpacityToken.Opacity16),
errorFaded: generateFadedColorVariant(ColorToken.Red1, OpacityToken.Opacity16),
positive: ColorToken.Green2,
negative: ColorToken.Red1,
@@ -231,7 +231,7 @@ Styled.CircleContainer = styled.div`
`;
Styled.Icon = styled(Icon)`
color: var(--color-negative);
color: var(--color-error);
`;
Styled.WithUsage = styled.div`
+3 -3
View File
@@ -557,11 +557,11 @@ Styled.PositionTile = styled(PositionTile)``;
Styled.ClosePositionButton = styled(Button)`
--button-border: solid var(--border-width) var(--color-border-red);
--button-textColor: var(--color-negative);
--button-textColor: var(--color-error);
`;
Styled.ClosePositionToggleButton = styled(ToggleButton)`
--button-border: solid var(--border-width) var(--color-border-red);
--button-toggle-off-textColor: var(--color-negative);
--button-toggle-on-textColor: var(--color-negative);
--button-toggle-off-textColor: var(--color-error);
--button-toggle-on-textColor: var(--color-error);
`;
+125 -2
View File
@@ -5,7 +5,7 @@ import { Root, Item, Indicator } from '@radix-ui/react-radio-group';
import { useStringGetter } from '@/hooks';
import { AppTheme, AppColorMode, setAppTheme } from '@/state/configs';
import { AppTheme, AppColorMode, setAppTheme, setAppColorMode } from '@/state/configs';
import { getAppTheme, getAppColorMode } from '@/state/configsSelectors';
import { layoutMixins } from '@/styles/layoutMixins';
@@ -76,6 +76,48 @@ export const DisplaySettingsDialog = ({ setIsOpen }: ElementProps) => {
);
};
const colorModeOptions = () => {
return (
<Styled.ColorPreferenceRoot value={currentColorMode}>
{[
{
colorMode: AppColorMode.GreenUp,
label: STRING_KEYS.GREEN_IS_UP,
},
{
colorMode: AppColorMode.RedUp,
label: STRING_KEYS.RED_IS_UP,
},
].map(({ colorMode, label }) => (
<Styled.ColorPreferenceItem
key={colorMode}
value={colorMode}
onClick={() => {
dispatch(setAppColorMode(colorMode));
}}
>
<Styled.ColorPreferenceLabel>
<Styled.ArrowIconContainer>
<Styled.ArrowIcon
iconName={IconName.Arrow}
direction="up"
color={colorMode === AppColorMode.GreenUp ? 'green' : 'red'}
/>
<Styled.ArrowIcon
iconName={IconName.Arrow}
direction="down"
color={colorMode === AppColorMode.GreenUp ? 'red' : 'green'}
/>
</Styled.ArrowIconContainer>
{stringGetter({ key: label })}
</Styled.ColorPreferenceLabel>
<Styled.DotIndicator $selected={currentColorMode === colorMode} />
</Styled.ColorPreferenceItem>
))}
</Styled.ColorPreferenceRoot>
);
};
return (
<Dialog
isOpen
@@ -86,6 +128,10 @@ export const DisplaySettingsDialog = ({ setIsOpen }: ElementProps) => {
{sectionHeader(stringGetter({ key: STRING_KEYS.THEME }))}
{themePanels()}
</Styled.Section>
<Styled.Section>
{sectionHeader(stringGetter({ key: STRING_KEYS.DIRECTION_COLOR_PREFERENCE }))}
{colorModeOptions()}
</Styled.Section>
</Dialog>
);
};
@@ -111,6 +157,11 @@ Styled.AppThemeRoot = styled(Root)`
grid-template-columns: 1fr 1fr;
`;
Styled.ColorPreferenceRoot = styled(Root)`
${gridStyle}
grid-template-columns: 1fr;
`;
Styled.Item = styled(Item)`
--border-color: var(--color-border);
--item-padding: 0.75rem;
@@ -121,9 +172,19 @@ Styled.Item = styled(Item)`
border: solid var(--border-width) var(--border-color);
border-radius: 0.875rem;
padding: var(--item-padding);
`;
Styled.ColorPreferenceItem = styled(Styled.Item)`
&[data-state='checked'] {
background-color: var(--color-layer-4);
}
${layoutMixins.row}
justify-content: space-between;
`;
Styled.AppThemeItem = styled(Styled.Item)<{ backgroundcolor: string; gridcolor: string }>`
${({ backgroundcolor, gridcolor }) => css`
--themePanel-backgroundColor: ${backgroundcolor};
@@ -134,6 +195,7 @@ Styled.AppThemeItem = styled(Styled.Item)<{ backgroundcolor: string; gridcolor:
flex-direction: column;
position: relative;
width: 100%;
background-color: var(--themePanel-backgroundColor);
&::before {
@@ -170,6 +232,43 @@ Styled.Image = styled.img`
z-index: 1;
`;
Styled.ColorPreferenceLabel = styled.div`
${layoutMixins.inlineRow};
gap: 1ch;
`;
Styled.ArrowIconContainer = styled.div`
${layoutMixins.column}
gap: 0.5ch;
svg {
height: 0.75em;
width: 0.75em;
}
`;
Styled.ArrowIcon = styled(Icon)<{ direction: 'up' | 'down'; color: 'green' | 'red' }>`
${({ direction }) =>
({
['up']: css`
transform: rotate(-90deg);
`,
['down']: css`
transform: rotate(90deg);
`,
}[direction])}
${({ color }) =>
({
['green']: css`
color: var(--color-success);
`,
['red']: css`
color: var(--color-error);
`,
}[color])}
`;
const indicatorStyle = css`
--indicator-size: 1.25rem;
--icon-size: 0.5rem;
@@ -183,9 +282,33 @@ const indicatorStyle = css`
justify-content: center;
`;
Styled.DotIndicator = styled.div<{ $selected: boolean }>`
${indicatorStyle}
--background-color: var(--color-layer-2);
--border-color: var(--color-border);
${({ $selected }) =>
$selected &&
css`
--background-color: var(--color-accent);
--border-color: var(--color-accent);
&::after {
content: '';
display: block;
width: var(--icon-size);
height: var(--icon-size);
background-color: var(--color-layer-2);
border-radius: 50%;
}
`}
background-color: var(--background-color);
border: solid var(--border-width) var(--border-color);
`;
Styled.CheckIndicator = styled(Indicator)`
${indicatorStyle}
position: absolute;
bottom: var(--item-padding);
right: var(--item-padding);
@@ -323,7 +323,7 @@ Styled.ReceiptArea = styled.div`
`;
Styled.Green = styled.span`
color: var(--color-positive);
color: var(--color-success);
`;
Styled.GreenCheckCircle = styled(GreenCheckCircle)`
@@ -453,6 +453,6 @@ Styled.FormInputButton = styled(Button)`
Styled.CheckIcon = styled(Icon)`
margin: 0 1ch;
color: var(--color-positive);
color: var(--color-success);
font-size: 0.625rem;
`;
+1 -1
View File
@@ -441,7 +441,7 @@ Styled.DestinationInputLabel = styled.span`
${layoutMixins.inlineRow}
svg {
color: var(--color-positive);
color: var(--color-success);
}
`;
+2 -2
View File
@@ -203,7 +203,7 @@ export const AccountMenu = () => {
value: 'MnemonicExport',
icon: <Icon iconName={IconName.ExportKeys} />,
label: <span>{stringGetter({ key: STRING_KEYS.EXPORT_SECRET_PHRASE })}</span>,
highlightColor: 'negative',
highlightColor: 'destroy',
onSelect: () => dispatch(openDialog({ type: DialogTypes.MnemonicExport })),
},
].filter(isTruthy)
@@ -212,7 +212,7 @@ export const AccountMenu = () => {
value: 'Disconnect',
icon: <Icon iconName={IconName.BoxClose} />,
label: stringGetter({ key: STRING_KEYS.DISCONNECT }),
highlightColor: 'negative',
highlightColor: 'destroy',
onSelect: () => dispatch(openDialog({ type: DialogTypes.DisconnectWallet })),
},
].filter(isTruthy)}
@@ -72,7 +72,7 @@ Styled.Notification = styled(Notification)`
Styled.Output = styled(Output)`
&:before {
content: '+';
color: var(--color-positive);
color: var(--color-success);
margin-right: 0.5ch;
}
`;
@@ -179,7 +179,7 @@ Styled.Icon = styled.div<{ state: 'complete' | 'default' }>`
${({ state }) =>
({
['complete']: css`
color: var(--color-positive);
color: var(--color-success);
`,
['default']: css`
color: var(--color-text-0);
@@ -82,6 +82,6 @@ Styled.ActionButton = styled(IconButton)`
Styled.CancelButton = styled(Styled.ActionButton)`
&:not(:disabled) {
--button-textColor: var(--color-negative);
--button-textColor: var(--color-error);
}
`;