react-panel-layout 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FloatingWindow-Bw2djgpz.js +1542 -0
- package/dist/FloatingWindow-Bw2djgpz.js.map +1 -0
- package/dist/FloatingWindow-Cvyokf0m.cjs +2 -0
- package/dist/FloatingWindow-Cvyokf0m.cjs.map +1 -0
- package/dist/GridLayout-B4aCqSyd.js +947 -0
- package/dist/{GridLayout-UWNxXw77.js.map → GridLayout-B4aCqSyd.js.map} +1 -1
- package/dist/GridLayout-DNOClFzz.cjs +2 -0
- package/dist/{GridLayout-DKTg_N61.cjs.map → GridLayout-DNOClFzz.cjs.map} +1 -1
- package/dist/PanelSystem-B8Igvnb2.cjs +3 -0
- package/dist/PanelSystem-B8Igvnb2.cjs.map +1 -0
- package/dist/{PanelSystem-BqUzNtf2.js → PanelSystem-DDUSFjXD.js} +208 -247
- package/dist/PanelSystem-DDUSFjXD.js.map +1 -0
- package/dist/components/window/Drawer.d.ts +1 -0
- package/dist/components/window/DrawerRevealContext.d.ts +61 -0
- package/dist/components/window/drawerRevealAnimationUtils.d.ts +212 -0
- package/dist/components/window/drawerStyles.d.ts +5 -0
- package/dist/components/window/useDrawerSwipeTransform.d.ts +8 -2
- package/dist/components/window/useDrawerTransform.d.ts +68 -0
- package/dist/components/window/useRevealDrawerTransform.d.ts +56 -0
- package/dist/config.cjs +1 -1
- package/dist/config.cjs.map +1 -1
- package/dist/config.js +8 -7
- package/dist/config.js.map +1 -1
- package/dist/grid.cjs +1 -1
- package/dist/grid.js +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.js +4 -4
- package/dist/modules/drawer/drawerStateMachine.d.ts +168 -0
- package/dist/modules/drawer/revealDrawerConstants.d.ts +33 -0
- package/dist/modules/drawer/revealDrawerStateMachine.d.ts +146 -0
- package/dist/modules/drawer/strategies/index.d.ts +8 -0
- package/dist/modules/drawer/strategies/overlayStrategy.d.ts +12 -0
- package/dist/modules/drawer/strategies/revealStrategy.d.ts +12 -0
- package/dist/modules/drawer/strategies/types.d.ts +116 -0
- package/dist/panels.cjs +1 -1
- package/dist/panels.js +1 -1
- package/dist/stack.cjs +1 -1
- package/dist/stack.cjs.map +1 -1
- package/dist/stack.js +306 -347
- package/dist/stack.js.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/useAnimationFrame-BZ6D2lMq.cjs +2 -0
- package/dist/useAnimationFrame-BZ6D2lMq.cjs.map +1 -0
- package/dist/useAnimationFrame-Bg4e-H8O.js +394 -0
- package/dist/useAnimationFrame-Bg4e-H8O.js.map +1 -0
- package/dist/window.cjs +1 -1
- package/dist/window.js +1 -1
- package/package.json +1 -1
- package/src/components/gesture/SwipeSafeZone.tsx +1 -0
- package/src/components/grid/GridLayout.tsx +110 -38
- package/src/components/window/Drawer.tsx +114 -10
- package/src/components/window/DrawerLayers.tsx +48 -15
- package/src/components/window/DrawerRevealContext.spec.ts +20 -0
- package/src/components/window/DrawerRevealContext.tsx +99 -0
- package/src/components/window/drawerRevealAnimationUtils.spec.ts +375 -0
- package/src/components/window/drawerRevealAnimationUtils.ts +415 -0
- package/src/components/window/drawerStyles.spec.ts +39 -0
- package/src/components/window/drawerStyles.ts +24 -0
- package/src/components/window/useDrawerSwipeTransform.ts +28 -90
- package/src/components/window/useDrawerTransform.ts +505 -0
- package/src/components/window/useRevealDrawerTransform.spec.ts +1936 -0
- package/src/components/window/useRevealDrawerTransform.ts +105 -0
- package/src/demo/components/FullscreenDemoPage.tsx +47 -0
- package/src/demo/fullscreenRoutes.tsx +32 -0
- package/src/demo/index.tsx +5 -0
- package/src/demo/pages/Dialog/components/CardExpandDemo.tsx +23 -8
- package/src/demo/pages/Drawer/components/DrawerBasics.module.css +6 -1
- package/src/demo/pages/Drawer/components/DrawerBasics.tsx +14 -4
- package/src/demo/pages/Drawer/components/DrawerReveal.module.css +157 -0
- package/src/demo/pages/Drawer/components/DrawerReveal.tsx +128 -0
- package/src/demo/pages/Drawer/reveal/index.tsx +17 -0
- package/src/demo/pages/Drawer/reveal-fullscreen/index.tsx +135 -0
- package/src/demo/pages/Drawer/reveal-fullscreen/styles.module.css +233 -0
- package/src/demo/pages/Stack/components/StackBasics.spec.tsx +56 -52
- package/src/demo/pages/Stack/components/StackTablet.spec.tsx +39 -49
- package/src/demo/routes.tsx +2 -0
- package/src/hooks/gesture/testing/createGestureSimulator.ts +1 -0
- package/src/hooks/gesture/useNativeGestureGuard.spec.ts +10 -2
- package/src/hooks/gesture/utils.ts +15 -4
- package/src/hooks/useAnimatedVisibility.spec.ts +3 -3
- package/src/hooks/useOperationContinuity.spec.ts +17 -10
- package/src/hooks/useOperationContinuity.ts +5 -5
- package/src/hooks/useSharedElementTransition.ts +28 -7
- package/src/modules/dialog/dialogAnimationUtils.spec.ts +0 -1
- package/src/modules/dialog/useDialogContainer.spec.ts +11 -3
- package/src/modules/dialog/useDialogSwipeInput.spec.ts +49 -28
- package/src/modules/dialog/useDialogSwipeInput.ts +37 -6
- package/src/modules/dialog/useDialogTransform.spec.ts +63 -30
- package/src/modules/drawer/drawerStateMachine.ts +500 -0
- package/src/modules/drawer/revealDrawerConstants.ts +38 -0
- package/src/modules/drawer/revealDrawerStateMachine.spec.ts +558 -0
- package/src/modules/drawer/revealDrawerStateMachine.ts +197 -0
- package/src/modules/drawer/strategies/index.ts +9 -0
- package/src/modules/drawer/strategies/overlayStrategy.ts +133 -0
- package/src/modules/drawer/strategies/revealStrategy.ts +111 -0
- package/src/modules/drawer/strategies/types.ts +160 -0
- package/src/modules/drawer/useDrawerSwipeInput.ts +7 -4
- package/src/modules/pivot/SwipePivotContent.spec.tsx +48 -37
- package/src/modules/pivot/usePivotSwipeInput.spec.ts +8 -8
- package/src/modules/stack/swipeTransitionContinuity.spec.tsx +1 -1
- package/src/types.ts +15 -0
- package/dist/FloatingWindow-CUXnEtrb.js +0 -827
- package/dist/FloatingWindow-CUXnEtrb.js.map +0 -1
- package/dist/FloatingWindow-DMwyK0eK.cjs +0 -2
- package/dist/FloatingWindow-DMwyK0eK.cjs.map +0 -1
- package/dist/GridLayout-DKTg_N61.cjs +0 -2
- package/dist/GridLayout-UWNxXw77.js +0 -926
- package/dist/PanelSystem-BqUzNtf2.js.map +0 -1
- package/dist/PanelSystem-D603LKKv.cjs +0 -3
- package/dist/PanelSystem-D603LKKv.cjs.map +0 -1
- package/dist/useNativeGestureGuard-C7TSqEkr.cjs +0 -2
- package/dist/useNativeGestureGuard-C7TSqEkr.cjs.map +0 -1
- package/dist/useNativeGestureGuard-CGYo6O0r.js +0 -347
- package/dist/useNativeGestureGuard-CGYo6O0r.js.map +0 -1
- package/src/components/window/useDrawerSwipeTransform.spec.ts +0 -234
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Hook for managing reveal-mode drawer transform (backward-compatible wrapper).
|
|
3
|
+
*
|
|
4
|
+
* This hook is a thin wrapper around useDrawerTransform with mode="reveal".
|
|
5
|
+
* For new code, prefer using useDrawerTransform directly.
|
|
6
|
+
*
|
|
7
|
+
* @deprecated Use useDrawerTransform with mode="reveal" instead.
|
|
8
|
+
*/
|
|
9
|
+
import * as React from "react";
|
|
10
|
+
import type { ContinuousOperationState } from "../../hooks/gesture/types.js";
|
|
11
|
+
import type { DrawerPlacement } from "./drawerStyles.js";
|
|
12
|
+
import {
|
|
13
|
+
useDrawerTransform,
|
|
14
|
+
type DrawerAnimationPhase,
|
|
15
|
+
type UseDrawerTransformResult,
|
|
16
|
+
} from "./useDrawerTransform.js";
|
|
17
|
+
import { getContentElement } from "./drawerRevealAnimationUtils.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Phase of reveal drawer animation lifecycle.
|
|
21
|
+
* @deprecated Use DrawerAnimationPhase from useDrawerTransform.ts
|
|
22
|
+
*/
|
|
23
|
+
export type RevealDrawerAnimationPhase = DrawerAnimationPhase;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Options for useRevealDrawerTransform hook.
|
|
27
|
+
*/
|
|
28
|
+
export type UseRevealDrawerTransformOptions = {
|
|
29
|
+
/** Ref to the drawer element */
|
|
30
|
+
drawerRef: React.RefObject<HTMLElement | null>;
|
|
31
|
+
/** Drawer placement */
|
|
32
|
+
placement: DrawerPlacement;
|
|
33
|
+
/** Drawer size in pixels */
|
|
34
|
+
drawerSize: number;
|
|
35
|
+
/** Whether the drawer is open */
|
|
36
|
+
isOpen: boolean;
|
|
37
|
+
/** Current swipe state */
|
|
38
|
+
swipeState: ContinuousOperationState;
|
|
39
|
+
/** Current swipe displacement */
|
|
40
|
+
displacement: number;
|
|
41
|
+
/** Whether opening via swipe */
|
|
42
|
+
isOpening: boolean;
|
|
43
|
+
/** Whether closing via swipe */
|
|
44
|
+
isClosing: boolean;
|
|
45
|
+
/** Whether this hook is enabled */
|
|
46
|
+
enabled: boolean;
|
|
47
|
+
/** Whether drawer is inline (affects target element) */
|
|
48
|
+
inline: boolean;
|
|
49
|
+
/** Grid container ref for inline mode */
|
|
50
|
+
gridRef?: React.RefObject<HTMLElement | null>;
|
|
51
|
+
/** Content background color for stacking context */
|
|
52
|
+
contentBackground?: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Result from useRevealDrawerTransform hook.
|
|
57
|
+
*/
|
|
58
|
+
export type UseRevealDrawerTransformResult = UseDrawerTransformResult;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Hook for managing reveal-mode drawer transform.
|
|
62
|
+
*
|
|
63
|
+
* @deprecated Use useDrawerTransform with mode="reveal" instead.
|
|
64
|
+
*/
|
|
65
|
+
export function useRevealDrawerTransform(
|
|
66
|
+
options: UseRevealDrawerTransformOptions,
|
|
67
|
+
): UseRevealDrawerTransformResult {
|
|
68
|
+
const {
|
|
69
|
+
drawerRef,
|
|
70
|
+
placement,
|
|
71
|
+
drawerSize,
|
|
72
|
+
isOpen,
|
|
73
|
+
swipeState,
|
|
74
|
+
displacement,
|
|
75
|
+
isOpening,
|
|
76
|
+
isClosing,
|
|
77
|
+
enabled,
|
|
78
|
+
inline,
|
|
79
|
+
gridRef,
|
|
80
|
+
contentBackground = "#fff",
|
|
81
|
+
} = options;
|
|
82
|
+
|
|
83
|
+
// Create a content ref that resolves the content element
|
|
84
|
+
const contentRef = React.useRef<HTMLElement | null>(null);
|
|
85
|
+
React.useLayoutEffect(() => {
|
|
86
|
+
contentRef.current = getContentElement(inline, gridRef);
|
|
87
|
+
}, [inline, gridRef]);
|
|
88
|
+
|
|
89
|
+
return useDrawerTransform({
|
|
90
|
+
mode: "reveal",
|
|
91
|
+
drawerRef,
|
|
92
|
+
contentRef,
|
|
93
|
+
placement,
|
|
94
|
+
drawerSize,
|
|
95
|
+
isOpen,
|
|
96
|
+
swipeState,
|
|
97
|
+
displacement,
|
|
98
|
+
isOpening,
|
|
99
|
+
isClosing,
|
|
100
|
+
enabled,
|
|
101
|
+
inline,
|
|
102
|
+
gridRef,
|
|
103
|
+
contentBackground,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Fullscreen demo page wrapper
|
|
3
|
+
*
|
|
4
|
+
* Renders fullscreen demos by ID from the route parameter.
|
|
5
|
+
*/
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { useParams, Link } from "react-router";
|
|
8
|
+
import { getFullscreenDemo } from "../fullscreenRoutes";
|
|
9
|
+
|
|
10
|
+
export const FullscreenDemoPage: React.FC = () => {
|
|
11
|
+
const { id } = useParams<{ id: string }>();
|
|
12
|
+
const demo = id ? getFullscreenDemo(id) : undefined;
|
|
13
|
+
|
|
14
|
+
if (!demo) {
|
|
15
|
+
return (
|
|
16
|
+
<div style={{
|
|
17
|
+
display: "flex",
|
|
18
|
+
flexDirection: "column",
|
|
19
|
+
alignItems: "center",
|
|
20
|
+
justifyContent: "center",
|
|
21
|
+
height: "100vh",
|
|
22
|
+
gap: "16px",
|
|
23
|
+
fontFamily: "system-ui, sans-serif",
|
|
24
|
+
}}>
|
|
25
|
+
<h1>Demo not found</h1>
|
|
26
|
+
<p>The fullscreen demo "{id}" does not exist.</p>
|
|
27
|
+
<Link to="/" style={{ color: "#1d9bf0" }}>Go back home</Link>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<React.Suspense fallback={
|
|
34
|
+
<div style={{
|
|
35
|
+
display: "flex",
|
|
36
|
+
alignItems: "center",
|
|
37
|
+
justifyContent: "center",
|
|
38
|
+
height: "100vh",
|
|
39
|
+
fontFamily: "system-ui, sans-serif",
|
|
40
|
+
}}>
|
|
41
|
+
Loading...
|
|
42
|
+
</div>
|
|
43
|
+
}>
|
|
44
|
+
{demo.element}
|
|
45
|
+
</React.Suspense>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Fullscreen demo route configuration
|
|
3
|
+
*
|
|
4
|
+
* Demos that need to be rendered outside the main Layout
|
|
5
|
+
* (e.g., reveal-mode drawer that transforms the body).
|
|
6
|
+
*/
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
|
|
9
|
+
export type FullscreenDemo = {
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
element: React.ReactNode;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// Lazy load fullscreen demos
|
|
16
|
+
// eslint-disable-next-line no-restricted-syntax -- dynamic import required for lazy loading
|
|
17
|
+
const DrawerRevealFullscreen = React.lazy(() => import("./pages/Drawer/reveal-fullscreen"));
|
|
18
|
+
|
|
19
|
+
export const fullscreenDemos: Record<string, FullscreenDemo> = {
|
|
20
|
+
"drawer-reveal": {
|
|
21
|
+
id: "drawer-reveal",
|
|
22
|
+
label: "Drawer Reveal Mode",
|
|
23
|
+
element: <DrawerRevealFullscreen />,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get a fullscreen demo by ID.
|
|
29
|
+
*/
|
|
30
|
+
export function getFullscreenDemo(id: string): FullscreenDemo | undefined {
|
|
31
|
+
return fullscreenDemos[id];
|
|
32
|
+
}
|
package/src/demo/index.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { HashRouter, Routes, Route, Outlet, Link } from "react-router";
|
|
|
8
8
|
import { Layout } from "./Layout";
|
|
9
9
|
import { PanelLayoutDemo } from "./pages/PanelLayout/PanelLayoutDemo";
|
|
10
10
|
import { demoCategories } from "./routes";
|
|
11
|
+
import { FullscreenDemoPage } from "./components/FullscreenDemoPage";
|
|
11
12
|
import * as React from "react";
|
|
12
13
|
import { useMedia } from "./hooks/useMedia";
|
|
13
14
|
import "./demo.css";
|
|
@@ -263,6 +264,10 @@ function App() {
|
|
|
263
264
|
return (
|
|
264
265
|
<HashRouter>
|
|
265
266
|
<Routes>
|
|
267
|
+
{/* Fullscreen pages (outside Layout) */}
|
|
268
|
+
<Route path="/fullscreen/:id" element={<FullscreenDemoPage />} />
|
|
269
|
+
|
|
270
|
+
{/* Regular pages (inside Layout) */}
|
|
266
271
|
<Route path="/" element={<Layout />}>
|
|
267
272
|
<Route index element={<Home />} />
|
|
268
273
|
<Route path="panel-demo" element={<PanelLayoutDemo />} />
|
|
@@ -158,6 +158,28 @@ const viewTransitionStyles = `
|
|
|
158
158
|
}
|
|
159
159
|
`;
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Render expanded view if item is expanded.
|
|
163
|
+
*/
|
|
164
|
+
function renderExpandedView(
|
|
165
|
+
expandedItem: Album | null,
|
|
166
|
+
getTargetProps: (nameIndex?: number) => { style: React.CSSProperties },
|
|
167
|
+
getSwipeContainerProps: () => React.HTMLAttributes<HTMLElement> & { style: React.CSSProperties },
|
|
168
|
+
collapse: () => void,
|
|
169
|
+
): React.ReactNode {
|
|
170
|
+
if (expandedItem === null) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
return (
|
|
174
|
+
<ExpandedView
|
|
175
|
+
album={expandedItem}
|
|
176
|
+
targetProps={getTargetProps()}
|
|
177
|
+
swipeContainerProps={getSwipeContainerProps()}
|
|
178
|
+
onClose={collapse}
|
|
179
|
+
/>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
161
183
|
/**
|
|
162
184
|
* Demo component for Apple Music style card expansion using viewTransition
|
|
163
185
|
*/
|
|
@@ -191,14 +213,7 @@ export const CardExpandDemo: React.FC = () => {
|
|
|
191
213
|
))}
|
|
192
214
|
</div>
|
|
193
215
|
|
|
194
|
-
{expandedItem
|
|
195
|
-
<ExpandedView
|
|
196
|
-
album={expandedItem}
|
|
197
|
-
targetProps={getTargetProps()}
|
|
198
|
-
swipeContainerProps={getSwipeContainerProps()}
|
|
199
|
-
onClose={collapse}
|
|
200
|
-
/>
|
|
201
|
-
)}
|
|
216
|
+
{renderExpandedView(expandedItem, getTargetProps, getSwipeContainerProps, collapse)}
|
|
202
217
|
</div>
|
|
203
218
|
);
|
|
204
219
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.
|
|
1
|
+
.wrapper {
|
|
2
2
|
position: relative;
|
|
3
3
|
width: 100%;
|
|
4
4
|
height: 100%;
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
box-shadow: var(--rpl-demo-shadow-md);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
.container {
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: 100%;
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
.hero {
|
|
13
18
|
display: grid;
|
|
14
19
|
place-items: center;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file Basic drawer layout sample (default Drawer styling)
|
|
2
|
+
* @file Basic drawer layout sample (default Drawer styling with swipe gestures)
|
|
3
3
|
*/
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { GridLayout } from "../../../../components/grid/GridLayout";
|
|
@@ -31,8 +31,7 @@ export const DrawerBasics: React.FC = () => {
|
|
|
31
31
|
Open drawer
|
|
32
32
|
</DemoButton>
|
|
33
33
|
<p className={styles.lead}>
|
|
34
|
-
|
|
35
|
-
uses the built-in header/close affordance.
|
|
34
|
+
Swipe from the left edge to open the drawer, or drag the drawer left to close it.
|
|
36
35
|
</p>
|
|
37
36
|
</div>
|
|
38
37
|
</div>
|
|
@@ -63,7 +62,14 @@ export const DrawerBasics: React.FC = () => {
|
|
|
63
62
|
open,
|
|
64
63
|
onStateChange: setOpen,
|
|
65
64
|
dismissible: true,
|
|
65
|
+
inline: true,
|
|
66
66
|
header: { title: "Navigation" },
|
|
67
|
+
swipeGestures: {
|
|
68
|
+
edgeSwipeOpen: true,
|
|
69
|
+
swipeClose: true,
|
|
70
|
+
edgeWidth: 24,
|
|
71
|
+
dismissThreshold: 0.3,
|
|
72
|
+
},
|
|
67
73
|
},
|
|
68
74
|
position: { left: 0 },
|
|
69
75
|
width: 320,
|
|
@@ -72,5 +78,9 @@ export const DrawerBasics: React.FC = () => {
|
|
|
72
78
|
},
|
|
73
79
|
];
|
|
74
80
|
|
|
75
|
-
return
|
|
81
|
+
return (
|
|
82
|
+
<div className={styles.wrapper}>
|
|
83
|
+
<GridLayout config={config} layers={layers} />
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
76
86
|
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Styles for DrawerReveal demo
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
.container {
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
height: 100%;
|
|
9
|
+
padding: 24px;
|
|
10
|
+
background: #fff;
|
|
11
|
+
color: #0f1419;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.hero {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
gap: 16px;
|
|
18
|
+
max-width: 480px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.lead {
|
|
22
|
+
color: #536471;
|
|
23
|
+
font-size: 14px;
|
|
24
|
+
line-height: 1.6;
|
|
25
|
+
margin: 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.instructions {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
gap: 12px;
|
|
32
|
+
margin-top: 24px;
|
|
33
|
+
padding: 16px;
|
|
34
|
+
background: #f7f9f9;
|
|
35
|
+
border-radius: 16px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.instruction {
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
gap: 12px;
|
|
42
|
+
font-size: 14px;
|
|
43
|
+
color: #536471;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.instructionIcon {
|
|
47
|
+
display: flex;
|
|
48
|
+
align-items: center;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
width: 28px;
|
|
51
|
+
height: 28px;
|
|
52
|
+
background: #1d9bf0;
|
|
53
|
+
border-radius: 50%;
|
|
54
|
+
color: #fff;
|
|
55
|
+
font-size: 12px;
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.fullscreenLink {
|
|
60
|
+
display: inline-block;
|
|
61
|
+
margin-top: 12px;
|
|
62
|
+
padding: 10px 20px;
|
|
63
|
+
background: #1d9bf0;
|
|
64
|
+
color: #fff;
|
|
65
|
+
border-radius: 9999px;
|
|
66
|
+
text-decoration: none;
|
|
67
|
+
font-weight: 600;
|
|
68
|
+
font-size: 14px;
|
|
69
|
+
transition: background 0.15s ease;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.fullscreenLink:hover {
|
|
73
|
+
background: #1a8cd8;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.drawerContent {
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-direction: column;
|
|
79
|
+
height: 100%;
|
|
80
|
+
padding: 16px;
|
|
81
|
+
background: #fff;
|
|
82
|
+
border-right: 1px solid #eff3f4;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.profile {
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
gap: 12px;
|
|
89
|
+
padding: 12px 0;
|
|
90
|
+
border-bottom: 1px solid #eff3f4;
|
|
91
|
+
margin-bottom: 8px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.avatar {
|
|
95
|
+
display: flex;
|
|
96
|
+
align-items: center;
|
|
97
|
+
justify-content: center;
|
|
98
|
+
width: 40px;
|
|
99
|
+
height: 40px;
|
|
100
|
+
background: #1d9bf0;
|
|
101
|
+
border-radius: 50%;
|
|
102
|
+
color: #fff;
|
|
103
|
+
font-size: 18px;
|
|
104
|
+
font-weight: 700;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.profileInfo {
|
|
108
|
+
display: flex;
|
|
109
|
+
flex-direction: column;
|
|
110
|
+
gap: 2px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.profileName {
|
|
114
|
+
font-size: 15px;
|
|
115
|
+
font-weight: 700;
|
|
116
|
+
color: #0f1419;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.profileHandle {
|
|
120
|
+
font-size: 13px;
|
|
121
|
+
color: #536471;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.nav {
|
|
125
|
+
display: flex;
|
|
126
|
+
flex-direction: column;
|
|
127
|
+
gap: 4px;
|
|
128
|
+
flex: 1;
|
|
129
|
+
padding: 8px 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.navItem {
|
|
133
|
+
display: flex;
|
|
134
|
+
align-items: center;
|
|
135
|
+
gap: 16px;
|
|
136
|
+
padding: 12px;
|
|
137
|
+
border-radius: 9999px;
|
|
138
|
+
color: #0f1419;
|
|
139
|
+
font-size: 20px;
|
|
140
|
+
font-weight: 500;
|
|
141
|
+
text-decoration: none;
|
|
142
|
+
transition: background 0.2s ease;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.navItem:hover {
|
|
146
|
+
background: #e7e7e8;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.navIcon {
|
|
150
|
+
display: flex;
|
|
151
|
+
align-items: center;
|
|
152
|
+
justify-content: center;
|
|
153
|
+
width: 26px;
|
|
154
|
+
height: 26px;
|
|
155
|
+
font-size: 14px;
|
|
156
|
+
font-weight: 700;
|
|
157
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Reveal mode drawer demo
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates the reveal animation mode where content slides away
|
|
5
|
+
* to reveal the drawer behind it (like X/Twitter's navigation menu).
|
|
6
|
+
*/
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import { Link } from "react-router";
|
|
9
|
+
import { GridLayout } from "../../../../components/grid/GridLayout";
|
|
10
|
+
import type { LayerDefinition, PanelLayoutConfig } from "../../../../types";
|
|
11
|
+
import { DemoButton } from "../../../components/ui/DemoButton";
|
|
12
|
+
import styles from "./DrawerReveal.module.css";
|
|
13
|
+
|
|
14
|
+
export const DrawerReveal: React.FC = () => {
|
|
15
|
+
const [open, setOpen] = React.useState(false);
|
|
16
|
+
|
|
17
|
+
const config = React.useMemo<PanelLayoutConfig>(
|
|
18
|
+
() => ({
|
|
19
|
+
areas: [["content"]],
|
|
20
|
+
rows: [{ size: "1fr" }],
|
|
21
|
+
columns: [{ size: "1fr" }],
|
|
22
|
+
gap: "0",
|
|
23
|
+
}),
|
|
24
|
+
[],
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const layers: LayerDefinition[] = [
|
|
28
|
+
{
|
|
29
|
+
id: "content",
|
|
30
|
+
gridArea: "content",
|
|
31
|
+
component: (
|
|
32
|
+
<div className={styles.container}>
|
|
33
|
+
<div className={styles.hero}>
|
|
34
|
+
<DemoButton variant="primary" size="lg" onClick={() => setOpen(true)}>
|
|
35
|
+
Open drawer
|
|
36
|
+
</DemoButton>
|
|
37
|
+
<p className={styles.lead}>
|
|
38
|
+
This demo shows the reveal animation mode with <code>inline: true</code>. The container slides to reveal
|
|
39
|
+
the drawer behind it, similar to X/Twitter's navigation menu.
|
|
40
|
+
</p>
|
|
41
|
+
<Link to="/fullscreen/drawer-reveal" className={styles.fullscreenLink} target="_blank">
|
|
42
|
+
View Fullscreen Demo
|
|
43
|
+
</Link>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div className={styles.instructions}>
|
|
47
|
+
<div className={styles.instruction}>
|
|
48
|
+
<span className={styles.instructionIcon}>1</span>
|
|
49
|
+
<span>Swipe from the left edge to open</span>
|
|
50
|
+
</div>
|
|
51
|
+
<div className={styles.instruction}>
|
|
52
|
+
<span className={styles.instructionIcon}>2</span>
|
|
53
|
+
<span>Content slides right to reveal drawer</span>
|
|
54
|
+
</div>
|
|
55
|
+
<div className={styles.instruction}>
|
|
56
|
+
<span className={styles.instructionIcon}>3</span>
|
|
57
|
+
<span>Swipe left on content to close</span>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
),
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: "drawer-reveal",
|
|
65
|
+
component: (
|
|
66
|
+
<div className={styles.drawerContent}>
|
|
67
|
+
<div className={styles.profile}>
|
|
68
|
+
<div className={styles.avatar}>U</div>
|
|
69
|
+
<div className={styles.profileInfo}>
|
|
70
|
+
<div className={styles.profileName}>User Name</div>
|
|
71
|
+
<div className={styles.profileHandle}>@username</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<nav className={styles.nav}>
|
|
76
|
+
<a href="#" className={styles.navItem}>
|
|
77
|
+
<span className={styles.navIcon}>H</span>
|
|
78
|
+
Home
|
|
79
|
+
</a>
|
|
80
|
+
<a href="#" className={styles.navItem}>
|
|
81
|
+
<span className={styles.navIcon}>S</span>
|
|
82
|
+
Search
|
|
83
|
+
</a>
|
|
84
|
+
<a href="#" className={styles.navItem}>
|
|
85
|
+
<span className={styles.navIcon}>N</span>
|
|
86
|
+
Notifications
|
|
87
|
+
</a>
|
|
88
|
+
<a href="#" className={styles.navItem}>
|
|
89
|
+
<span className={styles.navIcon}>M</span>
|
|
90
|
+
Messages
|
|
91
|
+
</a>
|
|
92
|
+
<a href="#" className={styles.navItem}>
|
|
93
|
+
<span className={styles.navIcon}>P</span>
|
|
94
|
+
Profile
|
|
95
|
+
</a>
|
|
96
|
+
<a href="#" className={styles.navItem}>
|
|
97
|
+
<span className={styles.navIcon}>C</span>
|
|
98
|
+
Settings
|
|
99
|
+
</a>
|
|
100
|
+
</nav>
|
|
101
|
+
|
|
102
|
+
<DemoButton variant="secondary" size="md" onClick={() => setOpen(false)}>
|
|
103
|
+
Close
|
|
104
|
+
</DemoButton>
|
|
105
|
+
</div>
|
|
106
|
+
),
|
|
107
|
+
drawer: {
|
|
108
|
+
open,
|
|
109
|
+
onStateChange: setOpen,
|
|
110
|
+
dismissible: true,
|
|
111
|
+
animationMode: "reveal",
|
|
112
|
+
inline: true,
|
|
113
|
+
swipeGestures: {
|
|
114
|
+
edgeSwipeOpen: true,
|
|
115
|
+
swipeClose: true,
|
|
116
|
+
edgeWidth: 24,
|
|
117
|
+
dismissThreshold: 0.3,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
position: { left: 0 },
|
|
121
|
+
width: 280,
|
|
122
|
+
height: "100%",
|
|
123
|
+
zIndex: 1200,
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
return <GridLayout config={config} layers={layers} />;
|
|
128
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Drawer - Reveal Mode page
|
|
3
|
+
*/
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { DrawerReveal } from "../components/DrawerReveal";
|
|
6
|
+
import DrawerRevealSource from "../components/DrawerReveal.tsx?raw";
|
|
7
|
+
import { SingleSamplePage } from "../../../components/layout";
|
|
8
|
+
|
|
9
|
+
const Page: React.FC = () => {
|
|
10
|
+
return (
|
|
11
|
+
<SingleSamplePage title="Drawer / Reveal Mode" code={DrawerRevealSource} codeTitle="DrawerReveal.tsx" previewHeight={520}>
|
|
12
|
+
<DrawerReveal />
|
|
13
|
+
</SingleSamplePage>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default Page;
|