feat(space): add fill support (#2716)

* feat(space): add fill support

* feat(space): Add fill add fillPercentage support

* docs(space): Add fillPrecentage explain

* refactor(space): rename fillPercentage to fillRatio

* docs(space): add description of the fill property

* feat(space): add test for fill
This commit is contained in:
Aex
2021-07-30 11:39:07 +08:00
committed by GitHub
parent e0b79f8eda
commit e4891ab023
7 changed files with 495 additions and 9 deletions

View File

@@ -98,4 +98,38 @@ describe('Space.vue', () => {
expect(wrapper.element.children).toHaveLength(3)
})
test('fill', async () => {
const wrapper = mount(Space, {
slots: {
default: () =>
Array.from({ length: 2 }).map((_, idx) => {
return `test${idx}`
}),
},
props: {
fill: true,
},
})
await nextTick()
expect(wrapper.find('.el-space').attributes('style')).toContain(
'flex-wrap: wrap',
)
expect(wrapper.find('.el-space__item').attributes('style')).toContain(
'flex-grow: 1',
)
expect(wrapper.find('.el-space__item').attributes('style')).toContain(
'min-width: 100%',
)
// custom fill ratio
await wrapper.setProps({
fillRatio: 50,
})
await nextTick()
expect(wrapper.find('.el-space__item').attributes('style')).toContain(
'min-width: 50%',
)
})
})

View File

@@ -50,6 +50,16 @@ export const defaultProps = {
default: false,
},
fill: {
type: Boolean,
default: false,
},
fillRatio: {
type: Number,
default: 100,
},
size: {
type: [String, Array, Number] as PropType<
ComponentSize | [number, number] | number
@@ -73,8 +83,8 @@ export function useSpace(props: ExtractPropTypes<typeof defaultProps>) {
const verticalSize = ref(0)
watch(
() => [props.size, props.wrap, props.direction],
([size = 'small', wrap, dir]) => {
() => [props.size, props.wrap, props.direction, props.fill],
([size = 'small', wrap, dir, fill]) => {
// when the specified size have been given
if (isArray(size)) {
const [h = 0, v = 0] = size
@@ -88,7 +98,7 @@ export function useSpace(props: ExtractPropTypes<typeof defaultProps>) {
val = SizeMap[size as string] || SizeMap.small
}
if (wrap && dir === 'horizontal') {
if ((wrap || fill) && dir === 'horizontal') {
horizontalSize.value = verticalSize.value = val
} else {
if (dir === 'horizontal') {
@@ -105,9 +115,10 @@ export function useSpace(props: ExtractPropTypes<typeof defaultProps>) {
)
const containerStyle = computed(() => {
const wrapKls: CSSProperties = props.wrap
? { flexWrap: 'wrap', marginBottom: `-${verticalSize.value}px` }
: null
const wrapKls: CSSProperties =
props.wrap || props.fill
? { flexWrap: 'wrap', marginBottom: `-${verticalSize.value}px` }
: null
const alignment: CSSProperties = {
alignItems: props.alignment,
}
@@ -115,10 +126,16 @@ export function useSpace(props: ExtractPropTypes<typeof defaultProps>) {
})
const itemStyle = computed(() => {
return {
const itemBaseStyle = {
paddingBottom: `${verticalSize.value}px`,
marginRight: `${horizontalSize.value}px`,
}
const fillStyle = props.fill
? { flexGrow: 1, minWidth: `${props.fillRatio}%` }
: null
return [itemBaseStyle, fillStyle] as Array<CSSProperties>
})
return {

View File

@@ -269,6 +269,91 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
```
:::
### Fill the container
Through the `fill` **(Boolean type)** parameter, you can control whether the child node automatically fills the container.
In the following example, when set to `fill`, the width of the child node will automatically adapt to the width of the container.
:::demo Use fill to automatically fill the container with child nodes
```html
<template>
<div>
<div style="margin-bottom:15px">
fill: <el-switch v-model="fill"></el-switch>
</div>
<el-space :fill="fill" wrap>
<el-card class="box-card" v-for="i in 3" :key="i">
<template #header>
<div class="card-header">
<span>Card name</span>
<el-button class="button" type="text">Operation button</el-button>
</div>
</template>
<div v-for="o in 4" :key="o" class="text item">
{{ 'List item ' + o }}
</div>
</el-card>
</el-space>
</div>
</template>
<script>
export default {
data() {
return { fill: true }
},
}
</script>
```
:::
You can also use the `fillRatio` parameter to customize the filling ratio. The default value is `100`, which represents filling based on the width of the parent container at `100%`.
It should be noted that the expression of horizontal layout and vertical layout is slightly different, the specific effect can be viewed in the following example.
:::demo Use fillRatio to customize the fill ratio
```html
<template>
<div>
<div style="margin-bottom: 15px">
direction:
<el-radio v-model="direction" label="horizontal">horizontal</el-radio>
<el-radio v-model="direction" label="vertical">vertical</el-radio>
</div>
<div style="margin-bottom: 15px">
fillRatio:<el-slider v-model="fillRatio"></el-slider>
</div>
<el-space fill wrap :fillRatio="fillRatio" :direction="direction" style=" width: 100%">
<el-card class="box-card" v-for="i in 5" :key="i">
<template #header>
<div class="card-header">
<span>Card name</span>
<el-button class="button" type="text">Operation button</el-button>
</div>
</template>
<div v-for="o in 4" :key="o" class="text item">
{{ 'List item ' + o }}
</div>
</el-card>
</el-space>
</div>
</template>
<script>
export default {
data() {
return { direction: 'horizontal', fillRatio: 30 }
},
}
</script>
```
:::
### Space Attributes
| Attribute | Description | Type | Available value | Default |
@@ -281,7 +366,9 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
| spacer | Spacer | string / number / VNode | - | - |
| size | Spacing size | string / number / [number, number] | - | 'small' |
| wrap | Auto wrapping | boolean | true / false | false |
### Space Slots
| Name | Description |
| fill | Whether to fill the container | boolean | true / false | false |
| fillRatio | Ratio of fill | number | - | 100 |
### Space Slot
| name | description |
|----|----|
| default | Items to be spaced |

View File

@@ -269,6 +269,91 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
```
:::
### Fill the container
Through the `fill` **(Boolean type)** parameter, you can control whether the child node automatically fills the container.
In the following example, when set to `fill`, the width of the child node will automatically adapt to the width of the container.
:::demo Use fill to automatically fill the container with child nodes
```html
<template>
<div>
<div style="margin-bottom:15px">
fill: <el-switch v-model="fill"></el-switch>
</div>
<el-space :fill="fill" wrap>
<el-card class="box-card" v-for="i in 3" :key="i">
<template #header>
<div class="card-header">
<span>Card name</span>
<el-button class="button" type="text">Operation button</el-button>
</div>
</template>
<div v-for="o in 4" :key="o" class="text item">
{{ 'List item ' + o }}
</div>
</el-card>
</el-space>
</div>
</template>
<script>
export default {
data() {
return { fill: true }
},
}
</script>
```
:::
You can also use the `fillRatio` parameter to customize the filling ratio. The default value is `100`, which represents filling based on the width of the parent container at `100%`.
It should be noted that the expression of horizontal layout and vertical layout is slightly different, the specific effect can be viewed in the following example.
:::demo Use fillRatio to customize the fill ratio
```html
<template>
<div>
<div style="margin-bottom: 15px">
direction:
<el-radio v-model="direction" label="horizontal">horizontal</el-radio>
<el-radio v-model="direction" label="vertical">vertical</el-radio>
</div>
<div style="margin-bottom: 15px">
fillRatio:<el-slider v-model="fillRatio"></el-slider>
</div>
<el-space fill wrap :fillRatio="fillRatio" :direction="direction" style=" width: 100%">
<el-card class="box-card" v-for="i in 5" :key="i">
<template #header>
<div class="card-header">
<span>Card name</span>
<el-button class="button" type="text">Operation button</el-button>
</div>
</template>
<div v-for="o in 4" :key="o" class="text item">
{{ 'List item ' + o }}
</div>
</el-card>
</el-space>
</div>
</template>
<script>
export default {
data() {
return { direction: 'horizontal', fillRatio: 30 }
},
}
</script>
```
:::
### Space Attributes
| Attribute | Description | Type | Available value | Defaults |
@@ -281,6 +366,8 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
| spacer | Spacer | string / number / VNode | - | - |
| size | Spacing size | string / number / [number, number] | - | 'small' |
| wrap | Auto wrapping | boolean | true / false | false |
| fill | Whether to fill the container | boolean | true / false | false |
| fillRatio | Ratio of fill | number | - | 100 |
### Space Slot
| name | description |
|----|----|

View File

@@ -269,6 +269,91 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
```
:::
### Fill the container
Through the `fill` **(Boolean type)** parameter, you can control whether the child node automatically fills the container.
In the following example, when set to `fill`, the width of the child node will automatically adapt to the width of the container.
:::demo Use fill to automatically fill the container with child nodes
```html
<template>
<div>
<div style="margin-bottom:15px">
fill: <el-switch v-model="fill"></el-switch>
</div>
<el-space :fill="fill" wrap>
<el-card class="box-card" v-for="i in 3" :key="i">
<template #header>
<div class="card-header">
<span>Card name</span>
<el-button class="button" type="text">Operation button</el-button>
</div>
</template>
<div v-for="o in 4" :key="o" class="text item">
{{ 'List item ' + o }}
</div>
</el-card>
</el-space>
</div>
</template>
<script>
export default {
data() {
return { fill: true }
},
}
</script>
```
:::
You can also use the `fillRatio` parameter to customize the filling ratio. The default value is `100`, which represents filling based on the width of the parent container at `100%`.
It should be noted that the expression of horizontal layout and vertical layout is slightly different, the specific effect can be viewed in the following example.
:::demo Use fillRatio to customize the fill ratio
```html
<template>
<div>
<div style="margin-bottom: 15px">
direction:
<el-radio v-model="direction" label="horizontal">horizontal</el-radio>
<el-radio v-model="direction" label="vertical">vertical</el-radio>
</div>
<div style="margin-bottom: 15px">
fillRatio:<el-slider v-model="fillRatio"></el-slider>
</div>
<el-space fill wrap :fillRatio="fillRatio" :direction="direction" style=" width: 100%">
<el-card class="box-card" v-for="i in 5" :key="i">
<template #header>
<div class="card-header">
<span>Card name</span>
<el-button class="button" type="text">Operation button</el-button>
</div>
</template>
<div v-for="o in 4" :key="o" class="text item">
{{ 'List item ' + o }}
</div>
</el-card>
</el-space>
</div>
</template>
<script>
export default {
data() {
return { direction: 'horizontal', fillRatio: 30 }
},
}
</script>
```
:::
### Space Attributes
| Attribute | Description | Type | Available value | Defaults |
@@ -281,6 +366,8 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
| spacer | Spacer | string / number / VNode | - | - |
| size | Spacing size | string / number / [number, number] | - | 'small' |
| wrap | Auto wrapping | boolean | true / false | false |
| fill | Whether to fill the container | boolean | true / false | false |
| fillRatio | Ratio of fill | number | - | 100 |
### Space Slot
| name | description |
|----|----|

View File

@@ -269,6 +269,91 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
```
:::
### Fill the container
Through the `fill` **(Boolean type)** parameter, you can control whether the child node automatically fills the container.
In the following example, when set to `fill`, the width of the child node will automatically adapt to the width of the container.
:::demo Use fill to automatically fill the container with child nodes
```html
<template>
<div>
<div style="margin-bottom:15px">
fill: <el-switch v-model="fill"></el-switch>
</div>
<el-space :fill="fill" wrap>
<el-card class="box-card" v-for="i in 3" :key="i">
<template #header>
<div class="card-header">
<span>Card name</span>
<el-button class="button" type="text">Operation button</el-button>
</div>
</template>
<div v-for="o in 4" :key="o" class="text item">
{{ 'List item ' + o }}
</div>
</el-card>
</el-space>
</div>
</template>
<script>
export default {
data() {
return { fill: true }
},
}
</script>
```
:::
You can also use the `fillRatio` parameter to customize the filling ratio. The default value is `100`, which represents filling based on the width of the parent container at `100%`.
It should be noted that the expression of horizontal layout and vertical layout is slightly different, the specific effect can be viewed in the following example.
:::demo Use fillRatio to customize the fill ratio
```html
<template>
<div>
<div style="margin-bottom: 15px">
direction:
<el-radio v-model="direction" label="horizontal">horizontal</el-radio>
<el-radio v-model="direction" label="vertical">vertical</el-radio>
</div>
<div style="margin-bottom: 15px">
fillRatio:<el-slider v-model="fillRatio"></el-slider>
</div>
<el-space fill wrap :fillRatio="fillRatio" :direction="direction" style=" width: 100%">
<el-card class="box-card" v-for="i in 5" :key="i">
<template #header>
<div class="card-header">
<span>Card name</span>
<el-button class="button" type="text">Operation button</el-button>
</div>
</template>
<div v-for="o in 4" :key="o" class="text item">
{{ 'List item ' + o }}
</div>
</el-card>
</el-space>
</div>
</template>
<script>
export default {
data() {
return { direction: 'horizontal', fillRatio: 30 }
},
}
</script>
```
:::
### Space Attributes
| Attribute | Description | Type | Available value | Defaults |
@@ -281,6 +366,8 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
| spacer | Spacer | string / number / VNode | - | - |
| size | Spacing size | string / number / [number, number] | - | 'small' |
| wrap | Auto wrapping | boolean | true / false | false |
| fill | Whether to fill the container | boolean | true / false | false |
| fillRatio | Ratio of fill | number | - | 100 |
### Space Slot
| name | description |
|----|----|

View File

@@ -269,6 +269,91 @@ export default {
```
:::
### 自动填充容器
通过 `fill` **(布尔类型)** 参数可以控制子节点是否自动填充容器
下面的例子中,当设置为 `fill` 时,子节点的宽度会自动适配容器的宽度
:::demo 用 fill 让子节点自动填充容器
```html
<template>
<div>
<div style="margin-bottom:15px">
fill: <el-switch v-model="fill"></el-switch>
</div>
<el-space :fill="fill" wrap>
<el-card class="box-card" v-for="i in 3" :key="i">
<template #header>
<div class="card-header">
<span>Card name</span>
<el-button class="button" type="text">Operation button</el-button>
</div>
</template>
<div v-for="o in 4" :key="o" class="text item">
{{ 'List item ' + o }}
</div>
</el-card>
</el-space>
</div>
</template>
<script>
export default {
data() {
return { fill: true }
},
}
</script>
```
:::
也可以使用 `fillRatio` 参数,自定义填充的比例,默认值为 `100`,代表基于父容器宽度的 `100%` 进行填充
需要注意的是,水平布局和垂直布局的表现形式稍有不同,具体的效果可以查看下面的例子
:::demo 用 fillRatio 自定义填充比例
```html
<template>
<div>
<div style="margin-bottom: 15px">
direction:
<el-radio v-model="direction" label="horizontal">horizontal</el-radio>
<el-radio v-model="direction" label="vertical">vertical</el-radio>
</div>
<div style="margin-bottom: 15px">
fillRatio:<el-slider v-model="fillRatio"></el-slider>
</div>
<el-space fill wrap :fillRatio="fillRatio" :direction="direction" style=" width: 100%">
<el-card class="box-card" v-for="i in 5" :key="i">
<template #header>
<div class="card-header">
<span>Card name</span>
<el-button class="button" type="text">Operation button</el-button>
</div>
</template>
<div v-for="o in 4" :key="o" class="text item">
{{ 'List item ' + o }}
</div>
</el-card>
</el-space>
</div>
</template>
<script>
export default {
data() {
return { direction: 'horizontal', fillRatio: 30 }
},
}
</script>
```
:::
### Space Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
@@ -281,6 +366,8 @@ export default {
| spacer | 间隔符 | string / number / VNode | - | - |
| size | 间隔大小 | string / number / [number, number] | - | 'small' |
| wrap | 设置是否自动折行 | boolean | true / false | false |
| fill | 子元素是否填充父容器 | boolean | true / false | false |
| fillRatio | 填充父容器的比例 | number | - | 100 |
### Space Slot
| name | 说明 |
|----|----|