diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html index 68dafe5d..4a75aaa4 100644 --- a/.storybook/preview-head.html +++ b/.storybook/preview-head.html @@ -1 +1 @@ - + diff --git a/src/components/button/Button.spec.tsx b/src/components/button/Button.spec.tsx index 5c5235d5..3c28da08 100644 --- a/src/components/button/Button.spec.tsx +++ b/src/components/button/Button.spec.tsx @@ -46,22 +46,33 @@ test('it works with size large', () => { expect(container.firstChild).toMatchSnapshot(); }); -test('it works with ghost', () => { +test('it works with loading', () => { const { container } = setup( - ); expect(container.firstChild).toMatchSnapshot(); }); -test('it works with loading', () => { +test('it works with anchor', () => { const { container } = setup( - ); expect(container.firstChild).toMatchSnapshot(); + expect(container.querySelectorAll('a').length).toBe(1); + expect(container.querySelector('a')).toHaveAttribute( + 'href', + 'https://google.com' + ); + expect(container.querySelector('a')).toHaveAttribute('target', '_blank'); }); test('it works with icon', () => { diff --git a/src/components/button/Button.stories.tsx b/src/components/button/Button.stories.tsx index 850a75ce..0c68798f 100644 --- a/src/components/button/Button.stories.tsx +++ b/src/components/button/Button.stories.tsx @@ -37,15 +37,18 @@ Danger.args = { styles: templateStyles }; -export const Grey = DefaultTemplate.bind({}); -Grey.args = { - kind: 'grey', - styles: templateStyles -}; - export const WithIcon = DefaultTemplate.bind({}); WithIcon.args = { kind: 'primary', icon: faXmark, styles: templateStyles }; + +export const AsAnchor = DefaultTemplate.bind({}); +AsAnchor.args = { + as: 'a', + kind: 'primary', + href: 'https://google.com', + target: '_blank', + styles: templateStyles +}; diff --git a/src/components/button/__snapshots__/Button.spec.tsx.snap b/src/components/button/__snapshots__/Button.spec.tsx.snap index b04c74b3..dded85c4 100644 --- a/src/components/button/__snapshots__/Button.spec.tsx.snap +++ b/src/components/button/__snapshots__/Button.spec.tsx.snap @@ -4,13 +4,17 @@ exports[`it works 1`] = ` .c0 { border-style: solid; text-align: center; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; position: relative; font-size: 1rem; - font-weight: 400; + font-weight: 500; font-family: Montserrat,sans-serif; line-height: 2; border-radius: 0.3rem; - border-width: 1px; + border-width: 2px; box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06); padding-left: 1rem; padding-right: 1rem; @@ -18,23 +22,23 @@ exports[`it works 1`] = ` padding-bottom: 0.5rem; background-color: #17a3a5; color: white; - border-color: #1a8385; + border-color: #17a3a5; } .c0:hover { cursor: pointer; - background-color: #1a8385; + background-color: #135f61; color: white; } .c0:hover:disabled { cursor: not-allowed; - background-color: #1a8385; + background-color: #135f61; } .c0:disabled { opacity: 0.7; - background-color: #1a8385; + background-color: #135f61; color: white; } @@ -62,31 +66,35 @@ exports[`it works 1`] = ` `; -exports[`it works with ghost 1`] = ` +exports[`it works with anchor 1`] = ` .c0 { border-style: solid; text-align: center; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; position: relative; font-size: 1rem; - font-weight: 400; + font-weight: 500; font-family: Montserrat,sans-serif; line-height: 2; border-radius: 0.3rem; - border-width: 1px; + border-width: 2px; box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06); padding-left: 1rem; padding-right: 1rem; padding-top: 0.5rem; padding-bottom: 0.5rem; background-color: transparent; - color: #292B3E; - border-color: #937032; + color: #17a3a5; + border-color: #d4d4d4; } .c0:hover { cursor: pointer; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #135f61; } .c0:hover:disabled { @@ -112,54 +120,59 @@ exports[`it works with ghost 1`] = ` align-items: center; } - + `; exports[`it works with icon 1`] = ` .c0 { border-style: solid; text-align: center; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; position: relative; font-size: 1rem; - font-weight: 400; + font-weight: 500; font-family: Montserrat,sans-serif; line-height: 2; border-radius: 0.3rem; - border-width: 1px; + border-width: 2px; box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06); padding-left: 1rem; padding-right: 1rem; padding-top: 0.5rem; padding-bottom: 0.5rem; - background-color: #ebc764; - color: white; - border-color: #937032; + background-color: transparent; + color: #17a3a5; + border-color: #d4d4d4; } .c0:hover { cursor: pointer; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #135f61; } .c0:hover:disabled { cursor: not-allowed; - background-color: #937032; + background-color: #fafafa; } .c0:disabled { opacity: 0.7; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #292B3E; } .c1 { @@ -206,38 +219,42 @@ exports[`it works with loading 1`] = ` .c0 { border-style: solid; text-align: center; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; position: relative; font-size: 1rem; - font-weight: 400; + font-weight: 500; font-family: Montserrat,sans-serif; line-height: 2; border-radius: 0.3rem; - border-width: 1px; + border-width: 2px; box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06); padding-left: 1rem; padding-right: 1rem; padding-top: 0.5rem; padding-bottom: 0.5rem; - background-color: #ebc764; - color: white; - border-color: #937032; + background-color: transparent; + color: #17a3a5; + border-color: #d4d4d4; } .c0:hover { cursor: pointer; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #135f61; } .c0:hover:disabled { cursor: not-allowed; - background-color: #937032; + background-color: #fafafa; } .c0:disabled { opacity: 0.7; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #292B3E; } .c1 { @@ -345,38 +362,42 @@ exports[`it works with size large 1`] = ` .c0 { border-style: solid; text-align: center; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; position: relative; font-size: 1rem; - font-weight: 400; + font-weight: 500; font-family: Montserrat,sans-serif; line-height: 2; border-radius: 0.3rem; - border-width: 1px; + border-width: 2px; box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06); padding-left: 1rem; padding-right: 1rem; padding-top: 0.5rem; padding-bottom: 0.5rem; - background-color: #ebc764; - color: white; - border-color: #937032; + background-color: transparent; + color: #17a3a5; + border-color: #d4d4d4; } .c0:hover { cursor: pointer; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #135f61; } .c0:hover:disabled { cursor: not-allowed; - background-color: #937032; + background-color: #fafafa; } .c0:disabled { opacity: 0.7; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #292B3E; } .c1 { @@ -408,38 +429,42 @@ exports[`it works with size medium 1`] = ` .c0 { border-style: solid; text-align: center; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; position: relative; font-size: 1rem; - font-weight: 400; + font-weight: 500; font-family: Montserrat,sans-serif; line-height: 2; border-radius: 0.3rem; - border-width: 1px; + border-width: 2px; box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06); padding-left: 1rem; padding-right: 1rem; padding-top: 0.5rem; padding-bottom: 0.5rem; - background-color: #ebc764; - color: white; - border-color: #937032; + background-color: transparent; + color: #17a3a5; + border-color: #d4d4d4; } .c0:hover { cursor: pointer; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #135f61; } .c0:hover:disabled { cursor: not-allowed; - background-color: #937032; + background-color: #fafafa; } .c0:disabled { opacity: 0.7; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #292B3E; } .c1 { @@ -471,38 +496,42 @@ exports[`it works with size small 1`] = ` .c0 { border-style: solid; text-align: center; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; position: relative; font-size: 1rem; - font-weight: 400; + font-weight: 500; font-family: Montserrat,sans-serif; line-height: 2; border-radius: 0.3rem; - border-width: 1px; + border-width: 2px; box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06); padding-left: 1rem; padding-right: 1rem; padding-top: 0.5rem; padding-bottom: 0.5rem; - background-color: #ebc764; - color: white; - border-color: #937032; + background-color: transparent; + color: #17a3a5; + border-color: #d4d4d4; } .c0:hover { cursor: pointer; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #135f61; } .c0:hover:disabled { cursor: not-allowed; - background-color: #937032; + background-color: #fafafa; } .c0:disabled { opacity: 0.7; - background-color: #937032; - color: white; + background-color: #fafafa; + color: #292B3E; } .c1 { diff --git a/src/components/button/index.tsx b/src/components/button/index.tsx index 6cb094e7..12ba7ba4 100644 --- a/src/components/button/index.tsx +++ b/src/components/button/index.tsx @@ -12,12 +12,16 @@ export * from './styles'; export type ButtonPropType = BoxProps & React.ButtonHTMLAttributes & - React.HTMLProps; + React.HTMLProps & + React.AnchorHTMLAttributes & + React.HTMLProps; export type ButtonSize = 'small' | 'medium' | 'large'; +export type ButtonKind = 'primary' | 'secondary' | 'tertiary' | 'danger'; + export interface ButtonProps { - readonly kind: string; + readonly kind: ButtonKind; readonly theme: Theme; readonly variant?: ButtonSize; readonly ghost?: boolean; @@ -31,7 +35,6 @@ const BaseButton: React.FC = ({ kind, theme, variant, - ghost, loading, icon, children, @@ -40,10 +43,7 @@ const BaseButton: React.FC = ({ return ( ({ fontSize: scale(variant, 2) }); +const primaryBase: ColorGroup = { group: 'primary', shade: 'base' }; + +const darkBase: ColorGroup = { group: 'primary', shade: 'dark' }; + const darkGrey: ColorGroup = { group: 'grey', shade: 'dark' }; +const baseGrey: ColorGroup = { group: 'grey', shade: 'base' }; + const lightBase: ColorGroup = { group: 'base', shade: 'light' }; +const lightGrey: ColorGroup = { group: 'grey', shade: 'light' }; + const lightestGrey: ColorGroup = { group: 'grey', shade: 'lightest' }; -const buttonColors = (dark: string, base: string, ghost?: boolean) => ({ - borderColor: dark, - hoverBackgroundColor: dark, - hoverTextColor: lightBase, - backgroundColor: ghost ? 'transparent' : base, - textColor: ghost ? darkGrey : lightBase, - disabledHoverBackgroundColor: ghost ? lightestGrey : dark, - disabledTextColor: ghost ? darkGrey : lightBase, - disabledBackgroundColor: ghost ? lightestGrey : dark -}); +const buttonColors = (dark: string, base: string, kind: string) => { + const isPrimary = kind === 'primary'; + const isSecondary = kind === 'secondary'; + const isTertiary = kind === 'tertiary'; + + const textColor = (): ColorGroup | string => { + if (isPrimary) return lightBase; + if (isSecondary) return primaryBase; + if (isTertiary) return baseGrey; + return base; + }; + + const hoverTextColor = (): ColorGroup | string => { + if (isPrimary) return lightBase; + if (isSecondary) return darkBase; + if (isTertiary) return darkGrey; + return dark; + }; + + return { + borderColor: isPrimary ? base : lightGrey, + backgroundColor: isPrimary ? base : 'transparent', + textColor: textColor(), + hoverBackgroundColor: isPrimary ? dark : lightestGrey, + hoverTextColor: hoverTextColor(), + disabledHoverBackgroundColor: isPrimary ? dark : lightestGrey, + disabledTextColor: isPrimary ? lightBase : darkGrey, + disabledBackgroundColor: isPrimary ? dark : lightestGrey + }; +}; const buttonVariants = ({ kind, theme, - variant, - ghost + variant }: ButtonProps): ButtonVariantStyles => { const { dark, base } = getProperty<{ [K: string]: string; @@ -60,18 +87,20 @@ const buttonVariants = ({ return { ...buttonSizing(variant || 'large'), - ...buttonColors(dark, base, ghost) + ...buttonColors(dark, base, kind) }; }; const buttonBaseStyles: Styles = { + display: 'inline-flex', position: 'relative', - borderWidth: 'px', + borderWidth: '1', boxShadow: '1', textAlign: 'center', paddingX: '4', borderRadius: '2', - borderStyle: 'solid' + borderStyle: 'solid', + fontWeight: '500' }; const buttonVariantStyles = ({ diff --git a/src/components/link/__snapshots__/Link.spec.tsx.snap b/src/components/link/__snapshots__/Link.spec.tsx.snap index bc55082c..acf625a2 100644 --- a/src/components/link/__snapshots__/Link.spec.tsx.snap +++ b/src/components/link/__snapshots__/Link.spec.tsx.snap @@ -8,13 +8,13 @@ exports[`it works 1`] = ` font-family: Montserrat,sans-serif; line-height: 2; border-bottom-width: 1px; - color: #1a8385; + color: #135f61; border-bottom-color: #4AD6D8; } .c0:hover { - color: #1a8385; - border-bottom-color: #1a8385; + color: #135f61; + border-bottom-color: #135f61; } = const handleDismiss = () => setDismissed(!dismissed); - const getIcon = (variant: StatusMessageVariantType) => { + const getIcon = (variant?: StatusMessageVariantType) => { switch (variant) { case 'warning': case 'error': @@ -82,9 +82,8 @@ const BaseStatusMessage: React.FC = {dismissable && (