拟态开关

switch · neumorphic · 灵感来源:Neumorphism(轨道压入、圆钮浮起,开启时圆钮点亮)

Wi-Fi

已连接 · UI-Echo-5G

蓝牙

已关闭

飞行模式

演示禁用态

小号尺寸

点击 / 空格切换 · 文案随状态联动

复用卡

Neumorphic Switch · 拟态开关 · 开关 / Neumorphic

规格 · 术语提示词(给 AI 用)

做一个 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(轨道压入、圆钮浮起,开启时圆钮点亮)

参数(CSS 变量)

--color-accent --color-surface --color-text-muted --dur-fast --ease-standard --glass-border --neuro-bg --neuro-dark --neuro-light --shadow-sm

必缺状态

焦点 / 按压 / 禁用

整页场景

(尚未接进整页场景)

安装(一条链接)

调研笔记

拟态开关

  • 与玻璃、极简开关同一份 props(checked / defaultChecked / onChange / disabled / size / aria-label)
  • 轨道是凹槽:--neuro-bg + 两条 inset 阴影;圆钮是同色浮起 + 两条外阴影
  • 开启态只点亮圆钮(accent),轨道不填色——深度关系始终是"槽里一个钮"
  • 按压走全站统一的 .press-feedback 0.97;圆钮平移 --dur-fast / --ease-standard

限制:关闭态圆钮与轨道同色,可点性完全依赖阴影;低对比屏幕或强环境光下会偏弱,这是拟态轴的固有代价。

实现

switch/neumorphic
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>
  );
}

元信息

标识
switch/neumorphic
状态
done
最后提交
2026-10-31
风格轴
neumorphic
依赖 token
--color-accent --color-surface --color-text-muted --dur-fast --ease-standard --glass-border --neuro-bg --neuro-dark --neuro-light --shadow-sm
在工作台打开 源码与 notes 都在 src/components/switch/neumorphic/