feat: ReSegmented分段控制器新增size属性,以便适配不同的场景 (#1016)

* feat: `ReSegmented`分段控制器新增`size`属性,以便适配不同的场景
This commit is contained in:
Fifteen 2024-03-24 13:55:44 +08:00 committed by GitHub
parent 4f44f72a2c
commit f486ba60a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 131 additions and 41 deletions

View File

@ -1,11 +1,20 @@
.pure-segmented {
--pure-control-padding-horizontal: 12px;
--pure-control-padding-horizontal-sm: 8px;
--pure-segmented-track-padding: 2px;
--pure-segmented-line-width: 1px;
--pure-segmented-border-radius-small: 4px;
--pure-segmented-border-radius-base: 6px;
--pure-segmented-border-radius-large: 8px;
box-sizing: border-box;
display: inline-block;
padding: 2px;
font-size: 14px;
padding: var(--pure-segmented-track-padding);
font-size: var(--el-font-size-base);
color: rgba(0, 0, 0, 0.65);
background-color: rgb(0 0 0 / 4%);
border-radius: 2px;
border-radius: var(--pure-segmented-border-radius-base);
}
.pure-segmented-block {
@ -23,6 +32,75 @@
text-overflow: ellipsis;
}
/* small */
.pure-segmented.pure-segmented--small {
border-radius: var(--pure-segmented-border-radius-small);
}
.pure-segmented.pure-segmented--small .pure-segmented-item {
border-radius: var(--el-border-radius-small);
}
.pure-segmented.pure-segmented--small .pure-segmented-item > div {
min-height: calc(
var(--el-component-size-small) - var(--pure-segmented-track-padding) * 2
);
line-height: calc(
var(--el-component-size-small) - var(--pure-segmented-track-padding) * 2
);
padding: 0
calc(
var(--pure-control-padding-horizontal-sm) -
var(--pure-segmented-line-width)
);
}
/* large */
.pure-segmented.pure-segmented--large {
border-radius: var(--pure-segmented-border-radius-large);
}
.pure-segmented.pure-segmented--large .pure-segmented-item {
border-radius: calc(
var(--el-border-radius-base) + var(--el-border-radius-small)
);
}
.pure-segmented.pure-segmented--large .pure-segmented-item > div {
min-height: calc(
var(--el-component-size-large) - var(--pure-segmented-track-padding) * 2
);
line-height: calc(
var(--el-component-size-large) - var(--pure-segmented-track-padding) * 2
);
padding: 0
calc(
var(--pure-control-padding-horizontal) - var(--pure-segmented-line-width)
);
font-size: var(--el-font-size-medium);
}
/* default */
.pure-segmented-item {
position: relative;
text-align: center;
cursor: pointer;
border-radius: var(--el-border-radius-base);
transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
}
.pure-segmented .pure-segmented-item > div {
min-height: calc(
var(--el-component-size) - var(--pure-segmented-track-padding) * 2
);
line-height: calc(
var(--el-component-size) - var(--pure-segmented-track-padding) * 2
);
padding: 0
calc(
var(--pure-control-padding-horizontal) - var(--pure-segmented-line-width)
);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
transition: 0.1s;
}
.pure-segmented-group {
position: relative;
display: flex;
@ -52,23 +130,6 @@
will-change: transform, width;
}
.pure-segmented-item {
position: relative;
text-align: center;
cursor: pointer;
border-radius: 4px;
transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
}
.pure-segmented-item > div {
min-height: 28px;
line-height: 28px;
padding: 0 11px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.pure-segmented-item > input {
position: absolute;
inset-block-start: 0;

View File

@ -1,5 +1,14 @@
import "./index.css";
import type { OptionsType } from "./type";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import {
useDark,
isNumber,
isFunction,
useResizeObserver
} from "@pureadmin/utils";
import {
type PropType,
h,
ref,
toRef,
@ -8,14 +17,6 @@ import {
defineComponent,
getCurrentInstance
} from "vue";
import type { OptionsType } from "./type";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import {
isFunction,
isNumber,
useDark,
useResizeObserver
} from "@pureadmin/utils";
const props = {
options: {
@ -32,6 +33,10 @@ const props = {
block: {
type: Boolean,
default: false
},
/** 控件尺寸 */
size: {
type: String as PropType<"small" | "default" | "large">
}
};
@ -81,13 +86,14 @@ export default defineComponent({
function handleInit(index = curIndex.value) {
nextTick(() => {
const curLabelRef = instance?.proxy?.$refs[`labelRef${index}`] as ElRef;
if (!curLabelRef) return;
width.value = curLabelRef.clientWidth;
translateX.value = curLabelRef.offsetLeft;
initStatus.value = true;
});
}
if (props.block) {
function handleResizeInit() {
useResizeObserver(".pure-segmented", () => {
nextTick(() => {
handleInit(curIndex.value);
@ -95,6 +101,8 @@ export default defineComponent({
});
}
props.block && handleResizeInit();
watch(
() => curIndex.value,
index => {
@ -103,11 +111,12 @@ export default defineComponent({
});
},
{
deep: true,
immediate: true
}
);
watch(() => props.size, handleResizeInit);
const rendLabel = () => {
return props.options.map((option, index) => {
return (
@ -167,7 +176,12 @@ export default defineComponent({
return () => (
<div
class={["pure-segmented", props.block ? "pure-segmented-block" : ""]}
class={{
"pure-segmented": true,
"pure-segmented-block": props.block,
"pure-segmented--large": props.size === "large",
"pure-segmented--small": props.size === "small"
}}
>
<div class="pure-segmented-group">
<div

View File

@ -1,5 +1,5 @@
<script setup lang="tsx">
import { h, ref } from "vue";
import { h, ref, watch } from "vue";
import { message } from "@/utils/message";
import HomeFilled from "@iconify-icons/ep/home-filled";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
@ -11,6 +11,8 @@ defineOptions({
/** 基础用法 */
const value = ref(4); // number
const size = ref("default");
const dynamicSize = ref();
const optionsBasis: Array<OptionsType> = [
{
@ -192,13 +194,22 @@ function onChange({ index, option }) {
type: "success"
});
}
watch(size, val => (dynamicSize.value = size.value));
</script>
<template>
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">分段控制器</span>
<el-space wrap :size="40">
<span style="font-size: 16px; font-weight: 800"> 分段控制器 </span>
<el-radio-group v-model="size" size="small">
<el-radio value="large">大尺寸</el-radio>
<el-radio value="default">默认尺寸</el-radio>
<el-radio value="small">小尺寸</el-radio>
</el-radio-group>
</el-space>
</div>
</template>
<el-scrollbar>
@ -207,28 +218,32 @@ function onChange({ index, option }) {
{{ optionsBasis[value].label }}
</span>
</p>
<Segmented v-model="value" :options="optionsBasis" />
<Segmented v-model="value" :options="optionsBasis" :size="dynamicSize" />
<el-divider />
<p class="mb-2">tooltip 提示</p>
<Segmented :options="optionsTooltip" />
<Segmented :options="optionsTooltip" :size="dynamicSize" />
<el-divider />
<p class="mb-2">change 事件</p>
<Segmented :options="optionsChange" @change="onChange" />
<Segmented
:options="optionsChange"
:size="dynamicSize"
@change="onChange"
/>
<el-divider />
<p class="mb-2">禁用</p>
<Segmented :options="optionsDisabled" />
<Segmented :options="optionsDisabled" :size="dynamicSize" />
<el-divider />
<p class="mb-2">block 属性(将宽度调整为父元素宽度)</p>
<Segmented :options="optionsBlock" block />
<Segmented :options="optionsBlock" block :size="dynamicSize" />
<el-divider />
<p class="mb-2">可设置图标</p>
<Segmented :options="optionsIcon" />
<Segmented :options="optionsIcon" :size="dynamicSize" />
<el-divider />
<p class="mb-2">只设置图标</p>
<Segmented :options="optionsOnlyIcon" />
<Segmented :options="optionsOnlyIcon" :size="dynamicSize" />
<el-divider />
<p class="mb-2">自定义渲染</p>
<Segmented :options="optionsLabel" />
<Segmented :options="optionsLabel" :size="dynamicSize" />
</el-scrollbar>
</el-card>
</template>