From 1a08f063a6cd186855f27788edb088bae731fbfb Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Fri, 24 Sep 2021 16:40:03 -0400 Subject: [PATCH] add outline buttons; closes #522 --- docs/components/button.md | 13 ++ docs/resources/changelog.md | 1 + src/components/button/button.styles.ts | 194 +++++++++++++++++++++---- src/components/button/button.ts | 7 + 4 files changed, 189 insertions(+), 26 deletions(-) diff --git a/docs/components/button.md b/docs/components/button.md index 3ebbbca7..075f13ef 100644 --- a/docs/components/button.md +++ b/docs/components/button.md @@ -33,6 +33,19 @@ Use the `size` attribute to change a button's size. Large ``` +### Outline Buttons + +Use the `outline` attribute to draw outlined buttons with transparent backgrounds. + +```html preview +Default +Primary +Success +Neutral +Warning +Danger +``` + ### Pill Buttons Use the `pill` attribute to give buttons rounded edges. diff --git a/docs/resources/changelog.md b/docs/resources/changelog.md index 527da3f9..e56d52ad 100644 --- a/docs/resources/changelog.md +++ b/docs/resources/changelog.md @@ -10,6 +10,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis - Added initial surface design tokens - Added missing background color to `` +- Added the `outline` attribute to `` for outlined buttons [#522](https://github.com/shoelace-style/shoelace/issues/522) - Added the `control` part to `` so you can target the main control with CSS [#538](https://github.com/shoelace-style/shoelace/issues/538) - Changed the default `distance` in `` from `2` to `0` [#538](https://github.com/shoelace-style/shoelace/issues/538) - Modified the color scale to no longer use a luminance shift diff --git a/src/components/button/button.styles.ts b/src/components/button/button.styles.ts index 133dec5f..bd984a7f 100644 --- a/src/components/button/button.styles.ts +++ b/src/components/button/button.styles.ts @@ -38,13 +38,13 @@ export default css` outline: none; } - .button.button--disabled { + .button--disabled { opacity: 0.5; cursor: not-allowed; } /* When disabled, prevent mouse events from bubbling up */ - .button.button--disabled * { + .button--disabled * { pointer-events: none; } @@ -69,160 +69,302 @@ export default css` */ /* Default */ - .button.button--default { + .button--standard.button--default { background-color: rgb(var(--sl-surface-base)); border-color: rgb(var(--sl-color-neutral-300)); color: rgb(var(--sl-color-neutral-700)); } - .button.button--default:hover:not(.button--disabled) { + .button--standard.button--default:hover:not(.button--disabled) { background-color: rgb(var(--sl-color-primary-50)); border-color: rgb(var(--sl-color-primary-300)); color: rgb(var(--sl-color-primary-700)); } - .button.button--default${focusVisibleSelector}:not(.button--disabled) { + .button--standard.button--default${focusVisibleSelector}:not(.button--disabled) { background-color: rgb(var(--sl-color-primary-50)); border-color: rgb(var(--sl-color-primary-400)); color: rgb(var(--sl-color-primary-700)); box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-primary-500) / var(--sl-focus-ring-alpha)); } - .button.button--default:active:not(.button--disabled) { + .button--standard.button--default:active:not(.button--disabled) { background-color: rgb(var(--sl-color-primary-100)); border-color: rgb(var(--sl-color-primary-400)); color: rgb(var(--sl-color-primary-700)); } /* Primary */ - .button.button--primary { + .button--standard.button--primary { background-color: rgb(var(--sl-color-primary-600)); border-color: rgb(var(--sl-color-primary-600)); color: rgb(var(--sl-color-neutral-0)); } - .button.button--primary:hover:not(.button--disabled) { + .button--standard.button--primary:hover:not(.button--disabled) { background-color: rgb(var(--sl-color-primary-500)); border-color: rgb(var(--sl-color-primary-500)); color: rgb(var(--sl-color-neutral-0)); } - .button.button--primary${focusVisibleSelector}:not(.button--disabled) { + .button--standard.button--primary${focusVisibleSelector}:not(.button--disabled) { background-color: rgb(var(--sl-color-primary-500)); border-color: rgb(var(--sl-color-primary-500)); color: rgb(var(--sl-color-neutral-0)); box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-primary-500) / var(--sl-focus-ring-alpha)); } - .button.button--primary:active:not(.button--disabled) { + .button--standard.button--primary:active:not(.button--disabled) { background-color: rgb(var(--sl-color-primary-600)); border-color: rgb(var(--sl-color-primary-600)); color: rgb(var(--sl-color-neutral-0)); } /* Success */ - .button.button--success { + .button--standard.button--success { background-color: rgb(var(--sl-color-success-600)); border-color: rgb(var(--sl-color-success-600)); color: rgb(var(--sl-color-neutral-0)); } - .button.button--success:hover:not(.button--disabled) { + .button--standard.button--success:hover:not(.button--disabled) { background-color: rgb(var(--sl-color-success-500)); border-color: rgb(var(--sl-color-success-500)); color: rgb(var(--sl-color-neutral-0)); } - .button.button--success${focusVisibleSelector}:not(.button--disabled) { + .button--standard.button--success${focusVisibleSelector}:not(.button--disabled) { background-color: rgb(var(--sl-color-success-600)); border-color: rgb(var(--sl-color-success-600)); color: rgb(var(--sl-color-neutral-0)); box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-success-500) / var(--sl-focus-ring-alpha)); } - .button.button--success:active:not(.button--disabled) { + .button--standard.button--success:active:not(.button--disabled) { background-color: rgb(var(--sl-color-success-600)); border-color: rgb(var(--sl-color-success-600)); color: rgb(var(--sl-color-neutral-0)); } /* Neutral */ - .button.button--neutral { + .button--standard.button--neutral { background-color: rgb(var(--sl-color-neutral-600)); border-color: rgb(var(--sl-color-neutral-600)); color: rgb(var(--sl-color-neutral-0)); } - .button.button--neutral:hover:not(.button--disabled) { + .button--standard.button--neutral:hover:not(.button--disabled) { background-color: rgb(var(--sl-color-neutral-500)); border-color: rgb(var(--sl-color-neutral-500)); color: rgb(var(--sl-color-neutral-0)); } - .button.button--neutral${focusVisibleSelector}:not(.button--disabled) { + .button--standard.button--neutral${focusVisibleSelector}:not(.button--disabled) { background-color: rgb(var(--sl-color-neutral-500)); border-color: rgb(var(--sl-color-neutral-500)); color: rgb(var(--sl-color-neutral-0)); box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-neutral-500) / var(--sl-focus-ring-alpha)); } - .button.button--neutral:active:not(.button--disabled) { + .button--standard.button--neutral:active:not(.button--disabled) { background-color: rgb(var(--sl-color-neutral-600)); border-color: rgb(var(--sl-color-neutral-600)); color: rgb(var(--sl-color-neutral-0)); } /* Warning */ - .button.button--warning { + .button--standard.button--warning { background-color: rgb(var(--sl-color-warning-600)); border-color: rgb(var(--sl-color-warning-600)); color: rgb(var(--sl-color-neutral-0)); } - .button.button--warning:hover:not(.button--disabled) { + .button--standard.button--warning:hover:not(.button--disabled) { background-color: rgb(var(--sl-color-warning-500)); border-color: rgb(var(--sl-color-warning-500)); color: rgb(var(--sl-color-neutral-0)); } - .button.button--warning${focusVisibleSelector}:not(.button--disabled) { + .button--standard.button--warning${focusVisibleSelector}:not(.button--disabled) { background-color: rgb(var(--sl-color-warning-500)); border-color: rgb(var(--sl-color-warning-500)); color: rgb(var(--sl-color-neutral-0)); box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-warning-500) / var(--sl-focus-ring-alpha)); } - .button.button--warning:active:not(.button--disabled) { + .button--standard.button--warning:active:not(.button--disabled) { background-color: rgb(var(--sl-color-warning-600)); border-color: rgb(var(--sl-color-warning-600)); color: rgb(var(--sl-color-neutral-0)); } /* Danger */ - .button.button--danger { + .button--standard.button--danger { background-color: rgb(var(--sl-color-danger-600)); border-color: rgb(var(--sl-color-danger-600)); color: rgb(var(--sl-color-neutral-0)); } - .button.button--danger:hover:not(.button--disabled) { + .button--standard.button--danger:hover:not(.button--disabled) { background-color: rgb(var(--sl-color-danger-500)); border-color: rgb(var(--sl-color-danger-500)); color: rgb(var(--sl-color-neutral-0)); } - .button.button--danger${focusVisibleSelector}:not(.button--disabled) { + .button--standard.button--danger${focusVisibleSelector}:not(.button--disabled) { background-color: rgb(var(--sl-color-danger-500)); border-color: rgb(var(--sl-color-danger-500)); color: rgb(var(--sl-color-neutral-0)); box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-danger-500) / var(--sl-focus-ring-alpha)); } - .button.button--danger:active:not(.button--disabled) { + .button--standard.button--danger:active:not(.button--disabled) { background-color: rgb(var(--sl-color-danger-600)); border-color: rgb(var(--sl-color-danger-600)); color: rgb(var(--sl-color-neutral-0)); } + /* + * Outline buttons + */ + + .button--outline { + background: none; + border: solid 1px; + } + + /* Default */ + .button--outline.button--default { + border-color: rgb(var(--sl-color-neutral-400)); + color: rgb(var(--sl-color-neutral-700)); + } + + .button--outline.button--default:hover:not(.button--disabled) { + border-color: rgb(var(--sl-color-primary-600)); + background-color: rgb(var(--sl-color-primary-600)); + color: rgb(var(--sl-color-neutral-0)); + } + + .button--outline.button--default${focusVisibleSelector}:not(.button--disabled) { + border-color: rgb(var(--sl-color-primary-500)); + box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-primary-500) / var(--sl-focus-ring-alpha)); + } + + .button--outline.button--default:active:not(.button--disabled) { + border-color: rgb(var(--sl-color-primary-700)); + background-color: rgb(var(--sl-color-primary-700)); + color: rgb(var(--sl-color-neutral-0)); + } + + /* Primary */ + .button--outline.button--primary { + border-color: rgb(var(--sl-color-primary-600)); + color: rgb(var(--sl-color-primary-600)); + } + + .button--outline.button--primary:hover:not(.button--disabled) { + background-color: rgb(var(--sl-color-primary-600)); + color: rgb(var(--sl-color-neutral-0)); + } + + .button--outline.button--primary${focusVisibleSelector}:not(.button--disabled) { + border-color: rgb(var(--sl-color-primary-500)); + box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-primary-500) / var(--sl-focus-ring-alpha)); + } + + .button--outline.button--primary:active:not(.button--disabled) { + border-color: rgb(var(--sl-color-primary-700)); + background-color: rgb(var(--sl-color-primary-700)); + color: rgb(var(--sl-color-neutral-0)); + } + + /* Success */ + .button--outline.button--success { + border-color: rgb(var(--sl-color-success-600)); + color: rgb(var(--sl-color-success-600)); + } + + .button--outline.button--success:hover:not(.button--disabled) { + background-color: rgb(var(--sl-color-success-600)); + color: rgb(var(--sl-color-neutral-0)); + } + + .button--outline.button--success${focusVisibleSelector}:not(.button--disabled) { + border-color: rgb(var(--sl-color-success-500)); + box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-success-500) / var(--sl-focus-ring-alpha)); + } + + .button--outline.button--success:active:not(.button--disabled) { + border-color: rgb(var(--sl-color-success-700)); + background-color: rgb(var(--sl-color-success-700)); + color: rgb(var(--sl-color-neutral-0)); + } + + /* Neutral */ + .button--outline.button--neutral { + border-color: rgb(var(--sl-color-neutral-600)); + color: rgb(var(--sl-color-neutral-600)); + } + + .button--outline.button--neutral:hover:not(.button--disabled) { + background-color: rgb(var(--sl-color-neutral-600)); + color: rgb(var(--sl-color-neutral-0)); + } + + .button--outline.button--neutral${focusVisibleSelector}:not(.button--disabled) { + border-color: rgb(var(--sl-color-neutral-500)); + box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-neutral-500) / var(--sl-focus-ring-alpha)); + } + + .button--outline.button--neutral:active:not(.button--disabled) { + border-color: rgb(var(--sl-color-neutral-700)); + background-color: rgb(var(--sl-color-neutral-700)); + color: rgb(var(--sl-color-neutral-0)); + } + + /* Warning */ + .button--outline.button--warning { + border-color: rgb(var(--sl-color-warning-600)); + color: rgb(var(--sl-color-warning-600)); + } + + .button--outline.button--warning:hover:not(.button--disabled) { + background-color: rgb(var(--sl-color-warning-600)); + color: rgb(var(--sl-color-neutral-0)); + } + + .button--outline.button--warning${focusVisibleSelector}:not(.button--disabled) { + border-color: rgb(var(--sl-color-warning-500)); + box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-warning-500) / var(--sl-focus-ring-alpha)); + } + + .button--outline.button--warning:active:not(.button--disabled) { + border-color: rgb(var(--sl-color-warning-700)); + background-color: rgb(var(--sl-color-warning-700)); + color: rgb(var(--sl-color-neutral-0)); + } + + /* Danger */ + .button--outline.button--danger { + border-color: rgb(var(--sl-color-danger-600)); + color: rgb(var(--sl-color-danger-600)); + } + + .button--outline.button--danger:hover:not(.button--disabled) { + background-color: rgb(var(--sl-color-danger-600)); + color: rgb(var(--sl-color-neutral-0)); + } + + .button--outline.button--danger${focusVisibleSelector}:not(.button--disabled) { + border-color: rgb(var(--sl-color-danger-500)); + box-shadow: 0 0 0 var(--sl-focus-ring-width) rgb(var(--sl-color-danger-500) / var(--sl-focus-ring-alpha)); + } + + .button--outline.button--danger:active:not(.button--disabled) { + border-color: rgb(var(--sl-color-danger-700)); + background-color: rgb(var(--sl-color-danger-700)); + color: rgb(var(--sl-color-neutral-0)); + } + /* * Text buttons */ diff --git a/src/components/button/button.ts b/src/components/button/button.ts index 32f02d6c..a9c2300e 100644 --- a/src/components/button/button.ts +++ b/src/components/button/button.ts @@ -54,6 +54,9 @@ export default class SlButton extends LitElement { /** Draws the button in a loading state. */ @property({ type: Boolean, reflect: true }) loading = false; + /** Draws an outlined button. */ + @property({ type: Boolean, reflect: true }) outline = false; + /** Draws a pill-style button with rounded edges. */ @property({ type: Boolean, reflect: true }) pill = false; @@ -174,6 +177,8 @@ export default class SlButton extends LitElement { 'button--disabled': this.disabled, 'button--focused': this.hasFocus, 'button--loading': this.loading, + 'button--standard': !this.outline, + 'button--outline': this.outline, 'button--pill': this.pill, 'button--has-label': this.hasLabel, 'button--has-prefix': this.hasPrefix, @@ -213,6 +218,8 @@ export default class SlButton extends LitElement { 'button--disabled': this.disabled, 'button--focused': this.hasFocus, 'button--loading': this.loading, + 'button--standard': !this.outline, + 'button--outline': this.outline, 'button--pill': this.pill, 'button--has-label': this.hasLabel, 'button--has-prefix': this.hasPrefix,