From 69c5fceebc835b0975328155faf32598589a2164 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 24 Jun 2023 15:31:36 -0700 Subject: [PATCH] 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. --- components/common/Button/index.module.scss | 189 ++++++++++++++------- components/common/Button/index.tsx | 34 ++-- 2 files changed, 149 insertions(+), 74 deletions(-) diff --git a/components/common/Button/index.module.scss b/components/common/Button/index.module.scss index a326559d..d71da0ae 100644 --- a/components/common/Button/index.module.scss +++ b/components/common/Button/index.module.scss @@ -11,6 +11,12 @@ transition: 0.18s opacity ease-in-out; user-select: none; + .text { + color: inherit; + display: block; + width: 100%; + } + &:hover, &.blended:hover, &.blended.active { @@ -28,29 +34,12 @@ } } + // Modifiers &.blended { background: transparent; } - &.iconButton.medium { - height: inherit; - padding: $unit-half; - - &:hover { - background: none; - } - - .text { - font-size: $font-small; - font-weight: $bold; - - @include breakpoint(phone) { - display: none; - } - } - } - - &.contained { + &.bound { background: var(--button-contained-bg); &: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 { box-shadow: 0px 1px 3px rgb(0 0 0 / 14%); - position: absolute; + left: 8px; top: 8px; - z-index: 3; } &:disabled { @@ -100,15 +200,6 @@ } } - &.medium { - height: $unit * 5.5; - padding: ($unit * 1.5) $unit-2x; - } - - &.small { - padding: $unit * 1.5; - } - @include breakpoint(phone) { &.destructive { 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 { background: $grey-90; } @@ -318,10 +384,11 @@ background: darken($light-bg-20, 10); } } - - .text { - color: inherit; - display: block; - width: 100%; - } +} + +// CSS modules suck +:global(.unit:hover) .floating, +:global(.unit) .floating.active { + pointer-events: initial; + opacity: 1; } diff --git a/components/common/Button/index.tsx b/components/common/Button/index.tsx index 72adea23..654378b1 100644 --- a/components/common/Button/index.tsx +++ b/components/common/Button/index.tsx @@ -14,8 +14,9 @@ interface Props rightAccessoryClassName?: string active?: boolean blended?: boolean - contained?: boolean - buttonSize?: 'small' | 'medium' | 'large' + bound?: boolean + floating?: boolean + size?: 'icon' | 'small' | 'medium' | 'large' text?: string } @@ -23,6 +24,7 @@ const defaultProps = { active: false, blended: false, contained: false, + floating: false, buttonSize: 'medium' as const, } @@ -34,22 +36,28 @@ const Button = React.forwardRef(function button( rightAccessoryClassName, active, blended, - contained, - buttonSize, + floating, + bound, + size, text, ...props }, forwardedRef ) { - const classes = classNames(buttonSize, props.className, { - [styles.button]: true, - [styles.active]: active, - [styles.blended]: blended, - [styles.contained]: contained, - [styles.small]: buttonSize === 'small', - [styles.medium]: buttonSize === 'medium', - [styles.large]: buttonSize === 'large', - }) + const classes = classNames( + { + [styles.button]: true, + [styles.active]: active, + [styles.bound]: bound, + [styles.blended]: blended, + [styles.floating]: floating, + [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, { [styles.accessory]: true,