@atlaskit/button
Version:
A button triggers an event or action. They let users know what will happen next.
349 lines (347 loc) • 11.1 kB
JavaScript
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
import { fg } from '@atlaskit/platform-feature-flags/fg';
const gridSize = 8;
const HAS_DISABLED_BACKGROUND = ['default', 'primary', 'danger', 'warning'];
const heights = {
default: `${32 / 14}em`,
// 32px
compact: `${24 / 14}em`,
none: 'auto'
};
const lineHeights = {
default: heights.default,
compact: heights.compact,
none: 'inherit'
};
const padding = {
// 10px gutter
default: `0 ${gridSize + gridSize / 4}px`,
compact: `0 ${gridSize + gridSize / 4}px`,
none: '0'
};
const singleIconPadding = {
// 2px gutter
compact: `0 ${gridSize / 4}px`,
default: `0 ${gridSize / 4}px`,
none: '0'
};
const verticalAlign = {
default: 'middle',
compact: 'middle',
none: 'baseline'
};
const defaultAfterStyles = {
borderRadius: 'inherit',
inset: "var(--ds-space-0, 0px)",
borderStyle: 'solid',
borderWidth: "var(--ds-border-width, 1px)",
pointerEvents: 'none',
position: 'absolute'
};
const defaultStyles = {
background: "var(--ds-background-neutral-subtle, #00000000)",
color: "var(--ds-text, #292A2E)",
'&::after': {
...defaultAfterStyles,
content: '""',
borderColor: "var(--ds-border, #0B120E24)"
},
'&:hover': {
background: "var(--ds-background-neutral-hovered, #0B120E24)"
},
'&:active': {
background: "var(--ds-background-neutral-pressed, #080F214A)"
},
'&[data-has-overlay="true"]:not([disabled]):hover': {
background: "var(--ds-background-neutral-subtle, #00000000)"
},
'&:disabled[disabled]': {
background: "var(--ds-background-neutral-subtle, #00000000)"
},
'&:disabled[disabled]:hover': {
background: "var(--ds-background-neutral-subtle, #00000000)"
},
'&:disabled[disabled]:active': {
background: "var(--ds-background-neutral-subtle, #00000000)"
}
};
const primaryStyles = {
background: "var(--ds-background-brand-bold, #1868DB)",
color: "var(--ds-text-inverse, #FFFFFF)",
'&:hover': {
background: "var(--ds-background-brand-bold-hovered, #1558BC)"
},
'&:active': {
background: "var(--ds-background-brand-bold-pressed, #144794)"
},
'&[data-has-overlay="true"]:not([disabled]):hover': {
background: "var(--ds-background-brand-bold, #1868DB)"
}
};
const linkStyles = {
background: 'transparent',
color: "var(--ds-link, #1868DB)",
'&:hover': {
color: "var(--ds-link, #1868DB)",
textDecoration: 'underline'
},
'&:active': {
color: "var(--ds-link-pressed, #1558BC)",
textDecoration: 'underline'
}
};
const subtleStyles = {
background: 'transparent',
color: "var(--ds-text-subtle, #505258)",
'&:hover': {
background: "var(--ds-background-neutral-subtle-hovered, #0515240F)"
},
'&:active': {
background: "var(--ds-background-neutral-subtle-pressed, #0B120E24)"
},
'&[data-has-overlay="true"]:not([disabled]):hover': {
background: 'transparent'
}
};
const subtleLinkStyles = {
background: 'transparent',
color: "var(--ds-text-subtle, #505258)",
'&:hover': {
background: 'transparent',
color: "var(--ds-text-subtle, #505258)",
textDecoration: 'underline'
},
'&:active': {
background: 'transparent',
color: "var(--ds-text, #292A2E)",
textDecoration: 'underline'
}
};
const warningStyles = {
background: "var(--ds-background-warning-bold, #FBC828)",
color: "var(--ds-text-warning-inverse, #292A2E)",
'&:hover': {
background: "var(--ds-background-warning-bold-hovered, #FCA700)"
},
'&:active': {
background: "var(--ds-background-warning-bold-pressed, #F68909)"
},
'&[data-has-overlay="true"]:not([disabled]):hover': {
background: "var(--ds-background-warning-bold, #FBC828)"
}
};
const dangerStyles = {
background: "var(--ds-background-danger-bold, #C9372C)",
color: "var(--ds-text-inverse, #FFFFFF)",
'&:hover': {
background: "var(--ds-background-danger-bold-hovered, #AE2E24)"
},
'&:active': {
background: "var(--ds-background-danger-bold-pressed, #872821)"
},
'&[data-has-overlay="true"]:not([disabled]):hover': {
background: "var(--ds-background-danger-bold, #C9372C)"
}
};
const selectedStyles = {
background: "var(--ds-background-selected, #E9F2FE)",
color: "var(--ds-text-selected, #1868DB)",
'&:not([disabled])::after': {
...defaultAfterStyles,
content: '""',
borderColor: "var(--ds-border-selected, #1868DB)"
}
};
/**
* Anchor-text-color variants applied when the legacy `Button` is rendered as
* an `<a>` (via `href`). Each `<variant>WithAnchorTextColorStyles` is a
* self-contained appearance object that adds explicit `color` /
* `text-decoration` on the base, `:hover`, and `:active` states, preventing
* browser default or ambient anchor styles from overriding the button's
* intended text color or adding an unwanted underline.
*
* Gated by `platform-dst-legacy-button-anchor-text-color` and used *instead*
* of the base `<variant>Styles`. When cleaning up the gate: delete the base
* `<variant>Styles` and rename the `WithAnchorTextColor` variant to replace
* it.
*
* Link-like variants (`link`, `subtle-link`) keep their intentional underline
* on `:hover` / `:active`.
*/
const defaultWithAnchorTextColorStyles = {
...defaultStyles,
textDecoration: 'none',
'&:hover': {
...defaultStyles['&:hover'],
color: "var(--ds-text, #292A2E)",
textDecoration: 'none'
},
'&:active': {
...defaultStyles['&:active'],
color: "var(--ds-text, #292A2E)",
textDecoration: 'none'
}
};
const primaryWithAnchorTextColorStyles = {
...primaryStyles,
textDecoration: 'none',
'&:hover': {
...primaryStyles['&:hover'],
color: "var(--ds-text-inverse, #FFFFFF)",
textDecoration: 'none'
},
'&:active': {
...primaryStyles['&:active'],
color: "var(--ds-text-inverse, #FFFFFF)",
textDecoration: 'none'
}
};
const linkWithAnchorTextColorStyles = {
...linkStyles,
textDecoration: 'none'
};
const subtleWithAnchorTextColorStyles = {
...subtleStyles,
textDecoration: 'none',
'&:hover': {
...subtleStyles['&:hover'],
color: "var(--ds-text-subtle, #505258)",
textDecoration: 'none'
},
'&:active': {
...subtleStyles['&:active'],
color: "var(--ds-text-subtle, #505258)",
textDecoration: 'none'
}
};
const subtleLinkWithAnchorTextColorStyles = {
...subtleLinkStyles,
textDecoration: 'none'
};
const warningWithAnchorTextColorStyles = {
...warningStyles,
textDecoration: 'none',
'&:hover': {
...warningStyles['&:hover'],
color: "var(--ds-text-warning-inverse, #292A2E)",
textDecoration: 'none'
},
'&:active': {
...warningStyles['&:active'],
color: "var(--ds-text-warning-inverse, #292A2E)",
textDecoration: 'none'
}
};
const dangerWithAnchorTextColorStyles = {
...dangerStyles,
textDecoration: 'none',
'&:hover': {
...dangerStyles['&:hover'],
color: "var(--ds-text-inverse, #FFFFFF)",
textDecoration: 'none'
},
'&:active': {
...dangerStyles['&:active'],
color: "var(--ds-text-inverse, #FFFFFF)",
textDecoration: 'none'
}
};
const hasOverlayStyles = {
'&[data-has-overlay="true"]': {
cursor: 'default',
textDecoration: 'none'
}
};
export function getCss({
appearance,
spacing,
isSelected,
shouldFitContainer,
isOnlySingleIcon
}) {
const baseAppearanceStyles = fg('platform-dst-legacy-button-anchor-text-color') ? {
...(appearance === 'default' && defaultWithAnchorTextColorStyles),
...(appearance === 'primary' && primaryWithAnchorTextColorStyles),
...(appearance === 'link' && linkWithAnchorTextColorStyles),
...(appearance === 'subtle' && subtleWithAnchorTextColorStyles),
...(appearance === 'subtle-link' && subtleLinkWithAnchorTextColorStyles),
...(appearance === 'warning' && warningWithAnchorTextColorStyles),
...(appearance === 'danger' && dangerWithAnchorTextColorStyles)
} : {
...(appearance === 'default' && defaultStyles),
...(appearance === 'primary' && primaryStyles),
...(appearance === 'link' && linkStyles),
...(appearance === 'subtle' && subtleStyles),
...(appearance === 'subtle-link' && subtleLinkStyles),
...(appearance === 'warning' && warningStyles),
...(appearance === 'danger' && dangerStyles)
};
const appearanceStyles = appearance === 'default' && fg('platform-dst-tokens-finesse') ? {
...baseAppearanceStyles,
'&:hover': {
...baseAppearanceStyles['&:hover'],
background: "var(--ds-background-neutral-subtle-hovered, #0515240F)"
},
'&:active': {
...baseAppearanceStyles['&:active'],
background: "var(--ds-background-neutral-subtle-pressed, #0B120E24)"
}
} : baseAppearanceStyles;
const activeStyles = appearanceStyles['&:active'];
return {
// 0px margin added to css-reset
alignItems: 'baseline',
borderWidth: 0,
borderRadius: "var(--ds-radius-medium, 6px)",
boxSizing: 'border-box',
display: 'inline-flex',
fontSize: 'inherit',
fontStyle: 'normal',
// Chrome recently changed button so that they use 'arial' as the font family
fontFamily: 'inherit',
fontWeight: "var(--ds-font-weight-medium, 500)",
// margin for button has been applied to css reset
maxWidth: '100%',
// Needed to position overlay
position: 'relative',
textAlign: 'center',
textDecoration: 'none',
transition: fg('platform-dst-motion-uplift-button') ? `${"var(--ds-button-hovered, background-color border-color 150ms cubic-bezier(0.4, 1, 0.6, 1))"}, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38)` : 'background 0.1s ease-out, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38)',
whiteSpace: 'nowrap',
cursor: 'pointer',
height: heights[spacing],
lineHeight: lineHeights[spacing],
padding: isOnlySingleIcon ? singleIconPadding[spacing] : padding[spacing],
verticalAlign: verticalAlign[spacing],
width: shouldFitContainer ? '100%' : 'auto',
// justifyContent required for shouldFitContainer buttons with an icon inside
justifyContent: 'center',
...(isSelected ? selectedStyles : {
...appearanceStyles,
...(activeStyles && fg('platform-dst-motion-uplift-button') && {
'&:active': {
...activeStyles,
transition: "var(--ds-button-pressed, background-color border-color 150ms cubic-bezier(0.4, 1, 0.6, 1))"
}
}),
'&[disabled]': {
color: "var(--ds-text-disabled, #080F214A)",
backgroundColor: HAS_DISABLED_BACKGROUND.includes(appearance) ? "var(--ds-background-disabled, #0515240F)" : 'transparent',
cursor: 'not-allowed',
textDecoration: 'none',
'&:hovered': {
backgroundColor: HAS_DISABLED_BACKGROUND.includes(appearance) ? "var(--ds-background-disabled, #0515240F)" : 'transparent'
},
'&:active': {
backgroundColor: HAS_DISABLED_BACKGROUND.includes(appearance) ? "var(--ds-background-disabled, #0515240F)" : 'transparent'
}
},
...hasOverlayStyles
}),
'&::-moz-focus-inner': {
border: 0,
margin: 0,
padding: 0
}
};
}