🔄
🩺看護師が医療現場で使う計算ツールの開発に挑戦してみた #6:③ ResultBoxデザイン統一と注意表示の最適化
📘 はじめに
現役看護師として働きながら、Next.js × TypeScript × Tailwind CSSで「看護師向け計算ツールアプリ」を開発しています。
医療現場でも“安心して使える”Webアプリを目指し、UIの改善を段階的に行ってきました。
今回は、ResultBoxコンポーネントを全計算共通化し、注意表示を最適化する工程です。
💡 背景
開発初期では、各ページで結果の見せ方がバラバラでした。
数値の見やすさや注意表示の位置が揃っていないことで、利用者が混乱する場面もありました。
| 問題点 | UX上の影響 |
|---|---|
| 数値サイズが小さい | 現場で確認しづらい |
| 背景色や余白が統一されていない | 一貫性が失われる |
| 注意欄の位置が不明確 | 見落としリスクあり |
これを解決するため、ResultBoxのUI構造を共通化し、どの計算機能でも同じレイアウト・操作感で結果を確認できるようにしました。
⚙️ 改善後のResultBox.tsx
"use client";
import React, { useRef, useEffect, useState } from "react";
import { Disclosure } from "@headlessui/react";
import Image from "next/image";
import { helpTexts } from "@/config/helpTexts";
interface ResultItem {
label: string;
value: string | number;
unit: string;
}
interface ResultBoxProps {
title?: string;
results: ResultItem[];
color?: "green" | "blue" | "amber" | "purple" | "cyan" | "teal" | "fuchsia" | "rose" | "yellow";
typeId?: string;
}
export const ResultBox: React.FC<ResultBoxProps> = ({
title = "計算結果",
results,
color = "blue",
typeId,
}) => {
const bg = {
green: "bg-green-50 border-green-200 text-green-800",
blue: "bg-blue-50 border-blue-200 text-blue-800",
amber: "bg-amber-50 border-amber-200 text-amber-800",
purple: "bg-purple-50 border-purple-200 text-purple-800",
cyan: "bg-cyan-50 border-cyan-200 text-cyan-800",
teal: "bg-teal-50 border-teal-200 text-teal-800",
fuchsia: "bg-fuchsia-50 border-fuchsia-200 text-fuchsia-800",
rose: "bg-rose-50 border-rose-200 text-rose-800",
yellow: "bg-yellow-50 border-yellow-200 text-yellow-800",
}[color];
const helpText = typeId ? helpTexts[typeId] : null;
const panelRef = useRef<HTMLDivElement>(null);
const [isOpen, setIsOpen] = useState(false);
useEffect(() => {
if (isOpen && panelRef.current) {
panelRef.current.scrollIntoView({ behavior: "smooth", block: "start" });
}
}, [isOpen]);
return (
<Disclosure>
{({ open }) => {
if (open !== isOpen) setIsOpen(open);
return (
<div className={`border rounded p-4 ${bg}`}>
{/* タイトル&ヘルプアイコン */}
<div className="flex items-start justify-between">
<h3 className="font-semibold">{title}</h3>
{helpText && (
<Disclosure.Button aria-label="注意説明">
<Image
src="/icons/help-icon.svg"
alt="注意"
width={28}
height={28}
className="cursor-pointer"
/>
</Disclosure.Button>
)}
</div>
{/* 結果リスト */}
<ul className="space-y-2 mt-2">
{results.map((item, i) => (
<li key={i} className="flex items-baseline gap-2">
<span className="text-base">{item.label}:</span>
<strong className="text-2xl font-bold">{item.value}</strong>
<span className="text-sm">{item.unit}</span>
</li>
))}
</ul>
{/* 注意書き */}
{helpText && (
<Disclosure.Panel
ref={panelRef}
className={`mt-3 p-3 border-t ${bg} rounded-t-none text-sm leading-relaxed`}
>
{helpText}
</Disclosure.Panel>
)}
</div>
);
}}
</Disclosure>
);
};
🎨 デザインの改善ポイント
| 要素 | 改善内容 | 意図 |
|---|---|---|
| 数値 | text-2xl font-bold | 見やすく即理解 |
| 背景色 | 種別カラーで統一 | 視覚的一貫性 |
| 注意欄 | Disclosure+scrollIntoView | 自然な展開でUX向上 |
| 余白 | space-y-2 | 可読性アップ |
| アイコン | 右上固定+28px | 押しやすく統一感 |
🧠 学びのまとめ
- ResultBoxは「全計算共通UI」として中心的役割を担う
- Disclosureを使えば、状態管理+アクセシビリティ対応が簡単
- scrollIntoViewとの組み合わせでUXが滑らかに
- 配色・構造・動きを統一することで“安心できるUI”が生まれる
Discussion