Stimeo UI が提供するのは振る舞いであって CSS ではありません。見た目を作るときに繰り返し出てくる話が 2 つあるので、先にお伝えします。部品がどうやって出し隠しするか、そして状態で変わる文言をどこに置くか、です。
部品は hidden で出し隠しします
部品は、あなたが宣言した領域を出したり隠したりします。絞り込みで外れた候補、「該当なし」の行、いまの状態に属さない方のラベルなどです。これに使うのは hidden 属性です。出し隠しは見た目ではなく振る舞いだから、というのが理由です。
hidden が display: none を得るのはブラウザ自身のスタイルシートからで、これは最も弱い出どころです。display を指定したあなたの規則があれば、そちらが勝ちます。結果として、隠したはずの要素が画面に残ります。
これはユーティリティ優先のフレームワークで起こりやすい問題です。Tailwind v4 はレイヤの順序を theme, base, components, utilities と宣言し、DaisyUI は .menu li や .tabs、.steps といったコンポーネントのクラスを最後のレイヤに置きます。その中にある要素は hidden を付けても見えたままになります。さらに厄介なことに、@layer components に display: none を足しても、前のレイヤにいるので負けます。
打ち消しはどのレイヤにも属さない場所に書いてください。レイヤの外の規則はどのレイヤよりも強いので、!important は要りません。
/* @layer の中に書かないこと。それが要点です。 */
.menu li[hidden],
.menu [role="option"][hidden] {
display: none;
}
出会いやすいのは combobox、listbox、multi-select、empty-state、filter、command-palette です。隠される対象が候補や空の行だからです。
状態で変わる文言はマークアップに置いてください
状態でラベルが入れ替わるとき、文言を CSS に書きたくなります。
/* おすすめしません。 */
.play::after { content: "自動送り:OFF"; }
.play[aria-pressed="true"]::after { content: "自動送り:ON"; }
これは 2 つの意味で困ります。content の中の文字列は辞書を通らないので、いつまでも 1 つの言語のままです。そして未翻訳の文言を探す方法は普通、描画された HTML を走査することなので、この文字列はそもそも引っかかりません。チェックは問題なしと出るのに、画面は間違ったまま残ります。
content: attr(aria-valuetext) も逆側から同じ問題を抱えます。その属性は部品が実行時に、部品の既定の言語で組み立てるものだからです。
文言はマークアップに置いて、どちらを出すかは部品に任せてください。ラベルを入れ替える部品は、2 つの側を target として受け取ります。
<button data-stimeo--read-more-target="trigger" aria-expanded="false">
<span data-stimeo--read-more-target="collapsedLabel">続きを読む</span>
<span data-stimeo--read-more-target="expandedLabel" hidden>閉じる</span>
</button>
いまの状態に属さない側へ部品が hidden を書くので、あなたの CSS ですることはありません。上の例のように、初期状態の側には hidden を自分で書いておいてください。部品が繋がる前に一瞬見えてしまうのを防ぐためで、書き忘れても部品が接続時に直します。
トグルボタン(aria-pressed)では、アクセシブルな名前を両方の状態で同じに保ってください。それがこのパターンの作法です。ラベルの組は、入れ替わるアイコンや記号に使います。
部品が読み上げる値については、CSS で組み立てるのではなく文言を渡してください。color-picker は data-value-text を、読み上げを行う部品は announce-*-text を受け取ります。