style: refactor Button and numericStepper components for improved accessibility and styling
This commit is contained in:
@@ -1,40 +1,97 @@
|
||||
@use '../../styles/tokens/typography' as *;
|
||||
@use "../../styles/tokens/typography" as *;
|
||||
|
||||
.button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--nds-spacing-xs);
|
||||
width: fit-content;
|
||||
padding: var(--nds-spacing-sm) var(--nds-spacing-md);
|
||||
border-radius: var(--nds-radius-sm);
|
||||
@include text-base;
|
||||
border: var(--nds-border-width-thin) solid transparent;
|
||||
border-radius: var(--nds-radius-md);
|
||||
@include text-label;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition:
|
||||
background-color 140ms ease,
|
||||
border-color 140ms ease,
|
||||
color 140ms ease,
|
||||
box-shadow 140ms ease,
|
||||
transform 80ms ease;
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 3px var(--nds-ring);
|
||||
}
|
||||
&:active:not(.button--disabled) {
|
||||
transform: translateY(0.5px);
|
||||
}
|
||||
&--sm {
|
||||
height: 30px;
|
||||
padding: 0 var(--nds-spacing-sm);
|
||||
}
|
||||
&--md {
|
||||
height: 38px;
|
||||
padding: 0 var(--nds-spacing-md);
|
||||
}
|
||||
&--lg {
|
||||
height: 46px;
|
||||
padding: 0 var(--nds-spacing-lg);
|
||||
font-size: 0.9375rem;
|
||||
}
|
||||
&--icon {
|
||||
padding: 0;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
&--icon.button--sm {
|
||||
width: 30px;
|
||||
}
|
||||
&--icon.button--md {
|
||||
width: 38px;
|
||||
}
|
||||
&--icon.button--lg {
|
||||
width: 46px;
|
||||
}
|
||||
&__primary {
|
||||
background-color: var(--nds-primary);
|
||||
color: var(--nds-text);
|
||||
color: var(--nds-on-primary);
|
||||
border-color: var(--nds-primary);
|
||||
&:hover:not(.button--disabled) {
|
||||
background-color: var(--nds-secondary);
|
||||
}
|
||||
&:active:not(.button--disabled) {
|
||||
background-color: var(--nds-accent);
|
||||
color: var(--nds-background);
|
||||
background-color: color-mix(in srgb, var(--nds-primary) 88%, #000);
|
||||
border-color: color-mix(in srgb, var(--nds-primary) 88%, #000);
|
||||
}
|
||||
}
|
||||
&__secondary {
|
||||
border: var(--nds-border-width-medium) solid;
|
||||
border-color: var(--nds-primary);
|
||||
background-color: transparent;
|
||||
color: var(--nds-primary);
|
||||
border-color: var(--nds-border-strong);
|
||||
&:hover:not(.button--disabled) {
|
||||
border-color: var(--nds-secondary);
|
||||
border-color: var(--nds-primary);
|
||||
background-color: var(--nds-primary-soft);
|
||||
}
|
||||
&:active:not(.button--disabled) {
|
||||
border-color: var(--nds-accent);
|
||||
color: var(--nds-accent);
|
||||
}
|
||||
&__ghost {
|
||||
background-color: transparent;
|
||||
color: var(--nds-text);
|
||||
border-color: transparent;
|
||||
&:hover:not(.button--disabled) {
|
||||
background-color: var(--nds-surface-hover);
|
||||
}
|
||||
}
|
||||
&__danger {
|
||||
background-color: var(--nds-error-medium);
|
||||
color: #fff;
|
||||
border-color: var(--nds-error-medium);
|
||||
&:hover:not(.button--disabled) {
|
||||
background-color: color-mix(in srgb, var(--nds-error-medium) 88%, #000);
|
||||
border-color: color-mix(in srgb, var(--nds-error-medium) 88%, #000);
|
||||
}
|
||||
}
|
||||
&--disabled {
|
||||
cursor: not-allowed;
|
||||
background-color: var(--nds-disabled);
|
||||
color: var(--nds-neutral);
|
||||
}
|
||||
&--icon {
|
||||
padding: var(--nds-spacing-2xs) var(--nds-spacing-xs);
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,44 @@
|
||||
---
|
||||
export interface Props {
|
||||
type: 'primary' | 'secondary';
|
||||
disabled?: boolean;
|
||||
icon?: boolean;
|
||||
type?: 'primary' | 'secondary' | 'ghost' | 'danger';
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
disabled?: boolean;
|
||||
icon?: boolean;
|
||||
href?: string;
|
||||
htmlType?: 'button' | 'submit' | 'reset';
|
||||
}
|
||||
const { type, disabled = false, icon = false } = Astro.props;
|
||||
const {
|
||||
type = 'primary',
|
||||
size = 'md',
|
||||
disabled = false,
|
||||
icon = false,
|
||||
href,
|
||||
htmlType = 'button',
|
||||
...rest
|
||||
} = Astro.props;
|
||||
|
||||
const classes = [
|
||||
'button',
|
||||
`button__${type}`,
|
||||
`button--${size}`,
|
||||
icon ? 'button--icon' : '',
|
||||
disabled ? 'button--disabled' : '',
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
const Tag = href ? 'a' : 'button';
|
||||
---
|
||||
|
||||
<div class={`button button__${type} ${disabled ? 'button--disabled' : ''} ${icon ? 'button--icon' : ''}`}>
|
||||
<slot/>
|
||||
</div>
|
||||
<Tag
|
||||
class={classes}
|
||||
href={href}
|
||||
type={href ? undefined : htmlType}
|
||||
aria-disabled={disabled ? 'true' : undefined}
|
||||
{...rest}
|
||||
>
|
||||
<slot name="icon-left" />
|
||||
<slot />
|
||||
<slot name="icon-right" />
|
||||
</Tag>
|
||||
|
||||
<style lang="scss">
|
||||
@use './_button.scss';
|
||||
|
||||
@@ -1,14 +1,44 @@
|
||||
@use '../../styles/tokens/typography' as *;
|
||||
@use "../../styles/tokens/typography" as *;
|
||||
|
||||
.numeric-stepper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--nds-spacing-xs);
|
||||
gap: 0;
|
||||
border: var(--nds-border-width-thin) solid var(--nds-border-strong);
|
||||
border-radius: var(--nds-radius-md);
|
||||
background-color: var(--nds-surface);
|
||||
overflow: hidden;
|
||||
width: fit-content;
|
||||
& p {
|
||||
@include text-xl;
|
||||
margin: 0;
|
||||
height: fit-content;
|
||||
|
||||
&__button {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--nds-text);
|
||||
transition: background-color 120ms ease;
|
||||
&:hover:not(:disabled) {
|
||||
background-color: var(--nds-surface-hover);
|
||||
}
|
||||
&:disabled {
|
||||
color: var(--nds-disabled);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
&__value {
|
||||
width: 48px;
|
||||
text-align: center;
|
||||
@include text-label;
|
||||
color: var(--nds-text);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import Button from '../Button/button.astro';
|
||||
import { Arrow2Icon } from '../Icons';
|
||||
import { MinusIcon, PlusIcon } from '../Icons';
|
||||
|
||||
export interface Props {
|
||||
id: string;
|
||||
@@ -23,16 +23,16 @@ const { id, min, max, value = 0, step = 1 } = Astro.props;
|
||||
data-step={step}
|
||||
>
|
||||
<span class="numeric-stepper__control" data-action="increment">
|
||||
<Button type="secondary" icon={true}>
|
||||
<Arrow2Icon size={24} orientation="up" />
|
||||
<Button type="ghost" icon={true}>
|
||||
<MinusIcon size={24} />
|
||||
</Button>
|
||||
</span>
|
||||
|
||||
<p class="numeric-stepper__value">{value}</p>
|
||||
|
||||
<span class="numeric-stepper__control" data-action="decrement">
|
||||
<Button type="secondary" icon={true}>
|
||||
<Arrow2Icon size={24} orientation="down" />
|
||||
<Button type="ghost" icon={true}>
|
||||
<PlusIcon size={24} />
|
||||
</Button>
|
||||
</span>
|
||||
</div>
|
||||
@@ -113,5 +113,5 @@ const { id, min, max, value = 0, step = 1 } = Astro.props;
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use './numericStepper';
|
||||
@use "./numericStepper";
|
||||
</style>
|
||||
Reference in New Issue
Block a user