Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
[PAY-1651] Implements Harmony Buttons (#3794)
Browse files Browse the repository at this point in the history
  • Loading branch information
schottra authored Jul 25, 2023
1 parent 5af77ec commit 3579dc2
Show file tree
Hide file tree
Showing 19 changed files with 531 additions and 30 deletions.
9 changes: 0 additions & 9 deletions packages/stems/src/assets/icons/iconCampFire.svg

This file was deleted.

3 changes: 3 additions & 0 deletions packages/stems/src/assets/icons/iconCampfire.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions packages/stems/src/assets/styles/animations.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
root {
--quick: 0.07s ease-in-out;
--expressive: 0.18s ease-in-out;
--hover: 0.14s cubic-bezier(0.44, 0, 0.56, 1);
--press: 0.1s cubic-bezier(0.44, 0, 0.56, 1);
--calm: 0.5s ease-in-out;
}
10 changes: 10 additions & 0 deletions packages/stems/src/assets/styles/colors.css
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ root {
--text-subdued: var(--neutral-light-4);
--text-disabled: var(--neutral-light-7);

/* Semantic Borders */
--border-default: var(--neutral-light-8);
--border-strong: var(--neutral-light-7);

/* Semantic Background */
--background-default: var(--background);
--background-surface-1: var(--neutral-light-10);
--background-surface-2: var(--neutral-light-9);
--background-white: var(--white);

--primary-gradient: linear-gradient(135deg, #ee00ed 0%, #c514e0 100%);
--secondary-gradient: linear-gradient(315deg, #6b0fb3 0%, #7e1bcc 100%);
--page-header-gradient-color-1: #5b23e1;
Expand Down
3 changes: 2 additions & 1 deletion packages/stems/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const TYPE_STYLE_MAP = {
[Type.DESTRUCTIVE]: styles.destructive
}

/**
/** @deprecated (use `HarmonyButton` for new code)
*
* A common Button component. Includes a few variants and options to
* include and position icons.
*/
Expand Down
220 changes: 220 additions & 0 deletions packages/stems/src/components/HarmonyButton/HarmonyButton.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/* ===Base Styles=== */
.button {
--button-color: var(--primary);
--text-color: var(--static-white);
--overlay-color: transparent;
--overlay-opacity: 0;
align-items: center;
border: 1px solid var(--button-color);
border-radius: var(--unit-1);
box-sizing: border-box;
color: var(--text-color);
cursor: pointer;
display: inline-flex;
flex-shrink: 0;
justify-content: center;
overflow: hidden;
position: relative;
text-align: center;
user-select: none;
white-space: nowrap;
}

.button:focus {
outline: none !important;
}

/* Only add hover styles on devices which support it */
@media (hover: hover) {
.button:not(.disabled):hover {
transition: all var(--hover);
transform: scale(1.04);
}
}

.button:not(.disabled):active {
transition: all var(--press);
transform: scale(0.98);
}

.button.disabled {
pointer-events: none;
}

/* Overlay used for hover/press styling */
.button::before {
content: '';
position: absolute;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--overlay-color, transparent);
opacity: var(--overlay-opacity, 0);
pointer-events: none;
}

.icon path {
fill: currentColor;
}

.fullWidth {
width: 100%;
}

/* === Sizes === */

/* Small */
.buttonSmall {
gap: var(--unit-1);
height: var(--unit-8);
padding: var(--unit-2) var(--unit-3);
}

.iconSmall {
width: var(--unit-4);
height: var(--unit-4);
}

.textSmall {
font-size: var(--font-s);
font-weight: var(--font-bold);
line-height: var(--unit-4);
text-transform: capitalize;
}

/* Default */
.buttonDefault {
gap: var(--unit-2);
height: var(--unit-12);
padding: var(--unit-3) var(--unit-6);
}

.iconDefault {
width: var(--unit-5);
height: var(--unit-5);
}

.textDefault {
font-size: var(--font-l);
font-weight: var(--font-bold);
line-height: calc(4.5 * var(--unit));
text-transform: capitalize;
}

/* Large */
.buttonLarge {
gap: var(--unit-2);
height: var(--unit-15);
padding: var(--unit-5) var(--unit-6);
}

.iconLarge {
width: var(--unit-6);
height: var(--unit-6);
}

.textLarge {
font-size: var(--font-xl);
font-weight: var(--font-bold);
line-height: var(--unit-5);
letter-spacing: 0.25px;
text-transform: uppercase;
}

/* === Color Variants === */

/* Primary */
.primary {
--text-color: var(--static-white);
--button-color: var(--primary);
background: var(--button-color);
box-shadow: var(--shadow-near);
}

.primary:hover {
--overlay-color: var(--static-white);
--overlay-opacity: 0.1;
box-shadow: var(--shadow-mid);
}

.primary:active {
--overlay-color: var(--static-black);
--overlay-opacity: 0.2;
box-shadow: none;
}

/* Secondary */
.secondary {
--button-color: var(--neutral-light-5);
--text-color: var(--text-default);
background: transparent;
}

.secondary:hover {
--button-color: var(--primary);
--text-color: var(--primary);
}
.secondary:active {
--button-color: var(--primary-dark-2);
--text-color: var(--primary-dark-2);
}

/* Tertiary */
.tertiary {
--button-color: var(--border-strong);
--text-color: var(--secondary);
background: var(--static-white);
}
.tertiary:hover {
--text-color: var(--secondary-light-1);
box-shadow: var(--shadow-mid);
}
.tertiary:active {
--overlay-color: var(--static-black);
--overlay-opacity: 0.2;
}

/* Destructive */
.destructive {
--button-color: var(--accent-red);
--text-color: var(--accent-red);
background: transparent;
}
.destructive:hover {
--text-color: var(--static-white);
background: var(--button-color);
}
.destructive:active {
--button-color: var(--accent-red-dark-1);
--text-color: var(--static-white);
background: var(--button-color);
}

/* Ghost */
.ghost {
--button-color: var(--neutral-light-5);
--text-color: var(--text-default);
background: transparent;
}
.ghost:hover {
--button-color: var(--neutral);
}
.ghost:active {
--button-color: var(--neutral-light-5);
background: var(--background-surface-2);
}

/* Disabled states */
.primary.disabled {
--button-color: var(--neutral-light-7);
--text-color: var(--background-white);
}

.secondary.disabled,
.tertiary.disabled,
.destructive.disabled,
.ghost.disabled {
opacity: 0.45;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { Story } from '@storybook/react'

import * as Icons from 'components/Icons'

import { HarmonyButton } from './HarmonyButton'
import {
HarmonyButtonProps,
HarmonyButtonSize,
HarmonyButtonType
} from './types'

export default {
component: HarmonyButton,
title: 'Components/HarmonyButton',
argTypes: { onClick: { action: 'clicked' } }
}

const baseProps: HarmonyButtonProps = {
iconLeft: Icons.IconCampfire,
iconRight: Icons.IconCampfire,
text: 'Click Me'
}

const Template: Story<HarmonyButtonProps> = (args) => (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '16px',
alignItems: 'flex-start'
}}
>
<div style={{ alignItems: 'center', display: 'flex', gap: '16px' }}>
<HarmonyButton {...baseProps} size={HarmonyButtonSize.SMALL} {...args} />
<HarmonyButton
{...baseProps}
size={HarmonyButtonSize.DEFAULT}
{...args}
/>
<HarmonyButton {...baseProps} size={HarmonyButtonSize.LARGE} {...args} />
</div>
<div style={{ alignItems: 'center', display: 'flex', gap: '16px' }}>
<HarmonyButton
{...baseProps}
size={HarmonyButtonSize.SMALL}
{...args}
disabled
/>
<HarmonyButton
{...baseProps}
size={HarmonyButtonSize.DEFAULT}
{...args}
disabled
/>
<HarmonyButton
{...baseProps}
size={HarmonyButtonSize.LARGE}
{...args}
disabled
/>
</div>
</div>
)

// Primary
export const Primary = Template.bind({})

// Primary w/ color
export const PrimaryWithColor = Template.bind({})
PrimaryWithColor.args = { color: 'accentBlue' }

// Secondary
export const Secondary = Template.bind({})
Secondary.args = { variant: HarmonyButtonType.SECONDARY }

// Tertiary
export const Tertiary = Template.bind({})
Tertiary.args = { variant: HarmonyButtonType.TERTIARY }

// Destructive
export const Destructive = Template.bind({})
Destructive.args = { variant: HarmonyButtonType.DESTRUCTIVE }

// Ghost
export const Ghost = Template.bind({})
Ghost.args = { variant: HarmonyButtonType.GHOST }
Loading

0 comments on commit 3579dc2

Please sign in to comment.