mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-06 08:22:24 +01:00
feature (admin): reduce onboarding friction
This commit is contained in:
parent
95c878f671
commit
a383322e1c
3 changed files with 113 additions and 2 deletions
|
|
@ -42,6 +42,52 @@
|
|||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
.component_setup #step2 #onboarding {
|
||||
position: fixed;
|
||||
right: 32px;
|
||||
bottom: 32px;
|
||||
border-radius: 16px;
|
||||
padding: 12px 18px;
|
||||
color: var(--light);
|
||||
}
|
||||
.component_setup #step2 #onboarding .dash-border {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.component_setup #step2 #onboarding .dash-border rect {
|
||||
width: calc(100% - 4px);
|
||||
height: calc(100% - 4px);
|
||||
fill: none;
|
||||
stroke: #57595A;
|
||||
stroke-width: 3;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-dasharray: 8 6;
|
||||
animation: dash-move 1.2s linear infinite;
|
||||
}
|
||||
@keyframes dash-move {
|
||||
to { stroke-dashoffset: -14; }
|
||||
}
|
||||
.component_setup #step2 #onboarding svg {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
.component_setup #step2 #onboarding svg path {
|
||||
stroke-width: 3;
|
||||
fill: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke: #57595A;
|
||||
}
|
||||
.component_setup #step2 #onboarding svg g {
|
||||
fill: #57595A;
|
||||
}
|
||||
|
||||
.component_setup .stepper-form-appear, .component_setup .stepper-form-enter {
|
||||
transition-delay: 0.3s;
|
||||
transform: scale(1.02);
|
||||
|
|
@ -58,3 +104,12 @@
|
|||
.component_setup .component_icon {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.pulse {
|
||||
animation: zoomPulse 1.2s ease-in-out infinite;
|
||||
transform-origin: center left;
|
||||
}
|
||||
@keyframes zoomPulse {
|
||||
0%, 100% { transform: scale(1.03); }
|
||||
50% { transform: scale(1.07); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ function componentStep2(render) {
|
|||
You're at the Helm now
|
||||
</h4>
|
||||
<div data-bind="dependencies"></div>
|
||||
<div data-bind="onboarding"></div>
|
||||
<style>${cssHideMenu}</style>
|
||||
</div>
|
||||
`);
|
||||
|
|
@ -187,6 +188,8 @@ function componentStep2(render) {
|
|||
};
|
||||
return ret.toPromise();
|
||||
};
|
||||
|
||||
// feature: modal
|
||||
effect(getAdminConfig().pipe(
|
||||
reshapeConfigBeforeSave,
|
||||
rxjs.delay(300),
|
||||
|
|
@ -197,7 +200,57 @@ function componentStep2(render) {
|
|||
config["log"]["telemetry"] = enabled;
|
||||
return config;
|
||||
}),
|
||||
rxjs.filter((config) => !!config),
|
||||
saveConfig(),
|
||||
rxjs.mergeMap((config) => {
|
||||
if (config) return rxjs.of(config).pipe(saveConfig());
|
||||
return rxjs.of(null);
|
||||
}),
|
||||
// feature: onboarding
|
||||
rxjs.mapTo(createElement(`
|
||||
<div id="onboarding">
|
||||
<strong>Next step: Link your storage</strong>
|
||||
<svg class="dash-border">
|
||||
<rect x="2" y="2" rx="16" ry="16"></rect>
|
||||
</svg>
|
||||
<svg>
|
||||
<path id="path" pathLength="1" stroke-dasharray="1" stroke-dashoffset="1">
|
||||
<animate attributeName="stroke-dashoffset" begin="indefinite" dur="700ms" fill="freeze" values="1;0" calcMode="linear" />
|
||||
</path>
|
||||
<g>
|
||||
<polygon points="4,0 -16,-8 -16,8"></polygon>
|
||||
<animateMotion begin="indefinite" dur="700ms" fill="freeze" rotate="auto" calcMode="linear">
|
||||
<mpath href="#path"></mpath>
|
||||
</animateMotion>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
`)),
|
||||
applyMutation(qs($page, "[data-bind=\"onboarding\"]"), "appendChild"),
|
||||
rxjs.delay(500),
|
||||
rxjs.map(($origin) => {
|
||||
const $target = document.querySelector("a[href=\"/admin/storage\"]");
|
||||
const $path = $origin.querySelector("svg path");
|
||||
const $anims = [
|
||||
$origin.querySelector("svg animate"),
|
||||
$origin.querySelector("svg animateMotion"),
|
||||
];
|
||||
|
||||
const arc = (start, end) => {
|
||||
const r = Math.min(Math.abs(end.x - start.x), Math.abs(end.y - start.y)) * 0.9;
|
||||
return `M ${start.x},${start.y} ` +
|
||||
`L ${start.x},${end.y + r} ` +
|
||||
`Q ${start.x},${end.y} ${start.x - r},${end.y} ` +
|
||||
`L ${end.x+20},${end.y+2}`;
|
||||
};
|
||||
const o = $origin.getBoundingClientRect();
|
||||
const t = $target.getBoundingClientRect();
|
||||
$path.setAttribute("d", arc(
|
||||
{ x: o.left + o.width/2, y: o.top },
|
||||
{ x: t.right, y: t.top + t.height/2 }
|
||||
));
|
||||
$anims.forEach(($el) => $el.beginElement());
|
||||
$target.classList.add("pulse");
|
||||
return $origin;
|
||||
}),
|
||||
rxjs.switchMap(($node) => rxjs.fromEvent(window, "resize").pipe(rxjs.tap(() => $node.remove()))),
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@
|
|||
bottom: 0;
|
||||
opacity: 0.25;
|
||||
}
|
||||
.component_menu_sidebar ul li a {
|
||||
display: inline-block;
|
||||
}
|
||||
.component_menu_sidebar .header {
|
||||
display: block;
|
||||
height: 40px;
|
||||
|
|
|
|||
Loading…
Reference in a new issue