Skip to content
Closed
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
* include documents in npm package for ai agents ([#960](https://github.com/WeBankFinTech/fes-design/issues/960)) ([3cc476c](https://github.com/WeBankFinTech/fes-design/commit/3cc476c81fb652c7fc3887884d99b46a02de0b74))


### Refactor

* refactor(space): 改用 grid gap 实现 ([#885](https://github.com/WeBankFinTech/fes-design/issues/885))



## [0.8.84](https://github.com/WeBankFinTech/fes-design/compare/v0.8.83...v0.8.84) (2025-11-04)

Expand Down
50 changes: 50 additions & 0 deletions components/space/__tests__/space-885.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { describe, it, expect } from 'vitest';
import { mount } from '@vue/test-utils';
import FSpace from '../index';
import '../space';

describe('Space Grid Layout #885', () => {
it('space.tsx uses grid display (not flex)', async () => {
const fsSpace = mount(FSpace, {
slots: {
default: [
{ template: '<span>1</span>' },
{ template: '<span>2</span>' },
{ template: '<span>3</span>' },
],
},
});
const el = fsSpace.element as HTMLElement;
expect(el.style.display).toBe('grid');
});

it('space.tsx sets gridTemplateColumns with repeat(auto-fit or auto-fill)', async () => {
const fsSpace = mount(FSpace, {
slots: {
default: [
{ template: '<span>1</span>' },
{ template: '<span>2</span>' },
{ template: '<span>3</span>' },
],
},
});
const el = fsSpace.element as HTMLElement;
expect(el.style.gridTemplateColumns).toMatch(/repeat\((auto-fit|auto-fill)/);
});

it('FSpace with 3 children renders with display grid', async () => {
const wrapper = mount(FSpace, {
props: { size: 8 },
slots: {
default: [
{ template: '<button>Btn1</button>' },
{ template: '<button>Btn2</button>' },
{ template: '<button>Btn3</button>' },
],
},
});
const el = wrapper.element as HTMLElement;
expect(el.style.display).toBe('grid');
expect(wrapper.findAll('.fes-space > *')).toHaveLength(3);
});
});
48 changes: 19 additions & 29 deletions components/space/space.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,25 @@ import type { TThemeVars } from '../_theme/base';
import { COMPONENT_NAME, prefixCls } from './const';
import { type SpaceInnerProps, spaceProps } from './props';

const useMargin = (props: SpaceInnerProps, themeVarsRef: Ref<TThemeVars>) => {
const margin = computed(() => {
const useGap = (props: SpaceInnerProps, themeVarsRef: Ref<TThemeVars>) => {
const gap = computed(() => {
const { size } = props;
let horizontal = 0;
let vertical = 0;

if (Array.isArray(size)) {
horizontal = size[0];
vertical = size[1];
return { row: size[0], col: size[1] };
} else if (typeof size === 'number') {
horizontal = size;
vertical = size;
} else {
const currentSize = depx(
themeVarsRef.value[createKey('padding', size)]
|| themeVarsRef.value[createKey('padding', 'small')],
);
horizontal = currentSize;
vertical = currentSize;
return { row: size, col: size };
}

return {
horizontal: `${horizontal}px`,
vertical: `${vertical}px`,
};
const currentSize = depx(
themeVarsRef.value[createKey('padding', size)]
|| themeVarsRef.value[createKey('padding', 'small')],
);
return { row: currentSize, col: currentSize };
});

return {
margin,
gap,
};
};

Expand All @@ -45,11 +35,11 @@ export default defineComponent({
setup(props) {
const { themeVars } = useTheme();

const { margin } = useMargin(props, themeVars);
const { gap } = useGap(props, themeVars);

return {
prefixCls,
margin,
gap,
};
},
render() {
Expand All @@ -62,7 +52,7 @@ export default defineComponent({
itemStyle,
wrap,
prefixCls,
margin,
gap,
} = this;

const children = flatten(getSlot(this.$slots) || []).filter((node) =>
Expand All @@ -74,14 +64,14 @@ export default defineComponent({
role="none"
class={`${prefixCls}`}
style={{
display: inline ? 'inline-flex' : 'flex',
flexDirection: vertical ? 'column' : 'row',
justifyContent: ['start', 'end'].includes(justify)
display: inline ? 'inline-grid' : 'grid',
gridTemplateColumns: vertical ? 'unset' : 'repeat(auto-fit, minmax(0, 1fr))',
gridTemplateRows: vertical ? 'repeat(auto-fit, minmax(0, 1fr))' : 'unset',
justifyItems: justify === 'start' || justify === 'end'
? `flex-${justify}`
: justify,
: justify === 'center' ? 'center' : justify,
alignItems: align,
flexWrap: !wrap || vertical ? 'nowrap' : 'wrap',
gap: `${margin.vertical} ${margin.horizontal}`,
gap: `${gap.row}px ${gap.col}px`,
}}
>
{ wrapItem
Expand Down
Loading