|
1 | 1 | import React, { forwardRef } from 'react';
|
2 |
| -import styled from 'styled-components'; |
| 2 | +import styled, { css } from 'styled-components'; |
3 | 3 |
|
4 | 4 | import { Colors, Radius, Spacings } from '../../foundations';
|
5 |
| -import { buttonReset } from '../../styles'; |
6 | 5 | import { Flex } from '../flex';
|
| 6 | +import { ButtonBase } from './ButtonBase'; |
7 | 7 | import { ButtonIcon, ButtonProvider, ButtonText, StyledIcon, StyledText } from './components';
|
8 | 8 |
|
9 | 9 | export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
10 | 10 | variant?: 'primary' | 'success' | 'destructive';
|
11 | 11 | size?: 'auto' | 'full' | '1/2';
|
12 | 12 | }
|
13 | 13 |
|
14 |
| -const variants = { |
15 |
| - primary: { |
16 |
| - background: Colors.blue, |
17 |
| - hover: Colors.blue60, |
18 |
| - disabled: Colors.blue50, |
| 14 | +const styles = { |
| 15 | + radius: Radius.radius4, |
| 16 | + variants: { |
| 17 | + primary: { |
| 18 | + background: Colors.blue, |
| 19 | + hover: Colors.blue60, |
| 20 | + disabled: Colors.blue50, |
| 21 | + }, |
| 22 | + success: { |
| 23 | + background: Colors.green, |
| 24 | + hover: Colors.green90, |
| 25 | + disabled: Colors.green40, |
| 26 | + }, |
| 27 | + destructive: { |
| 28 | + background: Colors.red, |
| 29 | + hover: Colors.red80, |
| 30 | + disabled: Colors.red60, |
| 31 | + }, |
19 | 32 | },
|
20 |
| - success: { |
21 |
| - background: Colors.green, |
22 |
| - hover: Colors.green90, |
23 |
| - disabled: Colors.green40, |
| 33 | + sizes: { |
| 34 | + auto: 'auto', |
| 35 | + full: '100%', |
| 36 | + '1/2': '50%', |
24 | 37 | },
|
25 |
| - destructive: { |
26 |
| - background: Colors.red, |
27 |
| - hover: Colors.red80, |
28 |
| - disabled: Colors.red60, |
29 |
| - }, |
30 |
| -} as const; |
31 |
| - |
32 |
| -const sizes = { |
33 |
| - auto: 'auto', |
34 |
| - full: '100%', |
35 |
| - '1/2': '50%', |
36 | 38 | };
|
37 | 39 |
|
38 |
| -const StyledButton = styled.button({ |
39 |
| - ...buttonReset, |
| 40 | +const StyledButton = styled(ButtonBase)<ButtonProps>` |
| 41 | + ${({ size: sizeProp = 'full', variant: variantProp = 'primary' }) => { |
| 42 | + const variant = styles.variants[variantProp]; |
| 43 | + const size = styles.sizes[sizeProp]; |
40 | 44 |
|
41 |
| - minHeight: '32px', |
42 |
| - borderRadius: Radius.radius4, |
43 |
| - minWidth: '60px', |
44 |
| - width: 'var(--size)', |
45 |
| - background: 'var(--background)', |
46 |
| - '&:not(:disabled):hover': { |
47 |
| - background: 'var(--hover)', |
48 |
| - }, |
49 |
| - '&:disabled': { |
50 |
| - background: 'var(--disabled)', |
51 |
| - }, |
52 |
| - '&:focus-visible': { |
53 |
| - outline: `2px solid ${Colors.white}`, |
54 |
| - outlineOffset: '2px', |
55 |
| - }, |
56 |
| -}); |
| 45 | + return css` |
| 46 | + --background: ${variant.background}; |
| 47 | + --hover: ${variant.hover}; |
| 48 | + --disabled: ${variant.disabled}; |
| 49 | + --radius: ${styles.radius}; |
| 50 | + --size: ${size}; |
| 51 | +
|
| 52 | + min-height: 32px; |
| 53 | + min-width: 60px; |
| 54 | + border-radius: var(--radius); |
| 55 | + width: var(--size); |
| 56 | + background: var(--background); |
| 57 | +
|
| 58 | + &:not(:disabled):hover { |
| 59 | + background: var(--hover); |
| 60 | + } |
| 61 | +
|
| 62 | + &:disabled { |
| 63 | + background: var(--disabled); |
| 64 | + } |
| 65 | +
|
| 66 | + &:focus-visible { |
| 67 | + outline: 2px solid ${Colors.white}; |
| 68 | + outline-offset: 2px; |
| 69 | + } |
| 70 | + `; |
| 71 | + }} |
| 72 | +`; |
57 | 73 |
|
58 | 74 | const StyledFlex = styled(Flex)`
|
59 | 75 | justify-content: space-between;
|
@@ -85,23 +101,10 @@ const StyledFlex = styled(Flex)`
|
85 | 101 | `;
|
86 | 102 |
|
87 | 103 | const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
88 |
| - ({ variant = 'primary', size = 'full', children, disabled = false, style, ...props }, ref) => { |
89 |
| - const styles = variants[variant]; |
| 104 | + ({ children, disabled = false, style, ...props }, ref) => { |
90 | 105 | return (
|
91 | 106 | <ButtonProvider disabled={disabled}>
|
92 |
| - <StyledButton |
93 |
| - ref={ref} |
94 |
| - style={ |
95 |
| - { |
96 |
| - '--background': styles.background, |
97 |
| - '--hover': styles.hover, |
98 |
| - '--disabled': styles.disabled, |
99 |
| - '--size': sizes[size], |
100 |
| - ...style, |
101 |
| - } as React.CSSProperties |
102 |
| - } |
103 |
| - disabled={disabled} |
104 |
| - {...props}> |
| 107 | + <StyledButton ref={ref} disabled={disabled} {...props}> |
105 | 108 | <StyledFlex
|
106 | 109 | $flex={1}
|
107 | 110 | $gap={Spacings.spacing3}
|
|
0 commit comments