Svelte组件:Steper
起由
在开发产品时,需要一个按照步骤进行配置的界面设计。查看了一些现有的方案后,决定自己来实现这个简单的功能。
效果
代码
Steper组件定义在文件Steper.svelte
中,代码如下:
<script>
/**
* @type (string[]) - 每个步进的显示名称
*/
export let steps = [];
export let currentActive = 1;
$: current_width = (currentActive - 1) / (steps.length - 1) * 100 + '%';
/**
*
* @param {number} stepIncrement - 步进, 例如: 1, -1
*/
export const handleProgress = (stepIncrement) => {
if(stepIncrement == 1){
currentActive++
if(currentActive > steps.length) {
currentActive = steps.length
}
} else {
currentActive--
if(currentActive < 1) {
currentActive = 1
}
}
}
</script>
<div class="progress-container">
<div class="progress" style:width={current_width} />
{#each steps as step, i}
<div class="circle" class:active={i < currentActive} data-title={step} >{i+1}</div>
{/each}
</div>
<style>
.progress-container {
display: flex;
justify-content: space-between;
position: relative;
margin-bottom: 30px;
max-width: 100%;
width: 350px;
}
.progress-container::before {
content: '';
background-color: #e0e0e0;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 100%;
z-index: -1;
}
.progress {
background-color: #3498db;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
height: 4px;
width: 0%;
z-index: -1;
transition: 0.4s ease;
}
.circle {
background-color: #fff;
color: #999;
border-radius: 50%;
height: 30px;
width: 30px;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid #e0e0e0;
transition: 0.4s ease;
cursor: pointer;
}
.circle::after{
content: attr(data-title) " ";
position: absolute;
bottom: 35px;
color: #999;
transition: 0.4s ease;
}
.circle.active::after {
color: #3498db;
}
.circle.active {
border-color: #3498db;
}
</style>
那么如何使用呢?
<script>
import Steper from '$lib/components/Steper.svelte';
</script>
<form class="w-full flex flex-col items-center mt-6">
<Steper {steps} bind:currentActive bind:this={steper}/>
<div class="w-full h-[300px]">
{#if currentActive == 1}
<div class="w-full h-full flex flex-col items-center justify-center">Info</div>
{:else if currentActive == 2}
<div class="w-full h-full flex flex-col items-center justify-center">Topic</div>
{:else if currentActive == 3}
<div class="w-full h-full flex flex-col items-center justify-center">Mode</div>
{/if}
</div>
<div class="w-full flex mt-4">
<Button class="w-24" on:click={prevStep}>Prev</Button>
{#if currentActive < steps.length}
<Button class="w-24 ml-auto" on:click={nextStep}>Next</Button>
{:else}
<Button class="w-24 ml-auto" variant="destructive" on:click={createProject}>Create</Button>
{/if}
</div>
</form>