Tailwind + Mantine | Switch 组件主题样式
概述
项目使用 Mantine 组件库配合 Tailwindcss 以实现切图和动画效果, 不使用 .css 文件单独写样式, 目的在于减少样式维护的成本, 使组件开发更加原子化, 降低不同组件间的影响和副作用
根据 UI 设计图来进行一些原子组件的样式适配, 这里记录一下在修改 Switch 组件时遇到的样式问题以及如何使用 Tailwindcss 修改
设计对比
设计图:

Mantine 的 Switch 组件初始样式:

比对:
track部分- 无边框, 改为内阴影
- 默认背景颜色和
active状态背景颜色修改
thumb部分- 无边框
hover状态下增加蓝色边框和一圈半透明的outline
最终修改
// Switch.ts
import { Switch } from '@mantine/core'
import { cn } from '../../utils/className'
export const SwitchTheme = Switch.extend({
// defaultProps: {
// NOTE 可行, 但不能控制未选中时的颜色
// color: 'var(--tw-color-brand5)',
// },
classNames: {
root: cn(' group cursor-pointer'),
thumb: cn(
cn(' bg-bg1 border-bg1'),
cn(' group-hover:border-[#00A6FF] group-hover:ring-[3px]'),
cn(' group-hover:ring-[rgba(81,193,253,0.4)]'),
),
input: cn(' peer'),
track: cn(
// NOTE 如果只有 bg-bg4, 会覆盖 checked 的 bg
cn(' bg-bg4 peer-checked:bg-brand5'),
cn('shadow-[0px_1px_1px_0px_rgba(0,0,0,0.06)_inset]'),
cn('overflow-visible border-0'),
),
},
vars: () => {
return {
root: {
// NOTE 这个生效, 和 defaultProps 的 color 一样
// '--switch-color': 'var(--tw-color-brand5)',
// NOTE 这个不生效, 虽然样式里是用的这个变量, 但是定义后不会生效
// '--switch-bg': 'var(--tw-color-bg4)',
},
}
},
})
代码解释
里面有几个 NOTE 可以看一下 (在 vscode 中, 可以使用 Todo Tree 插件来设置 NOTE 高亮)
color属性, 用于控制active状态下的track部分的背景颜色, 但是没有属性来设置默认的背景颜色- 给
root元素group样式, 用于控制root元素hover状态时, 子元素展示对应样式 (group-hover:xxx) - 给
input元素peer样式, 用于控制input元素checked状态时, 相邻的track元素展示对应样式 (peer-checked:xxx) thumb元素的bg和border使用相同颜色track元素的bg只能通过peer来控制, 其他方式都有不足
里面的 cn (className 的简写) 方法用于支持 tailwind 的开发, 代码如下:
// className.ts
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
配合 vscode 插件 Tailwind CSS IntelliSense 可以用于代码补全, .vscode/settings.json 中相关配置如下:
// .vscode/settings.json
{
"tailwindCSS.experimental.classRegex": [
["clsx\\(([^)]*)\\)"],
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
["classNames\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
["className: [\"'`]([^\"'`]*).*?[\"'`]"],
["cn\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
]
}
以上是全部内容, 最后效果:


转载自:https://juejin.cn/post/7366441097583722536