feat(ui): add optional transition animations to dialog
This commit is contained in:
@@ -14,7 +14,7 @@ export const DialogSettings: Component = () => {
|
|||||||
const platform = usePlatform()
|
const platform = usePlatform()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog size="x-large">
|
<Dialog size="x-large" transition>
|
||||||
<Tabs orientation="vertical" variant="settings" defaultValue="general" class="h-full settings-dialog">
|
<Tabs orientation="vertical" variant="settings" defaultValue="general" class="h-full settings-dialog">
|
||||||
<Tabs.List>
|
<Tabs.List>
|
||||||
<div class="flex flex-col justify-between h-full w-full">
|
<div class="flex flex-col justify-between h-full w-full">
|
||||||
|
|||||||
@@ -5,12 +5,6 @@
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
background-color: hsl(from var(--background-base) h s l / 0.2);
|
background-color: hsl(from var(--background-base) h s l / 0.2);
|
||||||
|
|
||||||
/* animation: overlayHide 250ms ease 100ms forwards; */
|
|
||||||
/**/
|
|
||||||
/* &[data-expanded] { */
|
|
||||||
/* animation: overlayShow 250ms ease; */
|
|
||||||
/* } */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-component="dialog"] {
|
[data-component="dialog"] {
|
||||||
@@ -58,12 +52,6 @@
|
|||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
box-shadow: var(--shadow-lg-border-base);
|
box-shadow: var(--shadow-lg-border-base);
|
||||||
|
|
||||||
/* animation: contentHide 300ms ease-in forwards; */
|
|
||||||
/**/
|
|
||||||
/* &[data-expanded] { */
|
|
||||||
/* animation: contentShow 300ms ease-out; */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
[data-slot="dialog-header"] {
|
[data-slot="dialog-header"] {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
@@ -147,6 +135,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-component="dialog"][data-transition] [data-slot="dialog-content"] {
|
||||||
|
animation: contentHide 100ms ease-in forwards;
|
||||||
|
|
||||||
|
&[data-expanded] {
|
||||||
|
animation: contentShow 200ms ease-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes overlayShow {
|
@keyframes overlayShow {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -166,7 +162,7 @@
|
|||||||
@keyframes contentShow {
|
@keyframes contentShow {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(0.96);
|
transform: scale(0.98);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -180,6 +176,6 @@
|
|||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(0.96);
|
transform: scale(0.98);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,18 @@ export interface DialogProps extends ParentProps {
|
|||||||
class?: ComponentProps<"div">["class"]
|
class?: ComponentProps<"div">["class"]
|
||||||
classList?: ComponentProps<"div">["classList"]
|
classList?: ComponentProps<"div">["classList"]
|
||||||
fit?: boolean
|
fit?: boolean
|
||||||
|
transition?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Dialog(props: DialogProps) {
|
export function Dialog(props: DialogProps) {
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
return (
|
return (
|
||||||
<div data-component="dialog" data-fit={props.fit ? true : undefined} data-size={props.size || "normal"}>
|
<div
|
||||||
|
data-component="dialog"
|
||||||
|
data-fit={props.fit ? true : undefined}
|
||||||
|
data-size={props.size || "normal"}
|
||||||
|
data-transition={props.transition ? true : undefined}
|
||||||
|
>
|
||||||
<div data-slot="dialog-container">
|
<div data-slot="dialog-container">
|
||||||
<Kobalte.Content
|
<Kobalte.Content
|
||||||
data-slot="dialog-content"
|
data-slot="dialog-content"
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type Active = {
|
|||||||
dispose: () => void
|
dispose: () => void
|
||||||
owner: Owner
|
owner: Owner
|
||||||
onClose?: () => void
|
onClose?: () => void
|
||||||
|
setClosing: (closing: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const Context = createContext<ReturnType<typeof init>>()
|
const Context = createContext<ReturnType<typeof init>>()
|
||||||
@@ -32,8 +33,11 @@ function init() {
|
|||||||
const current = active()
|
const current = active()
|
||||||
if (!current) return
|
if (!current) return
|
||||||
current.onClose?.()
|
current.onClose?.()
|
||||||
current.dispose()
|
current.setClosing(true)
|
||||||
setActive(undefined)
|
setTimeout(() => {
|
||||||
|
current.dispose()
|
||||||
|
setActive(undefined)
|
||||||
|
}, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
@@ -55,14 +59,17 @@ function init() {
|
|||||||
|
|
||||||
const id = Math.random().toString(36).slice(2)
|
const id = Math.random().toString(36).slice(2)
|
||||||
let dispose: (() => void) | undefined
|
let dispose: (() => void) | undefined
|
||||||
|
let setClosing: ((closing: boolean) => void) | undefined
|
||||||
|
|
||||||
const node = runWithOwner(owner, () =>
|
const node = runWithOwner(owner, () =>
|
||||||
createRoot((d: () => void) => {
|
createRoot((d: () => void) => {
|
||||||
dispose = d
|
dispose = d
|
||||||
|
const [closing, setClosingSignal] = createSignal(false)
|
||||||
|
setClosing = setClosingSignal
|
||||||
return (
|
return (
|
||||||
<Kobalte
|
<Kobalte
|
||||||
modal
|
modal
|
||||||
open={true}
|
open={!closing()}
|
||||||
onOpenChange={(open: boolean) => {
|
onOpenChange={(open: boolean) => {
|
||||||
if (open) return
|
if (open) return
|
||||||
close()
|
close()
|
||||||
@@ -77,9 +84,9 @@ function init() {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!dispose) return
|
if (!dispose || !setClosing) return
|
||||||
|
|
||||||
setActive({ id, node, dispose, owner, onClose })
|
setActive({ id, node, dispose, owner, onClose, setClosing })
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user