Add animation to group open
This commit is contained in:
parent
0917ef05a1
commit
4e5bd8bf02
@ -16,9 +16,13 @@ function MapTileGroup({ group, maps, isSelected, onSelect, onDoubleClick }) {
|
||||
onSelect={() => onSelect(group.id)}
|
||||
onDoubleClick={onDoubleClick}
|
||||
>
|
||||
<Grid columns={layout.gridTemplate} p={2} sx={{ gridGap: 2 }}>
|
||||
<Grid columns={layout.groupGridTemplate} p={2} sx={{ gridGap: 2 }}>
|
||||
{maps.slice(0, 16).map((map) => (
|
||||
<MapTileImage sx={{ borderRadius: "8px" }} map={map} key={map.id} />
|
||||
<MapTileImage
|
||||
sx={{ borderRadius: "8px" }}
|
||||
map={map}
|
||||
key={`${map.id}-group-tile`}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
</Tile>
|
||||
|
@ -13,6 +13,7 @@ function MapTiles({ maps, onMapEdit, onMapSelect, subgroup }) {
|
||||
const {
|
||||
groups,
|
||||
selectedGroupIds,
|
||||
openGroupId,
|
||||
openGroupItems,
|
||||
selectMode,
|
||||
onGroupOpen,
|
||||
@ -63,6 +64,7 @@ function MapTiles({ maps, onMapEdit, onMapSelect, subgroup }) {
|
||||
renderTile={renderTile}
|
||||
onTileSelect={onGroupSelect}
|
||||
disableGrouping={subgroup}
|
||||
openGroupId={openGroupId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -2,8 +2,9 @@ import React from "react";
|
||||
import { Box } from "theme-ui";
|
||||
import { useDroppable } from "@dnd-kit/core";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { animated, useSpring } from "react-spring";
|
||||
|
||||
function Sortable({ id, disableGrouping, children }) {
|
||||
function Sortable({ id, disableGrouping, hidden, children }) {
|
||||
const {
|
||||
attributes,
|
||||
listeners,
|
||||
@ -48,8 +49,10 @@ function Sortable({ id, disableGrouping, children }) {
|
||||
over?.id === `__group__${id}` && active.id !== id ? "solid" : "none",
|
||||
};
|
||||
|
||||
const { opacity } = useSpring({ opacity: hidden ? 0 : 1 });
|
||||
|
||||
return (
|
||||
<Box sx={{ position: "relative" }}>
|
||||
<animated.div style={{ opacity, position: "relative" }}>
|
||||
<Box
|
||||
ref={setDraggableNodeRef}
|
||||
style={dragStyle}
|
||||
@ -75,7 +78,7 @@ function Sortable({ id, disableGrouping, children }) {
|
||||
sx={{ borderColor: "primary" }}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</animated.div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -11,12 +11,9 @@ import {
|
||||
} from "@dnd-kit/core";
|
||||
import { SortableContext, arrayMove } from "@dnd-kit/sortable";
|
||||
import { animated, useSpring, config } from "react-spring";
|
||||
import { Grid } from "theme-ui";
|
||||
|
||||
import { combineGroups, moveGroups } from "../../helpers/group";
|
||||
|
||||
import useResponsiveLayout from "../../hooks/useResponsiveLayout";
|
||||
|
||||
import SortableTile from "./SortableTile";
|
||||
|
||||
function SortableTiles({
|
||||
@ -25,9 +22,8 @@ function SortableTiles({
|
||||
renderTile,
|
||||
onTileSelect,
|
||||
disableGrouping,
|
||||
openGroupId,
|
||||
}) {
|
||||
const layout = useResponsiveLayout();
|
||||
|
||||
const mouseSensor = useSensor(MouseSensor, {
|
||||
activationConstraint: { delay: 250, tolerance: 5 },
|
||||
});
|
||||
@ -105,27 +101,16 @@ function SortableTiles({
|
||||
collisionDetection={closestCenter}
|
||||
>
|
||||
<SortableContext items={groups}>
|
||||
<Grid
|
||||
p={3}
|
||||
pb={4}
|
||||
sx={{
|
||||
borderRadius: "4px",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
gap={2}
|
||||
columns={layout.gridTemplate}
|
||||
onClick={() => onTileSelect()}
|
||||
>
|
||||
{groups.map((group) => (
|
||||
<SortableTile
|
||||
id={group.id}
|
||||
key={group.id}
|
||||
disableGrouping={disableGrouping}
|
||||
>
|
||||
{renderSortableGroup(group)}
|
||||
</SortableTile>
|
||||
))}
|
||||
</Grid>
|
||||
{groups.map((group) => (
|
||||
<SortableTile
|
||||
id={group.id}
|
||||
key={group.id}
|
||||
disableGrouping={disableGrouping}
|
||||
hidden={group.id === openGroupId}
|
||||
>
|
||||
{renderSortableGroup(group)}
|
||||
</SortableTile>
|
||||
))}
|
||||
{createPortal(
|
||||
<DragOverlay dropAnimation={null}>
|
||||
{dragId && (
|
||||
|
@ -1,14 +1,40 @@
|
||||
import React from "react";
|
||||
import { Box, Grid } from "theme-ui";
|
||||
import SimpleBar from "simplebar-react";
|
||||
|
||||
import { useGroup } from "../../contexts/GroupContext";
|
||||
|
||||
import useResponsiveLayout from "../../hooks/useResponsiveLayout";
|
||||
|
||||
function TilesContainer({ children }) {
|
||||
const { onGroupSelect } = useGroup();
|
||||
|
||||
const layout = useResponsiveLayout();
|
||||
|
||||
return (
|
||||
<SimpleBar style={{ height: layout.tileContainerHeight }}>
|
||||
{children}
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
top: 0,
|
||||
}}
|
||||
bg="muted"
|
||||
onClick={() => onGroupSelect()}
|
||||
/>
|
||||
<Grid
|
||||
p={3}
|
||||
pb={4}
|
||||
sx={{
|
||||
borderRadius: "4px",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
gap={2}
|
||||
columns={layout.gridTemplate}
|
||||
>
|
||||
{children}
|
||||
</Grid>
|
||||
</SimpleBar>
|
||||
);
|
||||
}
|
||||
|
@ -1,48 +1,111 @@
|
||||
import React from "react";
|
||||
import { Box, Close } from "theme-ui";
|
||||
import React, { useState } from "react";
|
||||
import { Box, Close, Grid } from "theme-ui";
|
||||
import { useSpring, animated, config } from "react-spring";
|
||||
import ReactResizeDetector from "react-resize-detector";
|
||||
import SimpleBar from "simplebar-react";
|
||||
|
||||
import { useGroup } from "../../contexts/GroupContext";
|
||||
|
||||
function TilesOverlay({ children }) {
|
||||
const { openGroupId, onGroupClose } = useGroup();
|
||||
import useResponsiveLayout from "../../hooks/useResponsiveLayout";
|
||||
|
||||
if (!openGroupId) {
|
||||
return null;
|
||||
function TilesOverlay({ children }) {
|
||||
const { openGroupId, onGroupClose, onGroupSelect } = useGroup();
|
||||
|
||||
const openAnimation = useSpring({
|
||||
opacity: openGroupId ? 1 : 0,
|
||||
transform: openGroupId ? "scale(1)" : "scale(0.95)",
|
||||
config: config.gentle,
|
||||
});
|
||||
|
||||
const [containerSize, setContinerSize] = useState(0);
|
||||
function handleResize(width, height) {
|
||||
const size = Math.min(width, height) - 16;
|
||||
setContinerSize(size);
|
||||
}
|
||||
|
||||
const layout = useResponsiveLayout();
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
top: 0,
|
||||
cursor: "pointer",
|
||||
}}
|
||||
p={3}
|
||||
bg="overlay"
|
||||
onClick={() => onGroupClose()}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
borderRadius: "8px",
|
||||
border: "1px solid",
|
||||
borderColor: "border",
|
||||
cursor: "default",
|
||||
}}
|
||||
bg="muted"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
p={3}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
<Close
|
||||
onClick={() => onGroupClose()}
|
||||
sx={{ position: "absolute", top: "16px", right: "16px" }}
|
||||
/>
|
||||
</Box>
|
||||
<>
|
||||
{openGroupId && (
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
top: 0,
|
||||
}}
|
||||
bg="overlay"
|
||||
/>
|
||||
)}
|
||||
<ReactResizeDetector handleWidth handleHeight onResize={handleResize}>
|
||||
<animated.div
|
||||
style={{
|
||||
...openAnimation,
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
top: 0,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
cursor: "pointer",
|
||||
pointerEvents: openGroupId ? undefined : "none",
|
||||
}}
|
||||
onClick={() => openGroupId && onGroupClose()}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: containerSize,
|
||||
height: containerSize,
|
||||
borderRadius: "8px",
|
||||
border: "1px solid",
|
||||
borderColor: "border",
|
||||
cursor: "default",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
position: "relative",
|
||||
}}
|
||||
bg="background"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
top: 0,
|
||||
}}
|
||||
bg="muted"
|
||||
onClick={() => onGroupSelect()}
|
||||
/>
|
||||
<SimpleBar
|
||||
style={{
|
||||
width: containerSize - 16,
|
||||
height: containerSize - 48,
|
||||
}}
|
||||
>
|
||||
<Grid
|
||||
sx={{
|
||||
borderRadius: "4px",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
gap={2}
|
||||
columns={layout.groupGridTemplate}
|
||||
px={3}
|
||||
>
|
||||
{children}
|
||||
</Grid>
|
||||
</SimpleBar>
|
||||
<Close
|
||||
onClick={() => onGroupClose()}
|
||||
sx={{ position: "absolute", top: 0, right: 0 }}
|
||||
/>
|
||||
</Box>
|
||||
</animated.div>
|
||||
</ReactResizeDetector>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ function TokenBar({ onMapTokenStateCreate }) {
|
||||
height: "100%",
|
||||
width: "80px",
|
||||
minWidth: "80px",
|
||||
overflowY: "scroll",
|
||||
overflowY: "hidden",
|
||||
overflowX: "hidden",
|
||||
display: fullScreen ? "none" : "block",
|
||||
}}
|
||||
|
@ -23,12 +23,12 @@ function TokenTileGroup({
|
||||
onDoubleClick={onDoubleClick}
|
||||
columns="1fr 1fr"
|
||||
>
|
||||
<Grid columns={layout.gridTemplate} p={2} sx={{ gridGap: 2 }}>
|
||||
<Grid columns={layout.groupGridTemplate} p={2} sx={{ gridGap: 2 }}>
|
||||
{tokens.slice(0, 16).map((token) => (
|
||||
<TokenTileImage
|
||||
sx={{ borderRadius: "8px" }}
|
||||
token={token}
|
||||
key={token.id}
|
||||
key={`${token.id}-group-tile`}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
|
@ -13,6 +13,7 @@ function TokenTiles({ tokens, onTokenEdit, subgroup }) {
|
||||
const {
|
||||
groups,
|
||||
selectedGroupIds,
|
||||
openGroupId,
|
||||
openGroupItems,
|
||||
selectMode,
|
||||
onGroupOpen,
|
||||
@ -68,6 +69,7 @@ function TokenTiles({ tokens, onTokenEdit, subgroup }) {
|
||||
renderTile={renderTile}
|
||||
onTileSelect={onGroupSelect}
|
||||
disableGrouping={subgroup}
|
||||
openGroupId={openGroupId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -27,9 +27,18 @@ function useResponsiveLayout() {
|
||||
? "1fr 1fr 1fr"
|
||||
: "1fr 1fr";
|
||||
|
||||
const groupGridTemplate = isLargeScreen ? "1fr 1fr 1fr" : "1fr 1fr";
|
||||
|
||||
const tileContainerHeight = isLargeScreen ? "600px" : "400px";
|
||||
|
||||
return { screenSize, modalSize, tileSize, gridTemplate, tileContainerHeight };
|
||||
return {
|
||||
screenSize,
|
||||
modalSize,
|
||||
tileSize,
|
||||
gridTemplate,
|
||||
tileContainerHeight,
|
||||
groupGridTemplate,
|
||||
};
|
||||
}
|
||||
|
||||
export default useResponsiveLayout;
|
||||
|
@ -252,7 +252,7 @@ function SelectMapModal({
|
||||
<Label pt={2} pb={1}>
|
||||
Select or import a map
|
||||
</Label>
|
||||
<Box sx={{ position: "relative" }} bg="muted">
|
||||
<Box sx={{ position: "relative" }}>
|
||||
<GroupProvider
|
||||
groups={mapGroups}
|
||||
onGroupsChange={updateMapGroups}
|
||||
|
@ -193,7 +193,7 @@ function SelectTokensModal({ isOpen, onRequestClose }) {
|
||||
<Label pt={2} pb={1}>
|
||||
Edit or import a token
|
||||
</Label>
|
||||
<Box sx={{ position: "relative" }} bg="muted">
|
||||
<Box sx={{ position: "relative" }}>
|
||||
<GroupProvider
|
||||
groups={tokenGroups}
|
||||
onGroupsChange={updateTokenGroups}
|
||||
|
Loading…
Reference in New Issue
Block a user