Skip to content

refactor(Space): less to cssinjs & add compact mode #6229

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

Merged
merged 8 commits into from
Feb 12, 2023
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
39 changes: 24 additions & 15 deletions components/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import useStyle from './style';
import type { ButtonType } from './buttonTypes';
import type { VNode, Ref } from 'vue';
import { GroupSizeContext } from './button-group';
import { useCompactItemContext } from '../space/Compact';

type Loading = boolean | number;

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

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

// =============== Update Loading ===============
const loadingOrDelay = computed(() =>
Expand Down Expand Up @@ -79,22 +81,25 @@ export default defineComponent({
const pre = prefixCls.value;

const sizeClassNameMap = { large: 'lg', small: 'sm', middle: undefined };
const sizeFullname = groupSize?.value || size.value;
const sizeFullname = compactSize.value || groupSize?.value || size.value;
const sizeCls = sizeFullname ? sizeClassNameMap[sizeFullname] || '' : '';

return {
[hashId.value]: true,
[`${pre}`]: true,
[`${pre}-${shape}`]: shape !== 'default' && shape,
[`${pre}-${type}`]: type,
[`${pre}-${sizeCls}`]: sizeCls,
[`${pre}-loading`]: innerLoading.value,
[`${pre}-background-ghost`]: ghost && !isUnBorderedButtonType(type),
[`${pre}-two-chinese-chars`]: hasTwoCNChar.value && autoInsertSpace.value,
[`${pre}-block`]: block,
[`${pre}-dangerous`]: !!danger,
[`${pre}-rtl`]: direction.value === 'rtl',
};
return [
compactItemClassnames.value,
{
[hashId.value]: true,
[`${pre}`]: true,
[`${pre}-${shape}`]: shape !== 'default' && shape,
[`${pre}-${type}`]: type,
[`${pre}-${sizeCls}`]: sizeCls,
[`${pre}-loading`]: innerLoading.value,
[`${pre}-background-ghost`]: ghost && !isUnBorderedButtonType(type),
[`${pre}-two-chinese-chars`]: hasTwoCNChar.value && autoInsertSpace.value,
[`${pre}-block`]: block,
[`${pre}-dangerous`]: !!danger,
[`${pre}-rtl`]: direction.value === 'rtl',
},
];
});

const fixTwoCNChar = () => {
Expand Down Expand Up @@ -209,7 +214,11 @@ export default defineComponent({
);

if (!isUnBorderedButtonType(type)) {
buttonNode = <Wave ref="wave" disabled={!!innerLoading.value}>{buttonNode}</Wave>;
buttonNode = (
<Wave ref="wave" disabled={!!innerLoading.value}>
{buttonNode}
</Wave>
);
}

return wrapSSR(buttonNode);
Expand Down
135 changes: 135 additions & 0 deletions components/space/Compact.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import classNames from '../_util/classNames';
import type { DirectionType, SizeType } from '../config-provider';
import createContext from '../_util/createContext';
import useConfigInject from '../config-provider/hooks/useConfigInject';

import useStyle from './style';
import { computed, defineComponent } from 'vue';
import type { PropType, ExtractPropTypes, Ref } from 'vue';
import PropTypes from '../_util/vue-types';
import { booleanType, tuple } from '../_util/type';
import { isEmpty } from 'lodash-es';

export const spaceCompactItemProps = () => ({
compactSize: String as PropType<SizeType>,
compactDirection: PropTypes.oneOf(tuple('horizontal', 'vertical')).def('horizontal'),
isFirstItem: booleanType(),
isLastItem: booleanType(),
});

export type SpaceCompactItemContextType = Partial<
ExtractPropTypes<ReturnType<typeof spaceCompactItemProps>>
>;

export const SpaceCompactItemContext = createContext<SpaceCompactItemContextType | null>(null);

export const useCompactItemContext = (prefixCls: Ref<string>, direction: Ref<DirectionType>) => {
const compactItemContext = SpaceCompactItemContext.useInject();

const compactItemClassnames = computed(() => {
if (!compactItemContext || isEmpty(compactItemContext)) return '';

const { compactDirection, isFirstItem, isLastItem } = compactItemContext;
const separator = compactDirection === 'vertical' ? '-vertical-' : '-';

return classNames({
[`${prefixCls.value}-compact${separator}item`]: true,
[`${prefixCls.value}-compact${separator}first-item`]: isFirstItem,
[`${prefixCls.value}-compact${separator}last-item`]: isLastItem,
[`${prefixCls.value}-compact${separator}item-rtl`]: direction.value === 'rtl',
});
});

return {
compactSize: computed(() => compactItemContext?.compactSize),
compactDirection: computed(() => compactItemContext?.compactDirection),
compactItemClassnames,
};
};

export const NoCompactStyle = defineComponent({
name: 'NoCompactStyle',
setup(_, { slots }) {
SpaceCompactItemContext.useProvide(null);
return () => {
return slots.default?.();
};
},
});

export const spaceCompactProps = () => ({
prefixCls: String,
size: {
type: [String, Number, Array] as PropType<SizeType>,
},
direction: PropTypes.oneOf(tuple('horizontal', 'vertical')).def('horizontal'),
align: PropTypes.oneOf(tuple('start', 'end', 'center', 'baseline')),
block: { type: Boolean, default: undefined },
});

export type SpaceCompactProps = Partial<ExtractPropTypes<ReturnType<typeof spaceCompactProps>>>;

const CompactItem = defineComponent({
name: 'CompactItem',
props: spaceCompactItemProps(),
setup(props, { slots }) {
SpaceCompactItemContext.useProvide(props);

return () => slots.default?.();
},
});

const Compact = defineComponent({
name: 'ASpaceCompact',
inheritAttrs: false,
props: spaceCompactProps(),
setup(props, { attrs, slots }) {
const { prefixCls, direction: directionConfig } = useConfigInject('space-compact', props);
const compactItemContext = SpaceCompactItemContext.useInject();

const [wrapSSR, hashId] = useStyle(prefixCls);

const clx = computed(() => {
return classNames(prefixCls.value, hashId.value, {
[`${prefixCls.value}-rtl`]: directionConfig.value === 'rtl',
[`${prefixCls.value}-block`]: props.block,
[`${prefixCls.value}-vertical`]: props.direction === 'vertical',
});
});

return () => {
// =========================== Render ===========================
if (slots.default?.()?.length === 0) {
return null;
}

const childNodes = slots.default?.() || [];

return wrapSSR(
<div class={clx.value} {...attrs}>
{childNodes.map((child, i) => {
const key = (child && child.key) || `${prefixCls.value}-item-${i}`;
const noCompactItemContext = !compactItemContext || isEmpty(compactItemContext);

return (
<CompactItem
key={key}
compactSize={props.size}
compactDirection={props.direction}
isFirstItem={i === 0 && (noCompactItemContext || compactItemContext?.isFirstItem)}
isLastItem={
i === childNodes.length - 1 &&
(noCompactItemContext || compactItemContext?.isLastItem)
}
>
{child}
</CompactItem>
);
})}
</div>,
);
};
},
});

export default Compact;
43 changes: 43 additions & 0 deletions components/space/demo/compact-button-vertical.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<docs>
---
order: 8
title:
zh-CN: 垂直方向紧凑布局
en-US: Vertical Compact Mode
---

## zh-CN

垂直方向的紧凑布局,目前仅支持 Button 组合。

## en-US

Vertical Mode for Space.Compact, support Button only.

</docs>

<template>
<a-space>
<a-space-compact direction="vertical">
<a-button>Button 1</a-button>
<a-button>Button 2</a-button>
<a-button>Button 3</a-button>
</a-space-compact>
<a-space-compact direction="vertical">
<a-button type="dashed">Button 1</a-button>
<a-button type="dashed">Button 2</a-button>
<a-button type="dashed">Button 3</a-button>
</a-space-compact>
<a-space-compact direction="vertical">
<a-button type="primary">Button 1</a-button>
<a-button type="primary">Button 2</a-button>
<a-button type="primary">Button 3</a-button>
</a-space-compact>
</a-space>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({});
</script>
Loading