diff --git a/apps/web/content/docs/code/focus.mdx b/apps/web/content/docs/code/focus.mdx
index 93f74254..f2c1c166 100644
--- a/apps/web/content/docs/code/focus.mdx
+++ b/apps/web/content/docs/code/focus.mdx
@@ -20,25 +20,14 @@ We need two things:
- Get a `ref` of the `pre` element, and scroll it if needed
```tsx focus.tsx -c
-"use client"
-
-import {
- AnnotationHandler,
- InnerPre,
- getPreRef,
- InnerLine,
-} from "codehike/code"
-import React, { useLayoutEffect, useRef } from "react"
// !fold[/className="(.*?)"/gm]
+import { AnnotationHandler, InnerLine } from "codehike/code"
+import { PreWithFocus } from "./focus.client"
export const focus: AnnotationHandler = {
name: "focus",
onlyIfAnnotated: true,
- PreWithRef: (props) => {
- const ref = getPreRef(props)
- useScrollToFocus(ref)
- return
- },
+ PreWithRef: PreWithFocus,
Line: (props) => (
),
}
+```
+
+```tsx focus.client.tsx -c
+// !fold[/className="(.*?)"/gm]
+"use client"
+
+import React, { useLayoutEffect, useRef } from "react"
+import { AnnotationHandler, InnerPre, getPreRef } from "codehike/code"
+
+export const PreWithFocus: AnnotationHandler["PreWithRef"] = (props) => {
+ const ref = getPreRef(props)
+ useScrollToFocus(ref)
+ return
+}
function useScrollToFocus(ref: React.RefObject) {
const firstRender = useRef(true)
diff --git a/apps/web/content/docs/concepts/blocks.mdx b/apps/web/content/docs/concepts/blocks.mdx
index b7efc677..5035e24e 100644
--- a/apps/web/content/docs/concepts/blocks.mdx
+++ b/apps/web/content/docs/concepts/blocks.mdx
@@ -218,7 +218,7 @@ The same applies to images, codeblocks, and paragraphs.
## Nesting
-You can use headigns with different levels to create nested blocks.
+You can use headings with different levels to create nested blocks.
diff --git a/apps/web/demos/focus/code.tsx b/apps/web/demos/focus/code.tsx
index d357c6fe..b579cfc9 100644
--- a/apps/web/demos/focus/code.tsx
+++ b/apps/web/demos/focus/code.tsx
@@ -1,14 +1,8 @@
"use client"
-import {
- HighlightedCode,
- Pre,
- AnnotationHandler,
- InnerPre,
- getPreRef,
- InnerLine,
-} from "codehike/code"
-import React, { useLayoutEffect, useRef, useState } from "react"
+import { HighlightedCode, Pre } from "codehike/code"
+import React, { useState } from "react"
+import { focus } from "./focus"
const ranges = {
lorem: { fromLineNumber: 1, toLineNumber: 5 },
@@ -42,14 +36,14 @@ export function CodeContainer({ code }: { code: HighlightedCode }) {
{" "}
@@ -57,52 +51,3 @@ export function CodeContainer({ code }: { code: HighlightedCode }) {
>
)
}
-
-const focus: AnnotationHandler = {
- name: "focus",
- PreWithRef: (props) => {
- const ref = getPreRef(props)
- useScrollToFocus(ref)
- return
- },
- Line: (props) => (
-
- ),
- AnnotatedLine: ({ annotation, ...props }) => (
-
- ),
-}
-
-function useScrollToFocus(ref: React.RefObject) {
- const firstRender = useRef(true)
- useLayoutEffect(() => {
- if (ref.current) {
- // find all descendants whith data-focus="true"
- const focusedElements = ref.current.querySelectorAll(
- "[data-focus=true]",
- ) as NodeListOf
-
- // find top and bottom of the focused elements
- const containerRect = ref.current.getBoundingClientRect()
- let top = Infinity
- let bottom = -Infinity
- focusedElements.forEach((el) => {
- const rect = el.getBoundingClientRect()
- top = Math.min(top, rect.top - containerRect.top)
- bottom = Math.max(bottom, rect.bottom - containerRect.top)
- })
-
- // scroll to the focused elements if any part of them is not visible
- if (bottom > containerRect.height || top < 0) {
- ref.current.scrollTo({
- top: ref.current.scrollTop + top - 10,
- behavior: firstRender.current ? "instant" : "smooth",
- })
- }
- firstRender.current = false
- }
- })
-}
diff --git a/apps/web/demos/focus/focus.client.tsx b/apps/web/demos/focus/focus.client.tsx
new file mode 100644
index 00000000..d768737c
--- /dev/null
+++ b/apps/web/demos/focus/focus.client.tsx
@@ -0,0 +1,41 @@
+"use client"
+
+import React, { useLayoutEffect, useRef } from "react"
+import { AnnotationHandler, InnerPre, getPreRef } from "codehike/code"
+
+export const PreWithFocus: AnnotationHandler["PreWithRef"] = (props) => {
+ const ref = getPreRef(props)
+ useScrollToFocus(ref)
+ return
+}
+
+function useScrollToFocus(ref: React.RefObject) {
+ const firstRender = useRef(true)
+ useLayoutEffect(() => {
+ if (ref.current) {
+ // find all descendants whith data-focus="true"
+ const focusedElements = ref.current.querySelectorAll(
+ "[data-focus=true]",
+ ) as NodeListOf
+
+ // find top and bottom of the focused elements
+ const containerRect = ref.current.getBoundingClientRect()
+ let top = Infinity
+ let bottom = -Infinity
+ focusedElements.forEach((el) => {
+ const rect = el.getBoundingClientRect()
+ top = Math.min(top, rect.top - containerRect.top)
+ bottom = Math.max(bottom, rect.bottom - containerRect.top)
+ })
+
+ // scroll to the focused elements if any part of them is not visible
+ if (bottom > containerRect.height || top < 0) {
+ ref.current.scrollTo({
+ top: ref.current.scrollTop + top - 10,
+ behavior: firstRender.current ? "instant" : "smooth",
+ })
+ }
+ firstRender.current = false
+ }
+ })
+}
diff --git a/apps/web/demos/focus/focus.tsx b/apps/web/demos/focus/focus.tsx
new file mode 100644
index 00000000..b5b3ecea
--- /dev/null
+++ b/apps/web/demos/focus/focus.tsx
@@ -0,0 +1,17 @@
+import { AnnotationHandler, InnerLine } from "codehike/code"
+import { PreWithFocus } from "./focus.client"
+
+export const focus: AnnotationHandler = {
+ name: "focus",
+ onlyIfAnnotated: true,
+ PreWithRef: PreWithFocus,
+ Line: (props) => (
+
+ ),
+ AnnotatedLine: ({ annotation, ...props }) => (
+
+ ),
+}