Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Refactor button component #1065

Merged
merged 24 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 64 additions & 15 deletions packages/css/src/components/button/button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,96 @@
* Copyright (c) 2023 Gemeente Amsterdam
*/

@import "../../../node_modules/@utrecht/components/button/css";

@mixin reset {
-webkit-text-size-adjust: 100%;
}

.amsterdam-button {
@mixin amsterdam-button {
VincentSmedinga marked this conversation as resolved.
Show resolved Hide resolved
border: none;
cursor: var(--amsterdam-action-activate-cursor);
alimpens marked this conversation as resolved.
Show resolved Hide resolved
display: inline-flex;
font-family: var(--amsterdam-button-font-family);
font-size: var(--amsterdam-button-spacious-font-size);
gap: var(--amsterdam-button-gap);
line-height: var(--amsterdam-button-spacious-line-height);

@include reset;
outline-offset: var(--amsterdam-button-outline-offset);
padding-block: var(--amsterdam-button-padding-block-start) var(--amsterdam-button-padding-block-end);
alimpens marked this conversation as resolved.
Show resolved Hide resolved
padding-inline: var(--amsterdam-button-padding-inline-start) var(--amsterdam-button-padding-inline-end);
-webkit-text-size-adjust: 100%;
alimpens marked this conversation as resolved.
Show resolved Hide resolved

alimpens marked this conversation as resolved.
Show resolved Hide resolved
.amsterdam-theme--compact & {
font-size: var(--amsterdam-breadcrumb-compact-font-size);
line-height: var(--amsterdam-breadcrumb-compact-line-height);
}

&:disabled,
&[aria-disabled="true"] {
cursor: var(--amsterdam-action-disabled-cursor);
}

&:hover:not(:disabled, [aria-disabled="true"]) {
VincentSmedinga marked this conversation as resolved.
Show resolved Hide resolved
cursor: var(--amsterdam-action-activate-cursor);
}
}

@mixin amsterdam-button-forced-color-mode {
@media screen and (-ms-high-contrast: active), screen and (forced-colors: active) {
border: 2px solid ButtonBorder; // add border because forced colors changes box-shadow to none
}
}

.amsterdam-button--busy {
VincentSmedinga marked this conversation as resolved.
Show resolved Hide resolved
cursor: var(--amsterdam-action-busy-cursor);
}

.amsterdam-button--primary {
background-color: var(--amsterdam-button-primary-background-color);
color: var(--amsterdam-button-primary-color);
VincentSmedinga marked this conversation as resolved.
Show resolved Hide resolved

&:disabled,
[aria-disabled="true"] {
background-color: var(--amsterdam-button-primary-disabled-background-color);
}

&:hover:not(:disabled, [aria-disabled="true"]) {
background-color: var(--amsterdam-button-primary-hover-background-color);
}

@include amsterdam-button;
@include amsterdam-button-forced-color-mode;
}

.amsterdam-button--secondary {
background-color: var(--amsterdam-button-secondary-background-color);
box-shadow: var(--amsterdam-button-secondary-box-shadow);
color: var(--amsterdam-button-secondary-color);

&:disabled,
[aria-disabled="true"] {
background-color: var(--amsterdam-button-secondary-disabled-background-color);
box-shadow: var(--amsterdam-button-secondary-disabled-box-shadow);
color: var(--amsterdam-button-secondary-disabled-color);
}

&:hover:not(:disabled, [aria-disabled="true"]) {
box-shadow: var(--amsterdam-button-secondary-hover-box-shadow);
color: var(--amsterdam-button-secondary-hover-color);
}
}

.amsterdam-button--secondary:focus:not(:hover, [aria-disabled="true"]) {
box-shadow: var(--amsterdam-button-secondary-focus-box-shadow);
@include amsterdam-button;
@include amsterdam-button-forced-color-mode;
}

.amsterdam-button--tertiary {
background-color: var(--amsterdam-button-tertiary-background-color);
color: var(--amsterdam-button-tertiary-color);

&:disabled,
[aria-disabled="true"] {
background-color: var(--amsterdam-button-tertiary-disabled-background-color);
color: var(--amsterdam-button-tertiary-disabled-color);
}

&:hover:not(:disabled, [aria-disabled="true"]) {
box-shadow: var(--amsterdam-button-tertiary-hover-box-shadow);
color: var(--amsterdam-button-tertiary-hover-color);
}
}

.amsterdam-button--tertiary:focus:not(:hover, [aria-disabled="true"]) {
box-shadow: none;
@include amsterdam-button;
}
1 change: 0 additions & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
],
"dependencies": {
"@amsterdam/design-system-react-icons": "workspace:*",
"@utrecht/component-library-react": "3.0.0",
"clsx": "2.1.0"
},
"devDependencies": {
Expand Down
8 changes: 4 additions & 4 deletions packages/react/src/Button/Button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('Button', () => {

expect(button).toBeInTheDocument()
expect(button).toHaveAttribute('type', 'button')
expect(button).toHaveClass('utrecht-button--primary-action')
expect(button).toHaveClass('amsterdam-button--primary')
})

it('renders a button with a specified variant', () => {
Expand All @@ -49,11 +49,11 @@ describe('Button', () => {
})

expect(buttonPrimary).toBeInTheDocument()
expect(buttonPrimary).toHaveClass('utrecht-button--primary-action')
expect(buttonPrimary).toHaveClass('amsterdam-button--primary')
expect(buttonSecondary).toBeInTheDocument()
expect(buttonSecondary).toHaveClass('utrecht-button--secondary-action')
expect(buttonSecondary).toHaveClass('amsterdam-button--secondary')
expect(buttonTertiary).toBeInTheDocument()
expect(buttonTertiary).toHaveClass('utrecht-button--subtle')
expect(buttonTertiary).toHaveClass('amsterdam-button--tertiary')
})

it('renders a disabled button with a specified variant', () => {
Expand Down
37 changes: 12 additions & 25 deletions packages/react/src/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,34 @@
/**
* @license EUPL-1.2+
* Copyright (c) 2021 Robbert Broersma
* Copyright (c) 2023 Gemeente Amsterdam
* Copyright (c) 2024 Gemeente Amsterdam
*/

import { Button as CommunityButton } from '@utrecht/component-library-react'
import clsx from 'clsx'
import { forwardRef } from 'react'
import type { ButtonHTMLAttributes, ForwardedRef, PropsWithChildren } from 'react'

export type ButtonProps = {
variant?: 'primary' | 'secondary' | 'tertiary'
/** Render the button in a busy state to indicate something has to finish loading */
busy?: boolean
} & PropsWithChildren<ButtonHTMLAttributes<HTMLButtonElement>>

type CommunityButtonAppearance = 'primary-action-button' | 'secondary-action-button' | 'subtle-button'

function getAppearance(variant: ButtonProps['variant']): CommunityButtonAppearance {
switch (variant) {
case 'secondary':
return 'secondary-action-button'
case 'tertiary':
return 'subtle-button'
default:
return 'primary-action-button'
}
}

export const Button = forwardRef(
({ children, disabled, variant = 'primary', ...restProps }: ButtonProps, ref: ForwardedRef<HTMLButtonElement>) => {
(
{ children, type, disabled, busy, variant = 'primary', ...restProps }: ButtonProps,
ref: ForwardedRef<HTMLButtonElement>,
) => {
return (
<CommunityButton
<button
{...restProps}
appearance={getAppearance(variant)}
ref={ref}
disabled={disabled}
className={clsx(
'amsterdam-button',
variant === 'secondary' && 'amsterdam-button--secondary',
variant === 'tertiary' && 'amsterdam-button--tertiary',
)}
className={clsx('amsterdam-button', busy === true && 'amsterdam-button--busy', `amsterdam-button--${variant}`)}
type={type || 'button'}
aria-busy={busy || undefined}
>
{children}
</CommunityButton>
</button>
)
},
)
Expand Down
43 changes: 7 additions & 36 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"utrecht": {
"amsterdam": {
"action": {
"activate": { "cursor": { "value": "pointer" } },
"busy": { "cursor": { "value": "wait" } },
Expand Down
7 changes: 0 additions & 7 deletions proprietary/tokens/src/common/utrecht/focus.tokens.json

This file was deleted.

35 changes: 32 additions & 3 deletions proprietary/tokens/src/components/amsterdam/button.tokens.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
{
"amsterdam": {
"button": {
"font-family": { "value": "{amsterdam.typography.font-family}" },
"gap": { "value": "{amsterdam.spacing.inset.md}" },
"padding-inline-start": { "value": "{amsterdam.spacing.inset.md}" },
"padding-inline-end": { "value": "{amsterdam.spacing.inset.md}" },
"padding-block-start": { "value": "{amsterdam.spacing.inset.sm}" },
"padding-block-end": { "value": "{amsterdam.spacing.inset.sm}" },
alimpens marked this conversation as resolved.
Show resolved Hide resolved
"outline-offset": { "value": "{amsterdam.focus.outline-offset}" },
"spacious": {
"font-size": { "value": "{amsterdam.typography.spacious.text-level.5.font-size}" },
"line-height": { "value": "{amsterdam.typography.spacious.text-level.5.line-height}" }
Expand All @@ -9,21 +16,43 @@
"font-size": { "value": "{amsterdam.typography.compact.text-level.5.font-size}" },
"line-height": { "value": "{amsterdam.typography.compact.text-level.5.line-height}" }
},
"primary": {
"background-color": { "value": "{amsterdam.color.primary-blue}" },
"color": { "value": "{amsterdam.color.primary-white}" },
"disabled": {
"background-color": { "value": "{amsterdam.color.neutral-grey2}" }
},
"hover": {
"background-color": { "value": "{amsterdam.color.dark-blue}" }
}
},
"secondary": {
"background-color": { "value": "{amsterdam.color.primary-white}" },
"color": { "value": "{amsterdam.color.primary-blue}" },
"box-shadow": { "value": "inset 0 0 0 2px {amsterdam.color.primary-blue}" },
"hover": {
"box-shadow": { "value": "inset 0 0 0 3px {amsterdam.color.dark-blue}" }
"box-shadow": { "value": "inset 0 0 0 3px {amsterdam.color.dark-blue}" },
"color": { "value": "{amsterdam.color.dark-blue}" }
},
"disabled": {
"box-shadow": { "value": "inset 0 0 0 2px {amsterdam.color.neutral-grey2}" }
"background-color": { "value": "{amsterdam.color.primary-white}" },
"box-shadow": { "value": "inset 0 0 0 2px {amsterdam.color.neutral-grey2}" },
"color": { "value": "{amsterdam.color.neutral-grey2}" }
},
"focus": {
"box-shadow": { "value": "inset 0 0 0 2px {amsterdam.color.primary-blue}" }
}
},
"tertiary": {
"background-color": { "value": "transparent" },
"color": { "value": "{amsterdam.color.primary-blue}" },
"hover": {
"box-shadow": { "value": "inset 0 0 0 2px {amsterdam.color.dark-blue}" }
"box-shadow": { "value": "inset 0 0 0 2px {amsterdam.color.dark-blue}" },
"color": { "value": "{amsterdam.color.dark-blue}" }
},
"disabled": {
"background-color": { "value": "transparent" },
"color": { "value": "{amsterdam.color.neutral-grey2}" }
}
}
}
Expand Down
Loading
Loading