diff --git a/docs/components/button.md b/docs/components/button.md index bc113677..544f12c2 100644 --- a/docs/components/button.md +++ b/docs/components/button.md @@ -91,6 +91,24 @@ As expected, buttons can be given a custom width by setting its `width`. This is Use the `prefix` and `suffix` slots to add icons. ```html preview + + + Settings + + + + + Refresh + + + + + + Open + + +

+ Settings @@ -106,6 +124,24 @@ Use the `prefix` and `suffix` slots to add icons. Open + +

+ + + + Settings + + + + + Refresh + + + + + + Open + ``` ### Caret @@ -144,4 +180,22 @@ Use the `disabled` prop to disable a button. Clicks will be suppressed until the Danger ``` +### Split Buttons + +Create a split button using a [button group](/components/button-group) and a [dropdown](/components/dropdown). + +```html preview + + Save + + + + Save + Save as… + Save all + + + +``` + [component-metadata:sl-button] diff --git a/docs/getting-started/changelog.md b/docs/getting-started/changelog.md index e5cc0e44..7e09f249 100644 --- a/docs/getting-started/changelog.md +++ b/docs/getting-started/changelog.md @@ -25,6 +25,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis - Fixed a bug where `sl-color-picker` preview wouldn't update in Safari - Fixed a bug where removing an icon's `name` or `src` wouldn't remove the previously rendered SVG [#285](https://github.com/shoelace-style/shoelace/issues/285) - Fixed a bug where disabled link buttons didn't appear disabled +- Improved button spacings and added split button example - Improved elevation tokens in dark theme - Improved accessibility in `sl-tooltip` by allowing escape to dismiss it [#219](https://github.com/shoelace-style/shoelace/issues/219) - Improved slot detection in `sl-card`, `sl-dialog`, and `sl-drawer` diff --git a/src/components/button/button.scss b/src/components/button/button.scss index d9249446..d22bdc4b 100644 --- a/src/components/button/button.scss +++ b/src/components/button/button.scss @@ -19,6 +19,7 @@ user-select: none; white-space: nowrap; vertical-align: middle; + padding: 0; transition: var(--sl-transition-fast) background-color, var(--sl-transition-fast) color, var(--sl-transition-fast) border, var(--sl-transition-fast) box-shadow; cursor: inherit; @@ -55,13 +56,13 @@ } .button__prefix ::slotted(:first-child) { - margin-left: calc(-1 * var(--sl-spacing-x-small)); - margin-right: var(--sl-spacing-x-small); + // margin-left: calc(-1 * var(--sl-spacing-x-small)); + // margin-right: var(--sl-spacing-x-small); } .button__suffix ::slotted(:last-child) { - margin-left: var(--sl-spacing-x-small); - margin-right: calc(-1 * var(--sl-spacing-x-small)); + // margin-left: var(--sl-spacing-x-small); + // margin-right: calc(-1 * var(--sl-spacing-x-small)); } .button__label { @@ -264,7 +265,6 @@ height: var(--sl-input-height-small); line-height: calc(var(--sl-input-height-small) - var(--sl-input-border-width) * 2); border-radius: var(--sl-input-border-radius-small); - padding: 0 var(--sl-spacing-medium); } .button--medium { @@ -272,7 +272,6 @@ height: var(--sl-input-height-medium); line-height: calc(var(--sl-input-height-medium) - var(--sl-input-border-width) * 2); border-radius: var(--sl-input-border-radius-medium); - padding: 0 var(--sl-spacing-large); } .button--large { @@ -280,7 +279,6 @@ height: var(--sl-input-height-large); line-height: calc(var(--sl-input-height-large) - var(--sl-input-border-width) * 2); border-radius: var(--sl-input-border-radius-large); - padding: 0 var(--sl-spacing-x-large); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -343,8 +341,6 @@ .button__caret { display: flex; align-items: center; - margin-left: var(--sl-spacing-xx-small); - margin-right: calc(-1 * var(--sl-spacing-xx-small)); svg { width: 1em; @@ -389,3 +385,74 @@ transform: translateY(-50%) translateX(50%); pointer-events: none; } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Button spacing +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +.button--has-label { + &.button--small .button__label { + padding: 0 var(--sl-spacing-small); + } + + &.button--medium .button__label { + padding: 0 var(--sl-spacing-medium); + } + + &.button--large .button__label { + padding: 0 var(--sl-spacing-large); + } +} + +.button--has-prefix { + &.button--small { + padding-left: var(--sl-spacing-x-small); + + .button__label { + padding-left: var(--sl-spacing-x-small); + } + } + + &.button--medium { + padding-left: var(--sl-spacing-small); + + .button__label { + padding-left: var(--sl-spacing-small); + } + } + + &.button--large { + padding-left: var(--sl-spacing-small); + + .button__label { + padding-left: var(--sl-spacing-small); + } + } +} + +.button--has-suffix, +.button--caret { + &.button--small { + padding-right: var(--sl-spacing-x-small); + + .button__label { + padding-right: var(--sl-spacing-x-small); + } + } + + &.button--medium { + padding-right: var(--sl-spacing-small); + + .button__label { + padding-right: var(--sl-spacing-small); + } + } + + &.button--large { + padding-right: var(--sl-spacing-small); + + .button__label { + padding-right: var(--sl-spacing-small); + } + } +} diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx index 65fa62d9..e1411066 100644 --- a/src/components/button/button.tsx +++ b/src/components/button/button.tsx @@ -1,4 +1,5 @@ -import { Component, Event, EventEmitter, Method, Prop, State, h } from '@stencil/core'; +import { Component, Element, Event, EventEmitter, Method, Prop, State, h } from '@stencil/core'; +import { hasSlot } from '../../utilities/slot'; /** * @since 2.0 @@ -23,7 +24,12 @@ import { Component, Event, EventEmitter, Method, Prop, State, h } from '@stencil export class Button { button: HTMLButtonElement; + @Element() host: HTMLSlButtonElement; + @State() hasFocus = false; + @State() hasLabel = false; + @State() hasPrefix = false; + @State() hasSuffix = false; /** The button's type. */ @Prop({ reflect: true }) type: 'default' | 'primary' | 'success' | 'info' | 'warning' | 'danger' | 'text' = 'default'; @@ -74,6 +80,11 @@ export class Button { this.handleBlur = this.handleBlur.bind(this); this.handleFocus = this.handleFocus.bind(this); this.handleClick = this.handleClick.bind(this); + this.handleSlotChange = this.handleSlotChange.bind(this); + } + + componentWillLoad() { + this.handleSlotChange(); } /** Sets focus on the button. */ @@ -88,6 +99,12 @@ export class Button { this.button.blur(); } + handleSlotChange() { + this.hasLabel = hasSlot(this.host); + this.hasPrefix = hasSlot(this.host, 'prefix'); + this.hasSuffix = hasSlot(this.host, 'suffix'); + } + handleBlur() { this.hasFocus = false; this.slBlur.emit(); @@ -137,7 +154,10 @@ export class Button { 'button--disabled': this.disabled, 'button--focused': this.hasFocus, 'button--loading': this.loading, - 'button--pill': this.pill + 'button--pill': this.pill, + 'button--has-label': this.hasLabel, + 'button--has-prefix': this.hasPrefix, + 'button--has-suffix': this.hasSuffix }} disabled={isButton ? this.disabled : null} type={isButton ? (this.submit ? 'submit' : 'button') : null} @@ -152,13 +172,13 @@ export class Button { onClick={this.handleClick} > - + - + - + {this.caret && (