Astroテーマを改造するときのメモをまとめました。
AstroコンポーネントをMarkdownから使う
- Astro.jsのコンポーネントはMDXから呼び出せるようなので、Astro Iconを使ってMarkdownでアイコンを表示させることもできる
- MDXを使うには:
- npmで
@astrojs/mdxパッケージを追加する - astro.config.tsの
integrationsにmdx()を追加する - Markdownファイルの拡張子をmdxにする
- 合わせて、コンテンツコレクションが
.mdxを対象に含めるようにパターンを書き換える
- npmで
<Content />のcomponents属性で列挙されたモジュールがMDXで使えるようになる- Astro Iconの場合、
import { Icon } from "astro-icon/components";でインポートして<Content components={{Icon}} />と書くと、MDXで<Icon />が使えるようになる
- Astro Iconの場合、
ツールチップ表示
- マウスホバーで表示される要素を作りたい
- Astroでは:
import "@/styles/tooltip.css";でCSSを読み込む- スクリプトでDOMを操作するので、
<script src="../scripts/tooltip.ts"></script>を</body>の手前に置く- src内にあるtsファイルはちゃんとトランスパイルしてくれている?
- CSSは以下のようにしてみた
/* ツールチップのターゲット */
.tooltip {
position: relative;
text-decoration: dotted underline;
}
/* ツールチップのコンテンツ */
.tooltip-content {
/* 真上に表示 */
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
/* 手前に表示 */
z-index: 10;
/* 外枠 */
border: 1px solid var(--color-border);
border-radius: 4px;
padding: 4px 8px;
margin-bottom: 7px;
/* 中身 */
background-color: var(--color-background);
width: max-content;
max-width: 80ch;
box-sizing: border-box;
overflow-wrap: break-word;
text-align: center;
font-size: 0.8rem;
/* デフォルトで非表示 */
opacity: 0;
visibility: hidden;
/* スッと現れる */
transition: opacity 0.1s ease-in-out;
}
/* ツールチップのターゲットとコンテンツの隙間にカーソル判定を加える */
.tooltip-content::before {
content: "";
position: absolute;
top: 100%;
left: 0%;
width: 100%;
height: 8px;
pointer-events: auto;
}
/* ツールチップの吹き出し */
.tooltip-content::after {
content: "";
/* 真上に表示 */
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
/* ▼を描く */
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid var(--color-border);
}
/* ツールチップに触れたとき */
.tooltip:hover .tooltip-content {
/* 表示 */
opacity: 1;
visibility: visible;
}- ツールチップが画面外にはみ出すことがあるので、位置調整してみる
- もっと良いやり方がありそう
// ツールチップが画面外に出ないように位置を調整するイベントリスナーを追加する
for (const tooltip of document.querySelectorAll<HTMLElement>(".tooltip")) {
function listener(this: HTMLElement) {
const content = this.querySelector<HTMLElement>(".tooltip-content");
if (content === null) return;
// 初期位置でのツールチップの矩形を調べる
content.style.maxWidth = "80ch";
content.style.left = "50%";
content.style.right = "auto";
content.style.transform = "translateX(-50%)";
let rect = content.getBoundingClientRect();
// ツールチップが画面に収まらないなら、小さくする
if (rect.width > document.documentElement.clientWidth) {
content.style.maxWidth = `${document.documentElement.clientWidth}px`;
rect = content.getBoundingClientRect();
}
// ツールチップが画面からはみ出さないようにずらす
if (rect.left < 0) {
content.style.left = `${-tooltip.offsetLeft}px`;
content.style.transform = "none";
} else if (rect.right > document.documentElement.clientWidth) {
content.style.left = `${document.documentElement.clientWidth - tooltip.offsetLeft - rect.width}px`;
content.style.transform = "none";
}
}
tooltip.addEventListener("mouseenter", listener);
tooltip.addEventListener("touchstart", listener);
}