mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-01-07 02:22:52 +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 "print";
|
||||||
|
|
||||||
@use "elements/h1";
|
@use "elements/h1";
|
||||||
|
@use "elements/popover";
|
||||||
|
|
||||||
body {
|
body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -161,7 +161,10 @@
|
|||||||
><span class="icon">reset_settings</span>Reset Settings</button
|
><span class="icon">reset_settings</span>Reset Settings</button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
<button use:popup={ResetPopup}>Recovery...</button>
|
<button popovertarget="reset-device" popovertargetaction="toggle"
|
||||||
|
>Recovery...</button
|
||||||
|
>
|
||||||
|
<div id="reset-device" popover="auto"><ResetPopup /></div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<script lang="ts">
|
||||||
import { confirmChallenge } from "./confirm-challenge";
|
|
||||||
import { serialPort } from "$lib/serial/connection";
|
import { serialPort } from "$lib/serial/connection";
|
||||||
|
|
||||||
const options = [
|
const options = [
|
||||||
@@ -17,21 +16,27 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h3>Reset Device</h3>
|
<h3>Reset Device</h3>
|
||||||
|
<p>Resetting might take <b>up to 2 Minutes</b>.</p>
|
||||||
{#each options as category, i}
|
{#each options as category, i}
|
||||||
{#if i > 0}
|
{#if i > 0}
|
||||||
<hr />
|
<hr />
|
||||||
{/if}
|
{/if}
|
||||||
{#each category as [command, description]}
|
{#each category as [command, description]}
|
||||||
<button
|
<form
|
||||||
class="error"
|
onsubmit={(event) => {
|
||||||
use:confirmChallenge={{
|
event.preventDefault();
|
||||||
onConfirm() {
|
$serialPort?.reset(command);
|
||||||
$serialPort?.reset(command);
|
$serialPort = undefined;
|
||||||
$serialPort = undefined;
|
}}
|
||||||
},
|
|
||||||
challenge: description,
|
|
||||||
}}>{description}...</button
|
|
||||||
>
|
>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder={description}
|
||||||
|
required
|
||||||
|
pattern="^{description}$"
|
||||||
|
/>
|
||||||
|
<button class="icon" type="submit">send</button>
|
||||||
|
</form>
|
||||||
{/each}
|
{/each}
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
@@ -39,4 +44,43 @@
|
|||||||
hr {
|
hr {
|
||||||
opacity: 0.25;
|
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>
|
</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