diff --git a/src/components/Badge/index.scss b/src/components/Badge/index.scss new file mode 100644 index 000000000..698cbd4dc --- /dev/null +++ b/src/components/Badge/index.scss @@ -0,0 +1,38 @@ +@import '../../styles/variables.scss'; + +.vant-badge { + display: inline-block; + box-sizing: border-box; + min-width: $badge-size; + padding: $badge-padding; + color: $badge-color; + font-weight: $badge-font-weight; + font-size: $badge-font-size; + font-family: $badge-font-family; + line-height: 1.2; + text-align: center; + background-color: $badge-background-color; + border: $badge-border-width solid $white; + border-radius: $border-radius-max; + + &__fixed { + position: absolute; + top: 0; + right: 0; + transform: translate(50%, -50%); + transform-origin: 100%; + } + + &__dot { + width: $badge-dot-size; + min-width: 0; + height: $badge-dot-size; + background-color: $badge-dot-color; + border-radius: 100%; + } + + &__wrapper { + position: relative; + display: inline-block; + } +} diff --git a/src/components/Badge/index.stories.tsx b/src/components/Badge/index.stories.tsx new file mode 100644 index 000000000..b867d8aed --- /dev/null +++ b/src/components/Badge/index.stories.tsx @@ -0,0 +1,80 @@ +import React from 'react'; +import Badge from '.'; +import '../../styles/stories.scss'; + +export default { + title: 'Badge', + component: Badge +}; +const style = { + width: '50px', + height: '50px', + backgroundColor: '#f2f3f5', + borderRadius: '8px' +}; +const Child = () => { + return
; +}; +const Basic = () => { + return ( + + + + ); +}; +const BasicHigher = () => { + return ( + + + + ); +}; +const Color = () => { + return ( + + + + ); +}; +const Dot = () => { + return ( + + + + ); +}; +const FCContent = () => { + return
FCContent
; +}; +const WithFC = () => { + // console.log(+FCContent) + return ( + + + + ); +}; +class ClassContent extends React.Component { + render() { + return
ClassContent
; + } +} +const WithClass = () => { + return ( + + + + ); +}; +export const All = () => { + return ( +
+ + + + + + +
+ ); +}; diff --git a/src/components/Badge/index.tsx b/src/components/Badge/index.tsx new file mode 100644 index 000000000..c73e625bb --- /dev/null +++ b/src/components/Badge/index.tsx @@ -0,0 +1,56 @@ +import React, { FC, ReactNode } from 'react'; +import './index.scss'; +import classnames from '../../utils/classNames'; +export interface BadgeProps { + content: string | number | ReactNode; + color?: string; + dot?: boolean; + max: number | string; +} +const baseClass = 'vant-badge'; +const Badge: FC = ({ + content, + color = '#ee0a24', + dot = false, + max, + children +}) => { + const renderContent = () => { + if (dot) return ''; + if (content) { + if (!!max && Number.isInteger(+content) && +content > max) { + return <>{`${max}+`}; + } else { + if (typeof content === 'string' || typeof content === 'number') { + return <>{`${content}`}; + } else { + const ContentComponent = content as FC; + return <>{ContentComponent ? : null}; + } + } + } + return ''; + }; + const renderBadge = () => { + if (content || dot) { + return ( +
+ {renderContent()} +
+ ); + } + }; + if (children) { + return ( +
+ {children} + {renderBadge()} +
+ ); + } + return <>{renderBadge()}; +}; +export default Badge; diff --git a/src/styles/stories.scss b/src/styles/stories.scss index 31378b7a4..d75b0aded 100644 --- a/src/styles/stories.scss +++ b/src/styles/stories.scss @@ -145,3 +145,7 @@ body { font-weight: 100; } } +.badge{ + display: flex; + justify-content: space-around; +} diff --git a/src/styles/variables.scss b/src/styles/variables.scss index 89bf0f928..f0fadf4b8 100644 --- a/src/styles/variables.scss +++ b/src/styles/variables.scss @@ -1,3 +1,72 @@ +// Color Palette +$black: #000; +$white: #fff; +$gray-1: #f7f8fa; +$gray-2: #f2f3f5; +$gray-3: #ebedf0; +$gray-4: #dcdee0; +$gray-5: #c8c9cc; +$gray-6: #969799; +$gray-7: #646566; +$gray-8: #323233; +$red: #ee0a24; +$blue: #1989fa; +$orange: #ff976a; +$orange-dark: #ed6a0c; +$orange-light: #fffbe8; +$green: #07c160; + +// Gradient Colors +$gradient-red: linear-gradient(to right, #ff6034, #ee0a24); +$gradient-orange: linear-gradient(to right, #ffd01e, #ff8917); + +// Component Colors +$text-color: $gray-8; +$active-color: $gray-2; +$active-opacity: 0.7; +$disabled-opacity: 0.5; +$background-color: $gray-1; +$background-color-light: #fafafa; +$text-link-color: #576b95; + +// Padding +$padding-base: 4px; +$padding-xs: $padding-base * 2; +$padding-sm: $padding-base * 3; +$padding-md: $padding-base * 4; +$padding-lg: $padding-base * 6; +$padding-xl: $padding-base * 8; + +// Font +$font-size-xs: 10px; +$font-size-sm: 12px; +$font-size-md: 14px; +$font-size-lg: 16px; +$font-weight-bold: 500; +$line-height-xs: 14px; +$line-height-sm: 18px; +$line-height-md: 20px; +$line-height-lg: 22px; +$base-font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', + Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', + 'Microsoft Yahei', sans-serif; +$price-integer-font-family: Avenir-Heavy, PingFang SC, Helvetica Neue, Arial, + sans-serif; + +// Animation +$animation-duration-base: 0.3s; +$animation-duration-fast: 0.2s; +$animation-timing-function-enter: ease-out; +$animation-timing-function-leave: ease-in; + +// Border +$border-color: $gray-3; +$border-width-base: 1px; +$border-radius-sm: 2px; +$border-radius-md: 4px; +$border-radius-lg: 8px; +$border-radius-max: 999px; + // loaders $loader-size: 20px; $loader-animation-duration: 2s; @@ -16,3 +85,15 @@ $icon-dot-size: 8px; // popups $popup-alpha: 0.5; $popup-background-color: #000; + +// badge +$badge-size: 16px; +$badge-color: $white; +$badge-padding: 0 3px; +$badge-font-size: $font-size-sm; +$badge-font-weight: $font-weight-bold; +$badge-border-width: $border-width-base; +$badge-background-color: $red; +$badge-dot-color: $red; +$badge-dot-size: 8px; +$badge-font-family: -apple-system-font, Helvetica Neue, Arial, sans-serif