Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

evergreen-buttons outline #10

Closed
jeroenransijn opened this issue Sep 5, 2017 · 4 comments
Closed

evergreen-buttons outline #10

jeroenransijn opened this issue Sep 5, 2017 · 4 comments

Comments

@jeroenransijn
Copy link
Contributor

jeroenransijn commented Sep 5, 2017

evergreen-buttons is a package exporting React components and a ButtonAppearances object. I think this package should export some opinionated button components too: CloseButton, BackButton, IconButton. Maybe more in the future.

Usage

import {
  Button,
  CloseButton,
  BackButton,
  IconButton, 
  ButtonAppearances
}  from 'evergreen-buttons'

<Button>Default (32)</Button>
<Button height={40}>Default 40</Button>
<Button height={36}>Default 36</Button>
<Button height={28}>Default 28</Button>

<Button appearance="green">Green</Button>
<Button appearance="blue">Blue</Button>
<Button appearance="red">Label</Button>

Design Example

screen shot 2017-09-04 at 5 49 08 pm

Key Implementation take aways

  • Button is="button" by default
  • Button implements Text
  • Button, and other controls, are infinitely scaleable on our 4px soft grid
  • Button height determines text size
  • Button uses ui font family
  • Button implements a appearance property that maps to ButtonAppearances
  • ButtonAppearances is an object containing available styles
  • default is the default prop for the appearance property

Button implements Text

A button is build up of text styles and stateful layer styles (default, hover, active, focus). Therefore a button component should implement the Text component. The stateful layer styles will be implemented through the ButtonAppearances object.

Using the css property on ui-box for appearance.

Since there is not a huge value proposition for overwriting the appearance of a button, I am leaning towards using the css property on ui-box to implement the stateful layer styles (but not dimensions).

const ButtonAppearances = {
   default: { ... },
   red: { ... },
   green: { ... },
   blue: { ... },
}

Directly referencing colors

Instead of using a indirection of primary => green and danger => red, I lean towards the simpler green and red. You can make mappings or new components in your application layer to add semantics or abstractions like these.

Button, and other controls, are infinitely scaleable on our 4px soft grid

In a lot of cases, design systems implement a abstraction to express different button sizes. This can be something like small, medium, large. I have mixed feelings about this, because it's a level of indirection that is hard to change in the future. Instead I would like to try a different approach.

Infinitely scalable buttons

One of the premises I am building this design system on, is that you can never anticipate all future requirements, only prepare for it. In a different project I have implemented a button component that is infinitely scalable by simply setting the height property. Your components become less dependent on other use cases throughout your app. It is somewhat harder to change small or medium later on, or put a new size in between.

The benefit of referring to a small or medium button is almost non-existent in my experience, instead designers and engineers would use references as Button 32 and Button 40 in communication and design documentation.

Restricting the height you pass

While it is great to have buttons be available in any size, it becomes annoying for the implementer not to have any height constraints. To solve that, the height property will only accept values on the grid.

4px soft grid height enforcement

The grid scale we are using is a 8px major scale, with a 4px minor scale. I am not sure how this will be enforced, but I think we'll just accept anything you can divide by 4 — and otherwise throw an error / violation.

Using the height to get the text size

Because the height is infinitely scalable (on our soft grid), we need the text size to adjust when the height adjusts. In the past I have done this at one point using a function similar to getTextStyleForControl({ height }). The right final abstraction will require me playing around a little.

Disabled styles

Disabled styles should be implemented on [disabled] for buttons and [data-disabled] for links.

React Router Link and Link component

In some cases you need the styling of a Button with functionality of a ReactRouterLink or Link component. This can be done through setting the is property to this component:

<Button is={Link}>Label</Button>

IconButton

This should be used for a single icon.

BackButton

This should be a Button with a left arrow icon and text.

CloseButton

This should be a Button with a close icon and text.

@nettofarah
Copy link
Contributor

I like this!
Still not sure how I feel about referring to colors by name though.
I know it is unlikely that we'd change our brand colors anytime soon, but I still enjoy using abstractions such as danger and primary.

I don't feel strongly about this though, just my 2 cents.

@jeroenransijn
Copy link
Contributor Author

Love the timely feedback, keep them coming 👍 @nettofarah thanks for the input!

How it is currently implemented in the React UI Library (internal Segment library) It is kind of hard to pull the trigger on changing what primary means. Blue buttons will become more used throughout our app in the future as a primary button, green will reserved a more severe primary actions such as creating new things. Primary is very much a relative term, in a Dialog the primary button might be blue, whereas in a creation form it might be green.

That being said, I think there is still place for a primary and danger abstraction, but in our application:

const DangerButton = props => <Button appearance='red' {...props} />
const PrimaryButton = props => <Button appearance='green' {...props} />

// Or something like
const SemanticColors = {
   primary: colors.green['500'],
   danger: colors.red['500']
}

@nettofarah
Copy link
Contributor

Sounds good to me!
I'm sold :)

@jeroenransijn
Copy link
Contributor Author

Implemented, see #13.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants