Skip to content

Commit

Permalink
[components] Improve Button component
Browse files Browse the repository at this point in the history
  • Loading branch information
mariuslundgard authored and rexxars committed Oct 6, 2020
1 parent c26dbf3 commit bab150c
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 27 deletions.
12 changes: 8 additions & 4 deletions packages/@sanity/components/src/buttons/createButtonLike.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ export interface ButtonState {
}

export default function createButtonLike(
Component: ButtonComponent,
as: ButtonComponent | 'button' | 'a',
{displayName, defaultProps = {}}: ButtonComponentOpts
) {
const Component = as as ButtonComponent

return class ButtonLike extends React.Component<ButtonProps, ButtonState> {
static displayName =
displayName ||
Expand All @@ -26,7 +28,7 @@ export default function createButtonLike(

static defaultProps = defaultProps

_element: HTMLAnchorElement | HTMLButtonElement | null = null
_element: HTMLButtonElement | null = null

state = {
focusSetFromOutside: false
Expand All @@ -39,11 +41,11 @@ export default function createButtonLike(
}
}

setRootElement = (el: HTMLAnchorElement | HTMLButtonElement | null) => {
setRootElement = (el: HTMLButtonElement | null) => {
this._element = el
}

handleBlur = (event: React.FocusEvent<HTMLAnchorElement | HTMLButtonElement>) => {
handleBlur = (event: React.FocusEvent<HTMLButtonElement>) => {
if (this.props.onBlur) {
this.props.onBlur(event)
}
Expand All @@ -69,6 +71,7 @@ export default function createButtonLike(
bleed,
selected,
size,
tone,
...restProps
} = this.props

Expand All @@ -91,6 +94,7 @@ export default function createButtonLike(
{...restProps}
className={className}
data-icon-status={iconStatus}
data-tone={tone}
disabled={disabled || loading}
ref={this.setRootElement}
tabIndex={0}
Expand Down
3 changes: 2 additions & 1 deletion packages/@sanity/components/src/buttons/stories/default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export function DefaultStory() {
selected: boolean('Selected', false, 'props'),
size:
select('Size', ['', 'extra-small', 'small', 'medium', 'large', 'extra-large'], '', 'props') ||
undefined
undefined,
tone: select('Tone', {'': '(none)', navbar: 'Navbar'}, '', 'Props') || undefined
}

const children = text('Text', 'Touch Me!', 'props')
Expand Down
66 changes: 56 additions & 10 deletions packages/@sanity/components/src/buttons/styles/DefaultButton.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
/* :focus */
--color-button-focus-bg: color(var(--color-button-bg) lightness(- 5%));
--color-button-focus-shadow: 0 0 0 1px var(--component-bg), 0 0 0 3px var(--brand-primary);
--color-button-navbar-focus-shadow: 0 0 0 1px var(--main-navigation-color),
0 0 0 3px var(--brand-primary);
/* :hover */
--color-button-hover-bg: color(var(--color-button-bg) lightness(- 5%));
/* :active */
Expand All @@ -36,6 +38,19 @@
/* :selected */
--color-button-simple-selected-bg: color(var(--selected-item-color) alpha(15%));
--color-button-simple-selected-text: var(--selected-item-color);
/* simple={true} tone="navbar" */
--color-button-navbar-simple-color: var(--color-button-bg);
/* :focus */
--color-button-navbar-simple-focus-bg: color(var(--color-button-bg) alpha(10%));
--color-button-navbar-simple-focus-text: color(var(--color-button-bg) lightness(+ 20%));
/* :hover */
--color-button-navbar-simple-hover-bg: color(var(--color-button-bg) alpha(10%));
--color-button-navbar-simple-hover-text: color(var(--color-button-bg) lightness(+ 20%));
/* :active */
--color-button-navbar-simple-active-bg: color(var(--color-button-bg) alpha(20%));
/* :selected */
--color-button-navbar-simple-selected-bg: color(var(--selected-item-color) alpha(15%));
--color-button-navbar-simple-selected-text: var(--selected-item-color);

/**
* color="primary"
Expand Down Expand Up @@ -248,6 +263,10 @@
box-shadow: var(--color-button-focus-shadow);
}

@nest &:focus[data-tone='navbar'] > .inner {
box-shadow: var(--color-button-navbar-focus-shadow);
}

@media (hover: hover) {
@nest &:hover > .inner {
background-color: var(--color-button-hover-bg);
Expand All @@ -258,7 +277,7 @@
background-color: var(--color-button-active-bg);
}

@nest &.simple {
@nest &.simple:not([data-tone='navbar']) {
@nest & > .inner {
background-color: var(--color-button-simple-enabled-bg);
color: var(--color-button-simple-enabled-text);
Expand All @@ -284,6 +303,33 @@
color: var(--color-button-simple-selected-text);
}
}

@nest &.simple[data-tone='navbar'] {
@nest & > .inner {
background-color: transparent;
color: var(--color-button-navbar-simple-color);
}

@nest & .spinner {
background-color: color(var(--white) alpha(80%));
}

@media (hover: hover) {
@nest &:hover > .inner {
background-color: var(--color-button-navbar-simple-hover-bg);
color: var(--color-button-navbar-simple-hover-text);
}
}

@nest &:active > .inner {
background-color: var(--color-button-navbar-simple-active-bg);
}

@nest &.selected > .inner {
background-color: var(--color-button-navbar-simple-selected-bg);
color: var(--color-button-navbar-simple-selected-text);
}
}
}

@nest &.inverted:not(.disabled):not(:focus):not(:hover):not(:active) {
Expand Down Expand Up @@ -414,32 +460,32 @@
border-radius: 3px;
box-shadow: 0 0 0 1px var(--color-button-bg);

@nest .root[data-icon-status='primary'] & {
@nest .root:not(.disabled)[data-icon-status='primary'] & {
background: var(--brand-primary);
}

@nest .root[data-icon-status='success'] & {
@nest .root:not(.disabled)[data-icon-status='success'] & {
background: var(--state-success-color);
}

@nest .root[data-icon-status='warning'] & {
@nest .root:not(.disabled)[data-icon-status='warning'] & {
background: var(--state-success-color);
}

@nest .root[data-icon-status='danger']:not(.disabled) & {
@nest .root:not(.disabled)[data-icon-status='danger'] & {
background: var(--state-success-color);
}

@nest .root.simple & {
@nest .root:not(.disabled).simple & {
box-shadow: 0 0 0 1px var(--component-bg);
}

@nest .root:not(.disabled):hover & {
box-shadow: 0 0 0 1px var(--color-button-hover-bg);
@nest .root:not(.disabled).simple[data-tone='navbar'] & {
box-shadow: 0 0 0 1px var(--main-navigation-color);
}

@nest .root.simple:not(.disabled):hover & {
box-shadow: 0 0 0 1px var(--color-button-simple-hover-bg);
@nest .root:not(.disabled):hover & {
box-shadow: 0 0 0 1px var(--color-button-hover-bg);
}
}

Expand Down
20 changes: 8 additions & 12 deletions packages/@sanity/components/src/buttons/types.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
export type ButtonComponent = React.ComponentType<{}> | 'button' | 'a'

export type ButtonColor = 'primary' | 'success' | 'danger' | 'white' | 'warning'
export type ButtonKind = 'simple' | 'secondary'
export type ButtonPadding = 'small' | 'medium' | 'large'
export type ButtonSize = 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large'

export interface ButtonProps {
kind?: ButtonKind
export interface ButtonProps extends Omit<React.HTMLProps<HTMLButtonElement>, 'size' | 'ref'> {
bleed?: boolean
color?: ButtonColor
onBlur?: (event: React.FocusEvent<HTMLAnchorElement | HTMLButtonElement>) => void
onClick?: (event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>) => void
children?: React.ReactNode
inverted?: boolean
icon?: React.ComponentType<{}>
iconStatus?: 'primary' | 'success' | 'warning' | 'danger'
inverted?: boolean
kind?: ButtonKind
loading?: boolean
className?: string
disabled?: boolean
tabIndex?: number
padding?: ButtonPadding
bleed?: boolean
ref?: React.Ref<any /* @todo: ButtonLike */>
selected?: boolean
size?: ButtonSize
tone?: 'navbar'
}

export type ButtonComponent = React.ComponentType<ButtonProps>

0 comments on commit bab150c

Please sign in to comment.