From ece00537e5af48ea7ad3211211b10587273b7283 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Sun, 4 Apr 2021 11:46:36 +0800 Subject: [PATCH 1/2] refactor(PromotionList): UI redesign --- src/components/PromotionList/Holder.js | 26 --------- src/components/PromotionList/PartnerBanner.js | 33 ----------- src/components/PromotionList/Spotlight.tsx | 29 ++++++++++ src/components/PromotionList/WaitList.tsx | 23 ++++++++ src/components/PromotionList/fakeItems.ts | 34 +++++++++++ src/components/PromotionList/index.js | 48 ---------------- src/components/PromotionList/index.tsx | 56 ++++++++++++++++++ src/components/PromotionList/spec.ts | 7 +++ src/components/PromotionList/styles/holder.ts | 39 ------------- src/components/PromotionList/styles/index.ts | 17 ++---- .../PromotionList/styles/partner_banner.ts | 57 ------------------- .../PromotionList/styles/spotlight.ts | 37 ++++++++++++ .../PromotionList/styles/wait_list.ts | 20 +++++++ 13 files changed, 212 insertions(+), 214 deletions(-) delete mode 100755 src/components/PromotionList/Holder.js delete mode 100755 src/components/PromotionList/PartnerBanner.js create mode 100755 src/components/PromotionList/Spotlight.tsx create mode 100644 src/components/PromotionList/WaitList.tsx create mode 100644 src/components/PromotionList/fakeItems.ts delete mode 100755 src/components/PromotionList/index.js create mode 100755 src/components/PromotionList/index.tsx create mode 100644 src/components/PromotionList/spec.ts delete mode 100755 src/components/PromotionList/styles/holder.ts delete mode 100755 src/components/PromotionList/styles/partner_banner.ts create mode 100755 src/components/PromotionList/styles/spotlight.ts create mode 100644 src/components/PromotionList/styles/wait_list.ts diff --git a/src/components/PromotionList/Holder.js b/src/components/PromotionList/Holder.js deleted file mode 100755 index fb6656c10..000000000 --- a/src/components/PromotionList/Holder.js +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react' - -import { ICON_CMD } from '@/config' - -import { - Wrapper, - BannerWrapper, - Logo, - PartnerInfo, - Title, - Desc, -} from './styles/holder' - -const Holder = () => ( - - - - 空缺中 - 联系我们 - - - - -) - -export default React.memo(Holder) diff --git a/src/components/PromotionList/PartnerBanner.js b/src/components/PromotionList/PartnerBanner.js deleted file mode 100755 index 872b730e0..000000000 --- a/src/components/PromotionList/PartnerBanner.js +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react' - -import { ICON_CMD } from '@/config' -import { - Wrapper, - ItemWrapper, - PartnerInfo, - Logo, - Title, - Desc, -} from './styles/partner_banner' - -const PartnerBanner = () => ( - - - - - 拉勾网 - 一个找工作的网站 - - - - - - - xaudiopro - 音频剪辑,格式转换 - - - -) - -export default React.memo(PartnerBanner) diff --git a/src/components/PromotionList/Spotlight.tsx b/src/components/PromotionList/Spotlight.tsx new file mode 100755 index 000000000..72e4cf763 --- /dev/null +++ b/src/components/PromotionList/Spotlight.tsx @@ -0,0 +1,29 @@ +import React from 'react' + +import type { TItem } from './spec' +import { + Wrapper, + ItemWrapper, + Header, + Logo, + Title, + Desc, +} from './styles/spotlight' + +type TProps = { + item: TItem +} + +const Spotlight: React.FC = ({ item }) => ( + + +
+ {item.title} + +
+ {item.desc} +
+
+) + +export default React.memo(Spotlight) diff --git a/src/components/PromotionList/WaitList.tsx b/src/components/PromotionList/WaitList.tsx new file mode 100644 index 000000000..ce70c8494 --- /dev/null +++ b/src/components/PromotionList/WaitList.tsx @@ -0,0 +1,23 @@ +import React from 'react' + +import type { TItem } from './spec' +import { Wrapper, Item } from './styles/wait_list' + +type TProps = { + items: TItem[] + activeId: string +} + +const WaitList: React.FC = ({ items, activeId }) => { + return ( + + {items.map((item) => ( + + {item.title} + + ))} + + ) +} + +export default React.memo(WaitList) diff --git a/src/components/PromotionList/fakeItems.ts b/src/components/PromotionList/fakeItems.ts new file mode 100644 index 000000000..9cfe6d4d2 --- /dev/null +++ b/src/components/PromotionList/fakeItems.ts @@ -0,0 +1,34 @@ +import { ICON_CMD } from '@/config' + +const items = [ + { + id: '1', + title: 'xaudiopro', + link: 'https://xxxx', + desc: '音频剪辑,格式转换, 音频剪辑,格式转换 音频剪辑', + cover: `${ICON_CMD}/test_ad.jpg`, + }, + { + id: '2', + title: 'github', + link: 'https://xxxx', + desc: 'github 就不用多介绍了吧', + cover: `${ICON_CMD}/test_ad.jpg`, + }, + { + id: '3', + title: 'xxoo', + link: 'https://xxxx', + desc: 'xxx 就不用多介绍了吧', + cover: `${ICON_CMD}/test_ad.jpg`, + }, + { + id: '4', + title: 'xxoo2', + link: 'https://xxxx', + desc: 'xxx2 就不用多介绍了吧', + cover: `${ICON_CMD}/test_ad.jpg`, + }, +] + +export default items diff --git a/src/components/PromotionList/index.js b/src/components/PromotionList/index.js deleted file mode 100755 index 4c5740793..000000000 --- a/src/components/PromotionList/index.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * PromotionList - * - */ - -import React from 'react' -import T from 'prop-types' - -import { ICON_CMD } from '@/config' -import { buildLog } from '@/utils' -import PartnerBanner from './PartnerBanner' -// import Holder from './Holder' - -import { Wrapper, Header, Title, AboutIcon } from './styles' - -/* eslint-disable-next-line */ -const log = buildLog('c:PromotionList:index') - -const PromotionList = ({ show, onAbout }) => { - return ( - - {show && ( - <> -
- 产品推广 -
- -
-
- - - )} -
- ) -} - -PromotionList.propTypes = { - show: T.bool, - onAbout: T.func, -} - -PromotionList.defaultProps = { - show: true, - onAbout: log, -} - -export default React.memo(PromotionList) diff --git a/src/components/PromotionList/index.tsx b/src/components/PromotionList/index.tsx new file mode 100755 index 000000000..5451ba63f --- /dev/null +++ b/src/components/PromotionList/index.tsx @@ -0,0 +1,56 @@ +/* + * + * PromotionList + * + */ + +import React, { useState } from 'react' +import { findIndex } from 'ramda' + +import { ICON_CMD } from '@/config' +import { buildLog } from '@/utils' + +import type { TItem } from './spec' +import Spotlight from './Spotlight' +import WaitList from './WaitList' + +import { Wrapper, Header, Title, AboutIcon } from './styles' +import fakeItems from './fakeItems' + +/* eslint-disable-next-line */ +const log = buildLog('c:PromotionList:index') + +type TProps = { + show?: boolean + onAbout?: () => void + items: TItem[] +} + +const PromotionList: React.FC = ({ + show = true, + onAbout = log, + items = fakeItems, +}) => { + const [activeId, setActiveId] = useState(items[0].id) + const activeItemIndex = findIndex((item) => item.id === activeId, items) + const activeItem = items[activeItemIndex] + + return ( + + {show && ( + <> +
+ 产品推广 +
+ +
+
+ + + + )} +
+ ) +} + +export default React.memo(PromotionList) diff --git a/src/components/PromotionList/spec.ts b/src/components/PromotionList/spec.ts new file mode 100644 index 000000000..9cc1f7d44 --- /dev/null +++ b/src/components/PromotionList/spec.ts @@ -0,0 +1,7 @@ +export type TItem = { + id: string + title: string + link: string + desc: string + cover?: string +} diff --git a/src/components/PromotionList/styles/holder.ts b/src/components/PromotionList/styles/holder.ts deleted file mode 100755 index c7720ed7f..000000000 --- a/src/components/PromotionList/styles/holder.ts +++ /dev/null @@ -1,39 +0,0 @@ -import styled from 'styled-components' - -import { theme, css } from '@/utils' -import Img from '@/Img' - -export const Wrapper = styled.div` - ${css.flex()}; -` -export const BannerWrapper = styled.div` - ${css.flex()}; - margin-bottom: 12px; -` -export const Logo = styled(Img)` - fill: ${theme('thread.articleDigest')}; - ${css.size(30)}; - opacity: 0; - ${BannerWrapper}:hover & { - opacity: 1; - } - transition: all 0.2s; - transition-delay: 0.2s; -` -export const PartnerInfo = styled.div` - ${css.flexColumn('justify-center', 'align-center')}; - margin-right: 40px; -` -export const Title = styled.div` - color: ${theme('thread.articleTitle')}; - font-size: 0.9rem; -` -export const Desc = styled.div` - color: ${theme('thread.articleDigest')}; - font-size: 0.8rem; - opacity: 0; - ${BannerWrapper}:hover & { - opacity: 1; - } - transition: all 0.2s; -` diff --git a/src/components/PromotionList/styles/index.ts b/src/components/PromotionList/styles/index.ts index 13d01afef..9943be1d8 100755 --- a/src/components/PromotionList/styles/index.ts +++ b/src/components/PromotionList/styles/index.ts @@ -5,27 +5,22 @@ import { css, theme } from '@/utils' export const Wrapper = styled.div` margin-left: 20px; - margin-top: 40px; + margin-top: 30px; min-height: 150px; max-width: 180px; ` export const Header = styled.div` ${css.flex('justify-between', 'align-center')}; + padding-top: 20px; margin-bottom: 12px; + border-top: 1px solid; + border-top-color: ${theme('thread.articleSpliter')}; + width: 80%; ` export const Title = styled.div` + font-size: 12px; color: ${theme('thread.articleDigest')}; - border-top: 1px solid; - border-top-color: ${theme('thread.articleSpliter')}; padding-top: 15px; - width: 80px; - - ${Wrapper}:hover & { - width: 100%; - } - - transition: width 0.3s; - transition-delay: 0.2s; ` export const AboutIcon = styled(Img)` ${css.size(14)}; diff --git a/src/components/PromotionList/styles/partner_banner.ts b/src/components/PromotionList/styles/partner_banner.ts deleted file mode 100755 index 0f79c8550..000000000 --- a/src/components/PromotionList/styles/partner_banner.ts +++ /dev/null @@ -1,57 +0,0 @@ -import styled from 'styled-components' - -import { css, theme } from '@/utils' -import Img from '@/Img' - -export const Wrapper = styled.div` - ${css.flexColumn()}; -` -export const ItemWrapper = styled.div` - ${css.flex('align-center')}; - padding: 8px 0; - - &:hover { - cursor: pointer; - padding: 8px 5px; - border-radius: 4px; - } - transition: all 0.25s; - transition-delay: 0.2s; -` -export const Logo = styled(Img)` - ${css.size(20)}; - border-radius: 5px; - /* TODO: for dark themes */ - filter: saturate(0.8); - transition: all 0.25s; - transition-delay: 0.2s; - - ${ItemWrapper}:hover & { - width: 24px; - height: 24px; - } -` -export const PartnerInfo = styled.div` - ${css.flexColumn('justify-center')}; - margin-left: 10px; -` -export const Title = styled.div` - color: ${theme('thread.articleTitle')}; - font-size: 13px; - - ${ItemWrapper}:hover & { - font-weight: bold; - } -` -export const Desc = styled.div` - color: ${theme('thread.articleDigest')}; - font-size: 12px; - height: 1px; - overflow-y: hidden; - - ${ItemWrapper}:hover & { - height: 14px; - } - transition: all 0.25s; - transition-delay: 0.2s; -` diff --git a/src/components/PromotionList/styles/spotlight.ts b/src/components/PromotionList/styles/spotlight.ts new file mode 100755 index 000000000..7c2454893 --- /dev/null +++ b/src/components/PromotionList/styles/spotlight.ts @@ -0,0 +1,37 @@ +import styled from 'styled-components' + +import { css, theme } from '@/utils' +import Img from '@/Img' + +export const Wrapper = styled.div` + ${css.flexColumn()}; + background: #06303b; + padding: 15px 10px; + width: 100%; + height: auto; + border-radius: 5px; + margin-left: -12px; +` +export const ItemWrapper = styled.div` + ${css.flexColumn()}; +` +export const Header = styled.div` + ${css.flex('align-center', 'justify-between')}; + margin-left: 2px; +` +export const Logo = styled(Img)` + ${css.size(25)}; + border-radius: 5px; + margin-right: 10px; + /* TODO: for dark themes */ + filter: saturate(0.8); +` +export const Title = styled.div` + color: ${theme('thread.articleTitle')}; + font-size: 15px; +` +export const Desc = styled.div` + color: ${theme('thread.articleDigest')}; + font-size: 12px; + margin-top: 12px; +` diff --git a/src/components/PromotionList/styles/wait_list.ts b/src/components/PromotionList/styles/wait_list.ts new file mode 100644 index 000000000..10cb5ea3a --- /dev/null +++ b/src/components/PromotionList/styles/wait_list.ts @@ -0,0 +1,20 @@ +import styled from 'styled-components' + +import type { TActive } from '@/spec' +import { css, theme } from '@/utils' + +export const Wrapper = styled.div` + ${css.flex('align-center')}; + flex-wrap: wrap; + width: 100%; + margin-top: 10px; + margin-left: -2px; +` +export const Item = styled.div` + ${css.cutRest('50px')}; + color: ${({ active }) => + active ? theme('thread.articleTitle') : theme('thread.articleDigest')}; + font-size: ${({ active }) => (active ? '13px' : '12px')}; + margin-right: 8px; + margin-bottom: 2px; +` From 1b1a3f46257ea54b0ea0b6ce245c9d198ac2746d Mon Sep 17 00:00:00 2001 From: mydearxym Date: Sun, 4 Apr 2021 13:42:06 +0800 Subject: [PATCH 2/2] refactor(PromotionList): UX redesign --- public/icons/static/shape/about.svg | 1 + public/icons/static/shape/question.svg | 1 + src/components/PromotionList/WaitList.tsx | 9 ++++-- src/components/PromotionList/index.tsx | 32 +++++++++++++++---- src/components/PromotionList/styles/index.ts | 5 ++- .../PromotionList/styles/spotlight.ts | 2 +- .../PromotionList/styles/wait_list.ts | 9 +++++- src/hooks/index.ts | 1 + 8 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 public/icons/static/shape/about.svg create mode 100644 public/icons/static/shape/question.svg diff --git a/public/icons/static/shape/about.svg b/public/icons/static/shape/about.svg new file mode 100644 index 000000000..30a25636b --- /dev/null +++ b/public/icons/static/shape/about.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/static/shape/question.svg b/public/icons/static/shape/question.svg new file mode 100644 index 000000000..14cf8acf0 --- /dev/null +++ b/public/icons/static/shape/question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/PromotionList/WaitList.tsx b/src/components/PromotionList/WaitList.tsx index ce70c8494..2c28df092 100644 --- a/src/components/PromotionList/WaitList.tsx +++ b/src/components/PromotionList/WaitList.tsx @@ -6,13 +6,18 @@ import { Wrapper, Item } from './styles/wait_list' type TProps = { items: TItem[] activeId: string + setActiveId: (id: string) => void } -const WaitList: React.FC = ({ items, activeId }) => { +const WaitList: React.FC = ({ items, activeId, setActiveId }) => { return ( {items.map((item) => ( - + setActiveId(item.id)} + > {item.title} ))} diff --git a/src/components/PromotionList/index.tsx b/src/components/PromotionList/index.tsx index 5451ba63f..f76a76a50 100755 --- a/src/components/PromotionList/index.tsx +++ b/src/components/PromotionList/index.tsx @@ -4,11 +4,14 @@ * */ -import React, { useState } from 'react' +import React, { useState, useRef } from 'react' import { findIndex } from 'ramda' -import { ICON_CMD } from '@/config' +import { ICON } from '@/config' import { buildLog } from '@/utils' +import { useInterval } from '@/hooks' + +import useHoverDirty from 'react-use/lib/useHoverDirty' import type { TItem } from './spec' import Spotlight from './Spotlight' @@ -24,29 +27,46 @@ type TProps = { show?: boolean onAbout?: () => void items: TItem[] + intervalSec?: number } const PromotionList: React.FC = ({ show = true, onAbout = log, items = fakeItems, + intervalSec = 5000, }) => { - const [activeId, setActiveId] = useState(items[0].id) + const [activeId, setActiveId] = useState(items[0].id) const activeItemIndex = findIndex((item) => item.id === activeId, items) const activeItem = items[activeItemIndex] + const ref = useRef(null) + + const isHovering = useHoverDirty(ref) + + useInterval(() => { + if (isHovering) return + const nextIndex = + activeItemIndex < items.length - 1 ? activeItemIndex + 1 : 0 + setActiveId(items[nextIndex].id) + }, intervalSec) + return ( - + {show && ( <>
产品推广
- +
- + )}
diff --git a/src/components/PromotionList/styles/index.ts b/src/components/PromotionList/styles/index.ts index 9943be1d8..0d52c6c9f 100755 --- a/src/components/PromotionList/styles/index.ts +++ b/src/components/PromotionList/styles/index.ts @@ -23,7 +23,7 @@ export const Title = styled.div` padding-top: 15px; ` export const AboutIcon = styled(Img)` - ${css.size(14)}; + ${css.size(15)}; fill: ${theme('thread.articleDigest')}; opacity: 0; margin-top: 16px; @@ -36,6 +36,5 @@ export const AboutIcon = styled(Img)` ${Wrapper}:hover & { opacity: 1; } - transition: all 0.2s; - transition-delay: 0.2s; + transition: all 0.25s; ` diff --git a/src/components/PromotionList/styles/spotlight.ts b/src/components/PromotionList/styles/spotlight.ts index 7c2454893..31aab17f8 100755 --- a/src/components/PromotionList/styles/spotlight.ts +++ b/src/components/PromotionList/styles/spotlight.ts @@ -8,7 +8,7 @@ export const Wrapper = styled.div` background: #06303b; padding: 15px 10px; width: 100%; - height: auto; + min-height: 120px; border-radius: 5px; margin-left: -12px; ` diff --git a/src/components/PromotionList/styles/wait_list.ts b/src/components/PromotionList/styles/wait_list.ts index 10cb5ea3a..aa5c0c9a0 100644 --- a/src/components/PromotionList/styles/wait_list.ts +++ b/src/components/PromotionList/styles/wait_list.ts @@ -14,7 +14,14 @@ export const Item = styled.div` ${css.cutRest('50px')}; color: ${({ active }) => active ? theme('thread.articleTitle') : theme('thread.articleDigest')}; - font-size: ${({ active }) => (active ? '13px' : '12px')}; + font-size: 12px; margin-right: 8px; margin-bottom: 2px; + + &:hover { + cursor: pointer; + color: ${theme('thread.articleTitle')}; + } + + transition: all 0.3s; ` diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 1c0b6637c..44f925356 100755 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -11,5 +11,6 @@ export { default as useDevice } from './useDevice' export { default as useNetwork } from 'react-use/lib/useNetwork' export { default as useCopyToClipboard } from 'react-use/lib/useCopyToClipboard' +export { default as useInterval } from 'react-use/lib/useInterval' export { useSwipeable as useSwipe } from 'react-swipeable'