feat: brand new Modal component (#41)

* feat: brand new Modal component

* Apply suggestions from code review

Co-authored-by: Ax333l <main@axelen.xyz>
This commit is contained in:
mirgb
2022-12-10 12:11:17 -05:00
committed by GitHub
parent 31047103d3
commit 2e71974503
9 changed files with 264 additions and 80 deletions

View File

@@ -0,0 +1,126 @@
<script lang="ts">
import * as settings from '../../../data/api/settings';
import Modal from '$lib/components/atoms/Modal.svelte';
import { clear_and_reload } from '../../../data/api/cache';
let url = settings.api_base_url();
function save() {
settings.set_api_base_url(url);
clear_and_reload();
}
function reset() {
url = settings.default_base_url;
}
</script>
<Modal icon="/icons/settings.svg" alt="Settings">
<div class="settings-menu">
<h3>Configure the backend</h3>
<div class="url-stuff">
<h4>API URL:</h4>
<div class="input-wrapper">
<input name="api-url" type="text" bind:value={url} />
<button class="button-reset" on:click={reset}>
<img src="/icons/reset.svg" alt="Reset" />
</button>
</div>
</div>
<div class="btns">
<button class="save-url-btn" on:click={save}>
<h4>Save</h4>
</button>
<button class="clear-cache-btn" on:click={clear_and_reload}>
<h4>Clear cache</h4>
</button>
</div>
</div>
</Modal>
<style>
div.settings-menu {
position: fixed;
width: min(95%, 500px);
/* width: clamp(45vw, 850px, 850px); */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 40px;
border-radius: 12px;
background-color: var(--grey-six);
display: flex;
user-select: none;
gap: 5%;
z-index: 999;
white-space: normal;
display: flex;
flex-direction: column;
gap: 2px;
box-shadow: 0 3rem 5rem rgba(0, 0, 0, 0.3);
}
div.btns {
display: flex;
gap: 1rem;
text-align: center;
flex-wrap: wrap;
}
.btns button {
min-width: max-content;
font-size: 1rem;
color: var(--white);
font-weight: 600;
border: none;
border-radius: 12px;
flex-grow: 2;
padding: 1rem 1.75rem;
display: block;
cursor: pointer;
background-color: var(--grey-two);
transition: transform 0.4s var(--bezier-one), filter 0.4s var(--bezier-one);
user-select: none;
}
.btns .save-url-btn {
background-color: var(--accent-color);
box-shadow: 0px 0px 32px 1px var(--accent-color-glow);
flex-grow: 1;
}
.save-url-btn h4 {
color: var(--grey-four);
}
div.input-wrapper {
display: flex;
background-color: #2a2c33;
padding: 12px;
width: 100%;
margin: 10px 0 10px 0;
border-radius: 10px;
}
img {
height: 25px;
}
input[type='text'] {
background-color: transparent;
border: 0;
color: white;
font-size: 1rem;
outline: none;
width: 100%;
}
h3 {
margin: 0 0 20px 0;
}
@media (max-width: 780px) {
div.settings-menu {
flex-direction: column;
gap: 2rem;
}
}
</style>

View File

@@ -9,7 +9,9 @@
<a {href} {target}>
<div class={type} style="width: {maxWidth ? '100%' : 'max-content'}">
<img src="../icons/{icon}.svg" alt={icon} />
{#if icon}
<img src="../icons/{icon}.svg" alt={icon} />
{/if}
<slot />
</div>
</a>
@@ -46,8 +48,6 @@
filter: brightness(85%);
}
div,
.button-secondary {
display: flex;

View File

@@ -0,0 +1,71 @@
<script lang="ts">
import { click_outside } from '$lib/utils';
import { fade } from 'svelte/transition';
let modalOpen = false;
export let icon: string;
export let alt: string;
</script>
<div>
<button class="modal-btn" on:click={() => (modalOpen = !modalOpen)}>
<img src={icon} {alt} />
</button>
{#if modalOpen}
<div class="overlay" />
<div
class="modal-container"
role="dialog"
aria-modal="true"
use:click_outside
on:click_outside={() => (modalOpen = false)}
transition:fade={{ duration: 125 }}
>
<slot />
</div>
{/if}
</div>
<style>
button.modal-btn {
border: 0;
background-color: transparent;
transition-timing-function: var(--bezier-one);
transition-duration: 0.25s;
padding: 10px 25px;
border-radius: 200px;
display: flex;
align-items: center;
justify-content: center;
}
button.modal-btn:hover {
color: var(--white);
background-color: var(--grey-one);
}
img {
height: 1.75rem;
width: auto;
cursor: pointer;
display: flex;
align-items: center;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1;
}
@media (max-width: 768px) {
button.modal-btn {
padding: 1rem 1.5rem;
border-radius: 16px;
}
}
</style>

View File

@@ -1,10 +1,10 @@
<script lang="ts">
import Navigation from '../atoms/NavButton.svelte';
import { page } from '$app/stores';
import Button from '../atoms/Button.svelte';
import MobileDropdown from './MobileDropdown.svelte';
import { onMount } from 'svelte';
import RouterEvents from '../../../data/RouterEvents';
import ApiSettingsButton from '$lib/components/atoms/ApiSettingsButton.svelte';
let menuOpen = false;
@@ -25,7 +25,6 @@
<img src="/logo.svg" class="logo-image" alt="ReVanced Logo" />
</span>
</a>
<span class="desktop">
<Navigation href="/">Home</Navigation>
<Navigation href="/download">Download</Navigation>
@@ -44,14 +43,12 @@
<Navigation href="/contributors/">
<img src="/icons/contrib.svg" alt="Contributors" />
</Navigation>
<Navigation href="/api-settings/">
<img src="/icons/settings.svg" alt="Settings" />
</Navigation>
<ApiSettingsButton />
</span>
<!-- Should probably be moved to its own component. -->
<button
class="menu-btn mobile"
class="menu-btn button-reset mobile"
class:open={menuOpen}
on:click={() => {
menuOpen = !menuOpen;
@@ -76,9 +73,9 @@
<Navigation href="/contributors/">
<img src="/icons/contrib.svg" alt="Contributors" />
</Navigation>
<Navigation href="/api-settings/">
<img src="/icons/settings.svg" alt="Settings" />
</Navigation>
<ApiSettingsButton on:click={() => {
menuOpen = false;
}}/>
</div>
</div>
</MobileDropdown>
@@ -171,6 +168,7 @@
display: none !important;
}
}
.menu-btn {
user-select: none;
position: relative;
@@ -181,17 +179,8 @@
height: 60px;
cursor: pointer;
transition: all 0.5s var(--bezier-one);
/* We don't want it to look like a normal button. */
background-color: transparent;
border: none;
font-family: inherit;
font-size: inherit;
font-style: inherit;
font-weight: inherit;
line-height: inherit;
padding: 0;
}
.menu-btn__burger {
width: 25px;
height: 2px;