forked from chakra-ui/zag
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: floating panel machine (chakra-ui#1363)
* chore: initial scafold * chore: update * chore: improve set up * chore: update styles * chore: rm portal for now * chore: update transitions * feat: implement dragging * chore: get drag and resize to work * feat: support min and max size * chore: preserve * chore: update preserve * feat: complete features * refactor: stage types * feat: track boundary element * feat: complete v1 * style: fix * feat: update examples * feat: keyboard support * docs: add changeset
- Loading branch information
1 parent
c690354
commit 52a261e
Showing
84 changed files
with
2,205 additions
and
510 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@zag-js/floating-panel": minor | ||
--- | ||
|
||
Introduce new floating panel machine for draggable and resizable panels |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
"use strict"; | ||
|
||
var _xstate = require("xstate"); | ||
const { | ||
actions, | ||
createMachine, | ||
assign | ||
} = _xstate; | ||
const { | ||
choose | ||
} = actions; | ||
const fetchMachine = createMachine({ | ||
id: "floating-panel", | ||
initial: ctx.open ? "open" : "closed", | ||
context: { | ||
"!isMaximized": false, | ||
"!isMinimized": false, | ||
"closeOnEsc": false | ||
}, | ||
on: { | ||
UPDATE_CONTEXT: { | ||
actions: "updateContext" | ||
} | ||
}, | ||
states: { | ||
closed: { | ||
tags: ["closed"], | ||
on: { | ||
OPEN: { | ||
target: "open", | ||
actions: ["invokeOnOpen", "setPositionStyle", "setSizeStyle"] | ||
} | ||
} | ||
}, | ||
open: { | ||
tags: ["open"], | ||
activities: ["trackBoundaryRect"], | ||
on: { | ||
DRAG_START: { | ||
cond: "!isMaximized", | ||
target: "open.dragging", | ||
actions: ["setPrevPosition"] | ||
}, | ||
RESIZE_START: { | ||
cond: "!isMinimized", | ||
target: "open.resizing", | ||
actions: ["setPrevSize"] | ||
}, | ||
CLOSE: { | ||
target: "closed", | ||
actions: ["invokeOnClose", "resetRect"] | ||
}, | ||
ESCAPE: { | ||
cond: "closeOnEsc", | ||
target: "closed", | ||
actions: ["invokeOnClose", "resetRect"] | ||
}, | ||
MINIMIZE: { | ||
actions: ["setMinimized", "invokeOnMinimize"] | ||
}, | ||
MAXIMIZE: { | ||
actions: ["setMaximized", "invokeOnMaximize"] | ||
}, | ||
RESTORE: { | ||
actions: ["setRestored"] | ||
}, | ||
MOVE: { | ||
actions: ["setPositionFromKeybord"] | ||
} | ||
} | ||
}, | ||
"open.dragging": { | ||
tags: ["open"], | ||
activities: ["trackPointerMove", "trackBoundaryRect"], | ||
exit: ["clearPrevPosition"], | ||
on: { | ||
DRAG: { | ||
actions: ["setPosition"] | ||
}, | ||
DRAG_END: { | ||
target: "open", | ||
actions: ["invokeOnDragEnd"] | ||
}, | ||
CLOSE: { | ||
target: "closed", | ||
actions: ["invokeOnClose", "resetRect"] | ||
}, | ||
ESCAPE: { | ||
target: "open" | ||
} | ||
} | ||
}, | ||
"open.resizing": { | ||
tags: ["open"], | ||
activities: ["trackPointerMove", "trackBoundaryRect"], | ||
exit: ["clearPrevSize"], | ||
on: { | ||
DRAG: { | ||
actions: ["setSize"] | ||
}, | ||
DRAG_END: { | ||
target: "open", | ||
actions: ["invokeOnResizeEnd"] | ||
}, | ||
CLOSE: { | ||
target: "closed", | ||
actions: ["invokeOnClose", "resetRect"] | ||
}, | ||
ESCAPE: { | ||
target: "open" | ||
} | ||
} | ||
} | ||
} | ||
}, { | ||
actions: { | ||
updateContext: assign((context, event) => { | ||
return { | ||
[event.contextKey]: true | ||
}; | ||
}) | ||
}, | ||
guards: { | ||
"!isMaximized": ctx => ctx["!isMaximized"], | ||
"!isMinimized": ctx => ctx["!isMinimized"], | ||
"closeOnEsc": ctx => ctx["closeOnEsc"] | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import * as floatingPanel from "@zag-js/floating-panel" | ||
import { normalizeProps, useMachine } from "@zag-js/react" | ||
import { floatingPanelControls } from "@zag-js/shared" | ||
import { ArrowDownLeft, Maximize2, Minus, XIcon } from "lucide-react" | ||
import { useId } from "react" | ||
import { StateVisualizer } from "../components/state-visualizer" | ||
import { Toolbar } from "../components/toolbar" | ||
import { useControls } from "../hooks/use-controls" | ||
|
||
export default function Page() { | ||
const controls = useControls(floatingPanelControls) | ||
|
||
const [state, send] = useMachine(floatingPanel.machine({ id: useId() }), { | ||
context: controls.context, | ||
}) | ||
|
||
const api = floatingPanel.connect(state, send, normalizeProps) | ||
|
||
return ( | ||
<> | ||
<main className="floating-panel"> | ||
<div> | ||
<button {...api.triggerProps}>Toggle Panel</button> | ||
<div {...api.positionerProps}> | ||
<div {...api.contentProps}> | ||
<div {...api.dragTriggerProps}> | ||
<div {...api.headerProps}> | ||
<p {...api.titleProps}>Floating Panel</p> | ||
<div data-scope="floating-panel" data-part="trigger-group"> | ||
<button {...api.minimizeTriggerProps}> | ||
<Minus /> | ||
</button> | ||
<button {...api.maximizeTriggerProps}> | ||
<Maximize2 /> | ||
</button> | ||
<button {...api.restoreTriggerProps}> | ||
<ArrowDownLeft /> | ||
</button> | ||
<button {...api.closeTriggerProps}> | ||
<XIcon /> | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
<div {...api.bodyProps}> | ||
<p>Some content</p> | ||
</div> | ||
|
||
<div {...api.getResizeTriggerProps({ axis: "n" })} /> | ||
<div {...api.getResizeTriggerProps({ axis: "e" })} /> | ||
<div {...api.getResizeTriggerProps({ axis: "w" })} /> | ||
<div {...api.getResizeTriggerProps({ axis: "s" })} /> | ||
<div {...api.getResizeTriggerProps({ axis: "ne" })} /> | ||
<div {...api.getResizeTriggerProps({ axis: "se" })} /> | ||
<div {...api.getResizeTriggerProps({ axis: "sw" })} /> | ||
<div {...api.getResizeTriggerProps({ axis: "nw" })} /> | ||
</div> | ||
</div> | ||
</div> | ||
</main> | ||
|
||
<Toolbar controls={controls.ui}> | ||
<StateVisualizer state={state} /> | ||
</Toolbar> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<script setup lang="ts"> | ||
import * as floatingPanel from "@zag-js/floating-panel" | ||
import { floatingPanelControls } from "@zag-js/shared" | ||
import { normalizeProps, useMachine } from "@zag-js/vue" | ||
const controls = useControls(floatingPanelControls) | ||
const [state, send] = useMachine(floatingPanel.machine({ id: "1" }), { | ||
context: controls.context, | ||
}) | ||
const api = computed(() => floatingPanel.connect(state.value, send, normalizeProps)) | ||
</script> | ||
|
||
<template> | ||
<main class="floating-panel"> | ||
<div> | ||
<button v-bind="api.triggerProps">Toggle Panel</button> | ||
<div v-bind="api.positionerProps"> | ||
<div v-bind="api.contentProps"> | ||
<div v-bind="api.dragTriggerProps"> | ||
<div v-bind="api.headerProps"> | ||
<p v-bind="api.titleProps">Floating Panel</p> | ||
<div data-scope="floating-panel" data-part="trigger-group"> | ||
<button v-bind="api.minimizeTriggerProps"> | ||
<Minus /> | ||
</button> | ||
<button v-bind="api.maximizeTriggerProps"> | ||
<Maximize2 /> | ||
</button> | ||
<button v-bind="api.restoreTriggerProps"> | ||
<ArrowDownLeft /> | ||
</button> | ||
<button v-bind="api.closeTriggerProps"> | ||
<XIcon /> | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
<div v-bind="api.bodyProps"> | ||
<p>Some content</p> | ||
</div> | ||
|
||
<div v-bind="api.getResizeTriggerProps({ axis: 'n' })" /> | ||
<div v-bind="api.getResizeTriggerProps({ axis: 'e' })" /> | ||
<div v-bind="api.getResizeTriggerProps({ axis: 'w' })" /> | ||
<div v-bind="api.getResizeTriggerProps({ axis: 's' })" /> | ||
<div v-bind="api.getResizeTriggerProps({ axis: 'ne' })" /> | ||
<div v-bind="api.getResizeTriggerProps({ axis: 'se' })" /> | ||
<div v-bind="api.getResizeTriggerProps({ axis: 'sw' })" /> | ||
<div v-bind="api.getResizeTriggerProps({ axis: 'nw' })" /> | ||
</div> | ||
</div> | ||
</div> | ||
</main> | ||
|
||
<Toolbar> | ||
<StateVisualizer :state="state" /> | ||
<template #controls> | ||
<Controls :control="controls" /> | ||
</template> | ||
</Toolbar> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import * as floatingPanel from "@zag-js/floating-panel" | ||
import { floatingPanelControls } from "@zag-js/shared" | ||
import { normalizeProps, useMachine } from "@zag-js/solid" | ||
import { ArrowDownLeft, Maximize2, Minus, XIcon } from "lucide-solid" | ||
import { createMemo, createUniqueId } from "solid-js" | ||
import { StateVisualizer } from "../components/state-visualizer" | ||
import { Toolbar } from "../components/toolbar" | ||
import { useControls } from "../hooks/use-controls" | ||
|
||
export default function Page() { | ||
const controls = useControls(floatingPanelControls) | ||
|
||
const [state, send] = useMachine(floatingPanel.machine({ id: createUniqueId() }), { | ||
context: controls.context, | ||
}) | ||
|
||
const api = createMemo(() => floatingPanel.connect(state, send, normalizeProps)) | ||
|
||
return ( | ||
<> | ||
<main class="floating-panel"> | ||
<div> | ||
<button {...api().triggerProps}>Toggle Panel</button> | ||
<div {...api().positionerProps}> | ||
<div {...api().contentProps}> | ||
<div {...api().dragTriggerProps}> | ||
<div {...api().headerProps}> | ||
<p {...api().titleProps}>Floating Panel</p> | ||
<div data-scope="floating-panel" data-part="trigger-group"> | ||
<button {...api().minimizeTriggerProps}> | ||
<Minus /> | ||
</button> | ||
<button {...api().maximizeTriggerProps}> | ||
<Maximize2 /> | ||
</button> | ||
<button {...api().restoreTriggerProps}> | ||
<ArrowDownLeft /> | ||
</button> | ||
<button {...api().closeTriggerProps}> | ||
<XIcon /> | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
<div {...api().bodyProps}> | ||
<p>Some content</p> | ||
</div> | ||
|
||
<div {...api().getResizeTriggerProps({ axis: "n" })} /> | ||
<div {...api().getResizeTriggerProps({ axis: "e" })} /> | ||
<div {...api().getResizeTriggerProps({ axis: "w" })} /> | ||
<div {...api().getResizeTriggerProps({ axis: "s" })} /> | ||
<div {...api().getResizeTriggerProps({ axis: "ne" })} /> | ||
<div {...api().getResizeTriggerProps({ axis: "se" })} /> | ||
<div {...api().getResizeTriggerProps({ axis: "sw" })} /> | ||
<div {...api().getResizeTriggerProps({ axis: "nw" })} /> | ||
</div> | ||
</div> | ||
</div> | ||
</main> | ||
|
||
<Toolbar controls={controls.ui}> | ||
<StateVisualizer state={state} /> | ||
</Toolbar> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.