Badge
可以讓我們在其 children element 的右上角(預設位置)顯示一個小徽章,通常用來表示需要處理的訊息數量,透過醒目的視覺形式來吸引用戶處理。
Badge 位置
一般的 Badge 位置都是預設出現在右上角,但可能有些情境會需要調整位置,MUI 這邊提供了 anchorOrigin 的 props,這個 anchorOrigin 比較特別,是一個物件,裡面有兩個欄位,分別是 vertical 和 horizontal,顧名思義,就是提供我們可以決定要放在右上、右下、左上、左下這四個位置。
<Badge
anchorOrigin={{
vertical: 'bottom', // top, bottom
horizontal: 'right', // right, left
}}
>
{children}
</Badge>
當然 MUI 除了這四個位置可以透過 props 調整之外,也能夠藉由 overrides documentation 提供我們的方法,透過 class 去覆寫 css 屬性(ex: top, right)來微調偏移,所以可以客製化的幅度還蠻彈性的。
Antd 提供的 props 叫做 offset ,傳入值為一陣列,格式为 [left, top]
,用來表示其水平及垂直的偏移量。
<Badge count={5} offset={[10, 10]}>
{children}
</Badge>
展示的內容
比較常見的展示內容一般來說都是數字,所以 Antd 的 props 叫做 count,一般我們看到 count 的直覺會覺得應該要填入的是數字,但很特別的是,count 支援的類型為 ReactNode ,因此,如下範例,他也可以是一個 icon。
// Antd Badge
<Badge count={0} showZero>
{children}
</Badge>
<Badge count={<ClockCircleOutlined style={{ color: '#f5222d' }} />}>
{children}
</Badge>
MUI 所提供的 props 為 badgeContent ,其型別為 node,因此也支援我們傳入數字以外的資料。
最大展示值
Antd: overflowCount
MUI: max
variant
有時候我們希望 Badge 只是提醒我們有東西更新就好,不需要呈現數字,因此除了我們常見的 default 樣式之外,也提供了 dot 樣式。
在 MUI 上一樣是提供我們 variant 這個 props ,可以填入的值是 dot, standard,預設是 standard。
Antd 上則是提供我們一個布林值 dot,若為 true ,則只呈現一個小紅點,沒有內容;若為 false,則為我們常見的 Badge 含數字內容的樣式。
顏色
這個元件一樣在 MUI 及 Antd 都提供我們顏色的客製化彈性,因為雖然大家印象中 Badge 都是紅色的,但是難免在其他情境我們需要別的顏色。 MUI 的 color 可傳入一樣為預設的保留字 default, error, primary, secondary,而 Antd 除了預設的保留字之外,也支援我們色票的傳入。
是否呈現 0
當 Badge 的數字為 0 時,是否要展示 Badge 呢? MUI 及 Antd 都提供給我們這樣的選擇,很有共識的,兩邊的 props 命名很一致,都是 showZero 的 boolean。
屬性 | 說明 | 類型 | 默認值 |
---|---|---|---|
placement | 徽章位置 | top-left , top-right , bottom-left , bottom-right |
top-right |
badgeContent | 展示內容 | ReactNode | |
max | 最大顯示值 | number | 99 |
variant | 變化模式 | standard , dot |
standard |
themeColor | 顏色 | primary, secondary, 色票 | #FE6B8B |
showZero | 是否呈現 0 | boolean | false |
children | 內容 | ReactNode |
最基本的 Badge 使用方式如下:
<Badge badgeContent={7}>
<MailIcon />
</Badge>
因此根據上述的使用介面,把 Badge 的結構設計如下:
<BadgeWrapper>
{children}
<StandardBadge
className={className}
$color={color}
$placement={placement}
>
{badgeContent}
</StandardBadge>
</BadgeWrapper>
由於 Badge 會跟 children 有重疊的區塊,因此 Badge 勢必要設為 position: absolute;
,並把 <BadgeWrapper />
設為 position: relative;
如此 Badge 才能相對於他做定位。
徽章位置 Placement
在 Badge 當中我們需要一個 props 來決定 Badge 的位置是在 右上
、左上
、右下
、左下
我想要用跟在 FormControl 一樣的手法,透過 Object 的 key-value 對應,來取得相對應的樣式:
const placementStyleMap = {
'top-left': topLeftStyle,
'top-right': topRightStyle,
'bottom-left': bottomLeftStyle,
'bottom-right': bottomRightStyle,
};
因為前面我們已經將 Badge 設為 absolute 了,因此在定位方面,我們就能夠使用 top
, left
, right
, transform
來調配出 右上
、左上
、右下
、左下
各種位置:
const topLeftStyle = css`
top: 0px;
left: 0px;
transform: translate(-50%, -50%);
`;
const topRightStyle = css`
top: 0px;
right: 0px;
transform: translate(50%, -50%);
`;
const bottomLeftStyle = css`
bottom: 0px;
left: 0px;
transform: translate(-50%, 50%);
`;
const bottomRightStyle = css`
bottom: 0px;
right: 0px;
transform: translate(50%, 50%);
`;
變化模式 variant
Badge 有兩種變化模式,一個是 standard
,另一個是 dot
。
其中 dot 的樣式就比較單純,因為不需要考慮到內容的變化,他就只有一個點
而已。
const DotBadge = styled.div`
position: absolute;
width: 6px;
height: 6px;
border-radius: 100%;
background-color: ${(props) => props.$color};
${(props) => placementStyleMap[props.$placement] || topRightStyle}
`;
<BadgeWrapper>
{children}
{variant === 'dot' && (
<DotBadge
className={className}
$color={color}
$placement={placement}
/>
)}
</BadgeWrapper>
在 standard
當中,特別需要留意的是會使用到 box-sizing: border-box;
這個屬性,在 金魚都能懂的CSS必學屬性 當中有很詳細的講解,border-box
主要是讓我們能將寬高設定作用在邊框外緣的範圍內,所以當我們在設定 width 以及 height 的時候,指的是 border-box 範圍內的寬跟高。
最大值 max
Badge 內容當然不能讓人家隨便輸入,甚至也需要限制他的最大數字,否則就會像下圖這樣悲劇:
因此至少要有一個簡單的判斷,來限制我們最大值的輸入
const content = badgeContent > max ? `${max}+` : badgeContent;
是否呈現 0
最後一個小問題就是,到底 0 要不要呈現?可能有些情境要,有些情境不用,因此我們需要一個 boolean 來做到這件事,所以跟上述 max
的邏輯合併,我們來做一個 function 來產生我們 Badge 的內容:
const makeBadgeContent = ({ showZero, max, badgeContent }) => {
if (showZero && badgeContent === 0) {
return '0';
}
if (!showZero && badgeContent === 0) {
return null;
}
return badgeContent > max ? `${max}+` : badgeContent;
};
Badge 元件原始碼:
Source code
Storybook:
Badge