Skip to content

Commit c653c10

Browse files
committed
refactor: introduce dynamic sizing hooks for responsiveness and improve ReactPanelContainer functionality
1 parent 8887661 commit c653c10

File tree

6 files changed

+137
-25
lines changed

6 files changed

+137
-25
lines changed
Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,34 @@
11
import { IconLicense } from "@tabler/icons-react"
22
import React from "react"
3+
import useDimensions from "~/features/shared/hooks/useDimensions.ts"
4+
import useWindowSize from "~/features/shared/hooks/useWindowSize.ts"
35

46
interface ReactMarkdownContainerProps {
57
children: React.ReactNode
6-
tutorial: string
78
}
89

9-
export default function ReactMarkdownContainer({ children, tutorial }: ReactMarkdownContainerProps) {
10-
return (
11-
<>
12-
<div id="title-info" className="absolute left-0 top-14 w-full hidden">
13-
<div className="relative">
14-
<IconLicense stroke={2} size={14} className="rotate-90 absolute -top-9 left-4.5 text-yellow" />
15-
<h2 className="text-[12px] font-bold text-center rotate-90">Contenido</h2>
16-
</div>
10+
export default function ReactMarkdownContainer({ children }: ReactMarkdownContainerProps) {
11+
const [ref, { width }] = useDimensions<HTMLElement>()
12+
const windowSize = useWindowSize()
13+
14+
if (width <= windowSize.width / 10) {
15+
return (
16+
<div ref={ref} className="relative flex flex-col h-32 items-center justify-center p-2 text-yellow">
17+
<IconLicense stroke={2} size={20} className="rotate-90 mx-auto" />
18+
<h2 className="font-bold text-center rotate-90 mt-10">Contenido</h2>
1719
</div>
18-
<article id="article-info" className="scroll-container m-2 overflow-y-auto p-2">
19-
<article className="mb-6 text-secondary min-w-[400px]" id="content-markdown">
20-
<h2 className="text-xl font-bold mb-2">{tutorial}</h2>
21-
{children}
22-
<hr className="my-6 border-gray-700" />
23-
</article>
24-
<div className="flex justify-center pb-2 mt-auto min-w-[400px]">
25-
{/*<NavButtons previous={previous} next={next}/>*/}
26-
</div>
20+
)
21+
}
22+
23+
return (
24+
<article ref={ref} className="scroll-container m-2 overflow-y-auto p-2">
25+
<article className="mb-6 text-secondary min-w-[400px]" id="content-markdown">
26+
{children}
27+
<hr className="my-6 border-gray-700" />
2728
</article>
28-
</>
29+
<div className="flex justify-center pb-2 mt-auto min-w-[400px]">
30+
{/* <NavButtons previous={previous} next={next} /> */}
31+
</div>
32+
</article>
2933
)
3034
}

src/features/content/react/ReactPanelContainer.tsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { IconGripVertical } from "@tabler/icons-react"
2-
import type { ReactNode } from "react"
2+
import { type ReactNode, useMemo } from "react"
33
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"
4+
import useWindowSize from "~/features/shared/hooks/useWindowSize.ts"
45

56
interface PanelContainerProps {
67
direction: "horizontal" | "vertical"
@@ -16,17 +17,39 @@ export default function ReactPanelContainer({
1617
direction = "horizontal",
1718
defaultLayout = [50, 50],
1819
}: PanelContainerProps) {
20+
const { width } = useWindowSize()
21+
22+
const size = useMemo(() => {
23+
if (width >= 1024) return 5
24+
if (width >= 768) return 8
25+
return 10
26+
}, [width])
27+
28+
const offset = useMemo(() => 4, [])
29+
1930
return (
20-
<PanelGroup direction={direction} className="h-full min-h-0 ">
21-
<Panel defaultSize={defaultLayout[0]} className="min-h-0">
31+
<PanelGroup direction={direction} className="h-full min-h-0 grow">
32+
<Panel
33+
defaultSize={defaultLayout[0]}
34+
className="min-h-0"
35+
minSize={size + offset}
36+
collapsible
37+
collapsedSize={size}
38+
>
2239
{first}
2340
</Panel>
2441
<PanelResizeHandle className={"flex justify-center items-center"}>
2542
<div className={"bg-primary mx-auto cursor-col-resize grow flex items-center justify-center"}>
2643
<IconGripVertical size={14} className={direction === "vertical" ? "rotate-90" : ""} />
2744
</div>
2845
</PanelResizeHandle>
29-
<Panel defaultSize={defaultLayout[1]} className="min-h-0">
46+
<Panel
47+
defaultSize={defaultLayout[1]}
48+
className="min-h-0"
49+
minSize={size + offset}
50+
collapsible
51+
collapsedSize={size}
52+
>
3053
{second}
3154
</Panel>
3255
</PanelGroup>

src/features/content/react/ReactPlayground.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
1+
import { IconCode } from "@tabler/icons-react"
2+
import React from "react"
13
import ReactCodeEditor from "~/features/content/react/ReactCodeEditor.tsx"
24
import ReactPanelContainer from "~/features/content/react/ReactPanelContainer.tsx"
35
import ReactPanelHeader from "~/features/content/react/ReactPanelHeader.tsx"
46
import ReactTerminal from "~/features/content/react/ReactTerminal.tsx"
7+
import useDimensions from "~/features/shared/hooks/useDimensions.ts"
8+
import useWindowSize from "~/features/shared/hooks/useWindowSize.ts"
59

610
export default function ReactPlayground() {
11+
const [ref, { width }] = useDimensions<HTMLElement>()
12+
const windowSize = useWindowSize()
13+
14+
if (width <= windowSize.width / 10) {
15+
return (
16+
<div ref={ref} className="relative flex flex-col h-32 items-center justify-center p-2 text-yellow">
17+
<IconCode size={20} className="rotate-90 mx-auto" />
18+
<h2 className="font-bold text-center rotate-90 mt-10">Editor</h2>
19+
</div>
20+
)
21+
}
22+
723
return (
8-
<div className="flex h-full min-h-0 flex-col">
24+
<div ref={ref} className="flex h-full min-h-0 flex-col">
925
<ReactPanelHeader />
1026
<ReactPanelContainer
1127
direction={"vertical"}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { useCallback, useEffect, useRef, useState } from "react"
2+
3+
export type Dimensions = { width: number; height: number }
4+
5+
export default function useDimensions<T extends Element>() {
6+
const nodeRef = useRef<T | null>(null)
7+
const observerRef = useRef<ResizeObserver | null>(null)
8+
const [dimensions, setDimensions] = useState<Dimensions>({ width: 0, height: 0 })
9+
10+
const ref = useCallback((node: T | null) => {
11+
if (observerRef.current && nodeRef.current) {
12+
observerRef.current.unobserve(nodeRef.current)
13+
}
14+
15+
nodeRef.current = node
16+
17+
if (!node) return
18+
19+
if (typeof ResizeObserver === "undefined") {
20+
const rect = node.getBoundingClientRect()
21+
setDimensions({ width: rect.width, height: rect.height })
22+
return
23+
}
24+
25+
if (!observerRef.current) {
26+
observerRef.current = new ResizeObserver((entries) => {
27+
const entry = entries[0]
28+
if (!entry) return
29+
const { width, height } = entry.contentRect
30+
setDimensions({ width, height })
31+
})
32+
}
33+
34+
observerRef.current.observe(node)
35+
}, [])
36+
37+
useEffect(() => {
38+
return () => {
39+
if (observerRef.current) {
40+
observerRef.current.disconnect()
41+
observerRef.current = null
42+
}
43+
}
44+
}, [])
45+
46+
return [ref, dimensions] as const
47+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { useEffect, useState } from "react"
2+
3+
export default function useWindowSize() {
4+
const [windowSize, setWindowSize] = useState({
5+
width: typeof window !== "undefined" ? window.innerWidth : 0,
6+
height: typeof window !== "undefined" ? window.innerHeight : 0,
7+
})
8+
9+
useEffect(() => {
10+
function handleResize() {
11+
setWindowSize({
12+
width: window.innerWidth,
13+
height: window.innerHeight,
14+
})
15+
}
16+
17+
window.addEventListener("resize", handleResize)
18+
return () => window.removeEventListener("resize", handleResize)
19+
}, [])
20+
21+
return windowSize
22+
}

src/pages/[slug].astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const { Content } = await render(tutorial)
3333
slot="first"
3434
class="overflow-auto bg-dark-secondary h-full relative flex flex-col bg-light-bg border border-stroke-color ms-2 rounded-lg"
3535
>
36-
<ReactMarkdownContainer tutorial={'Probando Tutorial'}>
36+
<ReactMarkdownContainer client:only="react">
3737
<Content/>
3838
</ReactMarkdownContainer>
3939
</div>

0 commit comments

Comments
 (0)