kopia lustrzana https://github.com/shoelace-style/shoelace
fixes #985
rodzic
197a0c3048
commit
f64f144b4b
|
|
@ -72,14 +72,17 @@ Use the `setCustomValidity()` method to set a custom validation message. This wi
|
|||
const form = document.querySelector('.custom-validity');
|
||||
const checkbox = form.querySelector('sl-checkbox');
|
||||
const errorMessage = `Don't forget to check me!`;
|
||||
|
||||
// Set initial validity as soon as the element is defined
|
||||
customElements.whenDefined('sl-checkbox').then(() => {
|
||||
checkbox.setCustomValidity(errorMessage);
|
||||
});
|
||||
|
||||
// Update validity on change
|
||||
checkbox.addEventListener('sl-change', () => {
|
||||
checkbox.setCustomValidity(checkbox.checked ? '' : errorMessage);
|
||||
});
|
||||
|
||||
// Handle submit
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
|
|
@ -91,19 +94,24 @@ Use the `setCustomValidity()` method to set a custom validation message. This wi
|
|||
```jsx react
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { SlButton, SlCheckbox } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const App = () => {
|
||||
const checkbox = useRef(null);
|
||||
const errorMessage = `Don't forget to check me!`;
|
||||
|
||||
function handleChange() {
|
||||
checkbox.current.setCustomValidity(checkbox.current.checked ? '' : errorMessage);
|
||||
}
|
||||
|
||||
function handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
alert('All fields are valid!');
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
checkbox.current.setCustomValidity(errorMessage);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<form class="custom-validity" onSubmit={handleSubmit}>
|
||||
<SlCheckbox ref={checkbox} onSlChange={handleChange}>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
|
|||
- Added `--indicator-transition-duration` custom property to `<sl-progress-ring>` [#986](https://github.com/shoelace-style/shoelace/issues/986)
|
||||
- Added the ability to cancel `sl-show` and `sl-hide` events in `<sl-details>` [#993](https://github.com/shoelace-style/shoelace/issues/993)
|
||||
- Added `focus()` and `blur()` methods to `<sl-radio-button>`
|
||||
- Added the `handle-icon` part to `<sl-image-comparer>`
|
||||
- Added `caret`, `check`, `grip-vertical`, `indeterminate`, and `radio` icons to the system library and removed `check-lg` [#985](https://github.com/shoelace-style/shoelace/issues/985)
|
||||
- Fixed a bug in `<sl-card>` that prevented the border radius to apply correctly to the header [#934](https://github.com/shoelace-style/shoelace/pull/934)
|
||||
- Fixed a bug in `<sl-button-group>` where the inner border disappeared on focus [#980](https://github.com/shoelace-style/shoelace/pull/980)
|
||||
- Fixed a bug that caused prefix/suffix animations in `<sl-input>` to wobble [#996](https://github.com/shoelace-style/shoelace/issues/996)
|
||||
|
|
|
|||
|
|
@ -302,3 +302,13 @@ Form controls should support submission and validation through the following con
|
|||
- All form controls must have an `invalid` property that reflects their validity
|
||||
- All form controls should mirror their native validation attributes such as `required`, `pattern`, `minlength`, `maxlength`, etc. when possible
|
||||
- All form controls must be tested to work with the standard `<form>` element
|
||||
|
||||
### System Icons
|
||||
|
||||
Avoid inlining SVG icons inside of templates. If a component requires an icon, make sure `<sl-icon>` is a dependency of the component and use the [system library](/components/icon#customizing-the-system-library):
|
||||
|
||||
```html
|
||||
<sl-icon library="system" name="..."></sl-icon>
|
||||
```
|
||||
|
||||
This will render the icons instantly whereas the default library will fetch them from a remote source. If an icon isn't available in the system library, you will need to add it to `library.system.ts`. Using the system library ensures that all icons load instantly and are customizable by users who wish to provide a custom resolver for the system library.
|
||||
|
|
|
|||
|
|
@ -408,13 +408,7 @@ export default css`
|
|||
}
|
||||
|
||||
.button--caret .button__caret {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.button--caret .button__caret svg {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { FormSubmitController } from '../../internal/form';
|
|||
import ShoelaceElement from '../../internal/shoelace-element';
|
||||
import { HasSlotController } from '../../internal/slot';
|
||||
import { LocalizeController } from '../../utilities/localize';
|
||||
import '../icon/icon';
|
||||
import '../spinner/spinner';
|
||||
import styles from './button.styles';
|
||||
import type { CSSResultGroup } from 'lit';
|
||||
|
|
@ -16,6 +17,7 @@ import type { CSSResultGroup } from 'lit';
|
|||
* @since 2.0
|
||||
* @status stable
|
||||
*
|
||||
* @dependency sl-icon
|
||||
* @dependency sl-spinner
|
||||
*
|
||||
* @event sl-blur - Emitted when the button loses focus.
|
||||
|
|
@ -29,7 +31,7 @@ import type { CSSResultGroup } from 'lit';
|
|||
* @csspart prefix - The prefix slot's container.
|
||||
* @csspart label - The button's label.
|
||||
* @csspart suffix - The suffix slot's container.
|
||||
* @csspart caret - The button's caret.
|
||||
* @csspart caret - The button's caret icon.
|
||||
*/
|
||||
@customElement('sl-button')
|
||||
export default class SlButton extends ShoelaceElement {
|
||||
|
|
@ -219,22 +221,7 @@ export default class SlButton extends ShoelaceElement {
|
|||
<slot name="suffix"></slot>
|
||||
</span>
|
||||
${
|
||||
this.caret
|
||||
? html`
|
||||
<span part="caret" class="button__caret">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
</span>
|
||||
`
|
||||
: ''
|
||||
this.caret ? html` <sl-icon part="caret" class="button__caret" library="system" name="caret"></sl-icon> ` : ''
|
||||
}
|
||||
${this.loading ? html`<sl-spinner></sl-spinner>` : ''}
|
||||
</${tag}>
|
||||
|
|
|
|||
|
|
@ -49,11 +49,6 @@ export default css`
|
|||
height: var(--sl-toggle-size);
|
||||
}
|
||||
|
||||
.checkbox__control .checkbox__icon svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Hover */
|
||||
.checkbox:not(.checkbox--checked):not(.checkbox--disabled) .checkbox__control:hover {
|
||||
border-color: var(--sl-input-border-color-hover);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { defaultValue } from '../../internal/default-value';
|
|||
import { FormSubmitController } from '../../internal/form';
|
||||
import ShoelaceElement from '../../internal/shoelace-element';
|
||||
import { watch } from '../../internal/watch';
|
||||
import '../icon/icon';
|
||||
import styles from './checkbox.styles';
|
||||
import type { CSSResultGroup } from 'lit';
|
||||
|
||||
|
|
@ -16,6 +17,8 @@ import type { CSSResultGroup } from 'lit';
|
|||
* @since 2.0
|
||||
* @status stable
|
||||
*
|
||||
* @dependency sl-icon
|
||||
*
|
||||
* @slot - The checkbox's label.
|
||||
*
|
||||
* @event sl-blur - Emitted when the control loses focus.
|
||||
|
|
@ -24,8 +27,8 @@ import type { CSSResultGroup } from 'lit';
|
|||
*
|
||||
* @csspart base - The component's internal wrapper.
|
||||
* @csspart control - The checkbox control.
|
||||
* @csspart checked-icon - The container the wraps the checked icon.
|
||||
* @csspart indeterminate-icon - The container that wraps the indeterminate icon.
|
||||
* @csspart checked-icon - The checked icon.
|
||||
* @csspart indeterminate-icon - The indeterminate icon.
|
||||
* @csspart label - The checkbox label.
|
||||
*/
|
||||
@customElement('sl-checkbox')
|
||||
|
|
@ -155,32 +158,9 @@ export default class SlCheckbox extends ShoelaceElement {
|
|||
/>
|
||||
|
||||
<span part="control" class="checkbox__control">
|
||||
${this.checked
|
||||
? html`
|
||||
<svg part="checked-icon" class="checkbox__icon" viewBox="0 0 16 16">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
|
||||
<g stroke="currentColor" stroke-width="2">
|
||||
<g transform="translate(3.428571, 3.428571)">
|
||||
<path d="M0,5.71428571 L3.42857143,9.14285714"></path>
|
||||
<path d="M9.14285714,0 L3.42857143,9.14285714"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
`
|
||||
: ''}
|
||||
${this.checked ? html` <sl-icon part="checked-icon" library="system" name="check"></sl-icon> ` : ''}
|
||||
${!this.checked && this.indeterminate
|
||||
? html`
|
||||
<svg part="indeterminate-icon" class="checkbox__icon" viewBox="0 0 16 16">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
|
||||
<g stroke="currentColor" stroke-width="2">
|
||||
<g transform="translate(2.285714, 6.857143)">
|
||||
<path d="M10.2857143,1.14285714 L1.14285714,1.14285714"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
`
|
||||
? html` <sl-icon part="indeterminate-icon" library="system" name="indeterminate"></sl-icon> `
|
||||
: ''}
|
||||
</span>
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ describe('<sl-icon-button>', () => {
|
|||
html`
|
||||
<sl-icon-button
|
||||
library="system"
|
||||
name="check-lg"
|
||||
name="check"
|
||||
style="color: rgb(0, 136, 221); font-size: 2rem;"
|
||||
></sl-icon-button>
|
||||
`
|
||||
|
|
@ -48,9 +48,7 @@ describe('<sl-icon-button>', () => {
|
|||
|
||||
describe('when icon attributes are present', () => {
|
||||
it('renders an sl-icon from a library', async () => {
|
||||
const el = await fixture<SlIconButton>(
|
||||
html` <sl-icon-button library="system" name="check-lg"></sl-icon-button> `
|
||||
);
|
||||
const el = await fixture<SlIconButton>(html` <sl-icon-button library="system" name="check"></sl-icon-button> `);
|
||||
expect(el.shadowRoot?.querySelector('sl-icon')).to.exist;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,21 @@ import type { IconLibrary } from './library';
|
|||
// icons are a subset of Bootstrap Icons.
|
||||
//
|
||||
const icons = {
|
||||
'check-lg': `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check-lg" viewBox="0 0 16 16">
|
||||
<path d="M12.736 3.97a.733.733 0 0 1 1.047 0c.286.289.29.756.01 1.05L7.88 12.01a.733.733 0 0 1-1.065.02L3.217 8.384a.757.757 0 0 1 0-1.06.733.733 0 0 1 1.047 0l3.052 3.093 5.4-6.425a.247.247 0 0 1 .02-.022Z"></path>
|
||||
caret: `
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
`,
|
||||
check: `
|
||||
<svg part="checked-icon" class="checkbox__icon" viewBox="0 0 16 16">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
|
||||
<g stroke="currentColor" stroke-width="2">
|
||||
<g transform="translate(3.428571, 3.428571)">
|
||||
<path d="M0,5.71428571 L3.42857143,9.14285714"></path>
|
||||
<path d="M9.14285714,0 L3.42857143,9.14285714"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
`,
|
||||
'chevron-down': `
|
||||
|
|
@ -46,6 +58,22 @@ const icons = {
|
|||
<path d="M13.354.646a1.207 1.207 0 0 0-1.708 0L8.5 3.793l-.646-.647a.5.5 0 1 0-.708.708L8.293 5l-7.147 7.146A.5.5 0 0 0 1 12.5v1.793l-.854.853a.5.5 0 1 0 .708.707L1.707 15H3.5a.5.5 0 0 0 .354-.146L11 7.707l1.146 1.147a.5.5 0 0 0 .708-.708l-.647-.646 3.147-3.146a1.207 1.207 0 0 0 0-1.708l-2-2zM2 12.707l7-7L10.293 7l-7 7H2v-1.293z"></path>
|
||||
</svg>
|
||||
`,
|
||||
'grip-vertical': `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-grip-vertical" viewBox="0 0 16 16">
|
||||
<path d="M7 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"></path>
|
||||
</svg>
|
||||
`,
|
||||
indeterminate: `
|
||||
<svg part="indeterminate-icon" class="checkbox__icon" viewBox="0 0 16 16">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
|
||||
<g stroke="currentColor" stroke-width="2">
|
||||
<g transform="translate(2.285714, 6.857143)">
|
||||
<path d="M10.2857143,1.14285714 L1.14285714,1.14285714"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
`,
|
||||
'person-fill': `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-fill" viewBox="0 0 16 16">
|
||||
<path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
|
||||
|
|
@ -61,6 +89,15 @@ const icons = {
|
|||
<path d="M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5zm5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5z"></path>
|
||||
</svg>
|
||||
`,
|
||||
radio: `
|
||||
<svg part="checked-icon" class="radio__icon" viewBox="0 0 16 16">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g fill="currentColor">
|
||||
<circle cx="8" cy="8" r="3.42857143"></circle>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
`,
|
||||
'star-fill': `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-star-fill" viewBox="0 0 16 16">
|
||||
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export default css`
|
|||
background-color: var(--sl-color-neutral-0);
|
||||
border-radius: var(--sl-border-radius-circle);
|
||||
font-size: calc(var(--handle-size) * 0.5);
|
||||
color: var(--sl-color-neutral-600);
|
||||
color: var(--sl-color-neutral-700);
|
||||
cursor: inherit;
|
||||
z-index: 10;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import type { CSSResultGroup } from 'lit';
|
|||
* @csspart after - The container that holds the "after" image.
|
||||
* @csspart divider - The divider that separates the images.
|
||||
* @csspart handle - The handle that the user drags to expose the after image.
|
||||
* @csspart handle-icon - The drag icon that appears inside the handle.
|
||||
*
|
||||
* @cssproperty --divider-width - The width of the dividing line.
|
||||
* @cssproperty --handle-size - The size of the compare handle.
|
||||
|
|
@ -143,13 +144,7 @@ export default class SlImageComparer extends ShoelaceElement {
|
|||
tabindex="0"
|
||||
>
|
||||
<slot name="handle-icon">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="currentColor" fill-rule="nonzero">
|
||||
<path
|
||||
d="m21.14 12.55-5.482 4.796c-.646.566-1.658.106-1.658-.753V7a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506h.001ZM2.341 12.55l5.482 4.796c.646.566 1.658.106 1.658-.753V7a1 1 0 0 0-1.659-.753l-5.48 4.796a1 1 0 0 0 0 1.506h-.001Z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
<sl-icon part="handle-icon" library="system" name="grip-vertical"></sl-icon>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import type { CSSResultGroup } from 'lit';
|
|||
* @slot suffix - Used to append an icon or similar element to the menu item.
|
||||
*
|
||||
* @csspart base - The component's internal wrapper.
|
||||
* @csspart checked-icon - The checkmark's container, only visible when the menu item is checked.
|
||||
* @csspart checked-icon - The checked icon, which is only visible when the menu item is checked.
|
||||
* @csspart prefix - The prefix container.
|
||||
* @csspart label - The menu item label.
|
||||
* @csspart suffix - The suffix container.
|
||||
|
|
@ -93,7 +93,7 @@ export default class SlMenuItem extends ShoelaceElement {
|
|||
})}
|
||||
>
|
||||
<span part="checked-icon" class="menu-item__check">
|
||||
<sl-icon name="check-lg" library="system" aria-hidden="true"></sl-icon>
|
||||
<sl-icon name="check" library="system" aria-hidden="true"></sl-icon>
|
||||
</span>
|
||||
|
||||
<span part="prefix" class="menu-item__prefix">
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { customElement, property, state } from 'lit/decorators.js';
|
|||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import ShoelaceElement from '../../internal/shoelace-element';
|
||||
import { watch } from '../../internal/watch';
|
||||
import '../icon/icon';
|
||||
import styles from './radio.styles';
|
||||
import type { CSSResultGroup } from 'lit';
|
||||
|
||||
|
|
@ -12,6 +13,8 @@ import type { CSSResultGroup } from 'lit';
|
|||
* @since 2.0
|
||||
* @status stable
|
||||
*
|
||||
* @dependency sl-icon
|
||||
*
|
||||
* @slot - The radio's label.
|
||||
*
|
||||
* @event sl-blur - Emitted when the control loses focus.
|
||||
|
|
@ -20,7 +23,7 @@ import type { CSSResultGroup } from 'lit';
|
|||
* @csspart base - The component's internal wrapper.
|
||||
* @csspart control - The radio control.
|
||||
* @csspart control--checked - The radio control if radio is checked.
|
||||
* @csspart checked-icon - The container the wraps the checked icon.
|
||||
* @csspart checked-icon - The checked icon.
|
||||
* @csspart label - The radio label.
|
||||
*/
|
||||
@customElement('sl-radio')
|
||||
|
|
@ -93,13 +96,7 @@ export default class SlRadio extends ShoelaceElement {
|
|||
})}
|
||||
>
|
||||
<span part="${`control${this.checked ? ' control--checked' : ''}`}" class="radio__control">
|
||||
<svg part="checked-icon" class="radio__icon" viewBox="0 0 16 16">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g fill="currentColor">
|
||||
<circle cx="8" cy="8" r="3.42857143"></circle>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
${this.checked ? html` <sl-icon part="checked-icon" library="system" name="radio"></sl-icon> ` : ''}
|
||||
</span>
|
||||
|
||||
<span part="label" class="radio__label">
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue