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

feat(Button): add size prop #1716

Merged
merged 10 commits into from
Jul 25, 2019
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `Props` param is required in `ShorthandValue` and `ShorthandCollection` @layershifter ([#1605](https://github.com/stardust-ui/react/pull/1605))
- `LoaderPosition` type is no longer exported @layershifter ([#1634](https://github.com/stardust-ui/react/pull/1634))
- Changed values for `textAlign` prop and renamed it to `align` for `Header` component @Bugaa92 ([#1668](https://github.com/stardust-ui/react/pull/1668))
- `paddingLeftRightValue` variable in `buttonVariables` was renamed to `padding` in Teams theme @layershifter ([#1716](https://github.com/stardust-ui/react/pull/1716))

### Features
- Split action handlers with "OR" condition in accessibility behaviors @sophieH29 ([#1622](https://github.com/stardust-ui/react/pull/1622))
Expand All @@ -37,13 +38,15 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Add bidirectional navigation following DOM in `FocusZone` @sophieH29 ([#1637](https://github.com/stardust-ui/react/pull/1647))
- Open `Popup` on `contextmenu` @jurokapsiar ([#1524](https://github.com/stardust-ui/react/pull/1524))
- Add `align` prop for `Text` component @Bugaa92 ([#1668](https://github.com/stardust-ui/react/pull/1668))
- Add `size` prop for `Button` component @layershifter ([#1716](https://github.com/stardust-ui/react/pull/1716))

### Fixes
- Fix `ChatMessage`'s focus border overlays `actionMenu` in Teams theme @mnajdova ([#1637](https://github.com/stardust-ui/react/pull/1637))
- Update `Checkbox` files for Teams Theme to match [redlines] @bcalvery ([#1656](https://github.com/stardust-ui/react/pull/1656))
- Add `color` prop to `Segment` typings @layershifter ([#1702](https://github.com/stardust-ui/react/pull/1702))
- Remove `color` prop from `Dialog` typings @layershifter ([#1702](https://github.com/stardust-ui/react/pull/1702))
- `Loader` uses `Text` component for `label` slot instead of `Box` @layershifter ([#1701](https://github.com/stardust-ui/react/pull/1701))
- Fix test cut off in `Button` component @layershifter ([#1716](https://github.com/stardust-ui/react/pull/1716))

### Documentation
- Make sidebar categories collapsible @lucivpav ([#1611](https://github.com/stardust-ui/react/pull/1611))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Button, Divider, Flex } from '@stardust-ui/react'
import * as React from 'react'

const ButtonExampleSizeShorthand: React.FC = () => (
<>
<Flex gap="gap.smaller">
<Button size="smallest" content="Smallest" />
<Button size="smaller" content="Smaller" />
<Button size="small" content="Small" />
</Flex>
<Divider />

<Button content="Medium (default)" />
<Divider />

<Flex gap="gap.smaller">
<Button size="large" content="Large" />
<Button size="larger" content="Larger" />
<Button size="largest" content="Largest" />
</Flex>
</>
)

export default ButtonExampleSizeShorthand
5 changes: 5 additions & 0 deletions docs/src/examples/components/Button/Variations/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ const Variations = () => (
description="A button can be shown in form of a text to indicate some less-pronounced actions."
examplePath="components/Button/Variations/ButtonExampleText"
/>
<ComponentExample
title="Size"
description="A button can have assorted sizes."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to consolidate the description of the size in the components' examples. We have different for Avatar, Text, Button.. :\

examplePath="components/Button/Variations/ButtonExampleSize"
/>
</ExampleSection>
)

Expand Down
6 changes: 6 additions & 0 deletions packages/react/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
commonPropTypes,
rtlTextContainer,
applyAccessibilityKeyHandlers,
SizeValue,
} from '../../lib'
import Icon, { IconProps } from '../Icon/Icon'
import Box, { BoxProps } from '../Box/Box'
Expand Down Expand Up @@ -69,6 +70,9 @@ export interface ButtonProps

/** A button can be formatted to show different levels of emphasis. */
secondary?: boolean

/** A size of the button. */
size?: SizeValue
}

export interface ButtonState {
Expand Down Expand Up @@ -97,11 +101,13 @@ class Button extends UIComponent<WithAsProp<ButtonProps>, ButtonState> {
primary: customPropTypes.every([customPropTypes.disallow(['secondary']), PropTypes.bool]),
text: PropTypes.bool,
secondary: customPropTypes.every([customPropTypes.disallow(['primary']), PropTypes.bool]),
size: customPropTypes.size,
}

static defaultProps = {
as: 'button',
accessibility: buttonBehavior as Accessibility,
size: 'medium',
}

static Group = ButtonGroup
Expand Down
190 changes: 77 additions & 113 deletions packages/react/src/themes/teams/components/Button/buttonStyles.ts
Original file line number Diff line number Diff line change
@@ -1,215 +1,179 @@
import { pxToRem } from '../../../../lib'
import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types'
import { ButtonProps, ButtonState } from '../../../../components/Button/Button'
import { ButtonVariables } from './buttonVariables'
import getBorderFocusStyles from '../../getBorderFocusStyles'

const buttonStyles: ComponentSlotStylesInput<ButtonProps & ButtonState, ButtonVariables> = {
root: ({ props, variables, theme: { siteVariables } }): ICSSInJSStyle => {
const { circular, disabled, fluid, primary, text, iconOnly, isFromKeyboard } = props
root: ({ props: p, variables: v, theme: { siteVariables } }): ICSSInJSStyle => {
const { borderWidth } = siteVariables

const {
height,
minWidth,
maxWidth,
borderRadius,
circularBorderRadius,
paddingLeftRightValue,

color,
colorHover,
colorFocus,
colorDisabled,
backgroundColor,
backgroundColorActive,
backgroundColorHover,
backgroundColorFocus,
backgroundColorDisabled,
borderColor,
borderColorHover,
borderColorDisabled,

primaryColor,
primaryColorHover,
primaryColorFocus,
primaryBackgroundColor,
primaryBackgroundColorActive,
primaryBackgroundColorHover,
primaryBackgroundColorFocus,
primaryBorderColor,

circularColor,
circularColorActive,
circularBackgroundColor,
circularBackgroundColorActive,
circularBackgroundColorHover,
circularBackgroundColorFocus,
circularBorderColor,
circularBorderColorHover,
circularBorderColorFocus,

textColor,
textColorHover,
textPrimaryColor,
textPrimaryColorHover,
boxShadow,
} = variables

const { ':focus': borderFocusStyles } = getBorderFocusStyles({
siteVariables,
isFromKeyboard,
...(circular && {
borderRadius: circularBorderRadius,
focusOuterBorderColor: circularBorderColorFocus,
isFromKeyboard: p.isFromKeyboard,
...(p.circular && {
borderRadius: v.circularBorderRadius,
focusOuterBorderColor: v.circularBorderColorFocus,
}),
})

return {
height,
minWidth,
maxWidth,
color,
backgroundColor,
borderRadius,
height: v.height,
minWidth: v.minWidth,
maxWidth: v.maxWidth,
color: v.color,
backgroundColor: v.backgroundColor,
borderRadius: v.borderRadius,
display: 'inline-flex',
justifyContent: 'center',
alignItems: 'center',
position: 'relative',
padding: `0 ${pxToRem(paddingLeftRightValue)}`,
padding: v.padding,
verticalAlign: 'middle',
cursor: 'pointer',

// rectangular button defaults
...(!text && {
...(!p.text && {
outline: 0,
borderWidth,
borderStyle: 'solid',
borderColor,
boxShadow,
borderColor: v.borderColor,
boxShadow: v.boxShadow,

':hover': {
color: colorHover,
backgroundColor: backgroundColorHover,
borderColor: borderColorHover,
color: v.colorHover,
backgroundColor: v.backgroundColorHover,
borderColor: v.borderColorHover,
},

':focus': {
boxShadow: 'none',
...(isFromKeyboard
...(p.isFromKeyboard
? {
color: colorFocus,
backgroundColor: backgroundColorFocus,
color: v.colorFocus,
backgroundColor: v.backgroundColorFocus,
...borderFocusStyles,
}
: { ':active': { backgroundColor: backgroundColorActive } }),
: { ':active': { backgroundColor: v.backgroundColorActive } }),
},
}),

// circular button defaults
...(circular &&
!text && {
minWidth: height,
...(p.circular &&
!p.text && {
minWidth: v.height,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, shouldn't this be updated depending on the size? It seems like a special case..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

      <Button size="small" circular />
      <Button circular />

Yep, it should

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Updated 👍

padding: 0,
color: circularColor,
backgroundColor: circularBackgroundColor,
borderColor: circularBorderColor,
borderRadius: circularBorderRadius,
color: v.circularColor,
backgroundColor: v.circularBackgroundColor,
borderColor: v.circularBorderColor,
borderRadius: v.circularBorderRadius,

':hover': {
color: circularColorActive,
backgroundColor: circularBackgroundColorHover,
borderColor: circularBorderColorHover,
color: v.circularColorActive,
backgroundColor: v.circularBackgroundColorHover,
borderColor: v.circularBorderColorHover,
},

':focus': {
boxShadow: 'none',
...(isFromKeyboard
...(p.isFromKeyboard
? {
color: circularColorActive,
backgroundColor: circularBackgroundColorFocus,
color: v.circularColorActive,
backgroundColor: v.circularBackgroundColorFocus,
...borderFocusStyles,
}
: { ':active': { backgroundColor: circularBackgroundColorActive } }),
: { ':active': { backgroundColor: v.circularBackgroundColorActive } }),
},
}),

// text button defaults
...(text && {
color: textColor,
...(p.text && {
color: v.textColor,
backgroundColor: 'transparent',
borderColor: 'transparent',
':hover': {
color: textColorHover,
color: v.textColorHover,
},
...(primary && {
color: textPrimaryColor,
...(p.primary && {
color: v.textPrimaryColor,
':hover': {
color: textPrimaryColorHover,
color: v.textPrimaryColorHover,
},
}),

':focus': {
boxShadow: 'none',
outline: 'none',
...(isFromKeyboard && borderFocusStyles),
...(p.isFromKeyboard && borderFocusStyles),
},
}),

// Overrides for "primary" buttons
...(primary &&
!text && {
color: primaryColor,
backgroundColor: primaryBackgroundColor,
borderColor: primaryBorderColor,
...(p.primary &&
!p.text && {
color: v.primaryColor,
backgroundColor: v.primaryBackgroundColor,
borderColor: v.primaryBorderColor,

':hover': {
color: primaryColorHover,
backgroundColor: primaryBackgroundColorHover,
color: v.primaryColorHover,
backgroundColor: v.primaryBackgroundColorHover,
},

':focus': {
boxShadow: 'none',
...(isFromKeyboard
...(p.isFromKeyboard
? {
color: primaryColorFocus,
backgroundColor: primaryBackgroundColorFocus,
color: v.primaryColorFocus,
backgroundColor: v.primaryBackgroundColorFocus,
...borderFocusStyles,
}
: { ':active': { backgroundColor: primaryBackgroundColorActive } }),
: { ':active': { backgroundColor: v.primaryBackgroundColorActive } }),
},
}),

// Overrides for "disabled" buttons
...(disabled && {
...(p.disabled && {
cursor: 'default',
color: colorDisabled,
backgroundColor: backgroundColorDisabled,
borderColor: borderColorDisabled,
color: v.colorDisabled,
backgroundColor: v.backgroundColorDisabled,
borderColor: v.borderColorDisabled,
boxShadow: 'none',
':hover': {
backgroundColor: backgroundColorDisabled,
backgroundColor: v.backgroundColorDisabled,
},
}),

...(fluid && {
...(p.fluid && {
width: '100%',
maxWidth: '100%',
}),

...(iconOnly && {
minWidth: height,
...(p.size === 'small' && {
padding: v.sizeSmallPadding,
height: v.sizeSmallHeight,
minWidth: v.sizeSmallMinWidth,
}),

...(p.iconOnly && {
minWidth: v.height,
padding: 0,
}),
}
},

// modifies the text of the button
content: ({ variables }): ICSSInJSStyle => ({
content: ({ props: p, variables: v }): ICSSInJSStyle => ({
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
fontWeight: variables.contentFontWeight,
fontSize: v.contentFontSize,
fontWeight: v.contentFontWeight,
lineHeight: v.contentLineHeight,

...(p.size === 'small' && {
fontSize: v.sizeSmallContentFontSize,
lineHeight: v.sizeSmallContentLineHeight,
}),
}),
}

Expand Down
Loading