mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-16 19:01:05 +00:00
Align v10.38 (#698)
* chore(deps-dev): upgrade carbon-components to v10.38.0 * feat(text-input): support read-only variant * docs: use consistent lingo for inline variant examples * docs(popover): add Popover alignment example * fix(file-uploader): adjust markup to avoid accessibility errors Ref:0dfde60e3
* fix(inline-loading): use error filled icon * fix(inline-loading): render iconDescription as title in error/warning icons Ref:51c53c923
* fix(structured-list): update accessibility attributes * fix(tooltip-definition): use span instead of div Ref:cb6de3025
* fix(multi-select): close menu when blurring the last filterable option * fix(multi-select): open/focus field for filterable multiselect #635 * fix(multi-select): unblock focus when blurring input #635 * fix(combo-box): select correct item with keys, allow input after clearing #195 * fix(combo-box): update input text if item is selected * feat(combo-box): render checkmark icon for selected item * fix(ui-shell): toggle SideNav rail when clicking the hamburger menu #699 * fix(context-menu): update context menu classes #684 * docs(context-menu): improve demo instructions #684 * fix(context-menu): close menu when clicking anywhere
This commit is contained in:
parent
7c1e30476a
commit
e51f50da0c
33 changed files with 285 additions and 88 deletions
|
@ -79,6 +79,7 @@
|
|||
on:change="{() => {
|
||||
checked = !checked;
|
||||
}}"
|
||||
on:blur
|
||||
/>
|
||||
<label for="{id}" title="{title}" class:bx--checkbox-label="{true}">
|
||||
<span
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
export let listRef = null;
|
||||
|
||||
import { createEventDispatcher, afterUpdate, tick } from "svelte";
|
||||
import Checkmark16 from "carbon-icons-svelte/lib/Checkmark16/Checkmark16.svelte";
|
||||
import WarningFilled16 from "carbon-icons-svelte/lib/WarningFilled16/WarningFilled16.svelte";
|
||||
import WarningAltFilled16 from "carbon-icons-svelte/lib/WarningAltFilled16/WarningAltFilled16.svelte";
|
||||
import ListBox from "../ListBox/ListBox.svelte";
|
||||
|
@ -128,7 +129,6 @@
|
|||
filteredItems = items.filter((item) => shouldFilterItem(item, value));
|
||||
} else {
|
||||
highlightedIndex = -1;
|
||||
inputValue = selectedItem ? selectedItem.text : "";
|
||||
|
||||
if (!selectedItem) {
|
||||
selectedId = undefined;
|
||||
|
@ -149,7 +149,6 @@
|
|||
: undefined;
|
||||
$: filteredItems = items.filter((item) => shouldFilterItem(item, value));
|
||||
$: selectedItem = items[selectedIndex];
|
||||
$: inputValue = selectedItem ? selectedItem.text : undefined;
|
||||
$: value = inputValue;
|
||||
</script>
|
||||
|
||||
|
@ -217,16 +216,31 @@
|
|||
class:bx--text-input="{true}"
|
||||
class:bx--text-input--light="{light}"
|
||||
class:bx--text-input--empty="{inputValue === ''}"
|
||||
on:input="{({ target }) => {
|
||||
on:input="{async ({ target }) => {
|
||||
if (!open && target.value.length > 0) {
|
||||
open = true;
|
||||
}
|
||||
|
||||
inputValue = target.value;
|
||||
}}"
|
||||
on:keydown
|
||||
on:keydown|stopPropagation="{({ key }) => {
|
||||
if (key === 'Enter') {
|
||||
open = !open;
|
||||
|
||||
if (highlightedIndex > -1 && highlightedIndex !== selectedIndex) {
|
||||
selectedIndex = highlightedIndex;
|
||||
open = false;
|
||||
|
||||
if (filteredItems[selectedIndex]) {
|
||||
inputValue = filteredItems[selectedIndex].text;
|
||||
}
|
||||
}
|
||||
|
||||
if (highlightedIndex < 0 && selectedIndex > -1) {
|
||||
if (filteredItems[selectedIndex]) {
|
||||
inputValue = filteredItems[selectedIndex].text;
|
||||
}
|
||||
}
|
||||
} else if (key === 'Tab') {
|
||||
open = false;
|
||||
|
@ -242,6 +256,12 @@
|
|||
on:focus
|
||||
on:blur
|
||||
on:blur="{({ relatedTarget }) => {
|
||||
if (inputValue.length === 0 && selectedIndex > -1) {
|
||||
if (filteredItems[selectedIndex]) {
|
||||
inputValue = filteredItems[selectedIndex].text;
|
||||
}
|
||||
}
|
||||
|
||||
if (!open || !relatedTarget) return;
|
||||
if (
|
||||
relatedTarget &&
|
||||
|
@ -266,7 +286,9 @@
|
|||
on:clear
|
||||
on:clear="{() => {
|
||||
selectedIndex = -1;
|
||||
highlightedIndex = -1;
|
||||
open = false;
|
||||
inputValue = '';
|
||||
ref.focus();
|
||||
}}"
|
||||
translateWithId="{translateWithId}"
|
||||
|
@ -300,12 +322,19 @@
|
|||
.map(({ id }) => id)
|
||||
.indexOf(filteredItems[i].id);
|
||||
open = false;
|
||||
|
||||
if (filteredItems[i]) {
|
||||
inputValue = filteredItems[i].text;
|
||||
}
|
||||
}}"
|
||||
on:mouseenter="{() => {
|
||||
highlightedIndex = i;
|
||||
}}"
|
||||
>
|
||||
{itemToString(item)}
|
||||
{#if selectedItem && selectedItem.id === item.id}
|
||||
<Checkmark16 class="bx--list-box__menu-item__selected-icon" />
|
||||
{/if}
|
||||
</ListBoxMenuItem>
|
||||
{/each}
|
||||
</ListBoxMenu>
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
<svelte:window
|
||||
on:contextmenu|preventDefault="{(e) => {
|
||||
if (level > 1) return;
|
||||
if (!ref) return;
|
||||
|
||||
const { height, width } = ref.getBoundingClientRect();
|
||||
|
||||
|
@ -104,7 +105,7 @@
|
|||
}}"
|
||||
on:click="{(e) => {
|
||||
if (!open) return;
|
||||
if (e.target.contains(ref)) close();
|
||||
close();
|
||||
}}"
|
||||
on:keydown="{(e) => {
|
||||
if (open && e.key === 'Escape') close();
|
||||
|
@ -117,10 +118,10 @@
|
|||
tabindex="-1"
|
||||
data-direction="{direction}"
|
||||
data-level="{level}"
|
||||
class:bx--context-menu="{true}"
|
||||
class:bx--context-menu--open="{open}"
|
||||
class:bx--context-menu--invisible="{open && x === 0 && y === 0}"
|
||||
class:bx--context-menu--root="{level === 1}"
|
||||
class:bx--menu="{true}"
|
||||
class:bx--menu--open="{open}"
|
||||
class:bx--menu--invisible="{open && x === 0 && y === 0}"
|
||||
class:bx--menu--root="{level === 1}"
|
||||
{...$$restProps}
|
||||
style="left: {x}px; top: {y}px; {$$restProps.style}"
|
||||
on:click
|
||||
|
|
|
@ -1 +1 @@
|
|||
<li role="separator" class:bx--context-menu-divider="{true}"></li>
|
||||
<li role="separator" class:bx--menu-divider="{true}"></li>
|
||||
|
|
|
@ -173,14 +173,14 @@
|
|||
aria-disabled="{!subOptions && disabled}"
|
||||
aria-haspopup="{subOptions ? true : undefined}"
|
||||
aria-expanded="{subOptions ? submenuOpen : undefined}"
|
||||
class:bx--context-menu-option="{true}"
|
||||
class:bx--context-menu-option--disabled="{true}"
|
||||
class:bx--context-menu-option--active="{subOptions && submenuOpen}"
|
||||
class:bx--context-menu-option--danger="{!subOptions && kind === 'danger'}"
|
||||
class:bx--menu-option="{true}"
|
||||
class:bx--menu-option--disabled="{true}"
|
||||
class:bx--menu-option--active="{subOptions && submenuOpen}"
|
||||
class:bx--menu-option--danger="{!subOptions && kind === 'danger'}"
|
||||
indented="{indented}"
|
||||
aria-checked="{isSelectable || isRadio ? selected : undefined}"
|
||||
data-nested="{ref &&
|
||||
ref.closest('.bx--context-menu').getAttribute('data-level') === '2'}"
|
||||
ref.closest('.bx--menu').getAttribute('data-level') === '2'}"
|
||||
data-sub="{subOptions}"
|
||||
data-id="{id}"
|
||||
{...$$restProps}
|
||||
|
@ -240,18 +240,18 @@
|
|||
>
|
||||
{#if subOptions}
|
||||
<div
|
||||
class:bx--context-menu-option__content="{true}"
|
||||
class:bx--context-menu-option__content--disabled="{disabled}"
|
||||
class:bx--menu-option__content="{true}"
|
||||
class:bx--menu-option__content--disabled="{disabled}"
|
||||
>
|
||||
{#if indented}
|
||||
<div class:bx--context-menu-option__icon="{true}">
|
||||
<div class:bx--menu-option__icon="{true}">
|
||||
<svelte:component this="{icon}" />
|
||||
</div>
|
||||
{/if}
|
||||
<span class:bx--context-menu-option__label="{true}" title="{labelText}">
|
||||
<span class:bx--menu-option__label="{true}" title="{labelText}">
|
||||
<slot name="labelText">{labelText}</slot>
|
||||
</span>
|
||||
<div class:bx--context-menu-option__info="{true}"><CaretRight16 /></div>
|
||||
<div class:bx--menu-option__info="{true}"><CaretRight16 /></div>
|
||||
</div>
|
||||
|
||||
<ContextMenu
|
||||
|
@ -263,18 +263,18 @@
|
|||
</ContextMenu>
|
||||
{:else}
|
||||
<div
|
||||
class:bx--context-menu-option__content="{true}"
|
||||
class:bx--context-menu-option__content--disabled="{disabled}"
|
||||
class:bx--menu-option__content="{true}"
|
||||
class:bx--menu-option__content--disabled="{disabled}"
|
||||
>
|
||||
{#if indented}
|
||||
<div class:bx--context-menu-option__icon="{true}">
|
||||
<div class:bx--menu-option__icon="{true}">
|
||||
<svelte:component this="{icon}" />
|
||||
</div>
|
||||
{/if}
|
||||
<span class:bx--context-menu-option__label="{true}" title="{labelText}">
|
||||
<span class:bx--menu-option__label="{true}" title="{labelText}">
|
||||
<slot name="labelText">{labelText}</slot>
|
||||
</span>
|
||||
<div class:bx--context-menu-option__info="{true}">
|
||||
<div class:bx--menu-option__info="{true}">
|
||||
<slot name="shortcutText">{shortcutText}</slot>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -92,25 +92,25 @@
|
|||
<slot name="labelText">
|
||||
{labelText}
|
||||
</slot>
|
||||
<input
|
||||
bind:this="{ref}"
|
||||
type="file"
|
||||
tabindex="-1"
|
||||
id="{id}"
|
||||
disabled="{disabled}"
|
||||
accept="{accept}"
|
||||
name="{name}"
|
||||
multiple="{multiple}"
|
||||
class:bx--file-input="{true}"
|
||||
on:change
|
||||
on:change="{({ target }) => {
|
||||
dispatch('add', validateFiles(target.files));
|
||||
}}"
|
||||
on:click
|
||||
on:click="{({ target }) => {
|
||||
target.value = null;
|
||||
}}"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
bind:this="{ref}"
|
||||
type="file"
|
||||
tabindex="-1"
|
||||
id="{id}"
|
||||
disabled="{disabled}"
|
||||
accept="{accept}"
|
||||
name="{name}"
|
||||
multiple="{multiple}"
|
||||
class:bx--file-input="{true}"
|
||||
on:change
|
||||
on:change="{({ target }) => {
|
||||
dispatch('add', validateFiles(target.files));
|
||||
}}"
|
||||
on:click
|
||||
on:click="{({ target }) => {
|
||||
target.value = null;
|
||||
}}"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
import { createEventDispatcher, afterUpdate, onMount } from "svelte";
|
||||
import CheckmarkFilled16 from "carbon-icons-svelte/lib/CheckmarkFilled16/CheckmarkFilled16.svelte";
|
||||
import Error20 from "carbon-icons-svelte/lib/Error20/Error20.svelte";
|
||||
import ErrorFilled16 from "carbon-icons-svelte/lib/ErrorFilled16/ErrorFilled16.svelte";
|
||||
import Loading from "../Loading/Loading.svelte";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
@ -55,9 +55,15 @@
|
|||
>
|
||||
<div class:bx--inline-loading__animation="{true}">
|
||||
{#if status === "error"}
|
||||
<Error20 class="bx--inline-loading--error" />
|
||||
<ErrorFilled16
|
||||
class="bx--inline-loading--error"
|
||||
title="{iconDescription}"
|
||||
/>
|
||||
{:else if status === "finished"}
|
||||
<CheckmarkFilled16 class="bx--inline-loading__checkmark-container" />
|
||||
<CheckmarkFilled16
|
||||
class="bx--inline-loading__checkmark-container"
|
||||
title="{iconDescription}"
|
||||
/>
|
||||
{:else if status === "inactive" || status === "active"}
|
||||
<Loading
|
||||
small
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
on:mouseenter
|
||||
on:mouseleave
|
||||
on:keydown|preventDefault|stopPropagation
|
||||
on:focus
|
||||
on:blur
|
||||
>
|
||||
<slot />
|
||||
|
|
|
@ -319,6 +319,12 @@
|
|||
}
|
||||
}
|
||||
}}"
|
||||
on:focus="{() => {
|
||||
if (filterable) {
|
||||
open = true;
|
||||
if (inputRef) inputRef.focus();
|
||||
}
|
||||
}}"
|
||||
on:blur="{({ relatedTarget }) => {
|
||||
if (
|
||||
relatedTarget &&
|
||||
|
@ -342,7 +348,7 @@
|
|||
...item,
|
||||
checked: false,
|
||||
}));
|
||||
fieldRef.blur();
|
||||
if (fieldRef) fieldRef.blur();
|
||||
}}"
|
||||
translateWithId="{translateWithId}"
|
||||
disabled="{disabled}"
|
||||
|
@ -388,7 +394,11 @@
|
|||
on:blur="{({ relatedTarget }) => {
|
||||
if (
|
||||
relatedTarget &&
|
||||
relatedTarget.getAttribute('role') !== 'button'
|
||||
!['INPUT', 'SELECT', 'TEXTAREA'].includes(
|
||||
relatedTarget.tagName
|
||||
) &&
|
||||
relatedTarget.getAttribute('role') !== 'button' &&
|
||||
relatedTarget.getAttribute('role') !== 'searchbox'
|
||||
) {
|
||||
inputRef.focus();
|
||||
}
|
||||
|
@ -453,6 +463,9 @@
|
|||
labelText="{itemToString(item)}"
|
||||
checked="{item.checked}"
|
||||
disabled="{disabled}"
|
||||
on:blur="{() => {
|
||||
if (i === filteredItems.length - 1) open = false;
|
||||
}}"
|
||||
/>
|
||||
</ListBoxMenuItem>
|
||||
{/each}
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
</script>
|
||||
|
||||
<div
|
||||
aria-label="Structured list section"
|
||||
role="table"
|
||||
class:bx--structured-list="{true}"
|
||||
class:bx--structured-list--border="{border}"
|
||||
class:bx--structured-list--selection="{selection}"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div
|
||||
class:bx--structured-list-tbody="{true}"
|
||||
role="rowgroup"
|
||||
class:bx--structured-list-tbody="{true}"
|
||||
{...$$restProps}
|
||||
on:click
|
||||
on:mouseover
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
</script>
|
||||
|
||||
<div
|
||||
role="{head ? 'columnheader' : 'cell'}"
|
||||
class:bx--structured-list-th="{head}"
|
||||
class:bx--structured-list-td="{!head}"
|
||||
class:bx--structured-list-content--nowrap="{noWrap}"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<div
|
||||
role="rowgroup"
|
||||
class:bx--structured-list-thead="{true}"
|
||||
{...$$restProps}
|
||||
on:click
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
{#if label}
|
||||
<!-- svelte-ignore a11y-label-has-associated-control -->
|
||||
<label
|
||||
role="presentation"
|
||||
tabindex="{tabindex}"
|
||||
class:bx--structured-list-row="{true}"
|
||||
class:bx--structured-list-row--header-row="{head}"
|
||||
|
@ -27,6 +26,7 @@
|
|||
</label>
|
||||
{:else}
|
||||
<div
|
||||
role="row"
|
||||
class:bx--structured-list-row="{true}"
|
||||
class:bx--structured-list-row--header-row="{head}"
|
||||
{...$$restProps}
|
||||
|
|
|
@ -59,12 +59,16 @@
|
|||
/** Set to `true` to mark the field as required */
|
||||
export let required = false;
|
||||
|
||||
/** Set to `true` to use inline version */
|
||||
/** Set to `true` to use the inline variant */
|
||||
export let inline = false;
|
||||
|
||||
/** Set to `true` to use the read-only variant */
|
||||
export let readonly = false;
|
||||
|
||||
import { getContext } from "svelte";
|
||||
import WarningFilled16 from "carbon-icons-svelte/lib/WarningFilled16/WarningFilled16.svelte";
|
||||
import WarningAltFilled16 from "carbon-icons-svelte/lib/WarningAltFilled16/WarningAltFilled16.svelte";
|
||||
import EditOff16 from "carbon-icons-svelte/lib/EditOff16/EditOff16.svelte";
|
||||
|
||||
const ctx = getContext("Form");
|
||||
|
||||
|
@ -77,6 +81,8 @@
|
|||
class:bx--form-item="{true}"
|
||||
class:bx--text-input-wrapper="{true}"
|
||||
class:bx--text-input-wrapper--inline="{inline}"
|
||||
class:bx--text-input-wrapper--light="{light}"
|
||||
class:bx--text-input-wrapper--readonly="{readonly}"
|
||||
on:click
|
||||
on:mouseover
|
||||
on:mouseenter
|
||||
|
@ -142,6 +148,9 @@
|
|||
bx--text-input__invalid-icon--warning"
|
||||
/>
|
||||
{/if}
|
||||
{#if readonly}
|
||||
<EditOff16 class="bx--text-input__readonly-icon" />
|
||||
{/if}
|
||||
<input
|
||||
bind:this="{ref}"
|
||||
data-invalid="{invalid || undefined}"
|
||||
|
@ -155,6 +164,7 @@
|
|||
type="{type}"
|
||||
value="{value}"
|
||||
required="{required}"
|
||||
readonly="{readonly}"
|
||||
class:bx--text-input="{true}"
|
||||
class:bx--text-input--light="{light}"
|
||||
class:bx--text-input--invalid="{invalid}"
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
if (key === 'Escape') hide();
|
||||
}}" />
|
||||
|
||||
<div
|
||||
<span
|
||||
class:bx--tooltip--definition="{true}"
|
||||
class:bx--tooltip--a11y="{true}"
|
||||
{...$$restProps}
|
||||
|
@ -69,4 +69,4 @@
|
|||
<div role="tooltip" id="{id}" class:bx--assistive-text="{true}">
|
||||
<slot name="tooltip">{tooltipText}</slot>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let winWidth = undefined;
|
||||
|
||||
$: dispatch(isOpen ? "open" : "close");
|
||||
|
||||
onMount(() => {
|
||||
|
@ -33,6 +35,8 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerWidth="{winWidth}" />
|
||||
|
||||
{#if !fixed}
|
||||
<div
|
||||
on:click="{() => {
|
||||
|
@ -49,7 +53,7 @@
|
|||
class:bx--side-nav__navigation="{true}"
|
||||
class:bx--side-nav="{true}"
|
||||
class:bx--side-nav--ux="{true}"
|
||||
class:bx--side-nav--expanded="{isOpen && !rail}"
|
||||
class:bx--side-nav--expanded="{rail && winWidth >= 1056 ? false : isOpen}"
|
||||
class:bx--side-nav--collapsed="{!isOpen && !rail}"
|
||||
class:bx--side-nav--rail="{rail}"
|
||||
{...$$restProps}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue