141 lines
3.4 KiB
Plaintext
141 lines
3.4 KiB
Plaintext
package components
|
|
|
|
import "strconv"
|
|
|
|
// StepInfo represents a single step in the stepper
|
|
type StepInfo struct {
|
|
Number int
|
|
Label string
|
|
}
|
|
|
|
// OnboardingStepper renders a 3-step progress indicator
|
|
// currentStep: 1-indexed current step number
|
|
// steps: slice of step labels (e.g., []string{"Welcome", "Learn", "Get Started"})
|
|
templ OnboardingStepper(currentStep int, steps []string) {
|
|
@stepperStyles()
|
|
<div class="onboarding-stepper">
|
|
for i, label := range steps {
|
|
@stepperItem(i+1, label, currentStep)
|
|
if i < len(steps)-1 {
|
|
@stepperLine(i+1 < currentStep)
|
|
}
|
|
}
|
|
</div>
|
|
}
|
|
|
|
// stepperItem renders a single step circle with label
|
|
templ stepperItem(stepNum int, label string, currentStep int) {
|
|
<div class={ "stepper-item", templ.KV("active", stepNum == currentStep), templ.KV("completed", stepNum < currentStep) } data-step={ strconv.Itoa(stepNum) }>
|
|
<div class="stepper-number">
|
|
if stepNum < currentStep {
|
|
<wa-icon name="check" style="font-size: 14px;"></wa-icon>
|
|
} else {
|
|
{ strconv.Itoa(stepNum) }
|
|
}
|
|
</div>
|
|
<span class="stepper-label">{ label }</span>
|
|
</div>
|
|
}
|
|
|
|
// stepperLine renders the connecting line between steps
|
|
templ stepperLine(completed bool) {
|
|
<div class={ "stepper-line", templ.KV("completed", completed) }></div>
|
|
}
|
|
|
|
// ProgressDots renders a compact dot-based progress indicator
|
|
templ ProgressDots(current int, total int) {
|
|
<div class="progress-dots">
|
|
for i := 1; i <= total; i++ {
|
|
<div class={ "progress-dot", templ.KV("active", i == current), templ.KV("completed", i < current) }></div>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
templ stepperStyles() {
|
|
<style>
|
|
.onboarding-stepper {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: var(--wa-space-s);
|
|
padding: var(--wa-space-m) 0;
|
|
}
|
|
.stepper-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--wa-space-xs);
|
|
}
|
|
.stepper-number {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: var(--wa-font-size-s);
|
|
font-weight: 600;
|
|
background: var(--wa-color-neutral-200);
|
|
color: var(--wa-color-neutral-600);
|
|
transition: all 0.3s;
|
|
}
|
|
.stepper-item.active .stepper-number {
|
|
background: var(--wa-color-primary);
|
|
color: white;
|
|
box-shadow: 0 0 0 4px var(--wa-color-primary-subtle);
|
|
}
|
|
.stepper-item.completed .stepper-number {
|
|
background: var(--wa-color-success);
|
|
color: white;
|
|
}
|
|
.stepper-label {
|
|
font-size: var(--wa-font-size-xs);
|
|
color: var(--wa-color-neutral-500);
|
|
display: none;
|
|
}
|
|
@media (min-width: 480px) {
|
|
.stepper-label {
|
|
display: block;
|
|
}
|
|
}
|
|
.stepper-item.active .stepper-label {
|
|
color: var(--wa-color-primary);
|
|
font-weight: 500;
|
|
}
|
|
.stepper-line {
|
|
width: 40px;
|
|
height: 2px;
|
|
background: var(--wa-color-neutral-200);
|
|
transition: background 0.3s;
|
|
}
|
|
.stepper-line.completed {
|
|
background: var(--wa-color-success);
|
|
}
|
|
/* Progress dots */
|
|
.progress-dots {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: var(--wa-space-xs);
|
|
}
|
|
.progress-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: var(--wa-color-neutral-200);
|
|
transition: all 0.3s;
|
|
}
|
|
.progress-dot.active {
|
|
background: var(--wa-color-primary);
|
|
transform: scale(1.25);
|
|
}
|
|
.progress-dot.completed {
|
|
background: var(--wa-color-success);
|
|
}
|
|
/* Responsive adjustments */
|
|
@media (max-height: 600px) {
|
|
.onboarding-stepper {
|
|
padding: var(--wa-space-s) 0;
|
|
}
|
|
}
|
|
</style>
|
|
}
|