Knob
SVG で描く、操作できる回転ノブのコンポーネント。
Source Style- React
- Svelte
- Vue
Loading...
function App() { const [value, setValue] = useState(64) return ( <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', flexDirection: 'column', }} > <Knob.Root className={knobTheme.root} aria-label="Level" value={value} min={0} max={100} size={50} onChange={(v) => setValue(v)} > <Knob.SVGRoot> <Knob.ActiveLine className={knobTheme.activeLine} /> <Knob.InactiveLine className={knobTheme.inactiveLine} /> <Knob.Thumb className={knobTheme.thumb} classes={{ line: knobTheme.thumbLine }} /> </Knob.SVGRoot> </Knob.Root> {value} </div> ) }
/** The demo theme for `Knob`, as a CSS Module: one class per part, applied by* the caller. Copy this file into your project and edit it.** The knob draws itself as an SVG, so this is colour and cursor only.*/.root {/* 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 rowthat runs short shrinks the width and leaves the height alone, so the boxstops being square and the knob sits in it with dead space below.`aspect-ratio` is not the answer: it is ignored while both width andheight 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;&[data-readonly] {cursor: not-allowed;}&[data-dragging] {cursor: inherit;}}.activeLine {color: oklch(69.2% 0.17548 266.373);:where(.root:focus, .root:hover) & {color: oklch(59.5% 0.17548 266.373);}:where(.root[data-disabled]) & {color: oklch(50.5% 0.03307 270.021);}}.inactiveLine {color: oklch(95% 0 0);:where(.root:focus, .root:hover) & {color: oklch(90% 0 0);}}.thumb {color: oklch(85.7% 0 0);:where(.root:focus, .root:hover) & {color: oklch(84.5% 0 0);}}.thumbLine {color: oklch(94.2% 0 0);}/** Dark mode follows whatever marks the page — `.dark` and `[data-theme=dark]`* are what this site and Storybook set.*/:global(.dark) .activeLine,:global([data-theme='dark']) .activeLine {color: oklch(59.5% 0.17548 266.373);:where(.root:focus, .root:hover) & {color: oklch(65.2% 0.17548 266.373);}}:global(.dark) .inactiveLine,:global([data-theme='dark']) .inactiveLine {color: oklch(41.7% 0 0);:where(.root:focus, .root:hover) & {color: oklch(44.59% 0 0);}}:global(.dark) .thumb,:global([data-theme='dark']) .thumb {color: oklch(48.6% 0 0);:where(.root:focus, .root:hover) & {color: oklch(51.7% 0 0);}}:global(.dark) .thumbLine,:global([data-theme='dark']) .thumbLine {color: oklch(84.2% 0 0);}
App.svelte
<script lang="ts">
import { Knob } from '@tremolo-ui/svelte'
// Copy this file from the Styling page into your own project.
import knobTheme from './Knob.module.css'
let value = $state(64)
</script>
<Knob.Root
class={knobTheme.root}
aria-label="Level"
bind:value
min={0}
max={100}
size={50}
>
<Knob.SVGRoot>
<Knob.ActiveLine class={knobTheme.activeLine} />
<Knob.InactiveLine class={knobTheme.inactiveLine} />
<Knob.Thumb
class={knobTheme.thumb}
classes={{ line: knobTheme.thumbLine }}
/>
</Knob.SVGRoot>
</Knob.Root>
{value}
App.vue
<script setup lang="ts">
import { ref } from 'vue'
import {
Knob,
KnobActiveLine,
KnobInactiveLine,
KnobSVGRoot,
KnobThumb,
} from '@tremolo-ui/vue'
// Copy this file from the Styling page into your own project.
import knobTheme from './Knob.module.css'
const value = ref(64)
</script>
<template>
<Knob
v-model="value"
:class="knobTheme.root"
aria-label="Level"
:min="0"
:max="100"
:size="50"
>
<KnobSVGRoot>
<KnobActiveLine :class="knobTheme.activeLine" />
<KnobInactiveLine :class="knobTheme.inactiveLine" />
<KnobThumb
:class="knobTheme.thumb"
:classes="{ line: knobTheme.thumbLine }"
/>
</KnobSVGRoot>
</Knob>
{{ value }}
</template>
インポート
- React
- Svelte
- Vue
import { Knob } from '@tremolo-ui/react'
import { Knob } from '@tremolo-ui/svelte'
import {
Knob,
KnobActiveLine,
KnobInactiveLine,
KnobSVGRoot,
KnobThumb,
} from '@tremolo-ui/vue'
API リファレンス
各パートには、そのパート独自の props を載せています。これに加えて、描画する要素の属性(className や style など)も受け取ります。
Svelte / Vue でも props は同じで、書き方だけがそれぞれの流儀になります(className ではなく class、bind:value や v-model、中身は snippet やスロットなど)。Svelte と Vue を参照してください。
状態は data 属性として要素に乗っているので、セレクタ 1 つで届きます(スタイリングを参照)。属性はその状態が on の間だけ付きます。
Root
値を持ち、ドラッグ・ホイール・矢印キーを処理します。これ自体がコントロールで、フォーカスを受け取り ARIA を持ちます。
| Prop | 型 | 既定値 |
|---|---|---|
value* | number | — |
min* | number | — |
max* | number | — |
step | number | 1 |
scale | Scale | linearScale |
resetValue | number | null | startValue |
startValue | number | min |
size | string | number | — |
dragCursor | Cursor | 'grabbing' |
wheel | ModifierValue<InputEventOption> | null | ['raw', 1] |
dragSensitivity | ModifierValue<number> | { default: 1, shift: 0.1 } |
pointerLock | boolean | false |
keyboard | ModifierValue<InputEventOption> | null | { default: ['raw', 1], shift: ['raw', 0.1] } |
disabled | boolean | — |
readOnly | boolean | — |
angleRange | number | 270 |
onChange | (value: number) => void | — |
onChangeStart | (value: number, source: ChangeSource) => void | — |
onChangeEnd | (value: number, source: ChangeSource) => void | — |
changeEndDelay | number | 500 |
children* | ReactNode | — |
actionsRef | Ref<KnobMethods> | — |
すべての説明: KnobProps
| カスタムプロパティ | 書き込む prop | 決めるもの |
|---|---|---|
--knob-size | size | ノブの幅と高さ。 |
| Data 属性 | 値 |
|---|---|
[data-disabled] | disabled のときに付きます |
[data-readonly] | readonly のときに付きます |
[data-dragging] | ドラッグしている間に付きます |
SVGRoot
描画用のパートを入れる <svg>。パートが描く基準になる viewBox を設定します。
| Prop | 型 | 既定値 |
|---|---|---|
children* | ReactNode | — |
すべての説明: KnobSVGRootProps
InactiveLine
値の外側の円弧。独自の props は無く、SVG の <path> の属性を受け取ります。円弧は、渡した strokeWidth の分だけ内側に描かれ、viewBox に収まります。
ActiveLine
startValue と値の間の円弧。Knob.InactiveLine と同じく、SVG の <path> の属性を受け取ります。
Thumb
値に合わせて回る円と、その上で値を指す線。
| Prop | 型 | 既定値 |
|---|---|---|
color | string | 'currentColor' |
lineColor | string | 'currentColor' |
size | number | 84 |
lineWeight | number | 6 |
lineLength | number | 35 |
classes | { line?: string } | — |
すべての説明: KnobThumbProps