diff --git a/CHANGELOG.md b/CHANGELOG.md index f6de20655..7f36a688a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/components/space/__tests__/space-885.spec.ts b/components/space/__tests__/space-885.spec.ts new file mode 100644 index 000000000..0715210f0 --- /dev/null +++ b/components/space/__tests__/space-885.spec.ts @@ -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: '1' }, + { template: '2' }, + { template: '3' }, + ], + }, + }); + 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: '1' }, + { template: '2' }, + { template: '3' }, + ], + }, + }); + 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: '' }, + { template: '' }, + { template: '' }, + ], + }, + }); + const el = wrapper.element as HTMLElement; + expect(el.style.display).toBe('grid'); + expect(wrapper.findAll('.fes-space > *')).toHaveLength(3); + }); +}); \ No newline at end of file diff --git a/components/space/space.tsx b/components/space/space.tsx index 3377c4210..8f38829d4 100644 --- a/components/space/space.tsx +++ b/components/space/space.tsx @@ -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) => { - const margin = computed(() => { +const useGap = (props: SpaceInnerProps, themeVarsRef: Ref) => { + 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, }; }; @@ -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() { @@ -62,7 +52,7 @@ export default defineComponent({ itemStyle, wrap, prefixCls, - margin, + gap, } = this; const children = flatten(getSlot(this.$slots) || []).filter((node) => @@ -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