Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Breadcrumb): 新增面包屑组件 #706

Merged
merged 6 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions components/_style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ import './avatarGroup/style';
import './progress/style';
import './transfer/style';
import './input-file/style';
import './breadcrumb/style';
2 changes: 2 additions & 0 deletions components/avatar/avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from 'vue';
import getPrefixCls from '../_util/getPrefixCls';
import { PictureFailOutlined } from '../icon';
import { useTheme } from '../_theme/useTheme';
import { avatarProps } from './props';
import { sizeMap } from './const';

Expand All @@ -19,6 +20,7 @@ export default defineComponent({
props: avatarProps,
emits: ['error'],
setup(props, { emit, slots }) {
useTheme();
const avatarCls = computed(() => {
return [
`${prefixCls}`,
Expand Down
2 changes: 2 additions & 0 deletions components/avatarGroup/avatarGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import getPrefixCls from '../_util/getPrefixCls';
import { FAvatar } from '../avatar';
import { FTooltip } from '../tooltip';
import { useTheme } from '../_theme/useTheme';
import { avatarGroupProps } from './props';

const prefixCls = getPrefixCls('avatar-group');
Expand All @@ -16,6 +17,7 @@ export default defineComponent({
name: 'FAvatarGroup',
props: avatarGroupProps,
setup(props, { slots }) {
useTheme();
// 渲染option
const renderAvatarByOption = (num?: number) => {
const avatarList = props.options.map((avatar, index) => {
Expand Down
36 changes: 36 additions & 0 deletions components/breadcrumb/breadcrumb-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { computed, defineComponent, inject } from 'vue';
import { useTheme } from '../_theme/useTheme';
import { BREADCRUMB_KEY, itemCls } from './const';

export default defineComponent({
name: 'FBreadcrumbItem',
emits: ['click'],
setup(props, { emit, slots }) {
useTheme();

const { props: parentProps } = inject(BREADCRUMB_KEY);

const itemStyle = computed(() => {
return {
fontSize: `${parentProps.fontSize}px`,
lineHeight: 1,
};
});

// 处理点击跳转的事件
const handleClick = () => {
// 触发用户自定义的click事件
emit('click');
};

return () => (
<div
class={itemCls}
style={itemStyle.value}
onClick={() => handleClick()}
>
{slots.default?.()}
</div>
);
},
});
46 changes: 46 additions & 0 deletions components/breadcrumb/breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { computed, defineComponent, provide } from 'vue';
import { useTheme } from '../_theme/useTheme';
import { breadcrumbProps } from './props';
import { BREADCRUMB_KEY, prefixCls } from './const';

export default defineComponent({
name: 'FBreadcrumb',
props: breadcrumbProps,
setup(props, { slots }) {
useTheme();

provide(BREADCRUMB_KEY, {
props: props,
});
const breadcrumbStyle = computed(() => {
return {
fontSize: `${props.fontSize}px`,
};
});

const breadItemArr = computed(() => {
return slots.default ? slots.default() : [];
});

// 渲染所有的层级
const renderAllItem = () => {
return breadItemArr.value.map((item, index) => {
return (
<div class={`${prefixCls}-child`}>
{item}
{/* 渲染分隔符 */}
<div class={`${prefixCls}-separator`}>
{index !== breadItemArr.value.length - 1 &&
props.separator}
</div>
</div>
);
});
};
return () => (
<div class={prefixCls} style={breadcrumbStyle.value}>
{slots.default && renderAllItem()}
</div>
);
},
});
10 changes: 10 additions & 0 deletions components/breadcrumb/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { type InjectionKey } from 'vue';
import getPrefixCls from '../_util/getPrefixCls';
import { type BreadcrumbInject } from './props';

export const prefixCls = getPrefixCls('breadcrumb');

export const itemCls = getPrefixCls('breadcrumb-item');

export const BREADCRUMB_KEY: InjectionKey<BreadcrumbInject> =
Symbol('BREADCRUMB_KEY');
19 changes: 19 additions & 0 deletions components/breadcrumb/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { withInstall } from '../_util/withInstall';
import Breadcrumb from './breadcrumb';
import BreadcrumbItem from './breadcrumb-item';
import type { SFCWithInstall } from '../_util/interface';

export { breadcrumbProps } from './props';
export type { BreadcrumbProps } from './props';

type BreadcrumbType = SFCWithInstall<typeof Breadcrumb>;
export const FBreadcrumb = withInstall<BreadcrumbType>(
Breadcrumb as BreadcrumbType,
);

type BreadCrumbItemType = SFCWithInstall<typeof BreadcrumbItem>;
export const FBreadCrumbItem = withInstall<BreadCrumbItemType>(
BreadcrumbItem as BreadCrumbItemType,
);

export default FBreadcrumb;
25 changes: 25 additions & 0 deletions components/breadcrumb/props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { type ComponentObjectPropsOptions } from 'vue';
import {
type ExtractPublicPropTypes,
type ComponentInnerProps,
} from '../_util/interface';

export const breadcrumbProps = {
// 分隔符,默认为/
separator: {
type: String,
default: '/',
},
fontSize: {
type: Number,
default: 14,
},
} as const satisfies ComponentObjectPropsOptions;

export type BreadcrumbProps = ExtractPublicPropTypes<typeof breadcrumbProps>;

type BreadcrumbInnerProps = ComponentInnerProps<typeof breadcrumbProps>;

export type BreadcrumbInject = {
props: BreadcrumbInnerProps;
};
42 changes: 42 additions & 0 deletions components/breadcrumb/style/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';

@breadcrumb: ~'@{cls-prefix}-breadcrumb';
@text-color: var(--f-sub-head-color);

@breadcrumb-item: ~'@{cls-prefix}-breadcrumb-item';
@hover-text-color: var(--f-font-color-base);

.@{breadcrumb} {
display: flex;
flex-wrap: wrap;
align-items: center;
color: @text-color;

&-child {
display: flex;
align-items: center;

.icon {
margin-right: 4px;
}
}

&-separator {
display: flex;
align-items: center;
justify-content: center;
min-width: 14px;
margin: 0 4px;
line-height: 1;
}
}

.@{breadcrumb-item} {
margin: 4px 0;

&:hover {
color: @hover-text-color;
cursor: pointer;
}
}
2 changes: 2 additions & 0 deletions components/breadcrumb/style/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import '../../style';
import './index.less';
1 change: 1 addition & 0 deletions components/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ export * from './avatarGroup';
export * from './progress';
export * from './transfer';
export * from './input-file';
export * from './breadcrumb';
32 changes: 32 additions & 0 deletions docs/.vitepress/components/breadcrumb/base.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<template>
<FForm :labelWidth="60">
<FFormItem label="分隔符:">
<FInput v-model="separator" class="form-item"></FInput>
</FFormItem>
<FFormItem label="字体大小:">
<FInputNumber v-model="fontSize" class="form-item"></FInputNumber>
</FFormItem>
</FForm>
<FDivider></FDivider>
<FBreadcrumb :separator="separator" :fontSize="fontSize">
<FBreadcrumbItem>首页</FBreadcrumbItem>
<FBreadcrumbItem>二级页面 </FBreadcrumbItem>
<FBreadcrumbItem>三级页面</FBreadcrumbItem>
<FBreadcrumbItem>四级页面</FBreadcrumbItem>
<FBreadcrumbItem>五级页面</FBreadcrumbItem>
</FBreadcrumb>
</template>

<script setup>
import { ref } from 'vue';

const separator = ref('/');

const fontSize = ref(14);
</script>

<style>
.form-item {
width: 100px;
}
</style>
17 changes: 17 additions & 0 deletions docs/.vitepress/components/breadcrumb/click.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<template>
<FBreadcrumb>
<FBreadcrumbItem @click="handleClick">首页</FBreadcrumbItem>
<FBreadcrumbItem>
<router-link :to="{ path: 'apple', query: { color: 'red' } }">
二级页面
</router-link>
</FBreadcrumbItem>
<FBreadcrumbItem>三级页面</FBreadcrumbItem>
</FBreadcrumb>
</template>

<script setup>
const handleClick = () => {
window.location.href = '/';
};
</script>
35 changes: 35 additions & 0 deletions docs/.vitepress/components/breadcrumb/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Breadcrumb 面包屑

显示当前页面的路径,快速返回之前的任意页面。

## 组件注册

```js
import { FBreadcrumb } from '@fesjs/fes-design';

app.use(FBreadcrumb);
```

## 代码演示

### 基础用法

:::demo
base.vue
:::

### 自定义点击事件
自定义某个item的点击事件。
同时点击行为,也可以和 vue-router 一起结合使用。

:::demo
click.vue
:::

## Breadcrumb Props

| 属性 | 说明 | 类型 | 默认值 |
| --------- | ----------------- | -------- | ------ |
| separator | 分隔符,默认为`/` | `string` | `-` |
| fontSize | 字体大小 | `number` | `14` |

8 changes: 6 additions & 2 deletions docs/.vitepress/configs/sidebar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,17 @@ const sidebarConfig: Record<string, DefaultTheme.Config['sidebar']> = {
text: '导航组件',
items: [
{
text: 'Menu 导航菜单',
link: '/zh/components/menu',
text: 'Breadcrumb 面包屑',
link: '/zh/components/breadcrumb',
},
{
text: 'Dropdown 下拉菜单',
link: '/zh/components/dropdown',
},
{
text: 'Menu 导航菜单',
link: '/zh/components/menu',
},
{
text: 'Steps 步骤条',
link: '/zh/components/steps',
Expand Down