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

feat(bridge-ui-v2): bridge form #14056

Merged
merged 39 commits into from
Jul 1, 2023
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6f170e9
typescript module
jscriptcoder Jun 26, 2023
3ae1fba
add pages
jscriptcoder Jun 26, 2023
b6e22a0
wip
jscriptcoder Jun 26, 2023
d881b45
wip
jscriptcoder Jun 26, 2023
da75567
Merge branch 'main' into bridge_form
jscriptcoder Jun 26, 2023
2f493b6
wip
jscriptcoder Jun 26, 2023
8e4c675
Merge branch 'bridge_form' of https://github.com/taikoxyz/taiko-mono …
jscriptcoder Jun 26, 2023
d0bb01b
wip
jscriptcoder Jun 26, 2023
21650bf
TokenDropdown component
jscriptcoder Jun 27, 2023
0ea5713
wip
jscriptcoder Jun 27, 2023
ff4b397
improve TokenDropdown
jscriptcoder Jun 27, 2023
11ec35a
wip: Chain selector
jscriptcoder Jun 27, 2023
9021fca
wip
jscriptcoder Jun 27, 2023
43e1280
wip
jscriptcoder Jun 27, 2023
087cf47
ChainSelector component
jscriptcoder Jun 27, 2023
b3f4ecd
add RecipientInput
jscriptcoder Jun 28, 2023
138bda7
Add Tooltip
jscriptcoder Jun 28, 2023
4f446ba
add unit test
jscriptcoder Jun 28, 2023
bbacbd4
add unit test
jscriptcoder Jun 28, 2023
3ba0680
mobile version
jscriptcoder Jun 28, 2023
a6a63ee
wip
jscriptcoder Jun 28, 2023
b7a5b5d
wip
jscriptcoder Jun 28, 2023
3ba5824
wip
jscriptcoder Jun 28, 2023
0417333
wip
jscriptcoder Jun 28, 2023
186529e
wip
jscriptcoder Jun 29, 2023
fd23e84
wip
jscriptcoder Jun 29, 2023
2f44217
wip: processing fee
jscriptcoder Jun 29, 2023
652ff32
Merge branch 'main' into bridge_form
jscriptcoder Jun 29, 2023
8e3c002
wip: processing fee
jscriptcoder Jun 29, 2023
31ab860
Merge branch 'bridge_form' of https://github.com/taikoxyz/taiko-mono …
jscriptcoder Jun 29, 2023
e57dc5c
wip
jscriptcoder Jun 29, 2023
be21f54
wip
jscriptcoder Jun 29, 2023
6940dcf
Merge branch 'main' into bridge_form
jscriptcoder Jun 30, 2023
457dec6
Bridge form
jscriptcoder Jun 30, 2023
9ce39ba
Merge branch 'bridge_form' of https://github.com/taikoxyz/taiko-mono …
jscriptcoder Jun 30, 2023
e6c0b80
wip: mobile
jscriptcoder Jun 30, 2023
ddcef19
minor change
jscriptcoder Jun 30, 2023
32b9859
fix lint
jscriptcoder Jun 30, 2023
82c5e36
feat(bridge-ui-v2): faucet (#14080)
jscriptcoder Jul 1, 2023
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
12 changes: 5 additions & 7 deletions packages/bridge-ui-v2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@

## [2.1.0](https://github.com/taikoxyz/taiko-mono/compare/bridge-ui-v2-v2.0.0...bridge-ui-v2-v2.1.0) (2023-06-26)


### Features

* **bridge-ui-v2:** env vars ([#14034](https://github.com/taikoxyz/taiko-mono/issues/14034)) ([fccc0a7](https://github.com/taikoxyz/taiko-mono/commit/fccc0a7252b93148559a0438ee23366f04fc86f6))
* **bridge-ui-v2:** initial setup v2 ([#14013](https://github.com/taikoxyz/taiko-mono/issues/14013)) ([429bf7a](https://github.com/taikoxyz/taiko-mono/commit/429bf7a1619b9554f999db29d236ce0c9c6236da))
* **bridge-ui-v2:** tailwind config and other setups ([#14016](https://github.com/taikoxyz/taiko-mono/issues/14016)) ([be294c6](https://github.com/taikoxyz/taiko-mono/commit/be294c66764d658423d58902076594afdc470e96))
* **bridge-ui-v2:** use web3modal ([#14043](https://github.com/taikoxyz/taiko-mono/issues/14043)) ([911c701](https://github.com/taikoxyz/taiko-mono/commit/911c701ae738a9f2e12c14455c23951845d0c4c2))

- **bridge-ui-v2:** env vars ([#14034](https://github.com/taikoxyz/taiko-mono/issues/14034)) ([fccc0a7](https://github.com/taikoxyz/taiko-mono/commit/fccc0a7252b93148559a0438ee23366f04fc86f6))
- **bridge-ui-v2:** initial setup v2 ([#14013](https://github.com/taikoxyz/taiko-mono/issues/14013)) ([429bf7a](https://github.com/taikoxyz/taiko-mono/commit/429bf7a1619b9554f999db29d236ce0c9c6236da))
- **bridge-ui-v2:** tailwind config and other setups ([#14016](https://github.com/taikoxyz/taiko-mono/issues/14016)) ([be294c6](https://github.com/taikoxyz/taiko-mono/commit/be294c66764d658423d58902076594afdc470e96))
- **bridge-ui-v2:** use web3modal ([#14043](https://github.com/taikoxyz/taiko-mono/issues/14043)) ([911c701](https://github.com/taikoxyz/taiko-mono/commit/911c701ae738a9f2e12c14455c23951845d0c4c2))

### Bug Fixes

* **bridge-ui-v2:** fixing vercel build ([#14052](https://github.com/taikoxyz/taiko-mono/issues/14052)) ([3332e70](https://github.com/taikoxyz/taiko-mono/commit/3332e70bb3b821ab4efbcfe4aed4dbc3ed614850))
- **bridge-ui-v2:** fixing vercel build ([#14052](https://github.com/taikoxyz/taiko-mono/issues/14052)) ([3332e70](https://github.com/taikoxyz/taiko-mono/commit/3332e70bb3b821ab4efbcfe4aed4dbc3ed614850))
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/src/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ declare global {
type Maybe<T> = T | null | undefined;
type MaybeArray<T> = T | T[] | null | undefined;
type MaybePromise<T> = T | Promise<T> | null | undefined;
type Position = 'top' | 'top-right' | 'right' | 'bottom-right' | 'bottom' | 'bottom-left' | 'left' | 'top-left';
}

export {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
import { t } from 'svelte-i18n';

import { Card } from '$components/Card';
</script>

<Card title={$t('activities.title')} text={$t('activities.subtitle')}>TODO: Activities</Card>
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/src/components/Activities/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Activities } from './Activities.svelte';
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import { t } from 'svelte-i18n';

import { InputBox } from '$components/InputBox';
import { uid } from '$libs/util/uid';

let inputId = `input-${uid()}`;
</script>

<div class="f-col space-y-2">
<div class="f-between-center text-secondary-content body-regular">
<label for={inputId}>{$t('amount_input.label')}</label>
<div>
<span>{$t('amount_input.balance')}:</span>
<span>399.92 ETH</span>
</div>
</div>
<div class="relative f-items-center">
<InputBox
id={inputId}
type="number"
placeholder="0.01"
min="0"
class="w-full input-box outline-none py-6 pr-16 px-[26px] title-subsection-bold placeholder:text-tertiary-content" />
<button class="absolute right-6 uppercase">{$t('amount_input.max_button')}</button>
</div>
</div>
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/src/components/AmountInput/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './AmountInput.svelte';
43 changes: 43 additions & 0 deletions packages/bridge-ui-v2/src/components/Bridge/Bridge.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script>
import { t } from 'svelte-i18n';

import AmountInput from '$components/AmountInput';
import Button from '$components/Button/Button.svelte';
import { Card } from '$components/Card';
import { ChainSelector } from '$components/ChainSelector';
import Icon from '$components/Icon/Icon.svelte';
import { ProcessingFee } from '$components/ProcessingFee';
import { RecipientInput } from '$components/RecipientInput';
import { TokenDropdown } from '$components/TokenDropdown';
import { tokens } from '$libs/token';
</script>

<Card title={$t('bridge.title')} text={$t('bridge.subtitle')}>
<div class="space-y-4">
<div class="space-y-2">
<ChainSelector label={$t('chain.from')} />
<TokenDropdown {tokens} />
</div>

<AmountInput />

<div class="f-justify-center">
<button>
<Icon type="up-down-circle" size={36} />
</button>
</div>

<div class="space-y-2">
<ChainSelector label={$t('chain.to')} />
<RecipientInput />
</div>

<ProcessingFee />
</div>

<div class="h-sep my-[35px]" />

<Button type="primary" class="px-[28px] py-[14px]">
<span class="body-bold">{$t('bridge.bridge_button')}</span>
</Button>
</Card>
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/src/components/Bridge/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Bridge } from './Bridge.svelte';
25 changes: 13 additions & 12 deletions packages/bridge-ui-v2/src/components/Button/Button.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
<script lang="ts">
import { classNames } from '$libs/util/classNames';

type ButtonType = 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error' | 'ghost';
type ButtonSize = 'lg' | 'md' | 'sm' | 'xs';
type ButtonType =
| 'neutral'
| 'primary'
| 'secondary'
| 'accent'
| 'info'
| 'success'
| 'warning'
| 'error'
| 'ghost'
| 'link';
type ButtonShape = 'circle' | 'square';

export let type: Maybe<ButtonType> = null;
export let size: Maybe<ButtonSize> = null;
export let shape: Maybe<ButtonShape> = null;
export let outline = false;
export let block = false;
Expand All @@ -26,13 +34,7 @@
warning: 'btn-warning',
error: 'btn-error',
ghost: 'btn-ghost',
};

const sizeMap: Record<ButtonSize, string> = {
lg: 'btn-lg',
md: 'btn-md',
sm: 'btn-sm',
xs: 'btn-xs',
link: 'btn-link',
};

const shapeMap: Record<ButtonShape, string> = {
Expand All @@ -41,9 +43,8 @@
};

const classes = classNames(
'btn btn-sm md:btn-md',
'btn h-auto min-h-fit border-0',
type ? typeMap[type] : null,
size ? sizeMap[size] : null,
shape ? shapeMap[shape] : null,
outline ? 'btn-outline' : null,
block ? 'btn-block' : null,
Expand Down
2 changes: 1 addition & 1 deletion packages/bridge-ui-v2/src/components/Button/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default } from './Button.svelte';
export { default as Button } from './Button.svelte';
16 changes: 16 additions & 0 deletions packages/bridge-ui-v2/src/components/Card/Card.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script lang="ts">
export let title: string;
export let text = '';
</script>

<div class="card w-full md:w-[524px] md:bg-elevated-background rounded-[20px] md:border md:border-neutral-background">
<div class="card-body p-4 md:p-12 body-regular">
<h2 class="card-title title-screen-bold">{title}</h2>
{#if text}
<p>{text}</p>
{/if}
<div class="f-col mt-6 md:mt-8">
<slot />
</div>
</div>
</div>
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/src/components/Card/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Card } from './Card.svelte';
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<script lang="ts">
import type { ComponentType } from 'svelte';
import { noop, onDestroy } from 'svelte/internal';
import { t } from 'svelte-i18n';

import { EthIcon, Icon, TaikoIcon } from '$components/Icon';
import { PUBLIC_L1_CHAIN_ID, PUBLIC_L2_CHAIN_ID } from '$env/static/public';
import { chains, type ExtendedChain } from '$libs/chain';
import { uid } from '$libs/util/uid';

export let label: string;
export let onChange: (chain: ExtendedChain) => void = noop;

let chainToIconMap: Record<string, ComponentType> = {
[PUBLIC_L1_CHAIN_ID]: EthIcon,
[PUBLIC_L2_CHAIN_ID]: TaikoIcon,
};

let buttonId = `button-${uid()}`;
let dialogId = `dialog-${uid()}`;
let selectedChain: ExtendedChain;
let modalOpen = false;

function closeModal() {
modalOpen = false;
}

function openModal() {
modalOpen = true;
}

function selectChain(chain: ExtendedChain) {
selectedChain = chain;
onChange?.(chain); // TODO: data binding? 🤔
closeModal();
}

function onChainKeydown(event: KeyboardEvent, chain: ExtendedChain) {
if (event.key === 'Enter') {
selectChain(chain);
}
}

onDestroy(closeModal);
</script>

<div class="ChainSelector">
<div class="f-items-center space-x-[10px]">
<label class="text-secondary-content body-regular" for={buttonId}>{label}:</label>
<button
id={buttonId}
type="button"
aria-haspopup="dialog"
aria-controls={dialogId}
aria-expanded={modalOpen}
class="px-2 py-[6px] body-small-regular bg-neutral-background rounded-md min-w-[150px]"
on:click={openModal}>
<div class="f-items-center space-x-2">
{#if !selectedChain}
<span>{$t('chain_selector.placeholder')}…</span>
{/if}
{#if selectedChain}
<i role="img" aria-label={selectedChain.name}>
<svelte:component this={chainToIconMap[selectedChain.id]} size={20} />
</i>
<span>{selectedChain.name}</span>
{/if}
</div>
</button>
</div>

<dialog id={dialogId} class="modal" class:modal-open={modalOpen}>
<div class="modal-box relative px-6 py-[21px] bg-primary-base-background text-primary-base-content">
<button class="absolute right-6 top-[21px]" on:click={closeModal}>
<Icon type="x-close" fillClass="fill-secondary-icon" />
</button>
<h3 class="title-body-bold">{$t('chain_selector.placeholder')}</h3>
<ul class="menu space-y-4">
{#each chains as chain (chain.id)}
<li
role="menuitem"
tabindex="0"
on:click={() => selectChain(chain)}
on:keydown={(event) => onChainKeydown(event, chain)}>
<!-- TODO: agree on hover:bg color -->
<div class="f-row justify-between hover:text-primary-base-content hover:bg-grey-10">
<div class="f-items-center space-x-4">
<i role="img" aria-label={chain.name}>
<svelte:component this={chainToIconMap[chain.id]} size={32} />
</i>
<span class="body-bold">{chain.name}</span>
</div>
<span class="body-regular">{chain.network}</span>
</div>
</li>
{/each}
</ul>
</div>

<div class="overlay-backdrop" />
</dialog>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as ChainSelector } from './ChainSelector.svelte';
7 changes: 7 additions & 0 deletions packages/bridge-ui-v2/src/components/Faucet/Faucet.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
import { t } from 'svelte-i18n';

import { Card } from '$components/Card';
</script>

<Card title={$t('faucet.title')} text={$t('faucet.subtitle')}>TODO: Faucet</Card>
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/src/components/Faucet/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Faucet } from './Faucet.svelte';
37 changes: 23 additions & 14 deletions packages/bridge-ui-v2/src/components/Header/Header.svelte
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
<script lang="ts">
import { t } from 'svelte-i18n';

import { web3modal } from '$libs/connect';
import { t } from '$libs/i18n';

import Button from '../Button';
import Icon from '../Icon';
import { Button } from '../Button';
import { Icon } from '../Icon';
import { LogoWithText } from '../Logo';
import { drawerToogleId } from '../SideNavigation';
import { drawerToggleId } from '../SideNavigation';
</script>

<header class="sticky p-2 md:px-10 md:py-7 flex justify-between md:justify-end items-center">
<div class="flex space-x-2 items-center md:hidden">
<label for={drawerToogleId} class="btn btn-sm md:btn-md btn-ghost drawer-button">
<header
class="
f-between-center
py-[20px]
px-4 border-b
border-b-divider-border
md:border-b-0
md:px-10 md:py-7
md:justify-end">
<LogoWithText class="w-[77px] h-[20px] md:hidden" />

<div class="f-items-center justify-end space-x-[10px]">
<Button class="px-[20px] py-2 rounded-full" type="neutral" on:click={() => web3modal.openModal()}>
<Icon type="user-circle" class="md-show-block" />
<span class="body-small-regular">{$t('wallet.connect')}</span>
</Button>
<label for={drawerToggleId} class="md:hidden">
<Icon type="bars-menu" />
</label>
<LogoWithText class="w-[88px] h-[24px]" />
</div>

<!-- <Button on:click={() => web3modal.openModal()} class="rounded-full" type="neutral">
<Icon type="user-circle" />
<span>{$t('wallet.connect')}</span>
</Button> -->

<!-- TODO: think about the possibility of actually using w3m-core-button component -->
<w3m-core-button balance="show" icon="hide" />
<!-- <w3m-core-button balance="show" icon="hide" /> -->
</header>
2 changes: 1 addition & 1 deletion packages/bridge-ui-v2/src/components/Header/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default } from './Header.svelte';
export { default as Header } from './Header.svelte';
16 changes: 16 additions & 0 deletions packages/bridge-ui-v2/src/components/Icon/BLL.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script lang="ts">
export let width = 32;
export let height = 32;
</script>

<svg {width} {height} viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="16" fill="#772D5A" />
<path
d="M23.8628 17.3257L25.5703 23.7313H23.4532L22.6535 20.7817H16.2659V23.7313H14.2176V20.7817L11.3417 18.7104C10.1536 20.1082 8.40517 21.2733 7.04835 21.2733V16.5211L5 15.8657V14.8825H9.39494L13.0377 12.2966C13.372 12.0688 13.7784 11.9328 14.2192 11.9328C14.5076 11.9328 14.7813 11.9918 15.0304 12.0951L23.0746 15.8657H23.6777C24.2758 15.8657 24.9739 15.6084 24.9739 14.8825C24.9739 14.1565 24.2758 13.8992 23.6777 13.8992C22.0816 13.8992 20.8772 12.6309 20.8772 10.9496V8H21.9013L23.4384 10.9496H22.4142C22.4142 11.8034 22.9468 12.4244 23.6777 12.4244C25.3196 12.4244 26.5109 13.4584 26.5109 14.8825C26.5109 16.3065 25.4065 17.2487 23.8661 17.3257H23.8628Z"
fill="#FF715B" />
<path d="M20.8755 8H21.8997L23.4367 10.9496H20.8771V8H20.8755Z" fill="#DA4933" />
<path
opacity="0.3"
d="M9.0967 15.8658C9.0967 16.4082 8.63787 16.849 8.07252 16.849L5 15.8658V14.8826H8.07252C8.63787 14.8826 9.0967 15.3234 9.0967 15.8658Z"
fill="white" />
</svg>
26 changes: 26 additions & 0 deletions packages/bridge-ui-v2/src/components/Icon/ETH.svelte

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions packages/bridge-ui-v2/src/components/Icon/HORSE.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts">
export let width = 32;
export let height = 32;
</script>

<svg {width} {height} viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="16" cy="16" r="16" fill="#34328B" />
<path
d="M7.80116 9.19912L7 8H10.1486C12.1372 8 13.7481 9.60168 13.7481 11.5788V12.0256H18.9212C19.3261 12.0256 19.7123 12.1055 20.0454 12.2583C20.4417 11.9542 20.8997 11.7401 21.3505 11.6502C22.0612 11.5074 22.9342 11.5788 23.7439 12.1241C24.5451 12.6694 24.9672 13.663 24.9945 14.4238C25.039 15.2018 24.805 15.8642 24.6169 16.321L24.1402 17.3317C24.0411 17.5729 23.978 17.8413 24.0325 18.1725C24.0684 18.5208 24.2393 18.8977 24.4101 19.3174L23.7798 19.944C23.3304 19.7114 22.9069 19.4073 22.5207 18.9691C22.1431 18.5308 21.8458 17.8684 21.81 17.2246C21.7468 16.5808 21.8458 15.9984 21.8731 15.6058C21.9004 15.3189 21.8817 15.1233 21.8458 14.9891C21.8186 16.0541 21.2155 16.9748 20.334 17.4673L21.2514 19.0861C21.395 19.3188 21.4223 19.5872 21.395 19.8555L20.4948 24.1053H18.2191L19.0834 19.8199L18.0755 18.0212L14.0812 18.6835C13.9017 18.7107 13.7122 18.7378 13.5227 18.7378H13.2973V24.1053H11.0474V17.6457C10.499 17.0462 10.1472 16.2596 10.1472 15.3831V12.1783C10.1472 11.9542 9.85 11.8743 9.7337 12.0627L8.34819 14.264L7 13.8143V10.6837C7 10.067 7.31443 9.52031 7.80116 9.19912Z"
fill="#FFC6E9" />
<path
d="M21.3505 11.6503C20.8997 11.7402 20.4417 11.9543 20.0454 12.2584C20.6994 12.4984 21.9751 13.3806 21.8459 14.9893C21.8818 15.1234 21.9004 15.319 21.8731 15.6059C21.8459 15.9985 21.7468 16.5809 21.81 17.2247C21.8459 17.8686 22.1431 18.5309 22.5207 18.9692C22.9069 19.4074 23.3304 19.7115 23.7798 19.9442L24.4101 19.3175C24.2393 18.8978 24.0684 18.5209 24.0325 18.1726C23.978 17.8414 24.0412 17.5731 24.1402 17.3318L24.6169 16.3211C24.805 15.8643 25.039 15.202 24.9945 14.424C24.9672 13.6631 24.5451 12.6695 23.744 12.1242C22.9342 11.5789 22.0612 11.5075 21.3505 11.6503Z"
fill="#E283BE" />
</svg>
Loading