Skip to content

Commit 635c19b

Browse files
committed
server componentから使えるようラップ
1 parent a4d63ff commit 635c19b

6 files changed

Lines changed: 52 additions & 33 deletions

File tree

app/markdown/markdown.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
DaisyWarningIcon,
1818
} from "@/daisyAlertIcon";
1919
import { CSSProperties } from "react";
20-
import { updateTooltipPosition } from "./tooltipPosition";
20+
import { WithAutoTooltipPosition } from "./tooltipPosition";
2121
import Link from "next/link";
2222

2323
export function StyledMarkdown(props: {
@@ -61,8 +61,8 @@ const baseComponents: Components = {
6161
li: ({ node, ...props }) => <li className="my-1" {...props} />,
6262
a: ({ node, href, ...props }) =>
6363
href?.startsWith("http") ? (
64-
<a
65-
ref={(node) => updateTooltipPosition(node)}
64+
<WithAutoTooltipPosition
65+
as="a"
6666
className="link link-info tooltip tooltip-info before:whitespace-pre"
6767
href={href}
6868
data-tip={`外部リンク\n${href}`}

app/markdown/term.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
} from "@floating-ui/react";
2222
import clsx from "clsx";
2323
import { usePagesListForLang } from "@/pagesListContext";
24-
import { updateTooltipPosition } from "./tooltipPosition";
24+
import { WithAutoTooltipPosition } from "./tooltipPosition";
2525

2626
const TermDefinitionContext = createContext<{
2727
lang: LangId;
@@ -97,14 +97,14 @@ export default function Term(props: JSX.IntrinsicElements["q"] & ExtraProps) {
9797
const term = termDefinitions.find((t) => t.alias.includes(termText));
9898
if (!term) {
9999
const internalLink = (pageEntry: PageEntry) => (
100-
<Link
101-
ref={(node) => updateTooltipPosition(node)}
100+
<WithAutoTooltipPosition
101+
as={Link}
102102
className="link link-info decoration-dotted tooltip tooltip-info"
103103
data-tip={`${pageEntry.index}. ${pageEntry.name}`}
104104
href={`/${lang}/${pageEntry.slug}`}
105105
>
106106
{pageEntry.index}
107-
</Link>
107+
</WithAutoTooltipPosition>
108108
);
109109

110110
// ./1, ./1-foo, ./next, ./prev →同じ言語のドキュメントへのリンクで、「第n章」
@@ -147,13 +147,13 @@ export default function Term(props: JSX.IntrinsicElements["q"] & ExtraProps) {
147147

148148
console.error(`'${termText}' という用語は定義されていません`);
149149
return (
150-
<span
151-
ref={(node) => updateTooltipPosition(node)}
150+
<WithAutoTooltipPosition
151+
as="span"
152152
className="link link-error decoration-dotted tooltip tooltip-error"
153153
data-tip={`'${termText}' という用語は定義されていません`}
154154
>
155155
{props.children}
156-
</span>
156+
</WithAutoTooltipPosition>
157157
);
158158
}
159159

app/markdown/tooltipPosition.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

app/markdown/tooltipPosition.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"use client";
2+
3+
import { ComponentPropsWithoutRef, ElementType } from "react";
4+
5+
/**
6+
* レンダリングのたびに、この要素の左端と右端のスペースを計算し、画面内に収まるようtooltipを水平に平行移動する。
7+
*/
8+
function updateTooltipPosition(node: HTMLElement | null) {
9+
if (node) {
10+
const rect = node.getBoundingClientRect();
11+
node.style.setProperty(
12+
"--tt-trans",
13+
`clamp(${-(rect.left + rect.width / 2)}px, -50%, calc(${document.body.clientWidth - rect.right + rect.width / 2}px - 100%))`
14+
);
15+
}
16+
}
17+
18+
type Props<T extends ElementType> = { as: T } & Omit<
19+
ComponentPropsWithoutRef<T>,
20+
"as"
21+
>;
22+
export function WithAutoTooltipPosition<T extends ElementType = "div">({
23+
as,
24+
...props
25+
}: Props<T>) {
26+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
27+
const Component = as as React.ElementType<any>;
28+
return (
29+
<Component
30+
ref={(node: HTMLElement | null) => updateTooltipPosition(node)}
31+
{...props}
32+
/>
33+
);
34+
}

app/terminal/exec.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { LangConstants } from "@my-code/runtime/languages";
1515
import { useRuntime } from "@my-code/runtime/context";
1616
import { captureException } from "@sentry/nextjs";
1717
import { MinMaxButton, Modal } from "./modal";
18-
import { updateTooltipPosition } from "@/markdown/tooltipPosition";
18+
import { WithAutoTooltipPosition } from "@/markdown/tooltipPosition";
1919

2020
function handleRuntimeError(error: unknown) {
2121
captureException(error);
@@ -194,8 +194,8 @@ export function ExecFile(props: ExecProps) {
194194
<code className="text-left break-all text-sm my-1 ml-4">
195195
{getCommandlineStr?.(props.filenames)}
196196
</code>
197-
<div
198-
ref={(node) => updateTooltipPosition(node)}
197+
<WithAutoTooltipPosition
198+
as="div"
199199
className="ml-1 mr-1 tooltip tooltip-secondary tooltip-bottom z-1"
200200
>
201201
<div className="tooltip-content bg-secondary/60 backdrop-blur-xs">
@@ -226,7 +226,7 @@ export function ExecFile(props: ExecProps) {
226226
</div>
227227
<div className="flex-1" />
228228
<MinMaxButton open={isModal} id={`exec-${props.filenames.join("-")}`} />
229-
</div>
229+
</WithAutoTooltipPosition>
230230
<div className="flex-1 w-full overflow-hidden bg-base-300 p-4 pr-1 pt-2 relative rounded-b-box">
231231
{/*
232232
ターミナル表示の初期化が完了するまでの間、ターミナルは隠し、内容をそのまま表示する。

app/terminal/repl.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
import { useRuntime } from "@my-code/runtime/context";
2727
import { MinMaxButton, Modal } from "./modal";
2828
import { StopButtonContent } from "./exec";
29-
import { updateTooltipPosition } from "@/markdown/tooltipPosition";
29+
import { WithAutoTooltipPosition } from "@/markdown/tooltipPosition";
3030

3131
function handleRuntimeError(error: unknown) {
3232
captureException(error);
@@ -499,8 +499,8 @@ export function ReplTerminal({
499499
<span className="text-sm my-1 ml-3 text-left">
500500
{runtimeInfo?.prettyLangName || language.runtime} 実行環境
501501
</span>
502-
<div
503-
ref={(node) => updateTooltipPosition(node)}
502+
<WithAutoTooltipPosition
503+
as="div"
504504
className="ml-1 tooltip tooltip-secondary tooltip-bottom z-1"
505505
>
506506
<div className="tooltip-content bg-secondary/60 backdrop-blur-xs">
@@ -532,7 +532,7 @@ export function ReplTerminal({
532532
</div>
533533
<div className="flex-1" />
534534
<MinMaxButton open={isModal} id={`repl-${terminalId}`} />
535-
</div>
535+
</WithAutoTooltipPosition>
536536
{/*
537537
ターミナル表示の初期化が完了するまでの間、ターミナルは隠し、内容をそのまま表示する。
538538
可能な限りレイアウトが崩れないようにするため & SSRでも内容が読めるように(SEO?)という意味もある

0 commit comments

Comments
 (0)