Skip to content

Commit f064999

Browse files
refactor(Space): less to cssinjs & add compact mode (#6229)
* refactor(Space): less to cssinjs & add compact mode * chore(space): update md * chore(space): add demo * chore(space): add some demo * feat(button): add compact mode * fix: reactivity lose * docs: fix props version --------- Co-authored-by: tangjinzhou <415800467@qq.com>
1 parent e2d4f8c commit f064999

File tree

17 files changed

+827
-84
lines changed

17 files changed

+827
-84
lines changed

components/button/button.tsx

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import useStyle from './style';
1919
import type { ButtonType } from './buttonTypes';
2020
import type { VNode, Ref } from 'vue';
2121
import { GroupSizeContext } from './button-group';
22+
import { useCompactItemContext } from '../space/Compact';
2223

2324
type Loading = boolean | number;
2425

@@ -49,6 +50,7 @@ export default defineComponent({
4950
const hasTwoCNChar = ref(false);
5051

5152
const autoInsertSpace = computed(() => autoInsertSpaceInButton.value !== false);
53+
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);
5254

5355
// =============== Update Loading ===============
5456
const loadingOrDelay = computed(() =>
@@ -79,22 +81,25 @@ export default defineComponent({
7981
const pre = prefixCls.value;
8082

8183
const sizeClassNameMap = { large: 'lg', small: 'sm', middle: undefined };
82-
const sizeFullname = groupSize?.value || size.value;
84+
const sizeFullname = compactSize.value || groupSize?.value || size.value;
8385
const sizeCls = sizeFullname ? sizeClassNameMap[sizeFullname] || '' : '';
8486

85-
return {
86-
[hashId.value]: true,
87-
[`${pre}`]: true,
88-
[`${pre}-${shape}`]: shape !== 'default' && shape,
89-
[`${pre}-${type}`]: type,
90-
[`${pre}-${sizeCls}`]: sizeCls,
91-
[`${pre}-loading`]: innerLoading.value,
92-
[`${pre}-background-ghost`]: ghost && !isUnBorderedButtonType(type),
93-
[`${pre}-two-chinese-chars`]: hasTwoCNChar.value && autoInsertSpace.value,
94-
[`${pre}-block`]: block,
95-
[`${pre}-dangerous`]: !!danger,
96-
[`${pre}-rtl`]: direction.value === 'rtl',
97-
};
87+
return [
88+
compactItemClassnames.value,
89+
{
90+
[hashId.value]: true,
91+
[`${pre}`]: true,
92+
[`${pre}-${shape}`]: shape !== 'default' && shape,
93+
[`${pre}-${type}`]: type,
94+
[`${pre}-${sizeCls}`]: sizeCls,
95+
[`${pre}-loading`]: innerLoading.value,
96+
[`${pre}-background-ghost`]: ghost && !isUnBorderedButtonType(type),
97+
[`${pre}-two-chinese-chars`]: hasTwoCNChar.value && autoInsertSpace.value,
98+
[`${pre}-block`]: block,
99+
[`${pre}-dangerous`]: !!danger,
100+
[`${pre}-rtl`]: direction.value === 'rtl',
101+
},
102+
];
98103
});
99104

100105
const fixTwoCNChar = () => {
@@ -209,7 +214,11 @@ export default defineComponent({
209214
);
210215

211216
if (!isUnBorderedButtonType(type)) {
212-
buttonNode = <Wave ref="wave" disabled={!!innerLoading.value}>{buttonNode}</Wave>;
217+
buttonNode = (
218+
<Wave ref="wave" disabled={!!innerLoading.value}>
219+
{buttonNode}
220+
</Wave>
221+
);
213222
}
214223

215224
return wrapSSR(buttonNode);

components/space/Compact.tsx

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import classNames from '../_util/classNames';
2+
import type { DirectionType, SizeType } from '../config-provider';
3+
import createContext from '../_util/createContext';
4+
import useConfigInject from '../config-provider/hooks/useConfigInject';
5+
6+
import useStyle from './style';
7+
import { computed, defineComponent } from 'vue';
8+
import type { PropType, ExtractPropTypes, Ref } from 'vue';
9+
import PropTypes from '../_util/vue-types';
10+
import { booleanType, tuple } from '../_util/type';
11+
import { isEmpty } from 'lodash-es';
12+
13+
export const spaceCompactItemProps = () => ({
14+
compactSize: String as PropType<SizeType>,
15+
compactDirection: PropTypes.oneOf(tuple('horizontal', 'vertical')).def('horizontal'),
16+
isFirstItem: booleanType(),
17+
isLastItem: booleanType(),
18+
});
19+
20+
export type SpaceCompactItemContextType = Partial<
21+
ExtractPropTypes<ReturnType<typeof spaceCompactItemProps>>
22+
>;
23+
24+
export const SpaceCompactItemContext = createContext<SpaceCompactItemContextType | null>(null);
25+
26+
export const useCompactItemContext = (prefixCls: Ref<string>, direction: Ref<DirectionType>) => {
27+
const compactItemContext = SpaceCompactItemContext.useInject();
28+
29+
const compactItemClassnames = computed(() => {
30+
if (!compactItemContext || isEmpty(compactItemContext)) return '';
31+
32+
const { compactDirection, isFirstItem, isLastItem } = compactItemContext;
33+
const separator = compactDirection === 'vertical' ? '-vertical-' : '-';
34+
35+
return classNames({
36+
[`${prefixCls.value}-compact${separator}item`]: true,
37+
[`${prefixCls.value}-compact${separator}first-item`]: isFirstItem,
38+
[`${prefixCls.value}-compact${separator}last-item`]: isLastItem,
39+
[`${prefixCls.value}-compact${separator}item-rtl`]: direction.value === 'rtl',
40+
});
41+
});
42+
43+
return {
44+
compactSize: computed(() => compactItemContext?.compactSize),
45+
compactDirection: computed(() => compactItemContext?.compactDirection),
46+
compactItemClassnames,
47+
};
48+
};
49+
50+
export const NoCompactStyle = defineComponent({
51+
name: 'NoCompactStyle',
52+
setup(_, { slots }) {
53+
SpaceCompactItemContext.useProvide(null);
54+
return () => {
55+
return slots.default?.();
56+
};
57+
},
58+
});
59+
60+
export const spaceCompactProps = () => ({
61+
prefixCls: String,
62+
size: {
63+
type: [String, Number, Array] as PropType<SizeType>,
64+
},
65+
direction: PropTypes.oneOf(tuple('horizontal', 'vertical')).def('horizontal'),
66+
align: PropTypes.oneOf(tuple('start', 'end', 'center', 'baseline')),
67+
block: { type: Boolean, default: undefined },
68+
});
69+
70+
export type SpaceCompactProps = Partial<ExtractPropTypes<ReturnType<typeof spaceCompactProps>>>;
71+
72+
const CompactItem = defineComponent({
73+
name: 'CompactItem',
74+
props: spaceCompactItemProps(),
75+
setup(props, { slots }) {
76+
SpaceCompactItemContext.useProvide(props);
77+
78+
return () => slots.default?.();
79+
},
80+
});
81+
82+
const Compact = defineComponent({
83+
name: 'ASpaceCompact',
84+
inheritAttrs: false,
85+
props: spaceCompactProps(),
86+
setup(props, { attrs, slots }) {
87+
const { prefixCls, direction: directionConfig } = useConfigInject('space-compact', props);
88+
const compactItemContext = SpaceCompactItemContext.useInject();
89+
90+
const [wrapSSR, hashId] = useStyle(prefixCls);
91+
92+
const clx = computed(() => {
93+
return classNames(prefixCls.value, hashId.value, {
94+
[`${prefixCls.value}-rtl`]: directionConfig.value === 'rtl',
95+
[`${prefixCls.value}-block`]: props.block,
96+
[`${prefixCls.value}-vertical`]: props.direction === 'vertical',
97+
});
98+
});
99+
100+
return () => {
101+
// =========================== Render ===========================
102+
if (slots.default?.()?.length === 0) {
103+
return null;
104+
}
105+
106+
const childNodes = slots.default?.() || [];
107+
108+
return wrapSSR(
109+
<div class={clx.value} {...attrs}>
110+
{childNodes.map((child, i) => {
111+
const key = (child && child.key) || `${prefixCls.value}-item-${i}`;
112+
const noCompactItemContext = !compactItemContext || isEmpty(compactItemContext);
113+
114+
return (
115+
<CompactItem
116+
key={key}
117+
compactSize={props.size}
118+
compactDirection={props.direction}
119+
isFirstItem={i === 0 && (noCompactItemContext || compactItemContext?.isFirstItem)}
120+
isLastItem={
121+
i === childNodes.length - 1 &&
122+
(noCompactItemContext || compactItemContext?.isLastItem)
123+
}
124+
>
125+
{child}
126+
</CompactItem>
127+
);
128+
})}
129+
</div>,
130+
);
131+
};
132+
},
133+
});
134+
135+
export default Compact;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<docs>
2+
---
3+
order: 8
4+
title:
5+
zh-CN: 垂直方向紧凑布局
6+
en-US: Vertical Compact Mode
7+
---
8+
9+
## zh-CN
10+
11+
垂直方向的紧凑布局,目前仅支持 Button 组合。
12+
13+
## en-US
14+
15+
Vertical Mode for Space.Compact, support Button only.
16+
17+
</docs>
18+
19+
<template>
20+
<a-space>
21+
<a-space-compact direction="vertical">
22+
<a-button>Button 1</a-button>
23+
<a-button>Button 2</a-button>
24+
<a-button>Button 3</a-button>
25+
</a-space-compact>
26+
<a-space-compact direction="vertical">
27+
<a-button type="dashed">Button 1</a-button>
28+
<a-button type="dashed">Button 2</a-button>
29+
<a-button type="dashed">Button 3</a-button>
30+
</a-space-compact>
31+
<a-space-compact direction="vertical">
32+
<a-button type="primary">Button 1</a-button>
33+
<a-button type="primary">Button 2</a-button>
34+
<a-button type="primary">Button 3</a-button>
35+
</a-space-compact>
36+
</a-space>
37+
</template>
38+
39+
<script lang="ts">
40+
import { defineComponent } from 'vue';
41+
42+
export default defineComponent({});
43+
</script>

0 commit comments

Comments
 (0)