範囲の帯RangeBarExperimental

全体の幅の中で、区間がどこにあるかを1本の帯で見せます。週間予報の最低〜最高気温、プランごとの価格帯などに使います。

プレビュー

  • 今日23°29°
  • あす21°24°
  • 月曜20°28°
  • 火曜22°32°
  • 水曜20°27°
上が RangeBar の塗り方です。下のように区間ごとにやり直すと、同じ 20° が行ごとに違う色になります。

状態とバリエーション

グラデーションと単色

gradient は、全体の幅に低い値から高い値へ変わるグラデーションを1本描き、区間の外を隠します。同じ値はどの行でも同じ色になります。solid はテーマの主色(プライマリ色)1色で塗ります。

1422
2028
2028

両端が同じ

最低と最高が同じでも、帯の太さと同じ直径の丸を1つ出します。「26° から 26°」は値が無いのではなく、幅がゼロの区間だからです。

2626

まだ分からない

low か high が null のあいだは、背景の帯だけを出します。

——

プロパティ

表は横にスクロールできます
プロパティ型初期値説明
minnumber-全体の左端の値。帯を何行か並べるときは、すべての行で同じ値にします。
maxnumber-全体の右端の値。
lownumber | null-この行の区間の始まり(最低値)。分からなければ null。
highnumber | null-この行の区間の終わり(最高値)。
variant"solid" | "gradient""solid"gradient は全体の幅にグラデーションを1本描き、区間の外を隠します。
labelstring"Range"スクリーンリーダーが読み上げる文の先頭に付ける語。
unitstring-読み上げで両端の値に付ける単位("°")。
valueTextstring-読み上げる値の文を丸ごと差し替えます。

使い方

import { RangeBar } from "@gunjo/ui";

const WEEK = [
  { day: "今日", low: 26, high: 26 },
  { day: "あす", low: 21, high: 24 },
  { day: "月曜", low: 20, high: 28 },
  { day: "火曜", low: 22, high: 32 },
];

// 全部の行で同じ min / max を使うと、帯の位置で比べられます。
const MIN = Math.min(...WEEK.map((d) => d.low));
const MAX = Math.max(...WEEK.map((d) => d.high));

export function WeeklyTemperatures() {
  return (
    <ul className="divide-y rounded-lg border bg-card border-transparent contrast-more:border-border forced-colors:border-[CanvasText]">
      {WEEK.map((d) => (
        <li key={d.day} className="grid min-h-10 grid-cols-[4.5rem_2rem_1fr_2rem] items-center gap-2 px-4 py-2 text-sm">
          <span>{d.day}</span>
          <span className="text-right font-mono">{d.low}°</span>
          <RangeBar min={MIN} max={MAX} low={d.low} high={d.high} variant="gradient" label={`${d.day}の気温`} unit="°" />
          <span className="font-mono">{d.high}°</span>
        </li>
      ))}
    </ul>
  );
}

設計の判断

  • 数字は帯の外に置きます。両端の数字の幅や並べ方は画面ごとに違うので、呼び出し側が決めます。
  • グラデーションは区間ではなく全体の幅に描きます。区間ごとにグラデーションをやり直すと、20° が行ごとに違う色になり、色で比べられなくなります。
  • Meter に始点を足すやり方は採りませんでした。Meter は「0 から1つの値まで」を読み上げるコンポーネントで、始点を持たせると、見た目と読み上げる内容が合わなくなります。
  • SVG ではなく、HTML の要素に clip-path を掛けて描きます。
  • Meter

    0 から1つの値まで。区間の始まりを持たない。

  • DistributionBar

    合計100%の内訳。全体の中の位置ではない。

  • RangeSlider

    つまみで区間を選ぶ入力。RangeBar は見せるだけで操作はできない。

いつ・なぜ使うか(UIXHERO)

「いつ・なぜ使うか」の判断は、姉妹サイト UIXHERO の記事で解説しています。