パスワード強度メーター
stimeo--password-strength
パスワードの強さを目安として示します。メーターと文言の両方で伝えます。
入力中のパスワードの強さを見積もり、メーターと文言の両方で示します。判定は長さと文字の種類の多さを見る簡単なもので、辞書と突き合わせる本格的なものではありません。目安として扱ってください。より正確に測りたいときは、自分で計算した点数を渡せます。メーターの値と文言はその場で変わりますが、読み上げは打ち終わってから、しかも強さの段階が変わったときだけ届きます。打っている最中に読み上げが割り込みません。色だけでなく文言でも伝えるので、色が分かりにくい人にも届きます。
入力すると強さが変わります。判定は長さと文字の種類による簡単なもので、辞書との突き合わせではありません。目安として見てください。読み上げは打ち終わってから、段階が変わったときだけ届きます。
キーボード操作
このコンポーネント自体はキーボード操作を持ちません。
<%# Markup for the password-strength demo.
The controller scores the field with a lightweight zero-dependency heuristic and
drives the meter (aria-valuenow), the data-strength token, the 0–1 fill on the
--stimeo--password-strength custom property, and the visible readout — all on the
keystroke that caused them. The input sits inside the controller so its data-action
input->...#evaluate binds directly. Level labels are localized via the levels value;
demo.css colors the bar by the locale-independent data-strength band, so the look
never depends on the (translated) label text.
The readout is plain visible output, not a live region: the settled level is
debounced into the shared stimeo--announcer your app seats once, in its layout.
Announcing is opt-in through announce-text-value and only fires when the level
actually changes. The library writes no CSS. %>
<% levels = t("components.password_strength.demo.levels").to_json %>
<% announcement = t("components.password_strength.demo.announcement") %>
<div
class="password-strength"
data-controller="stimeo--password-strength"
data-stimeo--password-strength-levels-value="<%= levels %>"
data-stimeo--password-strength-announce-text-value="<%= announcement %>">
<label class="password-strength__label" for="password-strength-demo-input">
<%= t("components.password_strength.demo.label") %>
</label>
<input
class="password-strength__input"
id="password-strength-demo-input"
type="password"
autocomplete="new-password"
aria-describedby="password-strength-demo-readout"
data-stimeo--password-strength-target="input"
data-action="input->stimeo--password-strength#evaluate">
<div
class="password-strength__meter"
role="meter"
aria-valuemin="0"
aria-valuemax="4"
aria-valuenow="0"
aria-label="<%= t('components.password_strength.demo.meter_label') %>"
data-stimeo--password-strength-target="meter">
<span class="password-strength__bar"></span>
</div>
<span
class="password-strength__readout"
id="password-strength-demo-readout"
data-stimeo--password-strength-target="label"></span>
</div>
<p class="password-strength__hint"><%= t("components.password_strength.demo.hint") %></p>
/*
* Presentation-only styles for the password-strength demo.
* The bar width comes from --stimeo--password-strength (0–1); its color comes from
* the data-strength band (weak…strong), which is locale-independent — so the look
* holds even though the visible level label is localized via the levels value.
*/
.password-strength {
display: flex;
flex-direction: column;
gap: 0.5rem;
max-width: 24rem;
}
.password-strength__label {
font-weight: 600;
}
.password-strength__input {
padding: 0.5rem 0.75rem;
border: 1px solid var(--border-strong);
border-radius: 0.375rem;
background: var(--bg);
font: inherit;
color: var(--fg);
}
.password-strength__input:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 1px;
}
.password-strength__meter {
height: 0.5rem;
border-radius: 0.375rem;
background: var(--surface-subtle);
overflow: hidden;
}
.password-strength__bar {
display: block;
height: 100%;
border-radius: inherit;
width: calc(var(--stimeo--password-strength, 0) * 100%);
background: var(--border-interactive);
transition:
width 0.2s ease,
background-color 0.2s ease;
}
/* Color bands keyed on the locale-independent data-strength token (weak → strong). */
.password-strength[data-strength="weak"] .password-strength__bar {
background: var(--danger-500);
}
.password-strength[data-strength="fair"] .password-strength__bar {
background: var(--amber-500);
}
.password-strength[data-strength="good"] .password-strength__bar {
background: var(--amber-500);
}
.password-strength[data-strength="strong"] .password-strength__bar {
background: var(--leaf-500);
}
.password-strength__readout {
min-height: 1.25rem;
font-size: 0.85rem;
color: var(--muted);
}
.password-strength__hint {
margin: 0.25rem 0 0;
max-width: 32rem;
font-size: 0.85rem;
line-height: 1.5;
color: var(--muted);
}
@media (prefers-reduced-motion: reduce) {
.password-strength__bar {
transition: none;
}
}
このデモに固有の消費側 JS はありません(挙動はコントローラが担います)。
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--password-strength"
ターゲット
| 名前 | 説明 | 属性 |
|---|---|---|
input
必須
|
強度を算定する対象のパスワード入力。 | data-stimeo--password-strength-target="input" |
meter
必須
|
aria-valuenow がレベルを反映するメーター要素。 | data-stimeo--password-strength-target="meter" |
label
|
レベルのラベルを書き込む可視の読み出し。ライブリージョンではない。 | data-stimeo--password-strength-target="label" |
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
minScore
|
これ未満を不合格扱いとするスコア。data-below-min フックと change の meetsMin=false で通知。0(既定)はゲート無効。 |
data-stimeo--password-strength-min-score-value |
levels
|
昇順の表示ラベル(label と change の level に入る)。要素数が段階数を決める。2 件未満の宣言は既定スケールへ落ちる。翻訳可。data-strength は別系統の固定バンド(既定 weak, fair, good, strong)。 |
data-stimeo--password-strength-levels-value |
announceText
|
読み上げ文言のテンプレート。{level}・{score}・{max}・{band} を差し込める。未指定なら告知しない。 |
data-stimeo--password-strength-announce-text-value |
アクション
| 名前 | 説明 | アクション |
|---|---|---|
evaluate
|
入力を再採点する。入力欄の input イベントにバインドする。 |
stimeo--password-strength#evaluate |
setScore
|
自分で算出したスコア(アクションパラメータ score または detail.score)を宣言済みスケールへ収めて採用する。次の evaluate で内蔵の採点へ戻る。 |
stimeo--password-strength#setScore |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
change
|
evaluate または setScore のたびに発火。detail.score・detail.level・detail.max・detail.meetsMin を伴う。 |
stimeo--password-strength:change |
reconcile
|
実行時の Value・target 変更を再調停したあと、上記の導出状態が実際に動いたときだけ 1 回発火する。 | stimeo--password-strength:reconcile |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
aria-valuenow |
meter ターゲット | 強度レベル(0 = 空 … レベルの数)。 |
data-strength |
ルート要素 | ロケール非依存の固定バンド(weak / fair / good / strong)。levels を翻訳しても不変で CSS フックに使える。空のときは付かない。両端は固定され、最弱スコアは必ず weak、最強スコアは必ず strong になる。 |
data-below-min |
ルート要素 | 非空かつ score が minScore 未満のとき付与(既定 minScore=0 では付かない)。 |
--stimeo--password-strength |
ルート要素 | 利用側 CSS がバー幅に変換する 0–1 の塗り。 |