Building file tree, added modal
- Building file tree (ongoing) - Added modal to handle error messages and similar interactions.
This commit is contained in:
parent
463e18015f
commit
bf41d27353
3 changed files with 164 additions and 13 deletions
111
packages/src/lib/components/modal.svelte
Normal file
111
packages/src/lib/components/modal.svelte
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
<script>
|
||||||
|
import { onMount } from 'svelte'
|
||||||
|
|
||||||
|
let {
|
||||||
|
showModal = false, wide = true, hideSidebar = false,
|
||||||
|
enter, escape, children
|
||||||
|
} = $props()
|
||||||
|
|
||||||
|
const handleKeydown = (e) => {
|
||||||
|
if (showModal) {
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
escape()
|
||||||
|
} else if (e.keyCode === 13) {
|
||||||
|
enter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (showModal) {
|
||||||
|
window.addEventListener("keydown", handleKeydown)
|
||||||
|
} else {
|
||||||
|
window.removeEventListener("keydown", handleKeydown)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if showModal}
|
||||||
|
<div class='modal'>
|
||||||
|
<div class="overlay" role='button' tabindex='0' onclick={() => escape()} onkeydown={() => escape()}>
|
||||||
|
<div
|
||||||
|
class="dark"
|
||||||
|
role='button'
|
||||||
|
tabindex='0'
|
||||||
|
class:narrow={!wide}
|
||||||
|
class:hidden={hideSidebar}
|
||||||
|
onclick={() => escape()}
|
||||||
|
onkeydown={() => escape()}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wrap">
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.modal {
|
||||||
|
display: flex;
|
||||||
|
position: fixed;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrap {
|
||||||
|
z-index: 100;
|
||||||
|
margin: auto 1em;
|
||||||
|
background-color: var(--theme-background);
|
||||||
|
border: solid thin var(--theme-color);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 1em;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 50;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay .dark {
|
||||||
|
margin-top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: var(--shade-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay .dark::before {
|
||||||
|
content: "";
|
||||||
|
width: 40px;
|
||||||
|
height: 20px;
|
||||||
|
position: absolute;
|
||||||
|
top: -20px;
|
||||||
|
left: 0;
|
||||||
|
background-color: var(--shade-background);
|
||||||
|
border-radius: 40px 40px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay .dark.narrow::before {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay .dark.hidden::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 45em) {
|
||||||
|
.wrap {
|
||||||
|
margin: auto;
|
||||||
|
padding: 1em 3em;
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -10,10 +10,11 @@
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--border-color: #3b3b3b;
|
--border-color: #aaa;
|
||||||
|
--button-color: #f6f6f6;
|
||||||
--font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
--font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
||||||
--navbar-height: 3em;
|
--navbar-height: 3em;
|
||||||
--shade-color: #ccc;
|
--shade-color: #eee;
|
||||||
--theme-background: white;
|
--theme-background: white;
|
||||||
--theme-color: #444;
|
--theme-color: #444;
|
||||||
}
|
}
|
||||||
|
@ -39,11 +40,13 @@
|
||||||
:global(button) {
|
:global(button) {
|
||||||
margin: 1em;
|
margin: 1em;
|
||||||
width: 10em;
|
width: 10em;
|
||||||
height: 3em;
|
height: 2.5em;
|
||||||
font-family: var(--font-family-text);
|
font-family: var(--font-family-text);
|
||||||
font-weight: 400;
|
font-weight: 200;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: var(--button-color);
|
background: var(--button-color);
|
||||||
|
border: solid thin;
|
||||||
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(button:hover) {
|
:global(button:hover) {
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
<script>
|
<script>
|
||||||
import { enhance } from '$app/forms'
|
import { enhance } from '$app/forms'
|
||||||
import { beforeNavigate } from '$app/navigation'
|
import { beforeNavigate } from '$app/navigation'
|
||||||
|
import Modal from '$lib/components/modal.svelte'
|
||||||
|
|
||||||
let { form } = $props()
|
let { form } = $props()
|
||||||
let capKey = $state()
|
let capKey = $state()
|
||||||
let capKeyInput = $state()
|
let capKeyInput = $state()
|
||||||
let newCapKey = $state()
|
let newCapKey = $state()
|
||||||
let checked = $state(false)
|
let checked = $state(false)
|
||||||
|
let showModal = $state(false)
|
||||||
|
|
||||||
const submitKey = () => {
|
const submitKey = () => {
|
||||||
capKey = capKeyInput
|
capKey = capKeyInput
|
||||||
|
@ -42,7 +44,7 @@
|
||||||
})
|
})
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (form?.error) console.log({ error: form.error })
|
if (form?.capKey) capKey = form.capKey
|
||||||
})
|
})
|
||||||
|
|
||||||
$effect(() => console.log({ form }))
|
$effect(() => console.log({ form }))
|
||||||
|
@ -54,9 +56,11 @@
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
<h1>Dashboard</h1>
|
<h1>Dashboard</h1>
|
||||||
|
|
||||||
{#if !form?.capKey && !newCapKey}
|
<button onclick={() => showModal = true}>Modal</button>
|
||||||
|
|
||||||
|
{#if !capKey && !newCapKey}
|
||||||
<div class='cap-key-div add'>
|
<div class='cap-key-div add'>
|
||||||
<form action='?/listDirectories' class='cap-key' method='post' enctype='form-data' use:enhance={enhanceForm}>
|
<form action='?/listDirectories' method='post' enctype='form-data' use:enhance={enhanceForm}>
|
||||||
<label for='capKeyInput'>Cap key:</label>
|
<label for='capKeyInput'>Cap key:</label>
|
||||||
<input type='text' name='capKeyInput' />
|
<input type='text' name='capKeyInput' />
|
||||||
|
|
||||||
|
@ -67,7 +71,7 @@
|
||||||
<button type='submit'>New cap key</button>
|
<button type='submit'>New cap key</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{:else if !form?.capKey && newCapKey}
|
{:else if !capKey && newCapKey}
|
||||||
<div class='cap-key-div get'>
|
<div class='cap-key-div get'>
|
||||||
<label for='newCapKey'><h2>New cap key</h2></label>
|
<label for='newCapKey'><h2>New cap key</h2></label>
|
||||||
<input type='text' id='newCapKey' name='newCapKey' value={newCapKey} />
|
<input type='text' id='newCapKey' name='newCapKey' value={newCapKey} />
|
||||||
|
@ -91,19 +95,44 @@
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<h2>File tree</h2>
|
<h2>File tree</h2>
|
||||||
<p>{form.capKey}</p>
|
|
||||||
|
<ul>
|
||||||
|
{#each form?.list as item}
|
||||||
|
{#if item === 'dirnode'}
|
||||||
|
<li>/</li>
|
||||||
|
{:else}
|
||||||
|
<li>{Object.keys(item.children)[0]}</li>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<button>Add folder</button>
|
||||||
|
<button>Upload file</button>
|
||||||
|
<button onclick={() => capKey = undefined}>Change cap key</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<Modal {showModal} escape={() => showModal = false}>
|
||||||
|
<h1>Modal</h1>
|
||||||
|
<button onclick={() => showModal = false}>Ok</button>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
form, .cap-key {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
form button {
|
form button {
|
||||||
margin: 0 0 0 auto;
|
margin: 0 0 1em auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
form input {
|
||||||
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cap-key {
|
.cap-key {
|
||||||
|
display: flex;
|
||||||
margin: auto 0 2em 0;
|
margin: auto 0 2em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +151,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.cap-key-div {
|
.cap-key-div {
|
||||||
max-width: 40em;
|
max-width: 45em;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,4 +180,12 @@
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
margin: 2em auto;
|
margin: 2em auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
text-align: left;
|
||||||
|
background: var(--shade-color);
|
||||||
|
padding: 1em;
|
||||||
|
border: solid thin var(--border-color);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue