From df624e4c14482a765e6307fe59ebfc5de32e45d2 Mon Sep 17 00:00:00 2001 From: nakaterm <104970808+nakaterm@users.noreply.github.com> Date: Tue, 8 Sep 2026 01:04:35 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=B7=A8=E9=9B=86=E4=B8=AD=E3=81=AF?= =?UTF-8?q?=E4=BB=96=E3=82=B2=E3=82=B9=E3=83=88=E3=81=AE=E4=BA=88=E5=AE=9A?= =?UTF-8?q?=E3=82=92=E7=84=A1=E5=BD=A9=E8=89=B2=E3=81=AB=E3=81=97=E3=81=A6?= =?UTF-8?q?=E8=87=AA=E5=88=86=E3=81=AE=E4=BA=88=E5=AE=9A=E3=81=A8=E5=8C=BA?= =?UTF-8?q?=E5=88=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 編集モードでは自分のスロットと他ゲスト1人分のスロットがどちらも rgba(参加形態色, 0.2) で塗られ、1px の枠線しか違いがなく見分けが つかなかった。編集中のみ他ゲスト側の色を輝度で無彩色化し、「色付き =自分、グレー=他人」で判別できるようにする。 明度は 90〜170 にクランプし、淡い参加形態色が薄すぎて見えなくなる のと濃い色が黒く沈むのを防ぐ。人数による濃淡表現はグレーのまま維持 される。ツールチップ内のラベル色は内訳確認のため元の色を残す。 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01TabU9J9gxo7Av5UcrytYko --- client/src/components/Calendar.tsx | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/client/src/components/Calendar.tsx b/client/src/components/Calendar.tsx index b4c34b6..9251279 100644 --- a/client/src/components/Calendar.tsx +++ b/client/src/components/Calendar.tsx @@ -60,6 +60,16 @@ const MAX_SCROLL_SPEED = 8; const OPACITY = 0.2; const PRIMARY_RGB: [number, number, number] = [15, 130, 177]; +/** + * 編集中に自分の予定と見分けられるよう、他ゲストの色を無彩色に落とす。 + * 明度は帯域にクランプし、淡い参加形態色が薄すぎて見えなくならないようにする。 + */ +function toGrayscale([r, g, b]: [number, number, number]): [number, number, number] { + const luminance = 0.299 * r + 0.587 * g + 0.114 * b; + const y = Math.round(Math.min(Math.max(luminance, 90), 170)); + return [y, y, y]; +} + // TODO: colors.ts のものと共通化 function hexToRgb(hex: string): [number, number, number] { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); @@ -419,18 +429,19 @@ export const Calendar = ({ .map((opt) => { const guestIds = optionGroups.get(opt.id) ?? []; const opacity = 1 - (1 - OPACITY) ** guestIds.length; - return { ...opt, guestIds, opacity }; + const rgb = editMode ? toGrayscale(hexToRgb(opt.color)) : hexToRgb(opt.color); + return { ...opt, guestIds, opacity, rgb, displayColor: `rgb(${rgb.join(",")})` }; }); let background: string; if (breakdown.length === 1) { - const [r, g, b] = hexToRgb(breakdown[0].color); + const [r, g, b] = breakdown[0].rgb; background = `rgba(${r},${g},${b},${breakdown[0].opacity.toFixed(3)})`; } else if (breakdown.length > 1) { const w = 100 / breakdown.length; const stops = breakdown .map((bd, j) => { - const [r, g, b] = hexToRgb(bd.color); + const [r, g, b] = bd.rgb; return `rgba(${r},${g},${b},${bd.opacity.toFixed(3)}) ${j * w}%, rgba(${r},${g},${b},${bd.opacity.toFixed(3)}) ${(j + 1) * w}%`; }) .join(", "); @@ -470,7 +481,7 @@ export const Calendar = ({ >