From 6d25f254f746889379a68cc9242cf6ca33ccb01c Mon Sep 17 00:00:00 2001 From: abdel Date: Fri, 24 Oct 2025 07:45:23 +0800 Subject: [PATCH 01/11] fix: streamline animation handling and remove unused transition states --- .../components/element/html-element.svelte | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/lib/components/element/html-element.svelte b/src/lib/components/element/html-element.svelte index c7108b1..0dc51a5 100644 --- a/src/lib/components/element/html-element.svelte +++ b/src/lib/components/element/html-element.svelte @@ -23,18 +23,13 @@ let node = $state(); - let hasIntroTransitionStarted: boolean | undefined = $state(undefined); - let skipFirstAnimate = true; + let skipFirstAnimate = $state(!!enter); $effect(() => { if (!node) return; const unmount = untrack(() => onmount?.(node!)); - if (!enter || typeof hasIntroTransitionStarted === 'undefined') { - skipFirstAnimate = false; - } - return () => { if (typeof unmount === 'function') unmount(node!); ondestroy?.(node!); @@ -42,14 +37,17 @@ }); $effect(() => { + const fn = animate; + if (!node) return; + const shouldSkip = untrack(() => skipFirstAnimate); - if (skipFirstAnimate) { + if (shouldSkip) { skipFirstAnimate = false; return; } - animate?.(node); + fn?.(node); }); const elementProps = $derived({ @@ -57,12 +55,6 @@ node = n; }, class: cn(toClassValue(klass)), - onintrostart: () => { - hasIntroTransitionStarted = true; - }, - onintroend: () => { - hasIntroTransitionStarted = false; - }, ...restProps }); From b2f177fdef82a06dbcd8279655f0a75b7c114e0d Mon Sep 17 00:00:00 2001 From: abdel Date: Fri, 24 Oct 2025 07:45:39 +0800 Subject: [PATCH 02/11] fix: remove unused 'as' prop from CollapsibleRoot component --- src/lib/components/collapsible/collapsible-root.svelte | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib/components/collapsible/collapsible-root.svelte b/src/lib/components/collapsible/collapsible-root.svelte index f9137e2..1ea283f 100644 --- a/src/lib/components/collapsible/collapsible-root.svelte +++ b/src/lib/components/collapsible/collapsible-root.svelte @@ -30,7 +30,6 @@ value = nanoid(), data = undefined, disabled = false, - as = 'div' as E, factory = _factory, children = undefined, onmount = undefined, @@ -71,16 +70,15 @@ {@render children?.({ collapsible: bond })} From d3f32406d53e2904cbfe18710c059d78ee3ea173 Mon Sep 17 00:00:00 2001 From: abdel Date: Fri, 24 Oct 2025 07:50:24 +0800 Subject: [PATCH 03/11] fix: enhance accessibility and interaction handling in CollapsibleBond header --- src/lib/components/collapsible/bond.svelte.ts | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/lib/components/collapsible/bond.svelte.ts b/src/lib/components/collapsible/bond.svelte.ts index 9f015ab..2fc792c 100644 --- a/src/lib/components/collapsible/bond.svelte.ts +++ b/src/lib/components/collapsible/bond.svelte.ts @@ -50,19 +50,31 @@ export class CollapsibleBond extends Bond< } header(props: Record = {}) { + const isDisabled = this.state?.props?.disabled ?? false; + const isOpen = this.state?.props?.open ?? false; + const isButton = this.elements.header instanceof HTMLButtonElement; + return { - 'aria-disabled': this.state?.props?.disabled ?? false, - 'aria-expanded': this.state?.props?.open ?? false, + 'aria-disabled': isDisabled ? 'true' : 'false', + 'aria-expanded': isOpen ? 'true' : 'false', 'aria-controls': `collapsible-body-${this.id}`, - disabled: this.elements.header instanceof HTMLButtonElement ? this.state?.props.disabled : '', - role: this.elements.header instanceof HTMLButtonElement ? undefined : 'button', - tabindex: this.state?.props?.open ? 0 : -1, // Make focusable if open + disabled: isButton ? isDisabled : undefined, + role: isButton ? undefined : 'button', + tabindex: isButton ? undefined : isDisabled ? -1 : 0, id: `collapsible-header-${this.id}`, 'data-atom': this.id ?? '', 'data-kind': 'collapsible-header', ...props, onclick: () => { - this.state.toggle(); + if (!isDisabled) { + this.state.toggle(); + } + }, + onkeydown: (e: KeyboardEvent) => { + if (!isDisabled && (e.key === 'Enter' || e.key === ' ')) { + e.preventDefault(); + this.state.toggle(); + } }, [createAttachmentKey()]: (node: HTMLElement) => { this.elements.header = node; @@ -71,13 +83,15 @@ export class CollapsibleBond extends Bond< } body(props: Record = {}) { + const isOpen = this.state?.props?.open ?? false; + return { 'aria-labelledby': `collapsible-header-${this.id}`, - 'aria-hidden': !this.state?.props?.open, // Hide when closed - role: 'region', // Announce as a region + role: 'region', id: `collapsible-body-${this.id}`, 'data-atom': this.id ?? '', 'data-kind': 'collapsible-body', + inert: isOpen ? undefined : true, ...props, [createAttachmentKey()]: (node: HTMLElement) => { this.elements.body = node; From a3397c88f1e99de3589908e250ebb0778dbe5d1a Mon Sep 17 00:00:00 2001 From: abdel Date: Fri, 24 Oct 2025 07:51:00 +0800 Subject: [PATCH 04/11] fix: replace GSAP with motion for animation handling in Collapsible stories --- .../collapsible/collapsible.stories.svelte | 146 +++++++++--------- 1 file changed, 72 insertions(+), 74 deletions(-) diff --git a/src/lib/components/collapsible/collapsible.stories.svelte b/src/lib/components/collapsible/collapsible.stories.svelte index b8977b8..cd9eb5c 100644 --- a/src/lib/components/collapsible/collapsible.stories.svelte +++ b/src/lib/components/collapsible/collapsible.stories.svelte @@ -1,11 +1,9 @@