🩺

🩺看護師が医療現場で使う計算ツールの開発に挑戦してみた #6:②スムーススクロールで操作感を高める

に公開

📘 はじめに

現役看護師として働きながら、Next.js × TypeScript × Tailwind CSSで「看護師向け計算ツールアプリ」を開発しています。
本シリーズでは、医療現場でも“安心して使える”Webアプリを目指し、実装を1ステップずつ記録しています。

今回は scrollIntoView を活用して操作感を高める
「入力→結果→解説」の流れを自然に見せるスムーススクロールの実装です。

💡 背景

ユーザーが「計算する」ボタンを押しても、結果が画面下に隠れて見えない。
そんな“気づかない結果”は、ちょっとしたストレスになります。

小さな動きですが、これを解消するだけでアプリ全体の印象がぐっと良くなります。

⚙️ スクロール用ユーティリティを作成

どのページでも共通して使えるように、シンプルな関数を /lib/scrollToRef.ts に定義します。

lib/scrollToRef.ts
export const scrollToRef = (ref: React.RefObject<HTMLElement>) => {
  if (!ref.current) return;
  ref.current.scrollIntoView({
    behavior: "smooth",
    block: "start",
  });
};

✅ SSR安全(window参照なし)
✅ 各ページで再利用可能
✅ 型安全に定義できる

🧩 実装例①:投薬計算ページで結果までスムーズに移動


"use client";

import { useState, useRef, useEffect } from "react";
import { scrollToRef } from "@/lib/scrollToRef";
import { ResultBox } from "../ResultBox";
import SubmitButton from "../SubmitButton";

export default function MedicationCalculator() {
  const [result, setResult] = useState<{ totalDose: string; volume: string } | null>(null);
  const resultRef = useRef<HTMLDivElement>(null);

  const calculate = () => {
    const calcResult = { totalDose: "300", volume: "30" };
    setResult(calcResult);
  };

  useEffect(() => {
    if (result) scrollToRef(resultRef);
  }, [result]);

  return (
    <div className="space-y-4">
      <SubmitButton onClick={calculate} color="bg-yellow-500" />
      {result && (
        <div ref={resultRef}>
          <ResultBox
            color="yellow"
            results={[
              { label: "総投与量", value: result.totalDose, unit: "mg" },
              { label: "薬液量", value: result.volume, unit: "mL" },
            ]}
            typeId="medication"
          />
        </div>
      )}
    </div>
  );
}

📍 ポイント

  • 結果が state 更新された瞬間に scrollToRef() を呼ぶ
  • 描画完了を待つために useEffect で監視
  • setTimeout は不要(よりReact的で安定)

🧩 実装例②:Disclosure開閉時にもスムーズスクロール

ResultBox の説明欄(Disclosure)が開かれた瞬間に、自動でスクロールします。


useEffect(() => {
  if (isOpen && panelRef.current) {
    panelRef.current.scrollIntoView({ behavior: "smooth", block: "start" });
  }
}, [isOpen]);

📍 ポイント

  • Disclosureの状態(open)をuseStateで追跡
  • 開いた瞬間に説明欄が自然に見える位置へ移動
  • 「結果→解説」が1連の流れで表示され、操作が途切れない

🎨 UX設計のコツ

観点 ポイント 解説
タイミング 描画完了後にスクロール useEffectで自然制御
スクロール位置 block: "start" 結果ボックスの上端に合わせる
再利用性 /lib/scrollToRef.tsに共通化 全ページ同じ挙動で統一
安全性 SSR環境でも安全 windowアクセス不要

🧠 学びのまとめ

  • scrollIntoView だけでUXは大きく改善できる
  • useEffectを使えばsetTimeoutなしで自然に動作
  • 「入力 → 結果 → 解説」が途切れずつながると、ユーザーの集中が保たれる
  • 小さな動きが “看護現場でも安心して使えるUI” に直結する

🚀次回

ResultBoxデザイン統一と注意表示の最適化を進めていきます。

Discussion