From cdd090487aa22734442c6e74df62ad7577260f08 Mon Sep 17 00:00:00 2001 From: ONLY-yours <1349021570@qq.com> Date: Thu, 9 Nov 2023 15:33:11 +0800 Subject: [PATCH] :sparkles: feat: add highlight hover emotion & language tag show --- .../components/LanguageTag/index.tsx | 80 +++++++++++++++++++ src/Highlight/defalut.tsx | 13 ++- src/Highlight/index.md | 17 ++-- src/Highlight/index.tsx | 2 + src/Highlight/style.ts | 30 +++++++ src/Highlight/wrapper.tsx | 4 +- 6 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 src/Highlight/components/LanguageTag/index.tsx diff --git a/src/Highlight/components/LanguageTag/index.tsx b/src/Highlight/components/LanguageTag/index.tsx new file mode 100644 index 00000000..3c9c50d9 --- /dev/null +++ b/src/Highlight/components/LanguageTag/index.tsx @@ -0,0 +1,80 @@ +import { ThemeType } from '@/Highlight/theme/type'; +import { Tag, type TagProps as AntTagProps } from 'antd'; +import Color from 'color'; +import { ReactNode } from 'react'; +import { createStyles } from '../../../theme'; +import { getThemeColor } from '../../theme/colors'; + +const useStyles = createStyles(({ cx, css, token }, { prefixCls, theme }) => { + const prefix = `${prefixCls}`; + + const { colorFillTertiary, colorText, colorTextSecondary } = getThemeColor(theme === 'dark'); + + const background = Color(colorFillTertiary) + .mix(Color(theme === 'dark' ? 'white' : 'black'), 0.03) + .alpha(0.9) + .hsl() + .string(); + + console.log('background', background); + + return { + small: cx( + `${prefix}-tag-small`, + css` + padding: 2px 6px; + line-height: 1; + `, + ), + lang: cx( + css` + position: absolute; + z-index: 2; + right: 0; + bottom: 8px; + background-color: ${background}; + font-family: ${token.fontFamilyCode}; + color: ${colorTextSecondary}; + transition: opacity 0.1s; + `, + ), + tag: cx( + `${prefix}-tag`, + css` + color: ${colorText} !important; + border-radius: ${token.borderRadius}px; + P &:hover { + color: ${colorText}; + background: ${token.colorFill}; + } + `, + ), + }; +}); + +export interface TagProps extends AntTagProps { + icon?: ReactNode; + size?: 'default' | 'small'; + theme?: ThemeType; + prefixCls?: string; +} + +const LanguageTag: React.FC = (props) => { + const { icon, children, size = 'default', theme = 'light', prefixCls, ...rest } = props || {}; + const { styles, cx } = useStyles({ theme, prefixCls }); + + console.log('rest', rest); + + return ( + <> + + {children} + + + ); +}; + +export default LanguageTag; diff --git a/src/Highlight/defalut.tsx b/src/Highlight/defalut.tsx index 12cde406..30a10e3b 100644 --- a/src/Highlight/defalut.tsx +++ b/src/Highlight/defalut.tsx @@ -3,6 +3,7 @@ import { createRef } from 'react'; import { getPrefixCls } from '../theme'; import CopyButton from './components/CopyButton'; import HighLighter from './components/HighLighter'; +import LanguageTag from './components/LanguageTag'; import { useKeyDownCopyEvent } from './hooks/useKeyDownCopyEvent'; import { useStyles } from './style'; import { THEME_LIGHT, ThemeType } from './theme'; @@ -65,6 +66,10 @@ export interface HighlightProps { * 是否需要默认外层 wrapper */ containerWrapper?: boolean; + /** + * 是否需默认展示语言种类 + */ + showLanguage?: boolean; } const HighlightBase: React.FC = (props) => { @@ -75,8 +80,9 @@ const HighlightBase: React.FC = (props) => { lineNumber = false, copyable = true, theme = THEME_LIGHT, - language, + language = 'tsx', prefixCls: customPrefixCls, + showLanguage = true, type = 'block', onCopy, } = props; @@ -96,6 +102,11 @@ const HighlightBase: React.FC = (props) => { {copyable && ( )} + {showLanguage && language && ( + + {language.toLowerCase()} + + )} { return ; }; +export * from './defalut'; +export * from './wrapper'; export { Highlight }; diff --git a/src/Highlight/style.ts b/src/Highlight/style.ts index 4f3d9f61..29f4e3ea 100644 --- a/src/Highlight/style.ts +++ b/src/Highlight/style.ts @@ -56,6 +56,18 @@ export const useStyles = createStyles( border-radius: ${token.borderRadius}px; transition: background-color 100ms ${token.motionEaseOut}; + :not(:hover) { + .${prefix}-copy { + visibility: hidden; + opacity: 0; + } + + .${prefix}-tag { + visibility: hidden; + opacity: 0; + } + } + pre { margin: 0 !important; padding: ${type === 'pure' ? 0 : `16px 24px`} !important; @@ -71,7 +83,25 @@ export const useStyles = createStyles( min-width: 100px; display: flex; justify-content: center; + span { + font-family: ${token.fontFamilyCode} !important; + } `, + lang: cx( + css` + position: absolute; + z-index: 2; + right: 0; + bottom: 8px; + + font-family: ${token.fontFamilyCode}; + color: ${token.colorTextSecondary}; + + // opacity: 0; + + transition: opacity 0.1s; + `, + ), expandIcon: css` color: ${colorText}; &:hover { diff --git a/src/Highlight/wrapper.tsx b/src/Highlight/wrapper.tsx index a96ecc4d..40b71aeb 100644 --- a/src/Highlight/wrapper.tsx +++ b/src/Highlight/wrapper.tsx @@ -33,6 +33,7 @@ export const FullFeatureWrapper = memo style, prefixCls: customPrefixCls, theme = THEME_LIGHT, + copyable = true, type = 'block', } = props || {}; const prefixCls = getPrefixCls('highlight', customPrefixCls); @@ -73,13 +74,14 @@ export const FullFeatureWrapper = memo suffixIcon={false} value={lang.toLowerCase()} /> - + {copyable && } );