From f8101a9831fc75a0847ae1aaff23e3fde285748d Mon Sep 17 00:00:00 2001 From: blankzhang Date: Mon, 13 May 2024 17:05:14 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E9=93=BE=E6=8E=A5=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=BC=80=E5=8F=91=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/_style.ts | 1 + components/components.ts | 1 + components/link/index.ts | 11 ++++ components/link/link.tsx | 40 ++++++++++++ components/link/props.ts | 50 ++++++++++++++ components/link/style/index.less | 83 ++++++++++++++++++++++++ components/link/style/index.ts | 2 + docs/.vitepress/components/link/base.vue | 47 ++++++++++++++ docs/.vitepress/components/link/href.vue | 3 + docs/.vitepress/components/link/icon.vue | 12 ++++ docs/.vitepress/components/link/index.md | 51 +++++++++++++++ docs/.vitepress/configs/sidebar/index.ts | 6 +- 12 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 components/link/index.ts create mode 100644 components/link/link.tsx create mode 100644 components/link/props.ts create mode 100644 components/link/style/index.less create mode 100644 components/link/style/index.ts create mode 100644 docs/.vitepress/components/link/base.vue create mode 100644 docs/.vitepress/components/link/href.vue create mode 100644 docs/.vitepress/components/link/icon.vue create mode 100644 docs/.vitepress/components/link/index.md diff --git a/components/_style.ts b/components/_style.ts index b67dc744..51612f96 100644 --- a/components/_style.ts +++ b/components/_style.ts @@ -60,3 +60,4 @@ import './transfer/style'; import './input-file/style'; import './breadcrumb/style'; import './text-highlight/style'; +import './link/style'; diff --git a/components/components.ts b/components/components.ts index 24a8f8e5..f3d655c1 100644 --- a/components/components.ts +++ b/components/components.ts @@ -58,3 +58,4 @@ export * from './transfer'; export * from './input-file'; export * from './breadcrumb'; export * from './text-highlight'; +export * from './link'; diff --git a/components/link/index.ts b/components/link/index.ts new file mode 100644 index 00000000..d4ae69ea --- /dev/null +++ b/components/link/index.ts @@ -0,0 +1,11 @@ +import { withInstall } from '../_util/withInstall'; +import type { SFCWithInstall } from '../_util/interface'; +import Link from './link'; + +export { linkProps } from './props'; +export type { LinkProps } from './props'; + +type LinkType = SFCWithInstall; +export const FLink = withInstall(Link as LinkType); + +export default FLink; diff --git a/components/link/link.tsx b/components/link/link.tsx new file mode 100644 index 00000000..74e8113e --- /dev/null +++ b/components/link/link.tsx @@ -0,0 +1,40 @@ +import { computed, defineComponent } from 'vue'; +import getPrefixCls from '../_util/getPrefixCls'; +import { useTheme } from '../_theme/useTheme'; +import { linkProps } from './props'; + +const prefixCls = getPrefixCls('link'); + +export default defineComponent({ + name: 'FLink', + props: linkProps, + setup(props, { slots }) { + useTheme(); + + const linkClass = computed(() => { + const cls: string[] = [`${prefixCls}-container`, + `${prefixCls}-type-${props.type}`, + `${prefixCls}-size-${props.size}`, + ]; + + props.disabled && cls.push(`${prefixCls}-container-disabled`); + props.underline && cls.push('underline'); + return cls; + }); + + const renderLink = () => { + return ( + + {slots.icon ? (
{slots.icon?.()}
) : null} + {slots.default?.()} +
+ ); + }; + + return () => ( +
+ {renderLink()} +
+ ); + }, +}); diff --git a/components/link/props.ts b/components/link/props.ts new file mode 100644 index 00000000..11a6301d --- /dev/null +++ b/components/link/props.ts @@ -0,0 +1,50 @@ +import type { ComponentObjectPropsOptions, PropType } from 'vue'; +import type { ExtractPublicPropTypes } from '../_util/interface'; + +export enum Size { + LARGE = 'large', + MIDDLE = 'middle', + SMALL = 'small', +} + +export enum Type { + PRIMARY = 'primary', + SUCCESS = 'success', + DANGER = 'danger', + WARNING = 'warning', +} + +export enum TargetType { + BLANK = '_blank', + SELF = '_self', + PARENT = '_parent', + TOP = '_top', +} + +export const linkProps = { + size: { + type: String as PropType, + default: Size.MIDDLE, + }, + type: { + type: String as PropType, + default: Type.PRIMARY, + }, + underline: { + type: Boolean, + default: true, + }, + disabled: { + type: Boolean, + default: false, + }, + href: { + type: String, + }, + target: { + type: String as PropType, + default: TargetType.SELF, + }, +} as const satisfies ComponentObjectPropsOptions; + +export type LinkProps = ExtractPublicPropTypes; diff --git a/components/link/style/index.less b/components/link/style/index.less new file mode 100644 index 00000000..f6382724 --- /dev/null +++ b/components/link/style/index.less @@ -0,0 +1,83 @@ +@import '../../style/themes/index'; +@import '../../style/mixins/index'; + + +@link-prefix-cls: ~'@{cls-prefix}-link'; + +@link-height-small: @link-height-base - 2; +@link-height-base: 20px; +@link-height-large: @link-height-base + 2; + +.@{link-prefix-cls} { + --f-link-height: @link-height-base; + display: inline-flex; + height: var(--f-link-height); + line-height: var(--f-link-height); + + &-container { + position: relative; + display: inline-flex; + align-items: center; + height: var(--f-link-height); + line-height: var(--f-link-height); + cursor: pointer; + + .icon { + display: flex; + align-items: center; + justify-content: center; + margin-right: 4px; + } + + &-disabled, &:hover { + &::after { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgb(255 255 255 / 0.4); /* 半透明的白色 */ + content: ""; + pointer-events: none; /* 让鼠标事件穿透蒙层 */ + } + } + + &-disabled { + cursor: not-allowed; + } + + &:not(&-disabled).underline:hover { + border-bottom: 1px solid currentcolor; + } + } + + &-size-middle { + font-size: var(--f-font-size-base); + } + + &-size-small { + --f-link-height: @link-height-small; + font-size: calc(var(--f-font-size-base) - 2px); + } + + &-size-large { + --f-link-height: @link-height-large; + font-size: calc(var(--f-font-size-base) + 2px); + } + + &-type-success { + color: var(--f-success-color); + } + + &-type-danger { + color: var(--f-danger-color); + } + + &-type-warning { + color: var(--f-warning-color); + } + + &-type-primary { + color: var(--f-primary-color); + } +} \ No newline at end of file diff --git a/components/link/style/index.ts b/components/link/style/index.ts new file mode 100644 index 00000000..ed51d175 --- /dev/null +++ b/components/link/style/index.ts @@ -0,0 +1,2 @@ +import '../../style'; +import './index.less'; diff --git a/docs/.vitepress/components/link/base.vue b/docs/.vitepress/components/link/base.vue new file mode 100644 index 00000000..f659b7e1 --- /dev/null +++ b/docs/.vitepress/components/link/base.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/docs/.vitepress/components/link/href.vue b/docs/.vitepress/components/link/href.vue new file mode 100644 index 00000000..360b1dd6 --- /dev/null +++ b/docs/.vitepress/components/link/href.vue @@ -0,0 +1,3 @@ + diff --git a/docs/.vitepress/components/link/icon.vue b/docs/.vitepress/components/link/icon.vue new file mode 100644 index 00000000..dee4d61d --- /dev/null +++ b/docs/.vitepress/components/link/icon.vue @@ -0,0 +1,12 @@ + + + diff --git a/docs/.vitepress/components/link/index.md b/docs/.vitepress/components/link/index.md new file mode 100644 index 00000000..ee43cbad --- /dev/null +++ b/docs/.vitepress/components/link/index.md @@ -0,0 +1,51 @@ +# Link 链接 + +文字超链接 + +## 组件注册 + +```js +import { FLink } from '@fesjs/fes-design'; + +app.use(FLink); +``` + +## 代码演示 + +### 基础用法 + +:::demo +base.vue +::: + +### 跳转 +通过设置`target`,设定跳转行为,同原生a标签的`target`属性 +若`href`不设置,则点击不会发生任何跳转 + +:::demo +href.vue +::: + +### 图标 +提供了图标的插槽 + +:::demo +icon.vue +::: + +## Props +| 属性 | 说明 | 类型 | 默认值 | +| --------- | --------------------------------------------------- | --------- | --------- | +| size | 尺寸大小,可选`small`,`middle`,`large` | `string` | `middle` | +| type | 类型,可选`primary`,`success`,`danger`,`warning` | `string` | `primary` | +| underline | 展示下划线 | `boolean` | `true` | +| disabled | 是否禁用 | `boolean` | `false` | +| href | 跳转链接 | `string` | `-` | +| target | 跳转行为,同原生target | `string` | `_self` | + +## Slots + +| 名称 | 说明 | 参数 | +| ------- | -------- | ---- | +| default | 链接内容 | `-` | +| icon | 图标 | `-` | \ No newline at end of file diff --git a/docs/.vitepress/configs/sidebar/index.ts b/docs/.vitepress/configs/sidebar/index.ts index ca4b53b4..78ad5230 100644 --- a/docs/.vitepress/configs/sidebar/index.ts +++ b/docs/.vitepress/configs/sidebar/index.ts @@ -1,4 +1,4 @@ -import { type DefaultTheme } from 'vitepress'; +import type { DefaultTheme } from 'vitepress'; const sidebarConfig: Record = { zh: { @@ -178,6 +178,10 @@ const sidebarConfig: Record = { text: 'Image 图片', link: '/zh/components/image', }, + { + text: 'Link 链接', + link: '/zh/components/link', + }, { text: 'Table 表格', link: '/zh/components/table',