지정된 범위에서 하나 또는 두 개의 값을 선택하는 슬라이더 컴포넌트입니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
export default function Example () {
return (
< view className = "slider-preview" >
< Slider min = { 0 } max = { 100 } defaultValues = {[ 50 ]} getAccessibilityLabel = {() => "값" } />
</ view >
);
}
npx @seed-design/cli@latest add ui:slider pnpm dlx @seed-design/cli@latest add ui:slider yarn dlx @seed-design/cli@latest add ui:slider bun x @seed-design/cli@latest add ui:slider
의존성 설치
npm install @seed-design/lynx-react yarn add @seed-design/lynx-react pnpm add @seed-design/lynx-react bun add @seed-design/lynx-react 아래 코드를 복사 후 붙여넣고 사용하세요 /**
* @file ui:slider
* @requires @seed-design/lynx-react@^1.0.0
* @requires @seed-design/lynx-css@^1.0.0
**/
import * as React from "@lynx-js/react" ;
import { Field as SeedField, Slider as SeedSlider } from "@seed-design/lynx-react" ;
type SliderRootRef = React . ComponentRef < typeof SeedSlider.Root>;
type FieldRootRef = React . ComponentRef < typeof SeedField.Root>;
export interface SliderProps extends Omit < SeedSlider . RootProps , "children" > {
label ?: React . ReactNode ;
/**
* @default " medium "
*/
labelWeight ?: SeedField . LabelProps [ "weight" ];
indicator ?: React . ReactNode ;
description ?: React . ReactNode ;
errorMessage ?: React . ReactNode ;
showRequiredIndicator ?: boolean ;
required ?: SeedField . RootProps [ "required" ];
/**
* @default []
*/
markers ?:
| Array <
| {
value : number ;
label ?: React . ReactNode ;
align ?: SeedSlider . MarkerProps [ "align" ];
}
| number
>
| undefined ;
/**
* @default []
*/
ticks ?: number [];
/**
* @default " thin "
*/
tickWeight ?: SeedSlider . TickProps [ "weight" ];
/**
* @default false
*/
hideRange ?: boolean ;
/**
* @default false
*/
hideValueIndicator ?: boolean ;
fieldRef ?: React . Ref < FieldRootRef >;
}
/**
* @see https://seed-design.io/lynx/components/slider
*/
export const Slider = React. forwardRef < SliderRootRef , SliderProps >(
(
{
label,
labelWeight,
indicator,
description,
errorMessage,
showRequiredIndicator,
required,
min = 0 ,
max = 100 ,
markers = [],
ticks = [],
tickWeight,
hideRange = false ,
hideValueIndicator = false ,
fieldRef,
disabled,
invalid,
readOnly,
values,
defaultValues,
getAccessibilityLabel,
... rootProps
},
ref,
) => {
const renderHeader = label != null || indicator != null ;
const renderErrorMessage = invalid === true && errorMessage != null ;
const renderDescription = description != null && ! renderErrorMessage;
const renderFooter = renderDescription || renderErrorMessage;
const thumbCount = Math. max (values?. length ?? defaultValues?. length ?? 1 , 1 );
const defaultAccessibilityLabel = typeof label === "string" ? () => label : undefined ;
if (
process.env. NODE_ENV !== "production" &&
! getAccessibilityLabel &&
! defaultAccessibilityLabel
) {
console. warn (
"Slider: Provide a string `label` or `getAccessibilityLabel` so every thumb has an accessible name." ,
);
}
return (
< SeedField.Root
ref = {fieldRef}
required = {required}
disabled = {disabled}
invalid = {invalid}
readOnly = {readOnly}
>
{renderHeader ? (
< SeedField.Header >
< SeedField.Label weight = {labelWeight}>
{label}
{showRequiredIndicator ? < SeedField.RequiredIndicator /> : null }
{indicator != null ? (
< SeedField.IndicatorText >{indicator}</ SeedField.IndicatorText >
) : null }
</ SeedField.Label >
</ SeedField.Header >
) : null }
< SeedSlider.Root
ref = {ref}
min = {min}
max = {max}
values = {values}
defaultValues = {defaultValues}
disabled = {disabled}
invalid = {invalid}
readOnly = {readOnly}
getAccessibilityLabel = {getAccessibilityLabel ?? defaultAccessibilityLabel}
{ ... rootProps}
>
< SeedSlider.Control >
< SeedSlider.Track >
{ ! hideRange ? < SeedSlider.Range /> : null }
{ticks. map (( value ) => (
< SeedSlider.Tick key = {value} value = {value} weight = {tickWeight} />
))}
</ SeedSlider.Track >
{Array. from ({ length: thumbCount }, ( _ , index ) => (
< React.Fragment key = {index}>
{ ! hideValueIndicator ? (
< SeedSlider.ValueIndicatorRoot thumbIndex = {index}>
< SeedSlider.ValueIndicatorArrow >
< SeedSlider.ValueIndicatorArrowTip />
</ SeedSlider.ValueIndicatorArrow >
< SeedSlider.ValueIndicatorLabel thumbIndex = {index} />
</ SeedSlider.ValueIndicatorRoot >
) : null }
< SeedSlider.Thumb thumbIndex = {index} />
</ React.Fragment >
))}
</ SeedSlider.Control >
{markers. length > 0 ? (
< SeedSlider.Markers >
{markers. map (( marker ) =>
typeof marker === "number" ? (
< SeedSlider.Marker
key = {marker}
value = {marker}
align = {marker === min ? "start" : marker === max ? "end" : "center" }
>
{marker}
</ SeedSlider.Marker >
) : (
< SeedSlider.Marker
key = {marker.value}
value = {marker.value}
align = {
marker.align ??
(marker.value === min ? "start" : marker.value === max ? "end" : "center" )
}
>
{marker.label ?? marker.value}
</ SeedSlider.Marker >
),
)}
</ SeedSlider.Markers >
) : null }
</ SeedSlider.Root >
{renderFooter ? (
< SeedField.Footer >
{renderDescription ? (
< SeedField.Description >{description}</ SeedField.Description >
) : null }
{renderErrorMessage ? (
< SeedField.ErrorMessage >{errorMessage}</ SeedField.ErrorMessage >
) : null }
</ SeedField.Footer >
) : null }
</ SeedField.Root >
);
},
);
Slider.displayName = "Slider" ;
/**
* This file is a snippet from SEED Design, helping you get started quickly with @seed-design/* packages.
* You can extend this snippet however you want.
*/
Registry의 Slider는 Field 안내를 포함한 편의 컴포넌트입니다. 한 개의 값을 선택할 때는 defaultValues 또는 values에 한 값을, 범위를 선택할 때는 두 값을 전달합니다.
label?React.ReactNode
indicator?React.ReactNode
description?React.ReactNode
errorMessage?React.ReactNode
showRequiredIndicator?boolean | undefined
required?boolean | undefined
fieldRef?React.Ref < NodesRef > | undefined
getAccessibilityValueText?(( value : number , thumbIndex : number ) => string) | undefined
allowedValues를 지정하면 해당 값만 선택할 수 있으며 step과 minStepsBetweenThumbs보다 우선합니다. values와 onValuesChange를 함께 사용하면 값을 외부 상태로 제어할 수 있고, onValuesCommit은 값이 확정될 때 호출됩니다.
touch 좌표는 Slider의 전체 가로 범위를 기준으로 값으로 변환됩니다. Slider에 좌우 padding을 주거나 track 폭을 Slider와 다르게 설정하지 마세요.
min과 max로 선택 범위를 정하고 하나의 thumb으로 값을 선택합니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
export default function Example () {
return (
< view className = "slider-basic" >
< Slider min = { 0 } max = { 10 } defaultValues = {[ 5 ]} getAccessibilityLabel = {() => "값" } />
< Slider min = { 0 } max = { 1000 } defaultValues = {[ 600 ]} getAccessibilityLabel = {() => "값" } />
</ view >
);
}
step으로 선택 간격을 설정해 일정한 단위의 값만 선택합니다.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { Slider } from "@/components/ui/slider" ;
export default function Example () {
const [ value , setValue ] = useState ([ 50 ]);
function handleValuesChange ( nextValues : number []) {
"background only" ;
setValue (nextValues);
}
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 100 }
step = { 10 }
values = {value}
onValuesChange = {handleValuesChange}
getAccessibilityLabel = {() => "값" }
/>
< text className = "slider-preview__status" >{ JSON . stringify (value)}</ text >
</ view >
);
}
allowedValues로 선택 가능한 값을 명시합니다. 이 prop을 지정하면 step과 minStepsBetweenThumbs보다 allowedValues가 우선합니다.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { Slider } from "@/components/ui/slider" ;
const ALLOWED_VALUES = [ 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 ];
export default function Example () {
const [ values , setValues ] = useState ([ ALLOWED_VALUES [ 0 ], ALLOWED_VALUES [ 2 ]]);
function handleValuesChange ( nextValues : number []) {
"background only" ;
setValues (nextValues);
}
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 30 }
values = {values}
onValuesChange = {handleValuesChange}
allowedValues = { ALLOWED_VALUES }
markers = { ALLOWED_VALUES . map (( value ) => ({ label: value, value }))}
getAccessibilityLabel = {() => "값" }
/>
< text className = "slider-preview__status" >{ JSON . stringify (values)}</ text >
</ view >
);
}
track 위에 선택 단위를 나타내는 눈금을 표시할 수 있습니다.
연속적인 조작처럼 보이도록 작은 간격을 사용하고 얇은 눈금을 표시합니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
export default function Example () {
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 100 }
step = { 0.1 }
defaultValues = {[ 50 ]}
ticks = {[ 10 , 20 , 30 , 40 , 50 , 60 , 70 , 80 , 90 ]}
tickWeight = "thin"
getAccessibilityLabel = {() => "값" }
/>
</ view >
);
}
값의 단계가 크거나 눈금 위치에서만 선택할 수 있는 경우 굵은 눈금을 표시합니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
export default function Example () {
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 100 }
step = { 10 }
defaultValues = {[ 50 ]}
ticks = {[ 10 , 20 , 30 , 40 , 50 , 60 , 70 , 80 , 90 ]}
tickWeight = "thick"
getAccessibilityLabel = {() => "값" }
/>
</ view >
);
}
slider 아래에 주요 값을 설명하는 marker를 표시합니다. marker의 시각적 텍스트는 native accessibility 값에 자동으로 포함되지 않으므로, 필요한 의미는 getAccessibilityValueText로도 전달하세요.
markers에는 숫자 또는 { value, label?, align? } 객체를 전달할 수 있습니다. 객체에서 align을 생략하면 최소값은 시작, 최대값은 끝, 나머지는 가운데에 배치됩니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
export default function Example () {
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 100 }
defaultValues = {[ 50 ]}
markers = {[
{ value: 0 , label: "0°C" },
{ value: 25 , label: "25°C" },
{ value: 50 , label: "50°C" },
{ value: 75 , label: "75°C" },
{ value: 100 , label: "100°C" },
]}
getAccessibilityValueText = {( value ) => `${ value }°C` }
getValueIndicatorLabel = {({ value }) => `${ value }°C` }
getAccessibilityLabel = {() => "온도" }
/>
< Slider
min = { 0 }
max = { 100 }
defaultValues = {[ 30 ]}
markers = {[ 0 , 20 , 40 , 60 , 80 , 100 ]}
getAccessibilityLabel = {() => "값" }
/>
</ view >
);
}
values와 onValuesChange를 사용하여 슬라이더의 값을 앱 상태로 제어합니다.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { Slider } from "@/components/ui/slider" ;
const DEFAULT_VALUE = [ 50 ];
export default function Example () {
const [ value , setValue ] = useState ( DEFAULT_VALUE );
function handleValuesChange ( nextValues : number []) {
"background only" ;
setValue (nextValues);
}
function handleSetMin () {
"background only" ;
setValue ([ 0 ]);
}
function handleReset () {
"background only" ;
setValue ( DEFAULT_VALUE );
}
function handleSetMax () {
"background only" ;
setValue ([ 100 ]);
}
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 100 }
values = {value}
onValuesChange = {handleValuesChange}
getAccessibilityLabel = {() => "값" }
/>
< text className = "slider-preview__status" >{ JSON . stringify (value)}</ text >
< view className = "slider-preview__actions" >
< view
className = "slider-preview__button"
bindtap = {handleSetMin}
accessibility-label = "Set Min"
>
< text >Set Min</ text >
</ view >
< view className = "slider-preview__button" bindtap = {handleReset} accessibility-label = "Reset" >
< text >Reset</ text >
</ view >
< view
className = "slider-preview__button"
bindtap = {handleSetMax}
accessibility-label = "Set Max"
>
< text >Set Max</ text >
</ view >
</ view >
</ view >
);
}
onValuesChange: 드래그 중 값이 바뀔 때마다 호출됩니다. 화면에 현재 값을 표시하거나 앱 상태를 실시간으로 갱신할 때 사용합니다.
onValuesCommit: 값 변경이 끝났을 때 호출됩니다. Lynx native에서는 값이 변경된 drag의 touch release에서 한 번 호출됩니다. 이 callback에 debounce를 추가할 필요는 없습니다.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { Slider } from "@/components/ui/slider" ;
export default function Example () {
const [ value , setValue ] = useState ([ 20 ]);
const [ committedValue , setCommittedValue ] = useState ([ 20 ]);
function handleValuesChange ( nextValues : number []) {
"background only" ;
setValue (nextValues);
}
function handleValuesCommit ( nextValues : number []) {
"background only" ;
setCommittedValue (nextValues);
}
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 100 }
values = {value}
onValuesChange = {handleValuesChange}
onValuesCommit = {handleValuesCommit}
getAccessibilityLabel = {() => "값" }
/>
< view className = "slider-preview__status" >
< text >Current value: { JSON . stringify (value)}</ text >
< text >Committed value: { JSON . stringify (committedValue)}</ text >
</ view >
</ view >
);
}
disabled를 사용하면 thumb을 조작할 수 없고 비활성 상태 스타일을 표시합니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
export default function SliderDisabled () {
return (
< view className = "slider-preview" >
< Slider min = { 0 } max = { 100 } defaultValues = {[ 50 ]} disabled getAccessibilityLabel = {() => "값" } />
< Slider
min = { 0 }
max = { 100 }
defaultValues = {[ 25 , 75 ]}
disabled
getAccessibilityLabel = {( thumbIndex ) => (thumbIndex === 0 ? "최소값" : "최대값" )}
/>
</ view >
);
}
hideRange로 활성 구간 색상을 숨기고 track만 표시합니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
export default function SliderHideRange () {
return (
< view className = "slider-preview" >
< Slider min = { 0 } max = { 100 } defaultValues = {[ 60 ]} hideRange getAccessibilityLabel = {() => "값" } />
< Slider
min = { 0 }
max = { 100 }
defaultValues = {[ 20 , 80 ]}
hideRange
getAccessibilityLabel = {( thumbIndex ) => (thumbIndex === 0 ? "최소값" : "최대값" )}
/>
</ view >
);
}
getValueIndicatorLabel로 thumb을 조작할 때 표시되는 Value Indicator의 텍스트를 바꿀 수 있습니다.
Value Indicator는 native touch 조작 중에 표시되는 보조 UI이며, 접근성 탐색이 읽는 값은 아닙니다. 의미 있는 단위나 설명을 제공해야 한다면 getAccessibilityValueText도 함께 사용하세요.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
// Lynx JS 런타임에는 `Intl`이 없으므로 천 단위 구분 기호를 직접 넣습니다.
function formatNumber ( value : number ) {
return String (value). replace ( / \B (?=( \d {3} ) + (?! \d )) / g , "," );
}
export default function SliderCustomValueIndicatorLabel () {
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 1_000_000 }
defaultValues = {[ 20_000 , 500_000 ]}
getValueIndicatorLabel = {({ value , thumbIndex }) => (
< text >{ `thumb ${ thumbIndex } \n ${ formatNumber ( value ) }` }</ text >
)}
getAccessibilityValueText = {formatNumber}
getAccessibilityLabel = {() => "값" }
/>
</ view >
);
}
valueIndicatorTrigger로 Value Indicator가 표시되는 조건을 정합니다. Lynx에서는 "auto"와 "active"를 사용할 수 있습니다.
"active": 현재 touch로 조작하는 thumb에 표시합니다.
"auto" (기본값): native touch 환경에서는 "active"와 동일하게 동작합니다.
웹의 hover 기반 표시 조건이나 키보드 포커스 기반 동작은 Lynx native에 대응하지 않습니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
export default function SliderValueIndicatorTrigger () {
return (
< view className = "slider-preview" >
< Slider
label = "auto (default)"
min = { 0 }
max = { 100 }
defaultValues = {[ 50 ]}
valueIndicatorTrigger = "auto"
getAccessibilityLabel = {() => "값" }
/>
< Slider
label = "active"
min = { 0 }
max = { 100 }
defaultValues = {[ 50 ]}
valueIndicatorTrigger = "active"
getAccessibilityLabel = {() => "값" }
/>
< text className = "slider-preview__status" >
auto와 active 모두 터치로 활성화된 동안에만 값 표시
</ text >
</ view >
);
}
hideValueIndicator로 thumb 위의 Value Indicator를 숨깁니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
export default function SliderHideValueIndicator () {
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 100 }
defaultValues = {[ 50 ]}
hideValueIndicator
getAccessibilityLabel = {() => "값" }
/>
</ view >
);
}
defaultValues 또는 values에 두 값을 전달하여 두 thumb 사이의 범위를 선택합니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
import { useState } from "@lynx-js/react" ;
export default function Example () {
const [ priceRange , setPriceRange ] = useState ([ 20 , 80 ]);
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 100 }
values = {priceRange}
onValuesChange = {setPriceRange}
getAccessibilityLabel = {( thumbIndex ) => (thumbIndex === 0 ? "최소값" : "최대값" )}
/>
</ view >
);
}
minStepsBetweenThumbs로 두 thumb 사이에 유지할 최소 간격을 지정합니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
import { useState } from "@lynx-js/react" ;
export default function Example () {
const [ values , setValues ] = useState ([ 20 , 80 ]);
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 100 }
values = {values}
onValuesChange = {setValues}
step = { 5 }
minStepsBetweenThumbs = { 6 }
getAccessibilityLabel = {( thumbIndex ) => (thumbIndex === 0 ? "최소값" : "최대값" )}
/>
< text >{ JSON . stringify (values)}</ text >
</ view >
);
}
native accessibility 탐색은 기본적으로 각 thumb에 minimum <min>, maximum <max>, current <value> 형식의 값을 제공합니다. 숫자만으로 의미가 충분하지 않다면 getAccessibilityValueText로 단위나 값의 의미를 포함한 설명을 제공하세요.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { Slider } from "@/components/ui/slider" ;
const days = [ "일" , "월" , "화" , "수" , "목" , "금" , "토" ];
function getHumanReadableDayOfWeek ( value : number ) {
if (days[value] === undefined ) throw new Error ( "Invalid day value" );
return `${ days [ value ] }요일` ;
}
export default function Example () {
const [ values , setValues ] = useState ([ 1 , 3 ]);
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = {days. length - 1 }
minStepsBetweenThumbs = { 1 }
markers = {days. map (( label , value ) => ({ label, value }))}
ticks = {days. slice ( 1 , - 1 ). map (( _ , index ) => index + 1 )}
tickWeight = "thick"
values = {values}
onValuesChange = {setValues}
getAccessibilityLabel = {( thumbIndex ) => (thumbIndex === 0 ? "시작" : "종료" )}
getAccessibilityValueText = {getHumanReadableDayOfWeek}
getValueIndicatorLabel = {({ value }) => getHumanReadableDayOfWeek (value)}
/>
< text className = "slider-preview__status" >values: { JSON . stringify (values)}</ text >
< text className = "slider-preview__status" >
accessibility-value-text: { JSON . stringify (values. map (getHumanReadableDayOfWeek))}
</ text >
</ view >
);
}
getAccessibilityLabel로 각 thumb의 용도를 설명합니다. 특히 range slider에서는 각 thumb이 최소값·최대값 중 어떤 역할인지 구분할 수 있는 label을 제공하세요.
import "./styles" ;
import { useState } from "@lynx-js/react" ;
import { Slider } from "@/components/ui/slider" ;
const getAccessibilityLabel = ( thumbIndex : number ) => (thumbIndex === 0 ? "최소값" : "최대값" );
export default function Example () {
const [ values , setValues ] = useState ([ 10 , 30 ]);
return (
< view className = "slider-preview" >
< Slider
min = { 0 }
max = { 100 }
values = {values}
onValuesChange = {setValues}
getAccessibilityLabel = {getAccessibilityLabel}
/>
< text className = "slider-preview__status" >values: { JSON . stringify (values)}</ text >
< text className = "slider-preview__status" >
accessibility-label:{ " " }
{ JSON . stringify (values. map (( _ , index ) => getAccessibilityLabel (index)))}
</ text >
</ view >
);
}
label, labelWeight, indicator, description, errorMessage, showRequiredIndicator를 사용해 슬라이더 주변에 Field 안내를 표시할 수 있습니다. invalid가 true이고 errorMessage가 있으면 오류 안내를 표시합니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
const markers = [
{ value: 0 , label: "매우 동의하지 않음" },
{ value: 14 , label: "매우 동의함" },
];
export default function Example () {
return (
< view className = "slider-preview" >
< Slider
label = "내일 날씨가 좋을 것 같다고 생각한다."
min = { 0 }
max = { 14 }
defaultValues = {[ 7 ]}
ticks = {[ 2 , 4 , 6 , 8 , 10 , 12 ]}
markers = {markers}
hideRange
description = "내일 날씨에 대한 당신의 기대감을 0~14 사이 숫자로 나타내 주세요."
getAccessibilityValueText = {( value ) =>
`${ value } ${ markers . find (( marker ) => marker . value === value )?. label ?? ""}` . trim ()
}
/>
< Slider
label = "Invalid Slider"
labelWeight = "bold"
min = { 0 }
max = { 1000 }
defaultValues = {[ 500 ]}
invalid
errorMessage = "올바르지 않은 값입니다."
/>
</ view >
);
}
dir="rtl"로 값의 시작과 끝이 오른쪽에서 왼쪽으로 배치되는 슬라이더를 만들 수 있습니다.
import "./styles" ;
import { Slider } from "@/components/ui/slider" ;
export default function Example () {
return (
< view className = "slider-preview" >
< Slider
dir = "rtl"
min = { 0 }
max = { 100 }
step = { 0.5 }
defaultValues = {[ 36.5 ]}
ticks = {[ 36.5 ]}
tickWeight = "thick"
markers = {[
{ value: 0 , label: "0°C" },
{ value: 36.5 , label: "36.5°C" },
{ value: 100 , label: "100°C" },
]}
getAccessibilityValueText = {( value ) => `${ value }°C` }
getValueIndicatorLabel = {({ value }) => `${ value }°C` }
getAccessibilityLabel = {() => "온도" }
/>
< Slider
dir = "rtl"
min = { 0 }
max = { 100 }
defaultValues = {[ 30 , 50 ]}
ticks = {[ 20 , 40 , 60 , 80 ]}
markers = {[ 0 , 20 , 40 , 60 , 80 , 100 ]}
getAccessibilityLabel = {() => "값" }
/>
</ view >
);
}
Lynx Slider는 React Slider와 다음과 같은 차이가 있습니다.
렌더링 요소 : HTML form input과 DOM 요소 대신 native <view>와 <text>를 사용합니다.
입력 이벤트 : 브라우저 pointer/keyboard 이벤트 대신 native touch 입력을 사용하며, 값 변경은 onValuesChange, 확정은 onValuesCommit으로 전달합니다.
Value Indicator : valueIndicatorTrigger="auto"도 native에서는 touch-active와 같고 hover로 표시되지 않습니다. "active"와 동일한 결과를 제공합니다.
접근성 : DOM ARIA 대신 getAccessibilityLabel과 getAccessibilityValueText로 native accessibility 이름과 값을 제공합니다.
Field 안내 : Registry의 label, description, errorMessage는 native 레이아웃으로 표시됩니다. DOM id를 통한 label·description 연결은 사용하지 않습니다.
범위 선택 : values 배열과 두 개의 native thumb으로 범위를 표현합니다.
Lynx에는 HTML form과 브라우저 키보드 모델이 없으므로 다음 React 전용 기능은 실행 예제로 제공하지 않습니다.
기능 Lynx에서의 대체 또는 제한 form 제출, React Hook Formvalues와 onValuesChange로 앱 상태를 관리하고, 제출은 앱의 요청 흐름에서 처리합니다.HiddenInputHTML hidden input이 없습니다. 제출할 값은 앱 상태에서 직접 구성합니다. namenative form field name이 없습니다. 앱 상태의 키나 요청 payload를 사용합니다. 브라우저 검증 및 form field 연결 invalid, errorMessage로 화면 오류를 표시하고 검증은 앱에서 수행합니다.getAriaLabelledby와 DOM ARIADOM id 연결이 없습니다. getAccessibilityLabel과 getAccessibilityValueText로 native accessibility를 제공합니다. keyboard, focus, focus-visible 키보드 thumb focus 모델이 없습니다. native touch와 accessibility 탐색을 사용합니다. hover native에는 hover 상호작용이 없습니다. valueIndicatorTrigger="auto"는 "active"와 같이 touch-active로 동작합니다.
따라서 Form (Uncontrolled)과 React Hook Form은 Lynx 문서의 실행 예제에서 제외했습니다. 제출·검증이 필요한 경우에도 슬라이더 값을 앱 상태에 연결하고, 앱의 제출·검증 로직과 native accessibility 안내를 사용하세요.