相対時間表示
stimeo--relative-time
絶対時刻を「3分前」のように表示し、Intl で自動更新する。
stimeo--relative-time コントローラは HTML の <time> セマンティクスに従います。datetime 属性と現在時刻の差を算定し、Intl.RelativeTimeFormat(ブラウザ標準・追加依存なし)で整形します。ポーリング間隔は経過に応じて伸び(秒→分→時→日)、threshold を超えると元の絶対表記へフォールバックします(data-state="absolute")。機械可読な datetime は不変のまま表示テキストだけ更新し、読み上げの割り込みを避けるため意図的にライブリージョン化しません。ポーリング用タイマーは disconnect(Turbo 遷移含む)で破棄されます。ライブラリは挙動のみを提供し、見た目はこの Playground が持ちます。
- 投稿
- 更新
- 期限
- アーカイブ
表示テキストは時間の経過に合わせて自動更新されます(更新間隔は古くなるほど広がります。数分以内の項目はおおむね 1 分ごとに更新されるので、最初の「投稿」がやがて「4 分前」「5 分前」 …と進むのを確認できます)。読み上げの割り込みを避けるため、更新は通知されません。各時刻にカーソルを合わせると絶対時刻が表示されます。
<%# Markup for the relative-time demo.
Formats the absolute time in <time datetime> into "3 minutes ago" etc. via
Intl.RelativeTimeFormat, updating at an interval that grows with elapsed time. The
machine-readable datetime stays fixed and only the display text updates; it's not a
live region, to avoid interrupting screen readers. The locale follows the page
language. The last example, past the threshold, falls back to an absolute format. %>
<ul class="relative-time-demo">
<% [
{ at: 3.minutes.ago, label: t("components.relative_time.demo.posted") },
{ at: 2.hours.ago, label: t("components.relative_time.demo.updated") },
{ at: 3.days.from_now, label: t("components.relative_time.demo.due") }
].each do |row| %>
<li class="relative-time-demo__row">
<span class="relative-time-demo__label"><%= row[:label] %></span>
<time
class="relative-time"
data-controller="stimeo--relative-time"
datetime="<%= row[:at].iso8601 %>"
title="<%= row[:at].strftime("%Y-%m-%d %H:%M") %>"
data-stimeo--relative-time-locale-value="<%= I18n.locale %>">
<%= row[:at].strftime("%Y-%m-%d %H:%M") %>
</time>
</li>
<% end %>
<li class="relative-time-demo__row">
<span class="relative-time-demo__label"><%= t(
"components.relative_time.demo.archived"
) %></span>
<%# Example that falls back to an absolute format past the threshold
(30 days = 2592000 seconds). %>
<time
class="relative-time"
data-controller="stimeo--relative-time"
datetime="<%= 90.days.ago.iso8601 %>"
data-stimeo--relative-time-locale-value="<%= I18n.locale %>"
data-stimeo--relative-time-threshold-value="2592000">
<%= 90.days.ago.strftime("%Y-%m-%d %H:%M") %>
</time>
</li>
</ul>
<p class="relative-time-demo__hint"><%= t("components.relative_time.demo.hint") %></p>
/*
* Presentation-only styles for the relative-time demo.
* The library only updates the element's text and reflects data-state (relative / absolute).
*/
.relative-time-demo {
margin: 0;
padding: 0;
list-style: none;
display: flex;
flex-direction: column;
gap: 0.5rem;
max-width: 32rem;
}
.relative-time-demo__row {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 1rem;
padding: 0.5rem 0.75rem;
border: 1px solid var(--border);
border-radius: 0.375rem;
}
.relative-time-demo__label {
color: var(--color-text-muted);
font-size: 0.9rem;
}
.relative-time {
font-variant-numeric: tabular-nums;
color: var(--fg);
}
/* Times that fell back to absolute format are shown subtly, in a more monospace style. */
.relative-time[data-state="absolute"] {
font-size: 0.9rem;
color: var(--color-text-muted);
}
/* Explanatory caption: the relative text refreshes automatically over time. */
.relative-time-demo__hint {
margin: 0.75rem 0 0;
max-width: 32rem;
font-size: 0.85rem;
line-height: 1.5;
color: var(--color-text-muted);
}
このデモに固有の消費側 JS はありません(挙動はコントローラが担います)。
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。 共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--relative-time"
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
locale
|
Intl.RelativeTimeFormat のロケール。空なら要素の lang、次に文書の lang を使う。既定は空。 | data-stimeo--relative-time-locale-value |
threshold
|
これを超える秒数で元の絶対表記に戻す閾値。0 で無効(既定 0)。 | data-stimeo--relative-time-threshold-value |
tickInterval
|
最小の更新間隔(ミリ秒)。粗い単位ほど広がる(既定 60000)。 | data-stimeo--relative-time-tick-interval-value |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
テキスト |
ルート要素 | 相対表現(例「3分前」)。 |
datetime |
ルート要素 | 機械可読な絶対時刻(不変)。 |
data-state |
ルート要素 | "relative" / "absolute"(しきい値超過)。 |