react-panel-layout 0.6.1 → 0.7.1

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.
Files changed (127) hide show
  1. package/dist/FloatingWindow-CE-WzkNv.js +1542 -0
  2. package/dist/FloatingWindow-CE-WzkNv.js.map +1 -0
  3. package/dist/FloatingWindow-DpFpmX1f.cjs +2 -0
  4. package/dist/FloatingWindow-DpFpmX1f.cjs.map +1 -0
  5. package/dist/GridLayout-EwKszYBy.cjs +2 -0
  6. package/dist/{GridLayout-DKTg_N61.cjs.map → GridLayout-EwKszYBy.cjs.map} +1 -1
  7. package/dist/GridLayout-kiWdpMLQ.js +947 -0
  8. package/dist/{GridLayout-UWNxXw77.js.map → GridLayout-kiWdpMLQ.js.map} +1 -1
  9. package/dist/PanelSystem-Dmy5YI_6.cjs +3 -0
  10. package/dist/PanelSystem-Dmy5YI_6.cjs.map +1 -0
  11. package/dist/{PanelSystem-BqUzNtf2.js → PanelSystem-DrYsYwuV.js} +208 -247
  12. package/dist/PanelSystem-DrYsYwuV.js.map +1 -0
  13. package/dist/components/window/Drawer.d.ts +1 -0
  14. package/dist/components/window/DrawerRevealContext.d.ts +61 -0
  15. package/dist/components/window/drawerRevealAnimationUtils.d.ts +212 -0
  16. package/dist/components/window/drawerStyles.d.ts +5 -0
  17. package/dist/components/window/useDrawerSwipeTransform.d.ts +8 -2
  18. package/dist/components/window/useDrawerTransform.d.ts +68 -0
  19. package/dist/components/window/useRevealDrawerTransform.d.ts +56 -0
  20. package/dist/config.cjs +1 -1
  21. package/dist/config.cjs.map +1 -1
  22. package/dist/config.js +8 -7
  23. package/dist/config.js.map +1 -1
  24. package/dist/dialog/index.d.ts +1 -1
  25. package/dist/grid.cjs +1 -1
  26. package/dist/grid.js +2 -2
  27. package/dist/index.cjs +1 -1
  28. package/dist/index.js +4 -4
  29. package/dist/modules/dialog/DialogContainer.d.ts +22 -2
  30. package/dist/modules/dialog/Modal.d.ts +23 -2
  31. package/dist/modules/dialog/SwipeDialogContainer.d.ts +6 -2
  32. package/dist/modules/dialog/types.d.ts +12 -0
  33. package/dist/modules/drawer/drawerStateMachine.d.ts +168 -0
  34. package/dist/modules/drawer/revealDrawerConstants.d.ts +33 -0
  35. package/dist/modules/drawer/revealDrawerStateMachine.d.ts +146 -0
  36. package/dist/modules/drawer/strategies/index.d.ts +8 -0
  37. package/dist/modules/drawer/strategies/overlayStrategy.d.ts +12 -0
  38. package/dist/modules/drawer/strategies/revealStrategy.d.ts +12 -0
  39. package/dist/modules/drawer/strategies/types.d.ts +116 -0
  40. package/dist/panels.cjs +1 -1
  41. package/dist/panels.js +1 -1
  42. package/dist/stack.cjs +1 -1
  43. package/dist/stack.cjs.map +1 -1
  44. package/dist/stack.js +306 -347
  45. package/dist/stack.js.map +1 -1
  46. package/dist/types.d.ts +14 -0
  47. package/dist/useAnimationFrame-CRuFlk5t.js +394 -0
  48. package/dist/useAnimationFrame-CRuFlk5t.js.map +1 -0
  49. package/dist/useAnimationFrame-XRpDXkwV.cjs +2 -0
  50. package/dist/useAnimationFrame-XRpDXkwV.cjs.map +1 -0
  51. package/dist/window.cjs +1 -1
  52. package/dist/window.js +1 -1
  53. package/package.json +1 -1
  54. package/src/components/gesture/SwipeSafeZone.tsx +1 -0
  55. package/src/components/grid/GridLayout.tsx +110 -38
  56. package/src/components/window/Drawer.tsx +114 -10
  57. package/src/components/window/DrawerLayers.tsx +48 -15
  58. package/src/components/window/DrawerRevealContext.spec.ts +20 -0
  59. package/src/components/window/DrawerRevealContext.tsx +99 -0
  60. package/src/components/window/drawerRevealAnimationUtils.spec.ts +375 -0
  61. package/src/components/window/drawerRevealAnimationUtils.ts +415 -0
  62. package/src/components/window/drawerStyles.spec.ts +39 -0
  63. package/src/components/window/drawerStyles.ts +24 -0
  64. package/src/components/window/useDrawerSwipeTransform.ts +28 -90
  65. package/src/components/window/useDrawerTransform.ts +505 -0
  66. package/src/components/window/useRevealDrawerTransform.spec.ts +1936 -0
  67. package/src/components/window/useRevealDrawerTransform.ts +105 -0
  68. package/src/demo/components/FullscreenDemoPage.tsx +47 -0
  69. package/src/demo/fullscreenRoutes.tsx +32 -0
  70. package/src/demo/index.tsx +5 -0
  71. package/src/demo/pages/Dialog/components/CardExpandDemo.tsx +23 -8
  72. package/src/demo/pages/Drawer/components/DrawerBasics.module.css +6 -1
  73. package/src/demo/pages/Drawer/components/DrawerBasics.tsx +14 -4
  74. package/src/demo/pages/Drawer/components/DrawerReveal.module.css +157 -0
  75. package/src/demo/pages/Drawer/components/DrawerReveal.tsx +128 -0
  76. package/src/demo/pages/Drawer/reveal/index.tsx +17 -0
  77. package/src/demo/pages/Drawer/reveal-fullscreen/index.tsx +135 -0
  78. package/src/demo/pages/Drawer/reveal-fullscreen/styles.module.css +233 -0
  79. package/src/demo/pages/Stack/components/StackBasics.spec.tsx +56 -52
  80. package/src/demo/pages/Stack/components/StackTablet.spec.tsx +39 -49
  81. package/src/demo/routes.tsx +2 -0
  82. package/src/dialog/index.ts +2 -0
  83. package/src/hooks/gesture/testing/createGestureSimulator.ts +1 -0
  84. package/src/hooks/gesture/useNativeGestureGuard.spec.ts +10 -2
  85. package/src/hooks/gesture/useSwipeInput.spec.ts +69 -0
  86. package/src/hooks/gesture/useSwipeInput.ts +2 -0
  87. package/src/hooks/gesture/utils.ts +15 -4
  88. package/src/hooks/useAnimatedVisibility.spec.ts +3 -3
  89. package/src/hooks/useOperationContinuity.spec.ts +17 -10
  90. package/src/hooks/useOperationContinuity.ts +5 -5
  91. package/src/hooks/useSharedElementTransition.ts +28 -7
  92. package/src/modules/dialog/DialogContainer.tsx +39 -5
  93. package/src/modules/dialog/Modal.tsx +46 -4
  94. package/src/modules/dialog/SwipeDialogContainer.tsx +12 -2
  95. package/src/modules/dialog/dialogAnimationUtils.spec.ts +0 -1
  96. package/src/modules/dialog/types.ts +14 -0
  97. package/src/modules/dialog/useDialogContainer.spec.ts +11 -3
  98. package/src/modules/dialog/useDialogSwipeInput.spec.ts +49 -28
  99. package/src/modules/dialog/useDialogSwipeInput.ts +37 -6
  100. package/src/modules/dialog/useDialogTransform.spec.ts +63 -30
  101. package/src/modules/drawer/drawerStateMachine.ts +500 -0
  102. package/src/modules/drawer/revealDrawerConstants.ts +38 -0
  103. package/src/modules/drawer/revealDrawerStateMachine.spec.ts +558 -0
  104. package/src/modules/drawer/revealDrawerStateMachine.ts +197 -0
  105. package/src/modules/drawer/strategies/index.ts +9 -0
  106. package/src/modules/drawer/strategies/overlayStrategy.ts +133 -0
  107. package/src/modules/drawer/strategies/revealStrategy.ts +111 -0
  108. package/src/modules/drawer/strategies/types.ts +160 -0
  109. package/src/modules/drawer/useDrawerSwipeInput.ts +7 -4
  110. package/src/modules/pivot/SwipePivotContent.spec.tsx +48 -37
  111. package/src/modules/pivot/usePivotSwipeInput.spec.ts +8 -8
  112. package/src/modules/stack/swipeTransitionContinuity.spec.tsx +1 -1
  113. package/src/types.ts +15 -0
  114. package/dist/FloatingWindow-CUXnEtrb.js +0 -827
  115. package/dist/FloatingWindow-CUXnEtrb.js.map +0 -1
  116. package/dist/FloatingWindow-DMwyK0eK.cjs +0 -2
  117. package/dist/FloatingWindow-DMwyK0eK.cjs.map +0 -1
  118. package/dist/GridLayout-DKTg_N61.cjs +0 -2
  119. package/dist/GridLayout-UWNxXw77.js +0 -926
  120. package/dist/PanelSystem-BqUzNtf2.js.map +0 -1
  121. package/dist/PanelSystem-D603LKKv.cjs +0 -3
  122. package/dist/PanelSystem-D603LKKv.cjs.map +0 -1
  123. package/dist/useNativeGestureGuard-C7TSqEkr.cjs +0 -2
  124. package/dist/useNativeGestureGuard-C7TSqEkr.cjs.map +0 -1
  125. package/dist/useNativeGestureGuard-CGYo6O0r.js +0 -347
  126. package/dist/useNativeGestureGuard-CGYo6O0r.js.map +0 -1
  127. 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
+ }
@@ -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
- .container {
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
- This sample uses the default Drawer styling. The drawer anchors to the left, covers the page surface, and
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 <GridLayout config={config} layers={layers} />;
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;