Clean up button component some more

Here we add a floating prop for displaying buttons on top of things, like in units. We also renamed contained to bound to match other components and added an icon size.
This commit is contained in:
Justin Edmund 2023-06-24 15:31:36 -07:00
parent 35442bb83c
commit 69c5fceebc
2 changed files with 149 additions and 74 deletions

View file

@ -11,6 +11,12 @@
transition: 0.18s opacity ease-in-out; transition: 0.18s opacity ease-in-out;
user-select: none; user-select: none;
.text {
color: inherit;
display: block;
width: 100%;
}
&:hover, &:hover,
&.blended:hover, &.blended:hover,
&.blended.active { &.blended.active {
@ -28,29 +34,12 @@
} }
} }
// Modifiers
&.blended { &.blended {
background: transparent; background: transparent;
} }
&.iconButton.medium { &.bound {
height: inherit;
padding: $unit-half;
&:hover {
background: none;
}
.text {
font-size: $font-small;
font-weight: $bold;
@include breakpoint(phone) {
display: none;
}
}
}
&.contained {
background: var(--button-contained-bg); background: var(--button-contained-bg);
&:hover { &:hover {
@ -81,12 +70,123 @@
} }
} }
&.floating {
pointer-events: none;
position: absolute;
opacity: 0;
z-index: 99;
}
// Sizes
&.icon {
aspect-ratio: 1 / 1;
.text {
display: none;
@include breakpoint(tablet) {
display: block;
}
@include breakpoint(phone) {
display: block;
}
}
}
&.small {
font-size: $font-small;
padding: $unit * 1.5;
}
&.medium {
height: $unit * 5.5;
padding: ($unit * 1.5) $unit-2x;
}
&.large {
font-size: $font-large;
padding: $unit-2x $unit-3x;
}
// Special variations
&.filter {
&.filtersActive .accessory svg {
fill: var(--accent-blue);
stroke: none;
}
&:hover {
background: var(--button-bg);
.accessory svg {
fill: var(--button-text);
}
}
.accessory svg {
fill: none;
stroke: var(--button-text);
}
}
&.save {
.accessory svg {
fill: none;
stroke: var(--button-text);
}
&.saved {
color: $save-red;
.accessory svg {
fill: $save-red;
stroke: $save-red;
}
&:hover {
color: $save-red;
.accessory svg {
fill: none;
stroke: $save-red;
}
}
}
&:hover {
color: $save-red;
.accessory svg {
fill: $save-red;
stroke: $save-red;
}
}
}
&.iconButton.medium {
height: inherit;
padding: $unit-half;
&:hover {
background: none;
}
.text {
font-size: $font-small;
font-weight: $bold;
@include breakpoint(phone) {
display: none;
}
}
}
&.options { &.options {
box-shadow: 0px 1px 3px rgb(0 0 0 / 14%); box-shadow: 0px 1px 3px rgb(0 0 0 / 14%);
position: absolute;
left: 8px; left: 8px;
top: 8px; top: 8px;
z-index: 3;
} }
&:disabled { &:disabled {
@ -100,15 +200,6 @@
} }
} }
&.medium {
height: $unit * 5.5;
padding: ($unit * 1.5) $unit-2x;
}
&.small {
padding: $unit * 1.5;
}
@include breakpoint(phone) { @include breakpoint(phone) {
&.destructive { &.destructive {
background: $error; background: $error;
@ -129,31 +220,6 @@
} }
} }
&.Save {
.accessory svg {
fill: none;
stroke: var(--button-text);
}
&.Saved {
color: #ff4d4d;
.accessory svg {
fill: #ff4d4d;
stroke: none;
}
}
&:hover {
color: #ff4d4d;
.accessory svg {
fill: none;
stroke: #ff4d4d;
}
}
}
&.modal:hover { &.modal:hover {
background: $grey-90; background: $grey-90;
} }
@ -318,10 +384,11 @@
background: darken($light-bg-20, 10); background: darken($light-bg-20, 10);
} }
} }
}
.text {
color: inherit; // CSS modules suck
display: block; :global(.unit:hover) .floating,
width: 100%; :global(.unit) .floating.active {
} pointer-events: initial;
opacity: 1;
} }

View file

@ -14,8 +14,9 @@ interface Props
rightAccessoryClassName?: string rightAccessoryClassName?: string
active?: boolean active?: boolean
blended?: boolean blended?: boolean
contained?: boolean bound?: boolean
buttonSize?: 'small' | 'medium' | 'large' floating?: boolean
size?: 'icon' | 'small' | 'medium' | 'large'
text?: string text?: string
} }
@ -23,6 +24,7 @@ const defaultProps = {
active: false, active: false,
blended: false, blended: false,
contained: false, contained: false,
floating: false,
buttonSize: 'medium' as const, buttonSize: 'medium' as const,
} }
@ -34,22 +36,28 @@ const Button = React.forwardRef<HTMLButtonElement, Props>(function button(
rightAccessoryClassName, rightAccessoryClassName,
active, active,
blended, blended,
contained, floating,
buttonSize, bound,
size,
text, text,
...props ...props
}, },
forwardedRef forwardedRef
) { ) {
const classes = classNames(buttonSize, props.className, { const classes = classNames(
[styles.button]: true, {
[styles.active]: active, [styles.button]: true,
[styles.blended]: blended, [styles.active]: active,
[styles.contained]: contained, [styles.bound]: bound,
[styles.small]: buttonSize === 'small', [styles.blended]: blended,
[styles.medium]: buttonSize === 'medium', [styles.floating]: floating,
[styles.large]: buttonSize === 'large', [styles.icon]: size === 'icon',
}) [styles.small]: size === 'small',
[styles.medium]: size === 'medium' || !size,
[styles.large]: size === 'large',
},
props.className?.split(' ').map((className) => styles[className])
)
const leftAccessoryClasses = classNames(leftAccessoryClassName, { const leftAccessoryClasses = classNames(leftAccessoryClassName, {
[styles.accessory]: true, [styles.accessory]: true,