Skip to content
This repository has been archived by the owner on Aug 1, 2022. It is now read-only.

Commit

Permalink
feat(ui): navigate-to-project modal (#738)
Browse files Browse the repository at this point in the history
***
* navigation modal
* preliminary untracked page
* update to new typography system <3
* fixup
* touchup
* ModalOverlay component
* autofocus but still escapable
* proper sidebar link styling
* move local var under props
* Update ui/DesignSystem/Component/SearchModal.svelte
Co-authored-by: Rūdolfs Ošiņš <rudolfs@osins.org>

* fix stray event.code
* styling polish
* urn in tracking info reflects value entered
* fix circular dependency
* emoji component
* Update ui/src/modal.ts
Co-authored-by: Alexander Simmerl <a.simmerl@gmail.com>

* Apply suggestions from code review
Co-authored-by: Alexander Simmerl <a.simmerl@gmail.com>

* fix prettier
Co-authored-by: Rūdolfs Ošiņš <rudolfs@osins.org>
Co-authored-by: Alexander Simmerl <a.simmerl@gmail.com>
  • Loading branch information
sarahscott committed Aug 28, 2020
1 parent 72a7822 commit a3403e2
Show file tree
Hide file tree
Showing 16 changed files with 399 additions and 55 deletions.
13 changes: 10 additions & 3 deletions ui/App.svelte
@@ -1,12 +1,17 @@
<script>
import Router, { push, location } from "svelte-spa-router";
import * as modal from "./src/modal.ts";
import * as notification from "./src/notification.ts";
import * as path from "./src/path.ts";
import * as remote from "./src/remote.ts";
import { clear, fetch, session as store } from "./src/session.ts";
import { NotificationFaucet, Remote } from "./DesignSystem/Component";
import {
NotificationFaucet,
Remote,
ModalOverlay,
} from "./DesignSystem/Component";
import { Button } from "./DesignSystem/Primitive";
import Hotkeys from "./Hotkeys.svelte";
Expand All @@ -25,24 +30,24 @@
import Project from "./Screen/Project.svelte";
import ProjectCreation from "./Screen/ProjectCreation.svelte";
import ProjectRegistration from "./Screen/ProjectRegistration.svelte";
import Search from "./Screen/Search.svelte";
import SendFunds from "./Screen/SendFunds.svelte";
import Settings from "./Screen/Settings.svelte";
import TransactionDetails from "./Screen/TransactionDetails.svelte";
import Untracked from "./Screen/Project/Untracked.svelte";
import UserRegistration from "./Screen/UserRegistration.svelte";
import UserProfile from "./Screen/UserProfile.svelte";
const routes = {
"/": Blank,
"/identity/new": IdentityCreation,
"/search": Search,
"/settings": Settings,
"/discovery": Discovery,
"/profile/*": Profile,
"/orgs/register": OrgRegistration,
"/orgs/:id/members/register": MemberRegistration,
"/orgs/:id": Org,
"/orgs/:id/*": Org,
"/projects/untracked/:urn": Untracked,
"/projects/new": ProjectCreation,
"/projects/register/:domainId": ProjectRegistration,
"/projects/:projectId/register/:domainId": ProjectRegistration,
Expand Down Expand Up @@ -95,8 +100,10 @@
</style>

<Hotkeys />
<ModalOverlay store={modal.store} />
<NotificationFaucet />
<Theme />

<Remote {store} context="session">
<Router {routes} />

Expand Down
53 changes: 53 additions & 0 deletions ui/DesignSystem/Component/ModalOverlay.svelte
@@ -0,0 +1,53 @@
<script>
import * as modal from "../../src/modal";
export let store = null;
let content;
const clickOutside = ev => {
if (content && ev.target !== content && !content.contains(ev.target))
modal.hide();
};
</script>

<style>
.modal {
height: 100vh;
width: 100vw;
position: fixed;
z-index: 100;
}
.overlay {
background-color: black;
opacity: 0.7;
height: 100%;
width: 100%;
position: fixed;
}
.content {
position: relative;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
z-index: 200;
}
.hide {
display: none;
}
</style>

<svelte:window on:click={clickOutside} />

<div class="modal" class:hide={!$store.show}>
<div class="overlay" on:click={clickOutside} />
<div class="content">
<svelte:component
this={$store.component}
bind:content
on:hide={modal.hide} />
</div>
</div>
126 changes: 126 additions & 0 deletions ui/DesignSystem/Component/SearchModal.svelte
@@ -0,0 +1,126 @@
<script>
import { push } from "svelte-spa-router";
import { createEventDispatcher } from "svelte";
import { Icon, Input } from "../Primitive";
import TrackToggle from "./TrackToggle.svelte";
import Urn from "./Urn.svelte";
import * as path from "../../src/path";
import { Status } from "../../src/remote";
import { updateUrn, validation } from "../../src/search";
import { ValidationStatus } from "../../src/validation";
export let content;
let searchBar, value, hasExpanded, showTrackingInfo;
const dispatch = createEventDispatcher();
const navigateToProject = () => {
if ($validation.status !== ValidationStatus.Success) return;
dispatch("hide");
push(path.projectUntracked(value));
};
const onKeydown = ev => {
switch (ev.code) {
case "Enter":
navigateToProject();
break;
case "Escape":
dispatch("hide");
}
};
$: if (value && value.length > 0) {
updateUrn({ urn: value });
}
// TODO(sos): animate & show/hide based on actual remote response
$: {
showTrackingInfo = hasExpanded
? true
: value && value.length > 0 && $validation.status === Status.Success;
if (showTrackingInfo && !hasExpanded) hasExpanded = true;
}
</script>

<style>
.container {
width: 26.25rem;
}
.search-bar {
margin-bottom: 1rem;
}
.tracking-info {
background: var(--color-background);
cursor: pointer;
border-radius: 0.5rem;
height: 0;
overflow: hidden;
transition: height 0.5s linear;
}
.showTrackingInfo {
height: 13.5rem;
}
.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 0.25rem;
}
</style>

<svelte:window on:keydown={onKeydown} />

<div class="container" bind:this={content}>
<div class="search-bar" bind:this={searchBar}>
<!-- TODO(sos): fix autofocus / hotkey conflict -->
<Input.Text
autofocus
bind:value
placeholder="Have a Radicle project ID? Paste it here..."
showLeftItem
style="height: 3rem;"
inputStyle="border: none; border-radius: 0.5rem; height: 3rem;"
validation={$validation}>
<div slot="left" style="display: flex;">
<Icon.MagnifyingGlass />
</div>
</Input.Text>
</div>

<!-- TODO(sos): Once we determine how searching works, make sure this looks right
if user changes urn
-->
<div
class="tracking-info"
class:showTrackingInfo
on:click={navigateToProject}>
<div style="padding: 2rem;">
<div class="header">
<h3 style="color: var(--color-foreground-level-6);">my-new-project</h3>
<TrackToggle variant="expanded" />
</div>

<div style="display: flex; margin-bottom: 1rem;">
<Urn
urn={value || ''}
notificationText="The project ID was copied to your clipboard"
showOnHover />
</div>

<p style="color: var(--color-foreground-level-6);">
You’re not tracking this project yet, so there’s nothing to show here.
Track it and you’ll be notified as soon as it’s available.
</p>
</div>
</div>
</div>
13 changes: 13 additions & 0 deletions ui/DesignSystem/Component/Sidebar.svelte
@@ -1,6 +1,7 @@
<script>
import { location, link } from "svelte-spa-router";
import * as modal from "../../src/modal.ts";
import * as path from "../../src/path.ts";
import Tooltip from "./Tooltip.svelte";
Expand Down Expand Up @@ -59,6 +60,7 @@
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.indicator:hover:before {
Expand Down Expand Up @@ -119,6 +121,17 @@
</li>
</ul>
<ul class="bottom">
<li
class="item indicator"
data-cy="search"
on:click|stopPropagation={() => modal.toggle(path.search())}>
<Tooltip value="Navigate to a project">
<!-- svelte-ignore a11y-missing-attribute -->
<a>
<Icon.MagnifyingGlass />
</a>
</Tooltip>
</li>
<li
class="item indicator"
data-cy="settings"
Expand Down
4 changes: 4 additions & 0 deletions ui/DesignSystem/Component/index.js
Expand Up @@ -10,6 +10,7 @@ import HorizontalMenu from "./HorizontalMenu.svelte";
import Hoverable from "./Hoverable.svelte";
import Label from "./Label.svelte";
import List from "./List.svelte";
import ModalOverlay from "./ModalOverlay.svelte";
import NavigationButtons from "./Registration/NavigationButtons.svelte";
import Notification from "./Notification.svelte";
import NotificationFaucet from "./NotificationFaucet.svelte";
Expand All @@ -21,6 +22,7 @@ import Rad from "./Rad.svelte";
import RadicleLogo from "./RadicleLogo.svelte";
import RadioOption from "./RadioOption.svelte";
import Remote from "./Remote.svelte";
import SearchModal from "./SearchModal.svelte";
import RemoteHelperHint from "./RemoteHelperHint.svelte";
import SegmentedControl from "./SegmentedControl.svelte";
import Sidebar from "./Sidebar.svelte";
Expand Down Expand Up @@ -54,6 +56,7 @@ export {
Hoverable,
Label,
List,
ModalOverlay,
NavigationButtons,
Notification,
NotificationFaucet,
Expand All @@ -68,6 +71,7 @@ export {
Remote,
RemoteHelperHint,
Row,
SearchModal,
SegmentedControl,
Sidebar,
SidebarLayout,
Expand Down
34 changes: 2 additions & 32 deletions ui/DesignSystem/Primitive/Avatar.svelte
@@ -1,5 +1,5 @@
<script>
import twemoji from "twemoji";
import Emoji from "./Emoji.svelte";
import Icon from "./Icon";
export let style = null;
Expand Down Expand Up @@ -115,31 +115,6 @@
height: 32px;
border-radius: 16px;
}
.avatar :global(.emoji.small) {
height: 12px;
width: 12px;
}
.avatar :global(.emoji.regular) {
height: 16px;
width: 16px;
}
.avatar :global(.emoji.medium) {
height: 18px;
width: 18px;
}
.avatar :global(.emoji.big) {
height: 36px;
width: 36px;
}
.avatar :global(.emoji.huge) {
height: 60px;
width: 60px;
}
</style>

<div data-cy={dataCy} class={`container ${size}`} {style}>
Expand All @@ -154,12 +129,7 @@
class={`avatar ${avatarClass}`}
style="background: {fmt(avatarFallback.background)}"
data-cy="emoji">
{@html twemoji.parse(avatarFallback.emoji, {
className: `emoji ${size}`,
base: '',
folder: 'twemoji/',
ext: '.svg',
})}
<Emoji {size} emoji={avatarFallback.emoji} />
</div>
{:else}
<div
Expand Down

0 comments on commit a3403e2

Please sign in to comment.