Skip to content

Instantly share code, notes, and snippets.

@cheton
Last active November 22, 2016 02:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cheton/e12b4fefee101cbabb07fb34b3754411 to your computer and use it in GitHub Desktop.
Save cheton/e12b4fefee101cbabb07fb34b3754411 to your computer and use it in GitHub Desktop.
Buttons

Button Styles

<Button btnStyle="default">Default</Button>
<Button btnStyle="primary">Primary</Button>
<Button btnStyle="emphasis">Emphasis</Button>
<Button btnStyle="danger">Danger (Alias of Emphasis)</Button>
<Button btnStyle="flat">Flat</Button>
<Button btnStyle="border">Border (Alias of Flat)</Button>
<Button btnStyle="link">Link</Button>

Button Sizes

<Button btnSize="lg">Large<Button>
<Button btnSize="large">Large<Button>
<Button btnSize="md">Medium<Button>
<Button btnSize="medium">Medium<Button>
<Button btnSize="sm">Small<Button>
<Button btnSize="small">Small<Button>
<Button btnSize="xs">Extra Small<Button>
<Button btnSize="extra-small">Extra Small<Button>

Button States

<Button>Normal</Button>
<Button hover>Hover</Button>
<Button active>Active</Button>
<Button focus>Focus</Button>
<Button disabled>Disabled</Button>

Block Buttons

<Button block>Block Button<Button>

Button Groups

Default button group

<ButtonGroup>
    <Button active>Left</Button>
    <Button>Middle</Button>
    <Button>Right</Button>
</ButtonGroup>
<ButtonGroup>
    <Button iconOnly><i className="fa fa-pencil" /></Button>
    <Button iconOnly><i className="fa fa-mail-reply" /></Button>
</ButtonGroup>

Flat button group

<ButtonGroup>
    <Button btnStyle="flat" active>Left</Button>
    <Button btnStyle="flat">Middle</Button>
    <Button btnStyle="flat">Right</Button>
</ButtonGroup>
<ButtonGroup>
    <Button btnStyle="flat" iconOnly><i className="fa fa-pie-chart" /></Button>
    <Button btnStyle="flat" iconOnly><i className="fa fa-line-chart" /></Button>
    <Button btnStyle="flat" iconOnly><i className="fa fa-table" /></Button>
</ButtonGroup>

Vertical button group

<ButtonGroup vertical>
    <Button>Top</Button>
    <Button>Middle</Button>
    <Button>Bottom</Button>
</ButtonGroup>

Button Toolbar

<ButtonToolbar>
    <ButtonGroup>
        <Button>Button Group 1</Button>
        <Button>Button Group 1</Button>
    </ButtonGroup>
    <ButtonGroup>
        <Button>Button Group 2</Button>
        <Button>Button Group 2</Button>
    </ButtonGroup>
</ButtonToolbar>

Button (w/ Icon)

Static (default)

<Button>
    <i className="fa fa-download" />
    Download
</Button>
<Button btnStyle="primary">
    <i className="fa fa-plus" />
    Add Account
</Button>

Progressing

<Button disabled>
    <i className="fa fa-circle-o-notch rotate" />
    Uploading
</Button>
<Button btnStyle="primary" disabled>
    <i className="fa fa-circle-o-notch rotate" />
    Uploading
</Button>

Static (flat)

<Button disabled>
    <i className="fa fa-circle-o-notch rotate" />
    Uploading
</Button>
<Button btnStyle="primary" disabled>
    <i className="fa fa-circle-o-notch rotate" />
    Uploading
</Button>

Icon only

<Button iconOnly>
    <i className="fa fa-comment" />
</Button>
<Button btnStyle="primary" iconOnly>
    <i className="fa fa-plus" />
</Button>
<Button btnStyle="emphasis" iconOnly>
    <i className="fa fa-search" />
</Button>
<Button btnStyle="flat" iconOnly>
    <i className="fa fa-cog" />
</Button>

Dropdown Buttons

Single

<Button dropdown>
    Dropdown
</Button>

Split

<ButtonGroup>
    <Button>Default<Button>
    <Button dropdown />
</ButtonGroup>

Text

<Button btnStyle="link" dropdown>
All Devices
</Button>

Icon

<Button dropdown>
    <i className="fa fa-database" />
    All Devices
</Button>

Sizes

<Button btnSize="large" dropdown>Large</Button>
<Button btnSize="medium" dropdown>Default</Button>
<Button btnSize="small" dropdown>Small</Button>
<Button btnSize="extra-small" dropdown>Extra Small</Button>
import classNames from 'classnames';
import React, { PropTypes } from 'react';
import styles from './index.styl';
const Button = (props) => {
const {
type = 'button',
children,
className,
componentClass,
hover,
active,
focus,
disabled,
block,
dropdown,
iconOnly,
btnSize,
btnStyle,
...others
} = props;
const Component = componentClass || 'button';
return (
<Component
{...others}
type={type}
className={classNames(
className,
styles.btn,
{ [styles['btn-lg']]: btnSize === 'large' || btnSize === 'lg' },
{ [styles['btn-md']]: btnSize === 'medium' || btnSize === 'md' },
{ [styles['btn-sm']]: btnSize === 'small' || btnSize === 'sm' },
{ [styles['btn-xs']]: btnSize === 'extra-small' || btnSize === 'xs' },
{ [styles['btn-default']]: btnStyle === 'default' },
{ [styles['btn-primary']]: btnStyle === 'primary' },
{ [styles['btn-danger']]: btnStyle === 'danger' || btnStyle === 'emphasis' },
{ [styles['btn-border']]: btnStyle === 'border' || btnStyle === 'flat' },
{ [styles['btn-link']]: btnStyle === 'link' },
{ [styles['btn-block']]: block },
{ [styles['dropdown-toggle']]: dropdown },
{ [styles['btn-icon-only']]: iconOnly },
{ [styles.hover]: hover },
{ [styles.active]: active },
{ [styles.focus]: focus }
)}
disabled={!!disabled}
>
{dropdown &&
<span className={styles.caret} />
}
{children}
</Component>
);
};
Button.propTypes = {
hover: PropTypes.bool,
active: PropTypes.bool,
focus: PropTypes.bool,
disabled: PropTypes.bool,
block: PropTypes.bool,
dropdown: PropTypes.bool,
iconOnly: PropTypes.bool,
btnSize: PropTypes.oneOf([
'lg',
'md',
'sm',
'xs',
'large',
'medium',
'small',
'extra-small'
]),
btnStyle: PropTypes.oneOf([
'default',
'primary',
'danger',
'emphasis', // alias of "danger"
'border',
'flat', // anlias of "border"
'link'
]),
componentClass: PropTypes.element,
type: PropTypes.oneOf([
'button',
'reset',
'submit'
])
};
Button.defaultProps = {
hover: false,
active: false,
focus: false,
disabled: false,
block: false,
dropdown: false,
iconOnly: false,
btnSize: 'md',
btnStyle: 'default'
};
export default Button;
import classNames from 'classnames';
import React, { PropTypes } from 'react';
import styles from './index.styl';
const ButtonGroup = ({ className, btnSize, vertical, ...props }) => {
return (
<div
{...props}
className={classNames(
className,
styles['btn-group'],
{ [styles['btn-group-lg']]: btnSize === 'large' || btnSize === 'lg' },
{ [styles['btn-group-md']]: btnSize === 'medium' || btnSize === 'md' },
{ [styles['btn-group-sm']]: btnSize === 'small' || btnSize === 'sm' },
{ [styles['btn-group-xs']]: btnSize === 'extra-small' || btnSize === 'xs' },
{ [styles['btn-group-vertical']]: vertical }
)}
/>
);
};
ButtonGroup.propTypes = {
btnSize: PropTypes.oneOf([
'lg',
'md',
'sm',
'xs',
'large',
'medium',
'small',
'extra-small'
]),
vertical: PropTypes.bool
};
ButtonGroup.defaultProps = {
btnSize: '', // Defaults to empty string
vertical: false
};
export default ButtonGroup;
import classNames from 'classnames';
import React from 'react';
import styles from './index.styl';
const ButtonToolbar = ({ className, ...props }) => {
return (
<div
{...props}
className={classNames(
className,
styles['btn-toolbar']
)}
/>
);
};
export default ButtonToolbar;
export Button from './Button';
export ButtonGroup from './ButtonGroup';
export ButtonToolbar from './ButtonToolbar';
// Button
// --------------------------------------------------
.btn {
display: inline-block;
min-width: 80px;
padding: 5px 12px;
margin-bottom: 0; // For input.btn
font-size: 13px;
font-weight: normal;
line-height: 20px;
text-align: center;
white-space: nowrap;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
border: 1px solid transparent;
border-radius: 3px;
&,
&:active,
&.active {
&:focus,
&.focus {
outline: none;
}
}
&:hover,
&.hover,
&:focus,
&.focus {
color: #222;
text-decoration: none;
}
&:active,
&.active {
outline: none;
background-image: none;
box-shadow: 0 1px 4px rgba(0, 0, 0, .1) inset;
}
&.disabled,
&[disabled],
fieldset[disabled] & {
cursor: not-allowed;
opacity: .4;
}
a & {
&.disabled,
fieldset[disabled] & {
pointer-events: none; // Future-proof disabling of clicks on `<a>` elements
}
}
+ .btn {
margin-left: 4px;
}
:global {
.fa {
font-size: 14px;
margin-right: 8px;
}
}
&.btn-icon-only {
:global {
.fa {
margin-right: 0;
}
}
}
&.btn-lg,
&.btn-md,
&.btn-sm,
&.btn-xs {
:global {
.fa {
font-size: inherit;
}
}
}
// button with icon
&.btn-icon-only {
min-width: 0;
padding-left: 0;
padding-right: 0;
width: 42px;
}
}
// Alternate buttons
// --------------------------------------------------
.btn-default {
color: #222;
background-color: #fbfbfb;
background-image: linear-gradient(to bottom, #fbfbfb 0%, #ececec 100%);
background-repeat: repeat-x;
border-color: #ccc;
&:active,
&.active {
color: #222;
background-color: #eee;
background-image: none;
border-color: #bbb;
box-shadow: 0 1px 4px rgba(0, 0, 0, .1) inset;
}
&:focus,
&.focus {
color: #222;
border-color: #0096cc;
}
&:hover,
&.hover {
color: #222;
background-color: #fff;
background-image: linear-gradient(to bottom, #fff 0%, #f5f5f5 100%);
background-repeat: repeat-x;
border-color: #bbb;
}
&.disabled,
&[disabled],
fieldset[disabled] & {
&:hover,
&.hover,
&:focus,
&.focus {
background-color: #fbfbfb;
background-image: linear-gradient(to bottom, #fbfbfb 0%, #ececec 100%);
background-repeat: repeat-x;
border-color: #ccc;
}
}
}
.btn-primary {
color: #fff;
background-color: #0096cc;
background-image: linear-gradient(to bottom, #00a7e6 0%, #0096cc 100%);
background-repeat: repeat-x;
border-color: #0095ce;
&:active,
&.active {
color: #fff;
background-color: #009ed8;
background-image: none;
border-color: #00759f;
box-shadow: 0 1px 6px rgba(0, 0, 0, .15) inset;
}
&:focus,
&.focus {
color: #fff;
border-color: #444;
box-shadow: 0 0 1px #fff inset;
}
&:hover,
&.hover {
color: #fff;
background-color: #1daee5;
background-image: linear-gradient(to bottom, #1daee5 0%, #00a3df 100%);
background-repeat: repeat-x;
border-color: #00759f;
}
&.disabled,
&[disabled],
fieldset[disabled] & {
&:hover,
&.hover,
&:focus,
&.focus {
background-color: #0096cc;
background-image: linear-gradient(to bottom, #00a7e6 0%, #0096cc 100%);
background-repeat: repeat-x;
border-color: #0095ce;
}
}
}
.btn-danger {
color: #fff;
background-color: #db3d44;
background-image: linear-gradient(to bottom, #e15054 0%, #db3d44 100%);
background-repeat: repeat-x;
border-color: #d8262b;
&:active,
&.active {
color: #fff;
background-color: #e15054;
background-image: none;
border-color: #c22327;
box-shadow: 0 1px 6px rgba(0, 0, 0, .15) inset;
}
&:focus,
&.focus {
color: #fff;
border-color: #444;
box-shadow: 0 0 1px #fff inset;
}
&:hover,
&.hover {
color: #fff;
background-color: #e15f5f;
background-image: linear-gradient(to bottom, #e15f5f 0%, #e15054 100%);
background-repeat: repeat-x;
border-color: #c22327;
}
&.disabled,
&[disabled],
fieldset[disabled] & {
&:hover,
&.hover,
&:focus,
&.focus {
background-color: #db3d44;
background-image: linear-gradient(to bottom, #e15054 0%, #db3d44 100%);
background-repeat: repeat-x;
border-color: #d8262b;
}
}
}
.btn-border {
color: #222;
background-color: #fff;
background-image: linear-gradient(to bottom, #fff 0%, #fff 100%);
background-image: none! important;
background-repeat: repeat-x;
border-color: #ccc;
transition: all .2s linear 0s
&:active,
$.active {
color: #222;
background-color: #eee;
background-image: none;
border-color: #bbb;
box-shadow: 0 1px 2px rgba(0, 0, 0, .1) inset;
}
&:focus,
&.focus {
color: #222;
border-color: #0096cc;
}
&:hover,
&.hover {
color: #222;
background-color: #f4f4f4;
background-image: linear-gradient(to bottom, #f4f4f4 0%, #f4f4f4 100%);
background-repeat: repeat-x;
border-color: #bbb;
}
&.disabled,
&[disabled],
fieldset[disabled] & {
&:hover,
&.hover,
&:focus,
&.focus {
background-color: #fff;
background-image: linear-gradient(to bottom, #fff 0%, #fff 100%);
background-repeat: repeat-x;
border-color: #ccc;
}
}
}
// Link buttons
// -------------------------
// Make a button look and behave like a link
.btn-link {
padding-right: 0;
padding-left: 0;
font-weight: normal;
color: #0096cc;
border-radius: 0;
&,
&:active,
&.active,
&.disabled,
&[disabled],
fieldset[disabled] & {
background-color: transparent;
box-shadow: none;
}
&,
&:hover,
&.hover,
&:focus,
&:active {
border-color: transparent;
}
&:hover,
&.hover,
&:focus {
color: #db3d44;
text-decoration: underline;
background-color: transparent;
}
&.disabled,
&[disabled],
fieldset[disabled] & {
&:hover,
&.hover,
&:focus,
&.focus {
color: #e6e6e6;
text-decoration: none;
}
}
}
// Button Sizes
// --------------------------------------------------
.btn-lg,
.btn-group-lg > .btn {
padding: 9px 12px;
font-size: 16px;
line-height: 24px;
border-radius: 3px;
&.btn-icon-only {
width: 58px;
}
}
.btn-md,
.btn-group-md > .btn {
padding: 5px 12px;
font-size: 13px;
line-height: 20px;
border-radius: 3px;
}
.btn-sm,
.btn-group-sm > .btn {
padding: 4px 12px;
font-size: 12px;
line-height: 18px;
border-radius: 3px;
&.btn-icon-only {
width: 36px;
}
}
.btn-xs,
.btn-group-xs > .btn {
padding: 1px 12px;
font-size: 12px;
line-height: 18px;
border-radius: 3px;
&.btn-icon-only {
width: 28px;
}
}
// Block button
// --------------------------------------------------
.btn-block {
display: block;
width: 100%;
// Vertically space out multiple block buttons
&.btn + &.btn,
+ .btn-block {
margin-left: 0;
margin-top: 8px;
}
}
// Specificity overrides
input[type="submit"],
input[type="reset"],
input[type="button"] {
&.btn-block {
width: 100%;
}
}
// Button groups
// --------------------------------------------------
// Make the div behave like a button
.btn-group,
.btn-group-vertical {
position: relative;
display: inline-block;
vertical-align: top; // match .btn alignment given font-size hack above
> .btn {
position: relative;
float: left;
// Bring the "active" button to the front
&:hover,
&.hover,
&:active,
&.active {
z-index: 2;
}
&:focus,
&.focus {
z-index: 3;
}
}
}
// Prevent double borders when buttons are next to each other
.btn-group {
.btn + .btn,
.btn + .btn-group,
.btn-group + .btn,
.btn-group + .btn-group {
margin-left: -1px;
}
+ .btn-group {
margin-left: 4px;
}
}
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
margin-left: -5px; // Offset the first child's margin
clearfix();
.btn,
.btn-group,
.input-group {
float: left;
}
> .btn,
> .btn-group,
> .input-group {
margin-left: 5px;
}
}
.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
border-radius: 0;
}
// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
.btn-group > .btn:first-child {
margin-left: 0;
&:not(:last-child):not(.dropdown-toggle) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
}
// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it
.btn-group > .btn:last-child:not(:first-child),
.btn-group > .dropdown-toggle:not(:first-child) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)
.btn-group > .btn-group {
float: left;
}
.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
border-radius: 0;
}
.btn-group > .btn-group:first-child:not(:last-child) {
> .btn:last-child,
> .dropdown-toggle {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
}
.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
// On active and open, don't show outline
.btn-group .dropdown-toggle:active,
.btn-group.open .dropdown-toggle {
outline: 0;
}
// Sizing
//
// Remix the default button sizing classes into new ones for easier manipulation.
.btn-group-xs > .btn {
@extend .btn-xs;
}
.btn-group-sm > .btn {
@extend .btn-sm;
}
.btn-group-md > .btn {
@extend .btn-md;
}
.btn-group-lg > .btn {
@extend .btn-lg;
}
// Button dropdowns
// ----------------------
.caret {
display: inline-block;
width: 0;
height: 0;
vertical-align: middle;
border-top: 4px dashed #666;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
}
// Replace min-width from 80px (.btn) to 0
.dropdown-toggle {
min-width: 0;
.caret {
float: right; // To ensure the caret float to right
margin-top: 8px;
margin-right: 0;
margin-bottom: 8px;
margin-left: 8px;
.btn-lg& {
margin-top: 9.5px;
margin-bottom: 9.5px;
}
.btn-md& {
margin-top: 8px;
margin-bottom: 8px;
}
.btn-sm& {
margin-top: 7px;
margin-bottom: 7px;
}
.btn-xs& {
margin-top: 7px;
margin-bottom: 7px;
}
}
&.btn {
text-align: left;
padding-left: 12px;
padding-right: 12px;
}
&.btn-icon-only {
text-align: center;
}
&.btn-link {
color: @text-color;
padding-left: 0;
padding-right: 0;
text-decoration: none;
&:hover {
color: @link-color;
.fa {
color: @link-color;
}
.caret {
border-top-color: @link-color;
}
}
}
}
// Split button dropdowns
// ----------------------
// Give the line between buttons some depth
.btn-group > .btn + .dropdown-toggle {
padding-left: 8px;
padding-right: 8px;
min-width: 0;
// Reposition the caret
.caret {
margin-left: 0;
}
}
.btn-group > .btn-lg + .dropdown-toggle {
padding-left: 12px;
padding-right: 12px;
}
// Carets in other button sizes
.btn-lg .caret {
border-width: 5px 5px 0;
border-bottom-width: 0;
}
// Upside down carets for .dropup
.dropup .btn-lg .caret {
border-width: 0 5px 5px;
}
// Vertical button groups
// ----------------------
.btn-group-vertical {
> .btn,
> .btn-group,
> .btn-group > .btn {
display: block;
float: none;
width: 100%;
max-width: 100%;
}
// Clear floats so dropdown menus can be properly placed
> .btn-group {
clearfix();
> .btn {
float: none;
}
}
> .btn + .btn,
> .btn + .btn-group,
> .btn-group + .btn,
> .btn-group + .btn-group {
margin-top: -1px;
margin-left: 0;
}
}
.btn-group-vertical > .btn {
&:not(:first-child):not(:last-child) {
border-radius: 0;
}
&:first-child:not(:last-child) {
border-top-radius: 3px;
border-bottom-radius: 0;
}
&:last-child:not(:first-child) {
border-top-radius: 0;
border-bottom-radius: 3px;
}
}
.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
border-radius: 0;
}
.btn-group-vertical > .btn-group:first-child:not(:last-child) {
> .btn:last-child,
> .dropdown-toggle {
border-bottom-radius: 0;
}
}
.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
border-top-radius: 0;
}
// Justified button groups
// ----------------------
.btn-group-justified {
display: table;
width: 100%;
table-layout: fixed;
border-collapse: separate;
> .btn,
> .btn-group {
float: none;
display: table-cell;
width: 1%;
}
> .btn-group .btn {
width: 100%;
}
> .btn-group .dropdown-menu {
left: auto;
}
}
// Checkbox and radio options
//
// In order to support the browser's form validation feedback, powered by the
// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
// `display: none;` or `visibility: hidden;` as that also hides the popover.
// Simply visually hiding the inputs via `opacity` would leave them clickable in
// certain cases which is prevented by using `clip` and `pointer-events`.
// This way, we ensure a DOM element is visible to position the popover from.
//
// See https://github.com/twbs/bootstrap/pull/12794 and
// https://github.com/twbs/bootstrap/pull/14559 for more information.
[data-toggle="buttons"] {
> .btn,
> .btn-group > .btn {
input[type="radio"],
input[type="checkbox"] {
position: absolute;
clip: rect(0,0,0,0);
pointer-events: none;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment