メインコンテンツまでスキップ

Styling

tremolo-ui は CSS を配りません。 コンポーネントが受け持つのはマークアップの描画と、 値の管理と、ポインタ・キーボード・ホイールの処理までで、見た目は利用者のものです。 素の CSS でも CSS Modules でも Tailwind でも CSS-in-JS でも、アプリの他の部分で 使っているやり方をそのまま使えます。

🎨クラス名

すべての要素に tremolo- で始まるクラスが付いているので、自前のラッパーを 挟まなくても素の CSS で届きます。

.tremolo-knob-active-line {
color: rebeccapurple;
}

名前はコンポーネントとパートに対応します。tremolo-slidertremolo-slider-tracktremolo-slider-thumbtremolo-slider-marks のように。 すべては下のテーマに載っています。

🚦状態

状態はクラスを足す形ではなく、要素の属性として乗っています。セレクタ 1 つで届きます。

属性対象意味
[aria-disabled="true"]全コンポーネントdisabled が指定されている
[aria-readonly="true"]全コンポーネントreadonly が指定されている
[data-dragging="true"]Knob / PointsEditor.Pointドラッグ中
[data-vertical="true"]Slider / Slider.Track / Slider.MarksOption縦向きのスライダー
[data-active="true"]Piano の鍵盤その音が鳴っている
[data-out-of-range="true"]NumberInput.InputField値が min / max の外にある
.tremolo-slider[aria-disabled='true'] {
opacity: 0.5;
}

フォーカスを受けるのは実際の要素なので、:focus / :hover / :focus-within も どこでもと同じように使えます。

📋このサイトで使っているテーマ

ドキュメント中の例はすべて以下のファイルでスタイルを当てています。依存先ではなく 出発点なので、必要なものをプロジェクトにコピーして書き換えてください。

いずれもビルド不要の素の CSS で、カスタムプロパティ(--knob-size--thumb-size--active-color など)を使っているため、よくある変更は 1 行の上書きで済みます。

Knob.css
.tremolo-knob {
/* The knob has no intrinsic size: the SVG inside scales to its box.
Override with the `size` prop, or by setting this variable. */
--knob-size: 50px;

display: inline-block;
width: var(--knob-size);
height: var(--knob-size);
/* A knob is a fixed-size control, like a button. Without this a flex row
that runs short shrinks the width and leaves the height alone, so the box
stops being square and the knob sits in it with dead space below.
`aspect-ratio` is not the answer: it is ignored while both width and
height are definite, and dropping the height to free it up lets
`align-items: stretch` pull the box the other way. */
flex-shrink: 0;
cursor: grab;
outline: 0;

&[aria-readonly='true'] {
cursor: not-allowed;
}

&[data-dragging='true'] {
cursor: inherit;
}
}

.tremolo-knob-active-line {
color: oklch(69.2% 0.17548 266.373);

:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
color: oklch(59.5% 0.17548 266.373);
}

:where(.tremolo-knob[aria-disabled='true']) & {
color: oklch(50.5% 0.03307 270.021);
}
}

.tremolo-knob-inactive-line {
color: oklch(95% 0 0);

:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
color: oklch(90% 0 0);
}
}

.tremolo-knob-thumb {
color: oklch(85.7% 0 0);

:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
color: oklch(84.5% 0 0);
}
}

.tremolo-knob-thumb-line {
color: oklch(94.2% 0 0);
}

:where(.dark, [data-theme='dark']) {
.tremolo-knob-active-line {
color: oklch(59.5% 0.17548 266.373);

:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
color: oklch(65.2% 0.17548 266.373);
}
}

.tremolo-knob-inactive-line {
color: oklch(41.7% 0 0);

:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
color: oklch(44.59% 0 0);
}
}

.tremolo-knob-thumb {
color: oklch(48.6% 0 0);

:where(.tremolo-knob:focus, .tremolo-knob:hover) & {
color: oklch(51.7% 0 0);
}
}

.tremolo-knob-thumb-line {
color: oklch(84.2% 0 0);
}
}

🧩コンポーネント単位のスタイリング

スタイルをグローバルに置く必要はありません。同じノブを CSS Modules で書き、 クラスを対象のパートに渡す例です。

Loading...
import { useState } from 'react'

import { Knob } from '@tremolo-ui/react'

import myKnob from './my-knob.module.css'

function App() {
  const [value, setValue] = useState(64)

  return (
    <div className={myKnob.container}>
      <Knob.Root
        className={myKnob.knob}
        value={value}
        min={0}
        max={100}
        size={50}
        onChange={(v) => setValue(v)}
      >
        <Knob.SVGRoot>
          <Knob.ActiveLine className={myKnob.activeLine} />
          <Knob.InactiveLine />
          <Knob.Thumb />
        </Knob.SVGRoot>
      </Knob.Root>
      {value}
    </div>
  )
}

export default App

🧭次のステップ

tremolo-ui が提供するコンポーネントを見てみましょう。
Components - Knob