Skip to Content
@anker-in/headless-ui 2.0 is released 🎉
业务组件🌟 通用组件品牌权益-带链接

BrandCardLink (品牌权益-带链接)

展示品牌服务特色与权益的卡片组件,支持图标、标题、描述和链接按钮【✅ 已发布】

加载中...
当前视口: 1920px × 600px场景: 四项品牌权益展示
打开链接

功能特性

  • 链接卡片: 图标 + 标题 + 描述 + 链接按钮的完整卡片结构
  • 响应式布局: 桌面端网格(1→2→4 列),移动端 Swiper 轮播
  • 移动端分组: 每个轮播页显示 4 个卡片,自动分页
  • 形状变体: 支持圆角(round)和方形(square)两种卡片样式
  • 曝光追踪: 集成 useExposure Hook 实现自动曝光埋点
  • Swiper 轮播: 支持 FreeMode、鼠标滚轮和分页指示器
  • 固定高度: 不同断点下卡片自适应高度保持视觉一致
  • 文本截断: 标题和描述超长自动截断(line-clamp-2)

Props 参数

参数类型默认值必需说明
dataBrandCardLinkData-卡片数据配置
classNamestring''自定义类名
refReact.Ref<HTMLDivElement>-根容器 ref

BrandCardLinkData 配置

参数类型默认值必需说明
itemsBrandCardLinkItem[]-卡片列表数据
itemShape'round' | 'square'undefined卡片形状,不传则使用默认样式

BrandCardLinkItem 配置

参数类型必需说明
iconImg卡片图标对象
titlestring卡片标题文本
descriptionstring卡片描述文本
linkstring链接地址 URL
linkTextstring链接按钮显示文本
type'icon' | 'avatar'图标类型(当前实现中未使用)
avatarListArray<{ avatar: Img }>头像列表(当前实现中未使用)

Img 对象

参数类型必需说明
urlstring图片 URL 地址
altstring图片替代文本(无障碍)

类型定义

import type { Img } from '@anker-in/headless-ui' interface BrandCardLinkData { /** 卡片列表 */ items: BrandCardLinkItem[] /** 卡片形状: round(圆角) | square(方形) */ itemShape?: 'round' | 'square' } interface BrandCardLinkItem { /** 卡片图标 */ icon?: Img /** 卡片标题 */ title: string /** 卡片描述 */ description: string /** 链接地址 */ link: string /** 链接按钮文本 */ linkText: string /** 图标类型(未使用) */ type?: 'icon' | 'avatar' /** 头像列表(未使用) */ avatarList?: Array<{ avatar: Img }> } interface Img { /** 图片 URL */ url: string /** 替代文本 */ alt: string }

使用示例

示例 1: 基础卡片组(4 个卡片)

import { BrandCardLink } from '@anker-in/headless-ui/biz' import scenarios from './scenarios.json' export default function BasicExample() { const data = { items: [ { icon: { url: 'https://cdn.example.com/warranty.svg', alt: 'Warranty', }, title: '24-Month Warranty', description: 'Comprehensive Protection', link: '/warranty', linkText: 'Learn More', }, { icon: { url: 'https://cdn.example.com/shipping.svg', alt: 'Free Shipping', }, title: 'Free Shipping', description: 'On All Orders', link: '/shipping', linkText: 'View Policy', }, { icon: { url: 'https://cdn.example.com/support.svg', alt: '24/7 Support', }, title: '24/7 Customer Support', description: 'Always Here to Help', link: '/support', linkText: 'Contact Us', }, { icon: { url: 'https://cdn.example.com/secure.svg', alt: 'Secure Payment', }, title: 'Secure Payment', description: 'SSL Encrypted', link: '/security', linkText: 'Learn More', }, ], } return <BrandCardLink data={data} /> }

效果:

  • 桌面端: 4 列网格布局,所有卡片一次性显示
  • 移动端: 单页轮播显示 4 个卡片(无分页器)

示例 2: 圆角卡片样式

<BrandCardLink data={{ items: [ { icon: { url: 'https://cdn.example.com/fast-charge.svg', alt: 'Fast Charging', }, title: 'Fast Charging', description: 'Get 50% Charge in 30 Minutes', link: '/features/fast-charging', linkText: 'Discover', }, { icon: { url: 'https://cdn.example.com/battery.svg', alt: 'Long Battery', }, title: 'Long Battery Life', description: 'Up to 48 Hours of Use', link: '/features/battery', linkText: 'Discover', }, ], itemShape: 'round', // 圆角卡片 }} />

效果: 卡片应用 rounded-box 类,呈现圆角边框

示例 3: 方形卡片样式

<BrandCardLink data={{ items: [ { icon: { url: 'https://cdn.example.com/eco.svg', alt: 'Eco Friendly', }, title: 'Eco-Friendly Materials', description: '100% Recyclable Packaging', link: '/sustainability', linkText: 'Read More', }, { icon: { url: 'https://cdn.example.com/award.svg', alt: 'Award Winning', }, title: 'Award-Winning Design', description: 'CES Innovation Award 2025', link: '/awards', linkText: 'Read More', }, ], itemShape: 'square', // 方形卡片 }} />

效果: 卡片应用 rounded-none 类,呈现完全方形无圆角

示例 4: 8 个卡片(移动端分 2 页)

<BrandCardLink data={{ items: [ { icon: {...}, title: 'Feature 1', description: 'Desc 1', link: '/f1', linkText: 'Learn' }, { icon: {...}, title: 'Feature 2', description: 'Desc 2', link: '/f2', linkText: 'Learn' }, { icon: {...}, title: 'Feature 3', description: 'Desc 3', link: '/f3', linkText: 'Learn' }, { icon: {...}, title: 'Feature 4', description: 'Desc 4', link: '/f4', linkText: 'Learn' }, { icon: {...}, title: 'Feature 5', description: 'Desc 5', link: '/f5', linkText: 'Learn' }, { icon: {...}, title: 'Feature 6', description: 'Desc 6', link: '/f6', linkText: 'Learn' }, { icon: {...}, title: 'Feature 7', description: 'Desc 7', link: '/f7', linkText: 'Learn' }, { icon: {...}, title: 'Feature 8', description: 'Desc 8', link: '/f8', linkText: 'Learn' }, ], itemShape: 'round', }} />

效果:

  • 桌面端: 4 列网格,2 行显示 8 个卡片
  • 移动端: 第 1 页显示前 4 个卡片,第 2 页显示后 4 个卡片,带分页指示器

示例 5: 自定义背景色

<BrandCardLink data={{ items: [...], itemShape: 'round', }} className="[&amp;_.brand-equity-item]:bg-gray-100" />

说明: 使用 Tailwind 的任意值语法覆盖默认背景色 #DAE7F2


响应式行为

布局方式

屏幕尺寸屏幕宽度布局模式列数/分页Tailwind 类
移动端< 768pxSwiper 轮播4 items/页-
平板≥ 768pxGrid 网格2 列tablet:grid-cols-2
笔记本≥ 1025pxGrid 网格4 列laptop:grid-cols-4

布局切换逻辑:

  • 移动端(<768px): 使用 Swiper 组件实现水平轮播,每页垂直排列 4 个卡片
  • 桌面端(≥768px): 使用 CSS Grid 静态网格布局,无轮播

卡片高度

断点屏幕宽度高度内边距Tailwind 类
移动端< 1025px160px16pxh-[160px] p-4
笔记本1025px - 1439px192px16pxlaptop:h-[192px] laptop:p-4
桌面1440px - 1919px192px24pxdesktop:h-[192px] desktop:p-6
大屏≥ 1920px240px32pxlg-desktop:h-[240px] lg-desktop:p-8

设计考虑: 固定高度确保所有卡片视觉一致,避免不同内容长度导致的高度差异

文本尺寸

标题 (title):

断点字号Tailwind 类
移动端14pxtext-[14px]
桌面16pxdesktop:text-[16px]
大屏18pxlg-desktop:text-[18px]

描述 (description):

断点字号Tailwind 类
移动端20pxtext-[20px]
大屏24pxlg-desktop:text-[24px]

链接文本 (linkText):

断点字号Tailwind 类
移动端14pxtext-sm
笔记本及以上16pxlaptop:text-base

设计规范

卡片数量建议

场景推荐数量移动端表现桌面端表现
核心权益4 个单页显示,无分页器单行 4 列
完整服务8 个2 页显示,带分页器2 行 × 4 列
扩展特性12 个3 页显示,带分页器3 行 × 4 列

注意: 移动端每页固定显示 4 个卡片,超过 4 个会自动分页

文本长度限制

字段中文英文截断方式
title≤ 10 字≤ 20 字符line-clamp-2 (最多 2 行)
description≤ 20 字≤ 40 字符line-clamp-2 (最多 2 行)
linkText≤ 6 字≤ 12 字符不截断

示例:

标题: "This is a Very Long Title That Will Be Truncated After Two Lines..."

图标要求

  • 格式: SVG 或 PNG(建议 SVG 保证清晰度)
  • 尺寸: 建议 200×200px 或更大(组件内自适应)
  • 风格: 单色或简洁双色图标,避免过于复杂的设计
  • 背景: 透明背景,便于与卡片背景融合
  • alt 文本: 必须提供有意义的替代文本,描述图标含义

无障碍性

语义化 HTML

// 标题使用 <h3> 标签 <h3 className="...">{item.title}</h3> // 链接使用语义化 Link 组件 <Link href={item.link}> {item.linkText} <svg aria-hidden="true">...</svg> </Link>

键盘导航

  • ✅ Tab 键: 按顺序聚焦到每个卡片的链接按钮
  • ✅ Enter/Space: 激活当前聚焦的链接
  • ✅ 移动端轮播: 支持触摸滑动和鼠标滚轮导航

屏幕阅读器

  • ✅ 图标有 alt 属性,通过 Picture 组件自动实现
  • ✅ 描述文本有 title 属性,鼠标悬停显示完整文本
  • ✅ 链接按钮语义清晰,屏幕阅读器可正确识别

建议改进

  • ⚠️ 建议: 为整个卡片添加 aria-label,描述完整内容

    <div aria-label={`${item.title}: ${item.description}. ${item.linkText}`}> ... </div>
  • ⚠️ 建议: 为移动端轮播容器添加 ARIA 属性

    <div role="region" aria-label="Brand features carousel"> <Swiper>...</Swiper> </div>

颜色对比度

  • 默认背景色 #DAE7F2 与文本颜色对比度建议≥ 4.5:1(WCAG AA 标准)
  • 链接文本应使用品牌色且对比度充足
  • 测试工具: 使用浏览器 DevTools 的 Accessibility 面板验证

性能优化

React Hooks 优化

// 使用 React.forwardRef 和 useImperativeHandle 优化 ref 传递 const BrandCardLink = React.forwardRef((props, ref) => { const innerRef = useRef<HTMLDivElement>(null) useImperativeHandle(ref, () => innerRef.current!) // ... })

响应式加载

// 使用 useMediaQuery 避免不必要的移动端组件渲染 const isMobile = useMediaQuery('(max-width: 767px)') // 桌面端: 简单 Grid 布局,无 Swiper 依赖 // 移动端: 按需加载 Swiper 组件

优势:

  • 减少桌面端的 JavaScript Bundle 大小
  • 避免不必要的 Swiper 实例化

曝光追踪优化

// useExposure Hook 自动防止重复曝光 useExposure(innerRef, { componentType: 'copy', componentName: 'store_benefits', })

特性:

  • 仅在组件首次进入视口时触发
  • 基于 Intersection Observer API,性能开销低
  • 自动上报组件类型和名称

建议优化

  • 图片懒加载: 为 icon 图片添加 loading="lazy" 属性
  • CDN 加速: 图标资源使用 CDN 分发,减少加载时间
  • 预加载关键资源: 对首屏可见的图标进行 preload

常见问题

1. 为什么移动端每页固定显示 4 个卡片?

这是设计决策,确保移动端体验一致且每页内容完整。如需修改每页卡片数量,可以调整分组逻辑:

// 修改 chunkArray 的第二个参数 const itemsArray = isMobile ? chunkArray(items, 6) : items // 改为每页 6 个

2. 如何自定义轮播分页器样式?

分页器默认居中显示,通过覆盖 Swiper 的 CSS 类自定义:

.swiper-pagination-bullet { background: #000; opacity: 0.5; width: 8px; height: 8px; } .swiper-pagination-bullet-active { background: var(--brand-primary); opacity: 1; width: 24px; border-radius: 4px; }

3. 卡片高度为什么固定?

为了保证视觉一致性,避免不同内容长度导致的高度不一致。如需自适应高度,可以移除固定高度类:

// 移除 h-[160px]、laptop:h-[192px] 等类 // 保留 min-h-[160px] 设置最小高度避免过矮

4. 如何处理卡片点击事件?

当前实现中 onClick 回调未暴露。如需添加,可以修改 BrandCardLinkItem 类型并在 Link 组件中绑定:

interface BrandCardLinkItem { // 现有字段... onClick?: () => void // 新增 } // 组件内部 <Link href={item.link} onClick={item.onClick}> {item.linkText} </Link>

5. type 和 avatarList 字段有什么用?

这两个字段在当前实现中未使用,可能是为未来功能预留的接口(如头像展示模式)。暂时可以忽略这两个字段。

6. 如何隐藏链接箭头图标?

通过 CSS 隐藏:

.brand-equity-item svg { display: none; }

或使用 className 覆盖:

<BrandCardLink className="[&amp;_.brand-equity-item_svg]:hidden" data={{...}} />

7. 背景颜色可以自定义吗?

当前背景色硬编码为 #DAE7F2(浅蓝色)。自定义方式:

<BrandCardLink data={{...}} className="[&amp;_.brand-equity-item]:bg-gray-100" // 覆盖背景色 />

或直接修改组件源码中的颜色值


技术实现

移动端分组逻辑

/** * 将数组按指定大小分组 * @param arr - 原始数组 * @param size - 每组大小 */ const chunkArray = <T,>(arr: T[], size: number): T[][] => { const chunks: T[][] = [] for (let i = 0; i < arr.length; i += size) { chunks.push(arr.slice(i, i + size)) } return chunks } // 使用示例 const items = [1, 2, 3, 4, 5, 6, 7, 8, 9] const grouped = chunkArray(items, 4) // 结果: [[1,2,3,4], [5,6,7,8], [9]]

应用场景:

  • 8 个卡片 → 2 页(每页 4 个)
  • 9 个卡片 → 3 页(前 2 页 4 个,最后 1 页 1 个)
  • 12 个卡片 → 3 页(每页 4 个)

Swiper 配置详解

const swiperConfig = { modules: [FreeMode, Mousewheel, Pagination], freeMode: true, // 自由模式,滑动更流畅无吸附 mousewheel: { forceToAxis: true // 强制单方向滚动,防止斜向滑动 }, pagination: { clickable: true, // 分页器点(dots)可点击切换 el: paginationRef.current // 自定义分页器 DOM 位置 }, breakpoints: { 0: { spaceBetween: 12 // 移动端卡片间距 12px } } }

FreeMode 说明:

  • 启用后滑动无吸附效果,用户可自由停止在任意位置
  • 适合内容浏览场景,不适合精准分页切换

Mousewheel 说明:

  • forceToAxis: true 确保鼠标滚轮仅触发水平滚动
  • 防止用户垂直滚动页面时意外触发轮播

形状变体实现

// round(圆角) itemShape === 'round' // 应用类: rounded-box // 实际圆角取决于 Tailwind 配置中的 border-radius.box 值 // square(方形) itemShape === 'square' // 应用类: rounded-none // 完全移除圆角,呈现直角矩形 // 默认(未设置) itemShape === undefined // 不应用任何形状类,使用组件默认样式

条件渲染:

<div className={cn( 'brand-equity-item', { 'rounded-box': itemShape === 'round', 'rounded-none': itemShape === 'square', } )} > ... </div>

相关资源

源码位置

  • 组件源码: packages/ui/src/biz-components/BrandCardLink/BrandCardLink.tsx
  • 类型定义: packages/ui/src/biz-components/BrandCardLink/types.ts
  • Storybook: packages/ui/src/stories/brandCardLink.stories.tsx

依赖组件

  • Picture: 图片展示组件,支持响应式和懒加载
  • Link: 链接组件,支持内部路由和外部链接
  • Swiper: 第三方轮播库(swiper/react)
  • useMediaQuery: 响应式断点 Hook
  • useExposure: 曝光追踪 Hook

相关文档


维护者: DTC IT Team 最后更新: 2026-01-17 版本: v1.0.0

Last updated on