Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve modal focus #31

Merged
merged 1 commit into from
Oct 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/lib/ManageFilesModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@
{ label: 'Solution checkers', files: checkers },
{ label: 'Other files', files: other },
].filter((s) => s.files.length > 0);

function accept() {
dispatch('close');
}
</script>

<Modal {active} title="Manage files" on:cancel={() => dispatch('close')}>
<Modal {active} title="Manage files" on:submit={accept} on:cancel={accept}>
{#each sections as section}
<p>{section.label}</p>
<table class="table is-fullwidth">
Expand All @@ -75,6 +79,7 @@
: 'hide'} this file"
class:is-primary={!file.hidden}
class:is-light={file.hidden}
type="button"
on:click={() =>
dispatch('modifyFile', {
index,
Expand All @@ -97,6 +102,7 @@
<button
class="button is-small is-light"
title="Compiled checkers are read only"
type="button"
disabled
>
<span class="icon">
Expand All @@ -111,6 +117,7 @@
: 'lock'} this file for editing"
class:is-primary={!file.readOnly}
class:is-light={file.readOnly}
type="button"
on:click={() =>
dispatch('modifyFile', {
index,
Expand All @@ -134,6 +141,7 @@
<button
class="button is-small is-danger"
title="Delete this file"
type="button"
on:click={() =>
dispatch('delete', { index })}
>
Expand All @@ -154,6 +162,7 @@
<button
class="button is-fullwidth"
on:click={() => dispatch('newFile')}
type="button"
>
<span class="icon">
<Fa icon={faPlus} />
Expand All @@ -163,9 +172,9 @@
</div>

<div slot="footer">
<button class="button is-primary" on:click={() => dispatch('close')}
>Accept</button
>
<button class="button is-primary">
Accept
</button>
</div>
</Modal>

Expand Down
33 changes: 29 additions & 4 deletions src/lib/Modal.svelte
Original file line number Diff line number Diff line change
@@ -1,25 +1,50 @@
<script>
import { createEventDispatcher } from 'svelte';
import { createEventDispatcher, tick } from 'svelte';
import { fade, fly } from 'svelte/transition';

export let title;
export let active = false;
const dispatch = createEventDispatcher();
let form;

$: setFocus(active);

async function setFocus(active) {
if (active) {
await tick();
if (form) {
form.focus();
}
dispatch('activate');
}
}

function cancel() {
dispatch('cancel');
}
</script>

{#if active}
<div transition:fade={{ duration: 200 }} class="modal is-active">
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<form
tabindex="0"
bind:this={form}
transition:fade={{ duration: 200 }}
class="modal is-active"
on:submit
>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions-->
<div class="modal-background" on:click={cancel} />
<div transition:fly={{ y: -200, duration: 200 }} class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">{title}</p>
<button class="delete" aria-label="close" on:click={cancel} />
<button
type="button"
class="delete"
aria-label="close"
on:click={cancel}
/>
</header>
<section class="modal-card-body">
<slot />
Expand All @@ -30,5 +55,5 @@
</slot>
</footer>
</div>
</div>
</form>
{/if}
27 changes: 23 additions & 4 deletions src/lib/ModelModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,38 @@
<Modal
{active}
title="Select model to run"
on:submit={accept}
on:cancel={() => dispatch('cancel')}
>
<div class="select is-fullwidth">
<select bind:value={selectedModel}>
<div class="select is-fullwidth is-multiple">
<select
bind:value={selectedModel}
size={Math.min(8, modelFiles.length)}
>
{#each modelFiles as modelFile}
<option value={modelFile}>{modelFile}</option>
{/each}
</select>
</div>
<div slot="footer">
<button class="button is-primary" on:click={accept}> OK </button>
<button class="button" on:click={() => dispatch('cancel')}>
<button class="button is-primary"> OK </button>
<button
type="button"
class="button"
on:click={() => dispatch('cancel')}
>
Cancel
</button>
</div>
</Modal>

<style>
.select.is-multiple select {
height: auto;
padding: 0;
}

.select.is-multiple option {
padding: 0.5em 1em;
}
</style>
88 changes: 57 additions & 31 deletions src/lib/NewFileModal.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
<script>
import { createEventDispatcher } from 'svelte';
import { createEventDispatcher, tick } from 'svelte';
import Modal from './Modal.svelte';
export let active = false;

const dispatch = createEventDispatcher();
let fileInput;
let files;
let element;

async function setFocus() {
await tick();
if (element) {
element.focus();
}
}
async function uploaded() {
const promises = [];
for (const file of files) {
Expand All @@ -26,64 +33,76 @@
}
</script>

<Modal {active} title="Create new file" on:cancel={() => dispatch('cancel')}>
<Modal
{active}
title="Create new file"
on:activate={setFocus}
on:cancel={() => dispatch('cancel')}
>
<aside class="menu">
<p class="menu-label">Model</p>
<ul class="menu-list">
<li>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-missing-attribute -->
<!-- svelte-ignore a11y-no-static-element-interactions-->
<a on:click={() => dispatch('new', { type: '.mzn' })}
>Model file (.mzn)</a
<button
type="button"
class="button is-text"
bind:this={element}
on:click={() => dispatch('new', { type: '.mzn' })}
>
Model file (.mzn)
</button>
</li>
<li>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-missing-attribute -->
<!-- svelte-ignore a11y-no-static-element-interactions-->
<a on:click={() => dispatch('new', { type: '.mzc.mzn' })}
>Solution checker model (.mzc.mzn)</a
<button
type="button"
class="button is-text"
on:click={() => dispatch('new', { type: '.mzc.mzn' })}
>
Solution checker model (.mzc.mzn)
</button>
</li>
</ul>
<p class="menu-label">Data</p>
<ul class="menu-list">
<li>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-missing-attribute -->
<!-- svelte-ignore a11y-no-static-element-interactions-->
<a on:click={() => dispatch('new', { type: '.dzn' })}
>Data file (.dzn)</a
<button
type="button"
class="button is-text"
on:click={() => dispatch('new', { type: '.dzn' })}
>
Data file (.dzn)
</button>
</li>
<li>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-missing-attribute -->
<!-- svelte-ignore a11y-no-static-element-interactions-->
<a on:click={() => dispatch('new', { type: '.json' })}
>JSON data file (.json)</a
<button
type="button"
class="button is-text"
on:click={() => dispatch('new', { type: '.json' })}
>
JSON data file (.json)
</button>
</li>
</ul>
<p class="menu-label">Visualisation</p>
<ul class="menu-list">
<li>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-missing-attribute -->
<!-- svelte-ignore a11y-no-static-element-interactions-->
<a on:click={() => dispatch('new', { type: '.html' })}
>Custom visualisation (.html)</a
<button
type="button"
class="button is-text"
on:click={() => dispatch('new', { type: '.html' })}
>
Custom visualisation (.html)
</button>
</li>
</ul>
<p class="menu-label">Import</p>
<ul class="menu-list">
<li>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-missing-attribute -->
<!-- svelte-ignore a11y-no-static-element-interactions-->
<a on:click={() => fileInput.click()}>Upload file(s)</a>
<button
type="button"
class="button is-text"
on:click={() => fileInput.click()}>Upload file(s)</button
>
</li>
</ul>
</aside>
Expand All @@ -103,4 +122,11 @@
.is-hidden {
display: none;
}

.menu-list .button {
text-decoration: none;
display: block;
width: 100%;
text-align: left;
}
</style>
Loading