switch · neumorphic · 灵感来源:Neumorphism(轨道压入、圆钮浮起,开启时圆钮点亮)
Wi-Fi
已连接 · UI-Echo-5G
蓝牙
已关闭
飞行模式
演示禁用态
小号尺寸
点击 / 空格切换 · 文案随状态联动
Neumorphic Switch · 拟态开关 · 开关 / Neumorphic
做一个 Neumorphic Switch(拟态开关):
- role=switch + aria-checked,Space / Enter 切换
- 轨道压入(inset 双阴影),圆钮同色浮起(外双阴影)
- 开启只点亮圆钮为 accent,轨道保持凹槽
- 轨道高度 ≥24px,按压有 0.97 缩放反馈
用这些 CSS 变量:--color-accent --color-surface --color-text-muted --dur-fast --ease-standard --glass-border --neuro-bg --neuro-dark --neuro-light --shadow-sm
灵感参考:Neumorphism(轨道压入、圆钮浮起,开启时圆钮点亮)--color-accent --color-surface --color-text-muted --dur-fast --ease-standard --glass-border --neuro-bg --neuro-dark --neuro-light --shadow-sm
焦点 / 按压 / 禁用
(尚未接进整页场景)
/r/switch--neumorphic.json
免外壳的 markdown 版:/llms/components/switch--neumorphic.md--neuro-bg + 两条 inset 阴影;圆钮是同色浮起 + 两条外阴影.press-feedback 0.97;圆钮平移 --dur-fast / --ease-standard限制:关闭态圆钮与轨道同色,可点性完全依赖阴影;低对比屏幕或强环境光下会偏弱,这是拟态轴的固有代价。
import { useState } from 'react';
interface Props {
checked?: boolean;
defaultChecked?: boolean;
onChange?: (checked: boolean) => void;
disabled?: boolean;
size?: 'sm' | 'md';
'aria-label'?: string;
}
// 轨道高度都 ≥24px:SC 2.5.8 要求指针目标至少 24×24 CSS 像素
const dims = {
sm: { track: 'w-8 h-6', thumb: 'size-4', on: 'translateX(12px)' },
md: { track: 'w-11 h-[26px]', thumb: 'size-[22px]', on: 'translateX(18px)' },
};
/**
* 拟态开关:与玻璃开关同一份 props,
* 轨道是压进去的槽,圆钮浮在上面;开启时圆钮填 accent,轨道保持凹槽。
*/
export function NeumorphicSwitch({
checked,
defaultChecked,
onChange,
disabled,
size = 'md',
...rest
}: Props) {
const isControlled = checked !== undefined;
const [internal, setInternal] = useState(defaultChecked ?? false);
const on = isControlled ? checked : internal;
const d = dims[size];
const toggle = () => {
const next = !on;
if (!isControlled) setInternal(next);
onChange?.(next);
};
return (
<button
type="button"
role="switch"
aria-checked={on}
disabled={disabled}
onClick={toggle}
className={`
press-feedback
relative inline-flex items-center shrink-0
${d.track} rounded-full p-[2px]
bg-[var(--neuro-bg)]
shadow-[inset_2px_2px_4px_var(--neuro-dark),inset_-2px_-2px_4px_var(--neuro-light)]
cursor-pointer
disabled:opacity-40 disabled:cursor-not-allowed
`}
{...rest}
>
<span
aria-hidden="true"
className={`
${d.thumb} rounded-full
shadow-[2px_2px_5px_var(--neuro-dark),-2px_-2px_5px_var(--neuro-light)]
transition-[transform,background-color] duration-[var(--dur-fast)] ease-[var(--ease-standard)]
${on ? 'bg-[var(--color-accent)]' : 'bg-[var(--neuro-bg)]'}
`}
style={{ transform: on ? d.on : 'translateX(0)' }}
/>
</button>
);
}
src/components/switch/neumorphic/