Skip to content

Commit

Permalink
refactor(ds): Refactor Button with double background
Browse files Browse the repository at this point in the history
  • Loading branch information
jvaclavik committed Sep 27, 2024
1 parent 91123a2 commit 6beb2cb
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 30 deletions.
16 changes: 15 additions & 1 deletion packages/components/src/components/Banner/Banner.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,23 @@ export const Banner: StoryObj<BannerProps> = {
},
},
rightContent: {
options: ['nothing', 'button', 'combinedButtons', 'iconButton', 'iconButtons'],
options: [
'nothing',
'button',
'buttons',
'combinedButtons',
'iconButton',
'iconButtons',
],
mapping: {
nothing: undefined,
button: <BannerComponent.Button>Button</BannerComponent.Button>,
buttons: (
<Row gap={8}>
<BannerComponent.Button>Button 1</BannerComponent.Button>
<BannerComponent.Button isSubtle>Button 2</BannerComponent.Button>
</Row>
),
combinedButtons: (
<Row gap={8}>
<BannerComponent.Button>Button 1</BannerComponent.Button>
Expand All @@ -79,6 +92,7 @@ export const Banner: StoryObj<BannerProps> = {
labels: {
nothing: 'undefined',
button: '1 button',
buttons: '2 buttons',
combinedButtons: 'buttons and icon button',
iconButton: '1 icon button',
iconButtons: '2 icon buttons',
Expand Down
99 changes: 70 additions & 29 deletions packages/components/src/components/buttons/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { ButtonHTMLAttributes } from 'react';
import styled, { useTheme } from 'styled-components';
import { borders, Elevation, spacingsPx, typography } from '@trezor/theme';
import styled, { css, useTheme } from 'styled-components';
import {
borders,
Color,
CSSColor,
Elevation,
mapElevationToBackgroundToken,
spacingsPx,
typography,
} from '@trezor/theme';
import { Spinner } from '../../loaders/Spinner/Spinner';
import {
ButtonSize,
Expand All @@ -21,6 +29,7 @@ import {
} from '../../../utils/frameProps';
import { Icon, IconName } from '../../Icon/Icon';
import { useElevation } from '../../ElevationContext/ElevationContext';
import { BannerVariant } from '../../Banner/types';

export const allowedButtonFrameProps = [
'margin',
Expand All @@ -31,38 +40,65 @@ type AllowedFrameProps = Pick<FrameProps, (typeof allowedButtonFrameProps)[numbe

export type IconOrComponent = IconName | JSX.Element;

type ButtonContainerProps = TransientProps<AllowedFrameProps> & {
$elevation: Elevation;
$variant: ButtonVariant;
const SubtleContainer = styled.div<{
$size: ButtonSize;
$iconAlignment?: IconAlignment;
$hasIcon?: boolean;
$isFullWidth?: boolean;
$elevation: Elevation;
$variant: ButtonVariant;
$isSubtle: boolean;
as?: 'a' | 'button';
$borderRadius?: typeof borders.radii.sm | typeof borders.radii.full; // Do not allow all, we want consistency
};

export const ButtonContainer = styled.button<ButtonContainerProps>`
}>`
display: flex;
align-items: center;
justify-content: center;
flex-direction: ${({ $iconAlignment }) => $iconAlignment === 'right' && 'row-reverse'};
gap: ${({ $hasIcon }) => $hasIcon && spacingsPx.xs};
padding: ${({ $size }) => getPadding($size, true)};
flex: 1;
${({ $variant, $isSubtle, $elevation }) => useVariantStyle($variant, $isSubtle, $elevation)}
border: 1px solid transparent;
`;

type ButtonContainerProps = TransientProps<AllowedFrameProps> & {
$isFullWidth?: boolean;
as?: 'a' | 'button';
$borderRadius?: typeof borders.radii.sm | typeof borders.radii.full; // Do not allow all, we want consistency
$isSubtle: boolean;
$variant: ButtonVariant;
};

export const mapVariantToSurfaceColor = ({ $variant, theme }: any): CSSColor => {
const colorMap: Record<Partial<ButtonVariant>, Color> = {
info: 'backgroundAlertBlueSubtleOnElevation0',
warning: 'backgroundAlertYellowSubtleOnElevation0',
destructive: 'backgroundAlertRedSubtleOnElevation0',
};

return theme[colorMap[$variant]];
};

export const ButtonContainer = styled.button<ButtonContainerProps>`
display: flex;
width: ${({ $isFullWidth }) => ($isFullWidth ? '100%' : 'fit-content')};
border-radius: ${({ $borderRadius }) => $borderRadius ?? borders.radii.full};
transition:
${focusStyleTransition},
background 0.1s ease-out;
outline: none;
cursor: pointer;
border: 1px solid transparent;
overflow: hidden;
border: none;
${getFocusShadowStyle()}
${({ $variant, $isSubtle, $elevation }) => useVariantStyle($variant, $isSubtle, $elevation)}
${({ $isSubtle, theme, $variant }) =>
$isSubtle &&
css`
background: ${mapVariantToSurfaceColor({ $variant, theme })};
`}
${getFocusShadowStyle('> div:focus-visible')}
&:disabled {
&:disabled > ${SubtleContainer} {
background: ${({ theme }) => theme.backgroundNeutralDisabled};
color: ${({ theme }) => theme.textDisabled};
cursor: not-allowed;
Expand Down Expand Up @@ -185,13 +221,7 @@ export const Button = ({

return (
<ButtonContainer
$elevation={elevation}
$hasIcon={!!icon || isLoading}
$iconAlignment={iconAlignment}
$isFullWidth={isFullWidth}
$isSubtle={isSubtle}
$size={size}
$variant={variant}
as={isLink ? 'a' : 'button'}
className={className}
data-testid={dataTestId}
Expand All @@ -204,16 +234,27 @@ export const Button = ({
target={isLink ? target || '_blank' : undefined}
title={title}
type={type}
$isSubtle={isSubtle}
$variant={variant}
{...frameProps}
>
{!isLoading && icon && IconComponent}
{isLoading && Loader}

{children && (
<Content $size={size} $disabled={isDisabled || isLoading} $textWrap={textWrap}>
{children}
</Content>
)}
<SubtleContainer
$size={size}
$elevation={elevation}
$isSubtle={isSubtle}
$variant={variant}
$iconAlignment={iconAlignment}
$hasIcon={!!icon || isLoading}
>
{!isLoading && icon && IconComponent}
{isLoading && Loader}

{children && (
<Content $size={size} $disabled={isDisabled || isLoading} $textWrap={textWrap}>
{children}
</Content>
)}
</SubtleContainer>
</ButtonContainer>
);
};

0 comments on commit 6beb2cb

Please sign in to comment.