設(shè)計(jì)師自主設(shè)計(jì)的一款菜單
時(shí)間:2023-07-24 20:27:01 | 來源:網(wǎng)站運(yùn)營(yíng)
時(shí)間:2023-07-24 20:27:01 來源:網(wǎng)站運(yùn)營(yíng)
設(shè)計(jì)師自主設(shè)計(jì)的一款菜單:
背景:ant design的菜單很好用,我們有優(yōu)秀的設(shè)計(jì)師,給出了如下圖的菜單交互
曲溜拐彎的菜單https://www.zhihu.com/video/1569800953997488129Update at 2023.02.16
竟然這么快這款菜單就被迭代掉了,在使用的過程中這款菜單有兩個(gè)硬傷。
- 原文中也有提到hover展開二級(jí)菜單時(shí)會(huì)抖動(dòng),菜單原來越多,問題也沒放大最終導(dǎo)致無法接受。改成了二級(jí)菜單從右側(cè)劃出,從交互上避免了抖動(dòng)。
- 為了修改1的問題,把hover改成了click交互,又發(fā)現(xiàn)菜單選中和hover無法做到很好的區(qū)分,只好打開菜單即展示內(nèi)凹進(jìn)去的造型,會(huì)出現(xiàn)同時(shí)多個(gè)菜單被打開,樣式很難看。
新的菜單同時(shí)解決了上邊兩個(gè)問題。如下圖
注意點(diǎn)1:兩個(gè)圓弧,一邊向外凹,一邊向里凸。
本來打算從antd的菜單做些CSS覆蓋展示出來如效果圖的樣子,因?yàn)橹暗恼{(diào)整都是這樣干的,但是這次向里凹的造型沒有辦法通過border-radius來畫出來。
注意點(diǎn)2: active和selected兩種狀態(tài)的記錄
注意點(diǎn)3: full slim hide 三種狀態(tài)的切換
注意點(diǎn)4: 二級(jí)菜單如何打開,點(diǎn)擊 or hover
注意點(diǎn)5: 頁面初始化時(shí)默認(rèn)高亮對(duì)應(yīng)菜單
最終,還是重新寫一款全新的菜單組件吧,從交互和展示上已經(jīng)跟antd差異太大,而且CSS因?yàn)槿鄙傧鄳?yīng)的dom也無法作出弧形的效果。剛開始不用想太復(fù)雜,菜單不就是一個(gè)for循環(huán)展示item就可以了么。然后有了二級(jí)菜單,只需要碰到subMenu的時(shí)候再加一層循環(huán)就行。分析到這,順路說一下,TS還是香啊。提前把類型定義好,定義類型的過程其實(shí)也是梳理展示和依賴項(xiàng)的過程。
// https://github.com/n9e/fe-v5/blob/master/src/components/fc-menu/types.tsexport interface MenuItemProps { key: string; label: string; icon?: React.ReactNode;}export interface SubMenuProps extends MenuItemProps { children: MenuItemProps[];}export type IMenuProps = MenuItemProps | SubMenuProps | undefined;
兩層循環(huán)后,基本就能呈現(xiàn)所有的菜單項(xiàng)了,兩個(gè)圓弧都加上對(duì)應(yīng)位置的dom然后通過border-radius繪制圓弧,并不復(fù)雜,不再贅述。
antd的Menu組件是通過useContent來在不同組件中傳遞狀態(tài),習(xí)慣了createglobalstate的寫法,所以我是用了他來記錄active和selected狀態(tài),并在full slim hide三個(gè)組件中共享狀態(tài)。最后一點(diǎn),也就是通過click事件來打開二級(jí)菜單還是hover打開二級(jí)菜單。其實(shí)大多是點(diǎn)擊,但是設(shè)計(jì)師覺得hover打開,菜單有種手風(fēng)琴交互的感覺,比較絲滑。但是菜單長(zhǎng)短不一,加入hover一個(gè)有很多子菜單的一級(jí)菜單時(shí),滑入下一個(gè)很少子菜單時(shí)會(huì)選不中。因?yàn)閔over到太下邊了,而長(zhǎng)菜單收起了,短菜單并沒有這么高的高度。
失去焦點(diǎn)的菜單https://www.zhihu.com/video/1569801247393226752因?yàn)橐粋€(gè)菜單,比如用戶管理(/user)下可能還包含用戶詳情(/user/detail/:id),用戶列表(/user/list)多個(gè)頁面,而具體判斷當(dāng)前頁面處于哪個(gè)菜單有點(diǎn)太耦合業(yè)務(wù)了,不太好放在菜單組件來處理。參考了下antd的Menu也沒處理,我也就沒處理,其實(shí)要處理,只好把所有的[菜單]-> [路徑] 的映射傳入菜單,也可以解決。
開源代碼:
https://github.com/n9e/fe-v5/tree/master/src/components/fc-menu我們的產(chǎn)品:Flashcat:讓監(jiān)控分析變簡(jiǎn)單
@fc-components/menu