过滤卡组件
一个使用React和TypeScript构建的交互式、可访问的过滤卡组件,符合Figma的设计规范。具有语义颜色、平滑的状态转换、波纹效果和全键盘/屏幕阅读器支持。
🎯 特性
- ✅ 三个互动州:默认、悬停和选定
- ✅ 语义色彩:严重(红色)、警报(黄色)、信息(蓝色)、成功(绿色)、通知(橙色)
- ✅ 涟漪效应:材质设计灵感点击动画
- ✅ 完全无障碍:键盘导航、屏幕阅读器支持、ARIA标签
- ✅ 移动友好:触摸目标符合无障碍指南(最小44x44px)
- ✅ 响应式设计:在移动和桌面上无缝工作
- ✅ 类型安全:使用TypeScript构建,提供更好的开发人员体验
- ✅ CSS模块:限定样式以防止冲突
📸 预览
该组件包括五个语义变体:
| 类型 | 颜色 | 用例 |
|---|---|---|
| 关键的 | #ff7f7f | 需要立即关注的紧急问题 |
| 警报 | #ffd86e | 需要审查的警告或问题 |
| 信息 | #6775e4 | 信息更新或新项目 |
| 成功 | #29cf8d | 积极指标或健康状况 |
| 通知 | #ffa16e | 重要通知或需要注意的事项 |
州
- 默认状态背景
#2c2826 - 悬停状态背景
#332f2b(鼠标悬停时) - 被选定状态背景
#332f2b带有蓝色边框轮廓(单击后仍然存在) - 涟漪效应:点击时出现白色波纹动画(持续时间600ms)
🚀 快速开始
安装
- 克隆此存储库或复制组件文件:
- FilterCard.tsx - FilterCard.module.css
- 安装依赖项:
npm install- 运行开发服务器:
npm run dev- 打开浏览器
http://localhost:3000
基本用法
import React, { useState } from 'react';
import FilterCard from './FilterCard';
function App() {
const [selected, setSelected] = useState(false);
return (
setSelected(!selected)}
/>
);
}📚 API 参考
过滤卡属性
| 道具 | 类型 | 必填 | 默认 | 描述 | ||||
|---|---|---|---|---|---|---|---|---|
type | `'critical' \ | 'alert' \ | 'info' \ | 'success' \ | 'notice'` | ✅ 是 | - | 卡片的语义类型 |
title | string | ✅ 是 | - | 主标题文本 | ||||
subtitle | string | ✅ 是 | - | 字幕/描述文本 | ||||
selected | boolean | ❌ 没有 | false | 当前是否选中该卡 | ||||
onClick | () => void | ❌ 无 | - | 卡片点击时的回拨功能 | ||||
className | string | ❌ 没有 | '' | 其他CSS类名 | ||||
testId | string | ❌ 无 | - | 用于测试的测试ID |
类型定义
export type FilterCardType = 'critical' | 'alert' | 'info' | 'success' | 'notice';
export interface FilterCardProps {
type: FilterCardType;
title: string;
subtitle: string;
selected?: boolean;
onClick?: () => void;
className?: string;
testId?: string;
}🎨 设计标记
颜色
/* Background Colors */
--card-bg-default: #2c2826;
--card-bg-hover: #332f2b;
--card-bg-selected: #332f2b;
/* Text Colors */
--text-primary: #fffcfa;
--text-secondary: #a7a7a7;
/* Semantic Colors */
--color-critical: #ff7f7f;
--color-alert: #ffd86e;
--color-info: #6775e4;
--color-success: #29cf8d;
--color-notice: #ffa16e;
/* Border & Outline */
--border-radius-card: 8px;
--border-radius-icon: 4px;
--outline-color: #6775e4;排版
- 字体家族:DM Sans
- 标题:16px,行高20px,重量400
- 字幕:14px,行高16px,重量400
间距
- 卡片填充:16像素
- 图标填充:12像素
- 内容差距:12像素
- 文本间隙:4px
♿ 辅助功能
键盘导航
- 选项卡:在卡片之间导航
- 进入 或 太空:激活/选择聚焦卡
- 焦点指示器:通过键盘聚焦卡片时出现蓝色轮廓
屏幕阅读器支持
- 卡片包括适当的ARIA标签(
aria-label,aria-pressed) - 角色设置为
button为了获得正确的语义 - 向屏幕阅读器宣布状态更改
附加功能
- 高对比度模式:在高对比度模式下增强边框
- 减少运动:尊重
prefers-reduced-motion偏好 - 触摸目标:移动设备上的最小44x44px触摸目标
- 颜色对比度:符合WCAG AA标准
📱 响应式设计
该组件可适应不同的屏幕尺寸:
- 桌面:固定宽度(312px)
- 移动:适应集装箱宽度
- 触摸设备:增强触摸目标
🧪 测试
运行类型检查:
npm run type-check运行linting:
npm run lint使用数据属性进行测试
该组件公开数据属性以便于测试:
测试中的访问权限:
const card = screen.getByTestId('my-card');
expect(card).toHaveAttribute('data-type', 'critical');
expect(card).toHaveAttribute('data-selected', 'true');🎯 示例用例
仪表板警报
navigateToAlerts()}
/>状态概述
showHealthDetails()}
/>信息卡
showNewNodes()}
/>警告通知
showOfflineNodes()}
/>通知卡
showOfflineNodes()}
/>🛠️ 定制
自定义样式
您可以通过传递自定义类名来扩展组件的样式:
然后在CSS中:
.my-custom-card {
width: 400px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}受控与不受控
该组件可以在两种模式下工作:
受控的 (推荐):
const [selectedId, setSelectedId] = useState(null);
setSelectedId(selectedId === 1 ? null : 1)}
/>失控的:
console.log('Card clicked')}
/>📦 构建
生产建设:
npm run build预览生产版本:
npm run preview🤝 贡献
欢迎投稿!请按照以下步骤操作:
- 分叉存储库
- 创建要素分支(
git checkout -b feature/amazing-feature) - 提交您的更改(
git commit -m 'Add amazing feature') - 推到分支(
git push origin feature/amazing-feature) - 打开拉取请求
📄 许可证
此项目根据MIT许可证获得许可-有关详细信息,请参阅许可证文件。
🙏 致谢
- Figma的设计规范
- 受材料设计启发的图标
- 使用React和TypeScript构建
- 使用CSS模块进行样式设置
📞 支持
如果您遇到任何问题或有疑问:
- 检查 问题 页
- 创建一个带有详细描述的新问题
- 包括代码示例和屏幕截图(如适用)
______________________________________________________________________
内置于❤️ 使用React+TypeScript
