mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2025-12-11 13:26:16 +00:00
fix: revamp reset popup
This commit is contained in:
51
src/lib/style/elements/_popover.scss
Normal file
51
src/lib/style/elements/_popover.scss
Normal file
@@ -0,0 +1,51 @@
|
||||
$animation-duration: 150ms;
|
||||
$translate: translateY(8px);
|
||||
|
||||
[popover] {
|
||||
position: absolute;
|
||||
inset: unset;
|
||||
transform: $translate;
|
||||
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--md-sys-color-outline);
|
||||
border-radius: 8px;
|
||||
|
||||
color: var(--md-sys-color-on-surface);
|
||||
|
||||
opacity: 0;
|
||||
background: var(--md-sys-color-surface);
|
||||
|
||||
transition:
|
||||
transform $animation-duration ease,
|
||||
opacity $animation-duration ease,
|
||||
overlay $animation-duration allow-discrete,
|
||||
display $animation-duration allow-discrete;
|
||||
|
||||
position-area: bottom span-right;
|
||||
position-try-fallbacks:
|
||||
top span-right,
|
||||
bottom span-left,
|
||||
top span-left;
|
||||
|
||||
position-visibility: no-overflow;
|
||||
|
||||
&:popover-open {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> h1:first-child,
|
||||
h2:first-child,
|
||||
h3:first-child {
|
||||
margin-top: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@starting-style {
|
||||
[popover]:popover-open {
|
||||
transform: $translate;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
@use "print";
|
||||
|
||||
@use "elements/h1";
|
||||
@use "elements/popover";
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
|
||||
@@ -161,7 +161,10 @@
|
||||
><span class="icon">reset_settings</span>Reset Settings</button
|
||||
>
|
||||
{/if}
|
||||
<button use:popup={ResetPopup}>Recovery...</button>
|
||||
<button popovertarget="reset-device" popovertargetaction="toggle"
|
||||
>Recovery...</button
|
||||
>
|
||||
<div id="reset-device" popover="auto"><ResetPopup /></div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { serialPort } from "$lib/serial/connection";
|
||||
|
||||
let { challenge, onconfirm }: { challenge: string; onconfirm: () => void } =
|
||||
$props();
|
||||
|
||||
let challengeInput = $state("");
|
||||
let challengeString = $derived(`${challenge} ${$serialPort!.device}`);
|
||||
let isValid = $derived(challengeInput === challengeString);
|
||||
</script>
|
||||
|
||||
<h3>Type the following to confirm the action</h3>
|
||||
|
||||
<p>{challengeString}</p>
|
||||
<!-- svelte-ignore a11y_autofocus -->
|
||||
<input
|
||||
autofocus
|
||||
type="text"
|
||||
bind:value={challengeInput}
|
||||
placeholder={challengeString}
|
||||
/>
|
||||
|
||||
<button disabled={!isValid} onclick={onconfirm}>Confirm {challenge}</button>
|
||||
|
||||
<style lang="scss">
|
||||
input[type="text"] {
|
||||
color: inherit;
|
||||
font-family: inherit;
|
||||
background: none;
|
||||
border: none;
|
||||
border-bottom: 1px solid currentcolor;
|
||||
width: 100%;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: var(--md-sys-color-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
color: var(--md-sys-color-error);
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import { confirmChallenge } from "./confirm-challenge";
|
||||
import { serialPort } from "$lib/serial/connection";
|
||||
|
||||
const options = [
|
||||
@@ -17,21 +16,27 @@
|
||||
</script>
|
||||
|
||||
<h3>Reset Device</h3>
|
||||
<p>Resetting might take <b>up to 2 Minutes</b>.</p>
|
||||
{#each options as category, i}
|
||||
{#if i > 0}
|
||||
<hr />
|
||||
{/if}
|
||||
{#each category as [command, description]}
|
||||
<button
|
||||
class="error"
|
||||
use:confirmChallenge={{
|
||||
onConfirm() {
|
||||
$serialPort?.reset(command);
|
||||
$serialPort = undefined;
|
||||
},
|
||||
challenge: description,
|
||||
}}>{description}...</button
|
||||
<form
|
||||
onsubmit={(event) => {
|
||||
event.preventDefault();
|
||||
$serialPort?.reset(command);
|
||||
$serialPort = undefined;
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={description}
|
||||
required
|
||||
pattern="^{description}$"
|
||||
/>
|
||||
<button class="icon" type="submit">send</button>
|
||||
</form>
|
||||
{/each}
|
||||
{/each}
|
||||
|
||||
@@ -39,4 +44,43 @@
|
||||
hr {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 22ch;
|
||||
}
|
||||
|
||||
button.icon {
|
||||
font-size: 20px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
color: inherit;
|
||||
font-family: inherit;
|
||||
background: none;
|
||||
border: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
width: fit-content;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: var(--md-sys-color-outline);
|
||||
}
|
||||
}
|
||||
|
||||
input[type="text"]:valid {
|
||||
color: var(--md-sys-color-error);
|
||||
|
||||
& + button {
|
||||
color: var(--md-sys-color-error);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import type { Action } from "svelte/action";
|
||||
import ConfirmChallenge from "./ConfirmChallenge.svelte";
|
||||
import tippy from "tippy.js";
|
||||
import { mount, unmount } from "svelte";
|
||||
|
||||
export const confirmChallenge: Action<
|
||||
HTMLElement,
|
||||
{ onConfirm: () => void; challenge: string }
|
||||
> = (node, { onConfirm, challenge }) => {
|
||||
let component: {} | undefined;
|
||||
let target: HTMLElement | undefined;
|
||||
const edit = tippy(node, {
|
||||
interactive: true,
|
||||
trigger: "click",
|
||||
onShow(instance) {
|
||||
target = instance.popper.querySelector(".tippy-content") as HTMLElement;
|
||||
target.classList.add("active");
|
||||
if (component === undefined) {
|
||||
component = mount(ConfirmChallenge, {
|
||||
target,
|
||||
props: {
|
||||
challenge,
|
||||
onconfirm() {
|
||||
edit.hide();
|
||||
onConfirm();
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
onHidden() {
|
||||
if (component) {
|
||||
unmount(component);
|
||||
}
|
||||
target?.classList.remove("active");
|
||||
component = undefined;
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
edit.destroy();
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user