mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 04:09:12 +00:00
Define button-group util and use it in button-group and radio-group
This commit is contained in:
@@ -1,19 +1,3 @@
|
||||
:host {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex-wrap: wrap;
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
:host([orientation='vertical']) .button-group {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Show the focus indicator above other buttons */
|
||||
::slotted(:focus) {
|
||||
z-index: 1 !important;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { html } from 'lit';
|
||||
import { customElement, property, query, state } from 'lit/decorators.js';
|
||||
import WebAwesomeElement from '../../internal/webawesome-element.js';
|
||||
import buttonGroupStyles from '../../styles/utilities/button-group.css';
|
||||
import styles from './button-group.css';
|
||||
|
||||
/**
|
||||
@@ -15,7 +16,7 @@ import styles from './button-group.css';
|
||||
*/
|
||||
@customElement('wa-button-group')
|
||||
export default class WaButtonGroup extends WebAwesomeElement {
|
||||
static shadowStyle = styles;
|
||||
static shadowStyle = [buttonGroupStyles, styles];
|
||||
|
||||
@query('slot') defaultSlot: HTMLSlotElement;
|
||||
|
||||
@@ -82,20 +83,19 @@ export default class WaButtonGroup extends WebAwesomeElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
// eslint-disable-next-line lit-a11y/mouse-events-have-key-events
|
||||
return html`
|
||||
<div
|
||||
<slot
|
||||
part="base"
|
||||
class="button-group"
|
||||
class="wa-button-group"
|
||||
role="${this.disableRole ? 'presentation' : 'group'}"
|
||||
aria-label=${this.label}
|
||||
aria-orientation=${this.orientation}
|
||||
@focusout=${this.handleBlur}
|
||||
@focusin=${this.handleFocus}
|
||||
@mouseover=${this.handleMouseOver}
|
||||
@mouseout=${this.handleMouseOut}
|
||||
>
|
||||
<slot @slotchange=${this.handleSlotChange}></slot>
|
||||
</div>
|
||||
@slotchange=${this.handleSlotChange}
|
||||
></slot>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,76 +397,6 @@
|
||||
}
|
||||
*/
|
||||
|
||||
:host(.wa-button-group__button--inner) .button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
:host(.wa-button-group-horizontal.wa-button-group__button--first:not(.wa-button-group__button--last)) .button {
|
||||
border-start-end-radius: 0;
|
||||
border-end-end-radius: 0;
|
||||
}
|
||||
|
||||
:host(.wa-button-group-horizontal.wa-button-group__button--last:not(.wa-button-group__button--first)) .button {
|
||||
border-start-start-radius: 0;
|
||||
border-end-start-radius: 0;
|
||||
}
|
||||
|
||||
:host(.wa-button-group-vertical.wa-button-group__button--first:not(.wa-button-group__button--last)) .button {
|
||||
border-end-start-radius: 0;
|
||||
border-end-end-radius: 0;
|
||||
}
|
||||
|
||||
:host(.wa-button-group-vertical.wa-button-group__button--last:not(.wa-button-group__button--first)) .button {
|
||||
border-start-start-radius: 0;
|
||||
border-start-end-radius: 0;
|
||||
}
|
||||
|
||||
/* All except the first */
|
||||
:host(
|
||||
.wa-button-group-horizontal.wa-button-group-horizontal.wa-button-group__button:not(.wa-button-group__button--first)
|
||||
) {
|
||||
margin-inline-start: calc(-1 * var(--border-width));
|
||||
}
|
||||
|
||||
:host(
|
||||
.wa-button-group-vertical.wa-button-group-horizontal.wa-button-group__button:not(.wa-button-group__button--first)
|
||||
) {
|
||||
margin-block-start: calc(-1 * var(--border-width));
|
||||
}
|
||||
|
||||
/* Add a visual separator between filled buttons */
|
||||
:host(.wa-button-group__button:not(.wa-button-group__button--first, .wa-button-group__button--radio)) .button:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 2; /* Keep separators visible on hover */
|
||||
}
|
||||
|
||||
:host(
|
||||
.wa-button-group-horizontal.wa-button-group__button:not(
|
||||
.wa-button-group__button--first,
|
||||
.wa-button-group__button--radio
|
||||
)
|
||||
)
|
||||
.button:after {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
inset-inline-start: 0;
|
||||
border-left: solid max(var(--border-width), 1px) var(--border-color, rgb(0 0 0 / 0.3));
|
||||
}
|
||||
|
||||
:host(
|
||||
.wa-button-group-vertical.wa-button-group__button:not(
|
||||
.wa-button-group__button--first,
|
||||
.wa-button-group__button--radio
|
||||
)
|
||||
)
|
||||
.button:after {
|
||||
left: 0;
|
||||
right: 0;
|
||||
inset-block-start: 0;
|
||||
border-top: solid max(var(--border-width), 1px) var(--border-color, rgb(0 0 0 / 0.3));
|
||||
}
|
||||
|
||||
/* Bump hovered, focused, and checked buttons up so their focus ring isn't clipped */
|
||||
:host(.wa-button-group__button--hover) {
|
||||
z-index: 1;
|
||||
|
||||
@@ -17,3 +17,7 @@
|
||||
content: var(--wa-form-control-required-content);
|
||||
margin-inline-start: var(--wa-form-control-required-content-offset);
|
||||
}
|
||||
|
||||
.wa-button-group {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import { RequiredValidator } from '../../internal/validators/required-validator.
|
||||
import { watch } from '../../internal/watch.js';
|
||||
import { WebAwesomeFormAssociatedElement } from '../../internal/webawesome-element.js';
|
||||
import formControlStyles from '../../styles/shadow/form-control.css';
|
||||
import '../button-group/button-group.js';
|
||||
import sizeStyles from '../../styles/shadow/size.css';
|
||||
import buttonGroupStyles from '../../styles/utilities/button-group.css';
|
||||
import type WaRadioButton from '../radio-button/radio-button.js';
|
||||
import '../radio/radio.js';
|
||||
import type WaRadio from '../radio/radio.js';
|
||||
@@ -41,7 +42,7 @@ import styles from './radio-group.css';
|
||||
*/
|
||||
@customElement('wa-radio-group')
|
||||
export default class WaRadioGroup extends WebAwesomeFormAssociatedElement {
|
||||
static shadowStyle = [formControlStyles, styles];
|
||||
static shadowStyle = [sizeStyles, buttonGroupStyles, formControlStyles, styles];
|
||||
|
||||
static get validators() {
|
||||
const validators = isServer
|
||||
@@ -314,7 +315,6 @@ export default class WaRadioGroup extends WebAwesomeFormAssociatedElement {
|
||||
const hasHintSlot = this.hasUpdated ? this.hasSlotController.test('hint') : this.withHint;
|
||||
const hasLabel = this.label ? true : !!hasLabelSlot;
|
||||
const hasHint = this.hint ? true : !!hasHintSlot;
|
||||
const defaultSlot = html` <slot @slotchange=${this.syncRadioElements}></slot> `;
|
||||
|
||||
return html`
|
||||
<fieldset
|
||||
@@ -342,15 +342,11 @@ export default class WaRadioGroup extends WebAwesomeFormAssociatedElement {
|
||||
<slot name="label">${this.label}</slot>
|
||||
</label>
|
||||
|
||||
<div part="form-control-input" class="form-control-input" role="presentation">
|
||||
${this.hasButtonGroup
|
||||
? html`
|
||||
<wa-button-group part="button-group" exportparts="base:button-group__base" role="presentation">
|
||||
${defaultSlot}
|
||||
</wa-button-group>
|
||||
`
|
||||
: defaultSlot}
|
||||
</div>
|
||||
<slot
|
||||
part="form-control-input"
|
||||
class=${classMap({ 'wa-button-group': this.hasButtonGroup })}
|
||||
@slotchange=${this.syncRadioElements}
|
||||
></slot>
|
||||
|
||||
<slot
|
||||
name="hint"
|
||||
|
||||
57
src/styles/utilities/button-group.css
Normal file
57
src/styles/utilities/button-group.css
Normal file
@@ -0,0 +1,57 @@
|
||||
.wa-button-group {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
flex-wrap: wrap;
|
||||
isolation: isolate;
|
||||
|
||||
> :hover,
|
||||
&::slotted(:hover) {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Focus and checked are always on top */
|
||||
> :focus,
|
||||
&::slotted(:focus),
|
||||
> [aria-checked='true'],
|
||||
> [checked],
|
||||
&::slotted([aria-checked='true']),
|
||||
&::slotted([checked]) {
|
||||
z-index: 2 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Horizontal */
|
||||
.wa-button-group:not([aria-orientation='vertical']) {
|
||||
> :not(:first-child),
|
||||
&::slotted(:not(:first-child)) {
|
||||
border-start-start-radius: 0 !important;
|
||||
border-end-start-radius: 0 !important;
|
||||
border-inline-start-color: var(--border-color, rgb(0 0 0 / 0.3));
|
||||
margin-inline-start: calc(-1 * var(--border-width, 1px));
|
||||
}
|
||||
|
||||
> :not(:last-child),
|
||||
&::slotted(:not(:last-child)) {
|
||||
border-start-end-radius: 0 !important;
|
||||
border-end-end-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Vertical */
|
||||
.wa-button-group[aria-orientation='vertical'] {
|
||||
flex-direction: column;
|
||||
|
||||
> :not(:first-child),
|
||||
&::slotted(:not(:first-child)) {
|
||||
border-start-start-radius: 0 !important;
|
||||
border-start-end-radius: 0 !important;
|
||||
border-block-start-color: var(--border-color, rgb(0 0 0 / 0.3));
|
||||
margin-block-start: calc(-1 * var(--border-width, 1px));
|
||||
}
|
||||
|
||||
> :not(:last-child),
|
||||
&::slotted(:not(:last-child)) {
|
||||
border-end-start-radius: 0 !important;
|
||||
border-end-end-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user