1
0
mirror of https://github.com/kremalicious/blog.git synced 2024-11-22 18:00:06 +01:00

more form interactions

This commit is contained in:
Matthias Kretschmann 2023-11-02 23:33:06 +00:00
parent 498e5a1730
commit 0728c63b17
Signed by: m
GPG Key ID: 606EEEF3C479A91F
13 changed files with 79 additions and 96 deletions

View File

@ -1,6 +1,5 @@
.input { .input {
display: block; display: block;
width: 100%;
padding: var(--padding-base-vertical) var(--padding-base-horizontal); padding: var(--padding-base-vertical) var(--padding-base-horizontal);
font-size: var(--input-font-size); font-size: var(--input-font-size);
font-weight: var(--input-font-weight); font-weight: var(--input-font-weight);
@ -25,7 +24,8 @@
/* stylelint-enable selector-no-vendor-prefix */ /* stylelint-enable selector-no-vendor-prefix */
.input:focus { .input:focus {
border-color: var(--input-border-focus); /* box-shadow: 0 0 0 var(--border-width) var(--input-border-focus); */
border-color: var(--input-border-focus) !important;
outline: 0; outline: 0;
} }

View File

@ -1,6 +1,6 @@
.web3 { .web3 {
margin: calc(var(--spacer) / 2) auto calc(var(--spacer) / 4) auto; margin: calc(var(--spacer) / 2) auto calc(var(--spacer) / 4) auto;
max-width: 25rem; max-width: 100%;
width: 100%; width: 100%;
text-align: center; text-align: center;
min-height: 165px; min-height: 165px;

View File

@ -1,11 +1,13 @@
.inputGroup { .inputGroup {
--height: 60px;
margin: auto; margin: auto;
position: relative; position: relative;
animation: fadeIn 0.8s ease-out backwards; animation: fadeIn 0.8s ease-out backwards;
margin-top: calc(var(--spacer) / 3); margin-top: calc(var(--spacer) / 3);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-height: 54px; min-height: var(--height);
} }
@media (min-width: 40rem) { @media (min-width: 40rem) {
@ -21,31 +23,31 @@
} }
.token { .token {
width: 80px; width: 90px;
height: 55px; height: var(--height);
background: var(--box-background-color); background: var(--box-background-color);
border-top-left-radius: var(--border-radius); border-top-left-radius: var(--border-radius);
border-bottom-left-radius: var(--border-radius); border-bottom-left-radius: var(--border-radius);
border: 1px solid var(--border-color); border: var(--border-width) solid var(--border-color);
margin-right: -1px; border-right-color: var(--box-background-color);
} }
.inputInput { .inputInput {
text-align: center; text-align: center;
border: 1px solid var(--border-color); border: var(--border-width) solid var(--border-color);
font-size: var(--font-size-large); font-size: var(--font-size-large);
padding: 0 calc(var(--spacer) / 4); padding: 0 calc(var(--spacer) / 4);
border-bottom: 0; border-bottom: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
height: 55px; height: var(--height);
} }
@media (min-width: 40rem) { @media (min-width: 40rem) {
.inputInput { .inputInput {
border-radius: 0; border-radius: 0;
border-bottom: 1px solid var(--border-color); border-bottom: var(--border-width) solid var(--border-color);
border-right: 0; width: 70%;
} }
} }
@ -60,16 +62,15 @@
.submit { .submit {
width: calc(100% - calc(var(--spacer) / 2) - 2px); width: calc(100% - calc(var(--spacer) / 2) - 2px);
max-width: none; max-width: none;
height: 53px; height: calc(- var(--border-width));
border-top-left-radius: 0; border-top-left-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
border-color: var(--link-color-hover); border: var(--border-width) solid var(--link-color);
padding: 0 calc(var(--spacer) / 2);
} }
@media (min-width: 40rem) { @media (min-width: 40rem) {
.submit { .submit {
width: 115px; width: fit-content;
border-top-right-radius: var(--border-radius); border-top-right-radius: var(--border-radius);
border-top-left-radius: 0; border-top-left-radius: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
@ -77,6 +78,13 @@
} }
} }
/* .submit:disabled {
opacity: 0.8;
background: var(--text-color-light);
color: var(--text-color);
border-color: var(--text-color-light);
} */
@keyframes fadeIn { @keyframes fadeIn {
from { from {
opacity: 0.01; opacity: 0.01;

View File

@ -46,6 +46,12 @@ export function Send({ amount }: { amount: string }) {
init() init()
}, [selectedToken || amount || to || chain?.id]) }, [selectedToken || amount || to || chain?.id])
// Cancel send flow if chain changes as this can mess with token selection
// useEffect(() => {
// if (!chain?.id || $isInitSend.get() === false) return
// $isInitSend.set(false)
// }, [chain?.id])
async function handleSend(event: FormEvent<HTMLButtonElement>) { async function handleSend(event: FormEvent<HTMLButtonElement>) {
event?.preventDefault() event?.preventDefault()
try { try {

View File

@ -4,23 +4,26 @@
/* font-weight: var(--font-weight-bold); */ /* font-weight: var(--font-weight-bold); */
} }
.to { .to,
.from {
display: block; display: block;
word-break: break-all; word-break: break-all;
background: none; background: none;
padding: 0; padding: 0;
}
.to:last-child {
padding-left: 14px;
font-size: var(--font-size-mini); font-size: var(--font-size-mini);
} }
.to:last-child::first-letter { .to:last-child:not(:only-child),
.from:last-child:not(:only-child) {
padding-left: 14px;
}
.to:last-child:not(:only-child)::first-letter,
.from:last-child:not(:only-child)::first-letter {
margin-left: -14px; margin-left: -14px;
} }
.table { .from .table {
/* max-width: 386px; */ /* max-width: 386px; */
margin-bottom: calc(var(--spacer) / 1.5); margin-bottom: calc(var(--spacer) / 1.5);
} }
@ -31,10 +34,11 @@ table[aria-disabled='true'] {
} }
.table td { .table td {
padding: calc(var(--spacer) / 4); padding: calc(var(--spacer) / 4) calc(var(--spacer) / 3);
} }
.label { .label {
color: var(--text-color-light); color: var(--text-color-light);
vertical-align: top; vertical-align: top;
width: 6rem;
} }

View File

@ -1,5 +1,5 @@
import { formatEther } from 'viem' import { formatEther } from 'viem'
import { useNetwork } from 'wagmi' import { useAccount, useEnsName, useNetwork } from 'wagmi'
import type { import type {
SendTransactionArgs, SendTransactionArgs,
WriteContractPreparedArgs WriteContractPreparedArgs
@ -20,6 +20,8 @@ export function SendTable({
isDisabled: boolean isDisabled: boolean
}) { }) {
const { chain } = useNetwork() const { chain } = useNetwork()
const { address: from } = useAccount()
const { data: ensFrom } = useEnsName({ address: from, chainId: 1 })
const selectedToken = useStore($selectedToken) const selectedToken = useStore($selectedToken)
// Derive display values in preview from actual tx config // Derive display values in preview from actual tx config
@ -34,25 +36,35 @@ export function SendTable({
<table className={styles.table} aria-disabled={isDisabled}> <table className={styles.table} aria-disabled={isDisabled}>
<tbody> <tbody>
<tr> <tr>
<td className={styles.label}>Sending</td> <td className={styles.label}>You are</td>
{ensFrom ? (
<td title={`${ensFrom} successfully resolved to ${from}`}>
<code className={styles.from}>{ensFrom}</code>
<code className={styles.from}>{`${from}`}</code>
</td>
) : (
<td>
<code className={styles.from}>{from}</code>
</td>
)}
</tr>
<tr>
<td className={styles.label}>sending</td>
<td> <td>
<span className={styles.amount}> <span className={styles.amount}>
{displayAmountFromConfig} {selectedToken?.symbol} {displayAmountFromConfig} {selectedToken?.symbol}
</span> </span>
</td> </td>
</tr> </tr>
<tr> <tr>
<td className={styles.label}>on</td> <td className={styles.label}>on</td>
<td> <td>
<span className={styles.network}>{chain?.name}</span> <span className={styles.network}>{chain?.name}</span>
</td> </td>
</tr> </tr>
{/* <tr>
<td>From</td>
<td>
<code className={styles.from}>{from}</code>
</td>
</tr> */}
<tr> <tr>
<td className={styles.label}>to</td> <td className={styles.label}>to</td>
<td title={`${ensResolved} successfully resolved to ${to}`}> <td title={`${ensResolved} successfully resolved to ${to}`}>

View File

@ -26,7 +26,6 @@
border-radius: 50%; border-radius: 50%;
margin-right: calc(var(--spacer) / 4); margin-right: calc(var(--spacer) / 4);
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
background: var(--brand-light);
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;

View File

@ -1,39 +0,0 @@
.TokenLogo .loader {
--borderWidth: 5px;
--dashes: 10;
--gap: 5deg;
--color: var(--text-color);
display: block;
width: 100px;
aspect-ratio: 1;
border-radius: 50%;
padding: 1px;
background: conic-gradient(#0000, var(--color)) content-box;
--_m: repeating-conic-gradient(
#0000 0deg,
#000 1deg calc(360deg / var(--dashes) - var(--gap) - 1deg),
#0000 calc(360deg / var(--dashes) - var(--gap))
calc(360deg / var(--dashes))
),
radial-gradient(
farthest-side,
#0000 calc(98% - var(--borderWidth)),
#000 calc(100% - var(--borderWidth))
);
/* stylelint-disable-next-line property-no-vendor-prefix */
-webkit-mask: var(--_m);
mask: var(--_m);
/* stylelint-disable-next-line property-no-vendor-prefix */
-webkit-mask-composite: destination-in;
mask-composite: intersect;
animation: load 1s infinite steps(var(--dashes));
}
@keyframes load {
to {
transform: rotate(1turn);
}
}

View File

@ -1,9 +0,0 @@
import './TokenLoading.css'
export function TokenLoading() {
return (
<div className="TokenLogo TokenLoading">
<span className="loader"></span>
</div>
)
}

View File

@ -1,8 +1,8 @@
.SelectTrigger { .SelectTrigger {
display: inline-flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 80px; width: 100%;
height: 100%; height: 100%;
font-size: var(--font-size-small); font-size: var(--font-size-small);
line-height: 1; line-height: 1;
@ -14,9 +14,11 @@
background-color: var(--box-background-color); background-color: var(--box-background-color);
} }
/* .SelectTrigger:focus { .SelectTrigger:focus {
box-shadow: 0 0 0 2px blue; box-shadow: 0 0 0 var(--border-width) var(--input-border-focus);
} */
/* border-color: var(--input-border-focus) !important; */
}
.SelectTrigger[data-disabled] { .SelectTrigger[data-disabled] {
opacity: 0.5; opacity: 0.5;

View File

@ -4,7 +4,6 @@ import { Token } from './Token'
import { Icon as ChevronDown } from '@images/components/react/ChevronDown' import { Icon as ChevronDown } from '@images/components/react/ChevronDown'
import { Icon as ChevronsDown } from '@images/components/react/ChevronsDown' import { Icon as ChevronsDown } from '@images/components/react/ChevronsDown'
import { Icon as ChevronsUp } from '@images/components/react/ChevronsUp' import { Icon as ChevronsUp } from '@images/components/react/ChevronsUp'
import { TokenLoading } from './TokenLoading'
import { useFetchTokens } from '@features/Web3/hooks/useFetchTokens' import { useFetchTokens } from '@features/Web3/hooks/useFetchTokens'
import { useStore } from '@nanostores/react' import { useStore } from '@nanostores/react'
import { $tokens } from '@features/Web3/stores/tokens' import { $tokens } from '@features/Web3/stores/tokens'
@ -12,6 +11,7 @@ import {
$selectedToken, $selectedToken,
$setSelectedToken $setSelectedToken
} from '@features/Web3/stores/selectedToken' } from '@features/Web3/stores/selectedToken'
import { Loader } from '@components/Loader'
export function TokenSelect() { export function TokenSelect() {
const { isLoading } = useFetchTokens() const { isLoading } = useFetchTokens()
@ -28,7 +28,7 @@ export function TokenSelect() {
$setSelectedToken(token) $setSelectedToken(token)
} }
return tokens ? ( return tokens && selectedToken ? (
<Select.Root <Select.Root
defaultValue={selectedToken?.address} defaultValue={selectedToken?.address}
onValueChange={(value: `0x${string}`) => handleValueChange(value)} onValueChange={(value: `0x${string}`) => handleValueChange(value)}
@ -40,7 +40,7 @@ export function TokenSelect() {
aria-label="Token" aria-label="Token"
placeholder="..." placeholder="..."
> >
{isLoading ? <TokenLoading /> : <Select.Value />} <Select.Value />
<Select.Icon> <Select.Icon>
<ChevronDown /> <ChevronDown />
</Select.Icon> </Select.Icon>
@ -67,10 +67,10 @@ export function TokenSelect() {
</Select.Portal> </Select.Portal>
</Select.Root> </Select.Root>
) : isLoading ? ( ) : isLoading ? (
<> <div className="Token">
<div className="Token"> <div className="TokenLogo TokenLoading">
<TokenLoading /> <Loader />
</div> </div>
</> </div>
) : null ) : null
} }

View File

@ -15,7 +15,7 @@ import CodeCopy from '@components/CopyCode.astro'
@media (min-width: 40rem) { @media (min-width: 40rem) {
.grid { .grid {
grid-template-columns: 2fr 1fr; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
} }
} }

View File

@ -22,7 +22,7 @@
///////////////////////////////////// */ ///////////////////////////////////// */
--body-background-color: var(--brand-light); --body-background-color: var(--brand-light);
--box-background-color: rgba(255 255 255 / 40%); --box-background-color: #f1f5f8;
--box-shadow: 0 1.3px 5.4px rgba(1 85 101 / 15%), --box-shadow: 0 1.3px 5.4px rgba(1 85 101 / 15%),
0 4.5px 18.1px rgba(1 85 101 / 5%), 0 20px 81px rgba(1 85 101 / 2.5%); 0 4.5px 18.1px rgba(1 85 101 / 5%), 0 20px 81px rgba(1 85 101 / 2.5%);
@ -125,7 +125,7 @@
[data-theme='dark'] { [data-theme='dark'] {
--body-background-color: #161a1b; --body-background-color: #161a1b;
--box-background-color: rgba(255 255 255 / 3%); --box-background-color: #1e2122;
--box-shadow: 0 1.3px 5.4px rgba(0 7 8 / 50%), --box-shadow: 0 1.3px 5.4px rgba(0 7 8 / 50%),
0 4.5px 18.1px rgba(0 7 8 / 30%), 0 20px 81px rgba(0 7 8 / 10%); 0 4.5px 18.1px rgba(0 7 8 / 30%), 0 20px 81px rgba(0 7 8 / 10%);