Skip to content

Commit

Permalink
add in/out transition props to components (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
huntabyte authored Aug 21, 2023
1 parent 3f59cfb commit 5d2e054
Show file tree
Hide file tree
Showing 79 changed files with 1,576 additions and 281 deletions.
5 changes: 5 additions & 0 deletions .changeset/dry-yaks-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"bits-ui": patch
---

Feat: Improve transition props to support `in` and `out` transitions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,5 @@
"svelte": "^4.0.0"
},
"packageManager": "pnpm@8.6.3"

}
45 changes: 18 additions & 27 deletions patches/@melt-ui__svelte@0.37.2.patch
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
diff --git a/dist/builders/dialog/create.js b/dist/builders/dialog/create.js
index 13cf6ab7c4ee392ae7530813b6f5a3edc2819628..d42908e0e139327970718e5c32731b3d0cc09de5 100644
--- a/dist/builders/dialog/create.js
+++ b/dist/builders/dialog/create.js
@@ -38,13 +38,15 @@ export function createDialog(props) {
activeTrigger.set(triggerEl);
}
function handleClose() {
- open.set(false);
- const triggerEl = document.getElementById(ids.trigger);
- if (triggerEl) {
- tick().then(() => {
- triggerEl.focus();
- });
- }
+ tick().then(() => {
+ open.set(false);
+ const triggerEl = document.getElementById(ids.trigger);
+ if (triggerEl) {
+ tick().then(() => {
+ triggerEl.focus();
+ });
+ }
+ })
}
onMount(() => {
activeTrigger.set(document.getElementById(ids.trigger));
diff --git a/dist/internal/helpers/overridable.js b/dist/internal/helpers/overridable.js
index 4bfd74ec7fc838dbce59491c37180f9a3cd798c2..a92e724ef14e9148e5bdf40c1e5a1e5817d61ed7 100644
--- a/dist/internal/helpers/overridable.js
+++ b/dist/internal/helpers/overridable.js
@@ -1,10 +1,10 @@
-export const overridable = (store, onChange) => {
+export const overridable = async (store, onChange) => {
const update = (updater, sideEffect) => {
- store.update((curr) => {
+ store.update(async (curr) => {
const next = updater(curr);
let res = next;
if (onChange) {
- res = onChange({ curr, next });
+ res = await onChange({ curr, next });
}
sideEffect?.(res);
return res;
3 changes: 2 additions & 1 deletion src/components/ui/alert-dialog/alert-dialog-content.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
<AlertDialog.Portal>
<AlertDialog.Overlay />
<AlertDialogPrimitive.Content
transition={AlertDialog.transition}
class={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full",
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg sm:rounded-lg md:w-full",
className
)}
{...$$restProps}
Expand Down
8 changes: 4 additions & 4 deletions src/components/ui/alert-dialog/alert-dialog-overlay.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive } from "@/lib";
import { cn } from "@/utils";
import { fade } from "svelte/transition";
type $$Props = AlertDialogPrimitive.OverlayProps;
Expand All @@ -9,9 +10,8 @@
</script>

<AlertDialogPrimitive.Overlay
class={cn(
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className
)}
transition={fade}
transitionConfig={{ duration: 150 }}
class={cn("fixed inset-0 z-50 bg-background/80 backdrop-blur-sm ", className)}
{...$$restProps}
/>
48 changes: 48 additions & 0 deletions src/components/ui/alert-dialog/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import Header from "./alert-dialog-header.svelte";
import Overlay from "./alert-dialog-overlay.svelte";
import Content from "./alert-dialog-content.svelte";
import Description from "./alert-dialog-description.svelte";
import type { TransitionConfig } from "svelte/transition";
import { cubicOut } from "svelte/easing";

export {
Root,
Expand All @@ -38,3 +40,49 @@ export {
Content as AlertDialogContent,
Description as AlertDialogDescription
};

type TransitionParams = {
y: number;
start: number;
duration?: number;
};

export const transition = (
node: Element,
params: TransitionParams = { y: -8, start: 0.95, duration: 200 }
): TransitionConfig => {
const style = getComputedStyle(node);
const transform = style.transform === "none" ? "" : style.transform;

const scaleConversion = (valueA: number, scaleA: [number, number], scaleB: [number, number]) => {
const [minA, maxA] = scaleA;
const [minB, maxB] = scaleB;

const percentage = (valueA - minA) / (maxA - minA);
const valueB = percentage * (maxB - minB) + minB;

return valueB;
};

const styleToString = (style: Record<string, number | string | undefined>): string => {
return Object.keys(style).reduce((str, key) => {
if (style[key] === undefined) return str;
return str + `${key}:${style[key]};`;
}, "");
};

return {
duration: params.duration ?? 200,
delay: 0,
css: (t) => {
const y = scaleConversion(t, [0, 1], [params.y, 0]);
const scale = scaleConversion(t, [0, 1], [params.start, 1]);

return styleToString({
transform: `${transform} translate3d(0, ${y}px, 0) scale(${scale})`,
opacity: t
});
},
easing: cubicOut
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<ContextMenuPrimitive.CheckboxItem
bind:checked
class={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...$$restProps}
Expand Down
4 changes: 3 additions & 1 deletion src/components/ui/context-menu/context-menu-content.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "@/lib";
import * as ContextMenu from ".";
import { cn } from "@/utils";
type $$Props = ContextMenuPrimitive.ContentProps;
Expand All @@ -9,8 +10,9 @@
</script>

<ContextMenuPrimitive.Content
transition={ContextMenu.transition}
class={cn(
"z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 focus:outline-none",
"z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-md focus:outline-none",
className
)}
{...$$restProps}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/context-menu/context-menu-item.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

<ContextMenuPrimitive.Item
class={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 ",
inset && "pl-8",
className
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<ContextMenuPrimitive.RadioItem
class={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{value}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "@/lib";
import { cn } from "@/utils";
import { transition } from ".";
type $$Props = ContextMenuPrimitive.SubContentProps;
Expand All @@ -9,8 +10,10 @@
</script>

<ContextMenuPrimitive.SubContent
{transition}
transitionConfig={{ x: -10, y: 0 }}
class={cn(
"z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 focus:outline-none",
"z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-lg focus:outline-none",
className
)}
{...$$restProps}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

<ContextMenuPrimitive.SubTrigger
class={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
inset && "pl-8",
className
)}
Expand Down
50 changes: 50 additions & 0 deletions src/components/ui/context-menu/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import RadioGroup from "./context-menu-radio-group.svelte";
import SubContent from "./context-menu-sub-content.svelte";
import SubTrigger from "./context-menu-sub-trigger.svelte";
import CheckboxItem from "./context-menu-checkbox-item.svelte";
import type { TransitionConfig } from "svelte/transition";
import { cubicOut } from "svelte/easing";

const Sub = ContextMenuPrimitive.Sub;
const Root = ContextMenuPrimitive.Root;
Expand Down Expand Up @@ -47,3 +49,51 @@ export {
SubTrigger as ContextMenuSubTrigger,
CheckboxItem as ContextMenuCheckboxItem
};

type TransitionParams = {
y?: number;
x?: number;
start?: number;
duration?: number;
};

export const transition = (
node: Element,
params: TransitionParams = { y: -8, x: 0, start: 0.95, duration: 150 }
): TransitionConfig => {
const style = getComputedStyle(node);
const transform = style.transform === "none" ? "" : style.transform;

const scaleConversion = (valueA: number, scaleA: [number, number], scaleB: [number, number]) => {
const [minA, maxA] = scaleA;
const [minB, maxB] = scaleB;

const percentage = (valueA - minA) / (maxA - minA);
const valueB = percentage * (maxB - minB) + minB;

return valueB;
};

const styleToString = (style: Record<string, number | string | undefined>): string => {
return Object.keys(style).reduce((str, key) => {
if (style[key] === undefined) return str;
return str + `${key}:${style[key]};`;
}, "");
};

return {
duration: params.duration ?? 200,
delay: 0,
css: (t) => {
const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]);
const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]);
const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]);

return styleToString({
transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`,
opacity: t
});
},
easing: cubicOut
};
};
3 changes: 2 additions & 1 deletion src/components/ui/dialog/dialog-content.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
<Dialog.Portal>
<Dialog.Overlay />
<DialogPrimitive.Content
transition={Dialog.transition}
class={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full",
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg md:w-full",
className
)}
{...$$restProps}
Expand Down
8 changes: 4 additions & 4 deletions src/components/ui/dialog/dialog-overlay.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from "@/lib";
import { cn } from "@/utils";
import { fade } from "svelte/transition";
type $$Props = DialogPrimitive.OverlayProps;
Expand All @@ -9,9 +10,8 @@
</script>

<DialogPrimitive.Overlay
class={cn(
"fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className
)}
transition={fade}
transitionConfig={{ duration: 150 }}
class={cn("fixed inset-0 z-50 bg-background/80 backdrop-blur-sm", className)}
{...$$restProps}
/>
48 changes: 48 additions & 0 deletions src/components/ui/dialog/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import Header from "./dialog-header.svelte";
import Overlay from "./dialog-overlay.svelte";
import Content from "./dialog-content.svelte";
import Description from "./dialog-description.svelte";
import type { TransitionConfig } from "svelte/transition";
import { cubicOut } from "svelte/easing";

export {
Root,
Expand All @@ -32,3 +34,49 @@ export {
Content as DialogContent,
Description as DialogDescription
};

type TransitionParams = {
y: number;
start: number;
duration?: number;
};

export const transition = (
node: Element,
params: TransitionParams = { y: -8, start: 0.95, duration: 200 }
): TransitionConfig => {
const style = getComputedStyle(node);
const transform = style.transform === "none" ? "" : style.transform;

const scaleConversion = (valueA: number, scaleA: [number, number], scaleB: [number, number]) => {
const [minA, maxA] = scaleA;
const [minB, maxB] = scaleB;

const percentage = (valueA - minA) / (maxA - minA);
const valueB = percentage * (maxB - minB) + minB;

return valueB;
};

const styleToString = (style: Record<string, number | string | undefined>): string => {
return Object.keys(style).reduce((str, key) => {
if (style[key] === undefined) return str;
return str + `${key}:${style[key]};`;
}, "");
};

return {
duration: params.duration ?? 200,
delay: 0,
css: (t) => {
const y = scaleConversion(t, [0, 1], [params.y, 0]);
const scale = scaleConversion(t, [0, 1], [params.start, 1]);

return styleToString({
transform: `${transform} translate3d(0, ${y}px, 0) scale(${scale})`,
opacity: t
});
},
easing: cubicOut
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<DropdownMenuPrimitive.CheckboxItem
bind:checked
class={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...$$restProps}
Expand Down
Loading

0 comments on commit 5d2e054

Please sign in to comment.