simple mobile screen adaptiveness added

Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
Uncle Fatso 2025-07-23 15:33:56 +03:00
parent c8c1ef2739
commit 1120b710a6
Signed by: f4ts0
GPG Key ID: 565F4F2860226EBB
7 changed files with 81 additions and 72 deletions

View File

@ -1,6 +1,6 @@
{
"name": "ghost-lite",
"version": "0.0.18",
"version": "0.0.19",
"description": "Web application for Ghost and Casper chain.",
"author": "Uncle f4ts0 <f4ts0@ghostchain.io>",
"maintainers": [

View File

@ -69,7 +69,7 @@ export const ChainSelect = () => {
const api = select.connect(state, send, normalizeProps)
return (
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-2 w-full items-end">
<Select
value={state.context.value[0]}
onValueChange={(chainId) => {
@ -78,7 +78,7 @@ export const ChainSelect = () => {
}}
>
<SelectTrigger
className={"text-muted-foreground w-[200px]"}
className={"text-muted-foreground sm:w-[200px] w-full"}
data-testid="chain-select"
>
<SelectValue placeholder="Select Chain" />
@ -93,8 +93,8 @@ export const ChainSelect = () => {
</Select>
{state.context.value[0] && (
isConnected
? <div className="text-center text-sm text-secondary font-bold tracking-wide bg-accent rounded">Connected</div>
: <div className="text-center text-sm text-secondary font-bold tracking-wide bg-destructive rounded">Connecting...</div>
? <div className="text-center text-sm text-secondary font-bold tracking-wide bg-accent rounded sm:w-[200px] w-full">Connected</div>
: <div className="text-center text-sm text-secondary font-bold tracking-wide bg-destructive rounded sm:w-[200px] w-full">Connecting...</div>
)}
</div>
)

View File

@ -19,8 +19,8 @@ export const Header = () => {
return (
<div className="flex flex-row w-full justify-between">
<h2 className="text-3xl font-semibold">
<div className="flex sm:flex-row flex-col gap-4 justify-between items-center pb-6 sm:w-full w-[85%] self-center">
<h2 className="sm:text-3xl text-2xl font-semibold w-full">
{currentPath}
</h2>
<ChainSelect />

View File

@ -28,7 +28,7 @@ const AddressRecord: React.FC<AddressRecordProps> = ({ name, address, removeReco
return (
<AccordionItem className="bg-muted rounded px-4" value={name}>
<AccordionTrigger className="w-full hover:no-underline">
<div className="flex flex-row items-center gap-2 w-[90%] justify-between">
<div className="w-[90%] sm:text-base text-xs overflow-hidden whitespace-nowrap overflow-ellipsis text-left">
{name}
</div>
</AccordionTrigger>
@ -36,22 +36,22 @@ const AddressRecord: React.FC<AddressRecordProps> = ({ name, address, removeReco
<Button
variant="secondary"
size="full"
className="flex-1 text-accent text-xs"
className="flex-1 text-accent flex text-xs sm:flex hidden"
onClick={() => openTransfer({ address })}
>
<Send className="w-4 h-4" />
<Send className="w-4 h-4 mr-1" />
</Button>
<Input
readOnly
value={address}
aria-label={name}
type="text"
className="w-[300px] flex-6"
className="sm:w-[300px] flex-6"
/>
<Button
variant="destructive"
size="full"
className="flex-2 text-accent text-xs"
className="flex-2 text-accent text-xs sm:flex hidden"
onClick={() => removeRecord({ name })}
>
<Trash className="w-4 h-4 mr-2" />
@ -89,9 +89,12 @@ export const AddressBook = () => {
return
}
try {
ss58Decode(address)
const [, prefix] = ss58Decode(address)
if (prefix !== 1995 && prefix !== 1996) {
throw ""
}
} catch (e) {
setError("Incorrect Ghost address provided")
setError("Incorrect Ghost or Casper address provided")
return
}
const newRecord = { name, address }
@ -111,7 +114,7 @@ export const AddressBook = () => {
}
return (
<Accordion type="multiple" className="w-[500px] h-fit flex flex-col flex-1 gap-4 justify-center self-center py-8">
<Accordion type="multiple" className="sm:w-[500px] w-[85%] h-fit flex flex-col flex-1 gap-4 justify-center self-center py-2">
{addressBook.map(({ name, address }: AddressBookRecord, idx: number) => (
<AddressRecord
key={idx}
@ -121,14 +124,14 @@ export const AddressBook = () => {
openTransfer={openTransfer}
/>
))}
<div className="bg-muted flex flex-col gap-2 w-full rounded px-4 py-6">
<div className="flex flex-row gap-4">
<div className="bg-muted flex flex-col sm:gap-2 gap-4 w-full rounded px-4 py-6">
<div className="flex sm:flex-row flex-col gap-4">
<Input
value={name}
onChange={e => setName(e.target.value)}
aria-label="New Name"
type="text"
className="w-full"
className="w-full sm:text-base text-xs sm:placeholder:text-base placeholder:text-xs"
placeholder="Record Name"
/>
<Input
@ -136,7 +139,7 @@ export const AddressBook = () => {
onChange={e => setAddress(e.target.value)}
aria-label="New Address"
type="text"
className="w-full"
className="w-full sm:text-base text-xs sm:placeholder:text-base placeholder:text-xs"
placeholder="Record Address"
/>
</div>

View File

@ -17,7 +17,7 @@ export const App = () => {
<MetadataProviderProvider>
<Layout>
<Sidebar />
<div className="w-full h-full flex flex-col px-6 py-8">
<div style={{ maxWidth: "calc(100% - 100px)"}} className="w-full h-full flex flex-col sm:px-6 px-2 sm:py-8 py-2">
<Header />
<Routes>
<Route path="/health" element={<HealthCheck />} />

View File

@ -30,8 +30,9 @@ const Item: React.FC<ItemProps> = ({ value, elements, icon }) => {
return (
<AccordionItem className="bg-muted rounded px-4" value={value}>
<AccordionTrigger>
<div className="flex items-center gap-2 space-x-2 cursor-pointer">
{icon} {value}
<div className="flex flex-row items-center gap-2 space-x-2 cursor-pointer">
<div>{icon}</div>
<div className="sm:block hidden">{value}</div>
</div>
</AccordionTrigger>
<AccordionContent className="flex flex-col gap-2">
@ -50,8 +51,8 @@ interface RowProps {
const Row: React.FC<RowProps> = ({ title, element }) => {
return (
<div className="flex flex-row gap-2 justify-between items-center">
<div className="text-sm">{title}</div>
<div className="flex sm:flex-row flex-col gap-2 justify-between sm:items-center items-start">
<div className="sm:text-sm text-xs">{title}</div>
{element}
</div>
)
@ -62,6 +63,8 @@ export const HealthCheck = () => {
const blocks = useBlocks()
const health = useSystemHealth()
const widthClass = "sm:w-[300px] w-full"
const metadataElements = [
{
title: "Chain Name",
@ -69,7 +72,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Chain Name"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={chainSpec?.chainName}
/>
},
@ -79,7 +82,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Genesis Hash"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={chainSpec?.genesisHash}
/>
}
@ -91,7 +94,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Sync State"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={!health ? "" : health.isSyncing ? "Syncing..." : "Synced"}
/>
},
@ -101,7 +104,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Peers Connected"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={health?.peers}
/>
}
@ -113,7 +116,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Block Number"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={blocks?.latest?.number}
/>
},
@ -123,7 +126,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Block Hash"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={blocks?.latest?.hash}
/>
},
@ -133,7 +136,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Parent Hash"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={blocks?.latest?.parent}
/>
}
@ -145,7 +148,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Block Number"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={blocks?.finalized?.number}
/>
},
@ -155,7 +158,7 @@ export const HealthCheck = () => {
readOnly
aria-label="BlockHash"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={blocks?.finalized?.hash}
/>
},
@ -165,7 +168,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Parent Hash"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={blocks?.finalized?.parent}
/>
}
@ -177,7 +180,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Coin Symbol"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={chainSpec?.properties?.tokenSymbol}
/>
},
@ -187,7 +190,7 @@ export const HealthCheck = () => {
readOnly
aria-label="Block Hash"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={chainSpec?.properties?.tokenDecimals?.toString() ?? ""}
/>
},
@ -197,14 +200,14 @@ export const HealthCheck = () => {
readOnly
aria-label="Base58 Prefix"
type="text"
className="w-[300px]"
className={widthClass}
placeholder={chainSpec?.properties?.ss58Format?.toString() ?? ""}
/>
}
]
return (
<Accordion type="single" defaultValue="Chain metadata" className="w-[500px] h-fit flex flex-col flex-1 gap-4 justify-center self-center">
<Accordion type="single" defaultValue="Chain metadata" className="sm:w-[500px] w-[85%] h-fit flex flex-col flex-1 gap-4 justify-center self-center sm:text-base text-xs">
<Item value="Chain metadata" elements={metadataElements} icon={<Info className="w-4 h-4" />} />
<Item value="Peers information" elements={peersElements} icon={<Binary className="w-4 h-4" />} />
<Item value="Latest block" elements={bestBlockElements} icon={<Cuboid className="w-4 h-4" />} />

View File

@ -3,7 +3,8 @@ import {
Send,
Trash,
Settings2,
ArrowBigRightDash
ArrowBigRightDash,
ArrowBigDownDash
} from "lucide-react"
import React, { useState, useEffect, useCallback, useMemo, ReactNode } from "react"
import { useLocation } from "react-router-dom"
@ -73,7 +74,7 @@ interface RowProps {
const Row: React.FC<RowProps> = ({ title, element }) => {
return (
<div className="flex flex-row gap-2 justify-between items-center">
<div className="flex sm:flex-row flex-col gap-2 justify-between sm:items-center items-left">
<div className="text-sm">{title}</div>
{element}
</div>
@ -116,7 +117,7 @@ const Sender: React.FC<SenderProps> = ({
}}
>
<SelectTrigger
className={"text-muted-foreground w-[300px]"}
className={"text-muted-foreground sm:w-[300px] w-full"}
data-testid="chain-select"
>
<SelectValue placeholder="Select Account" />
@ -137,7 +138,7 @@ const Sender: React.FC<SenderProps> = ({
readOnly
aria-label="Account Balance"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder={senderBalance}
/>} />
{senderAccount && (<Accordion type="multiple" className="w-full flex flex-col gap-4 mb-4">
@ -152,28 +153,28 @@ const Sender: React.FC<SenderProps> = ({
readOnly
aria-label="Fee"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder={applyDecimals(senderAccount?.data?.free, tokenDecimals, tokenSymbol)}
/>} />
<Row title={"Frozen"} element={<Input
readOnly
aria-label="Frozen"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder={applyDecimals(senderAccount?.data?.frozen, tokenDecimals, tokenSymbol)}
/>} />
<Row title={"Reserved"} element={<Input
readOnly
aria-label="Reserved"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder={applyDecimals(senderAccount?.data?.reserved, tokenDecimals, tokenSymbol)}
/>} />
<Row title={"Nonce"} element={<Input
readOnly
aria-label="Nonce"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder={senderAccount?.nonce ? senderAccount.nonce.toString() : ""}
/>} />
</AccordionContent>
@ -214,7 +215,7 @@ const Receiver: React.FC<ReceiverProps> = ({
disabled={isSubmittingTransaction}
aria-label="Transfer Receiver"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder="Input receiver address"
/>} />
<Row title="Amount" element={<Input
@ -223,7 +224,7 @@ const Receiver: React.FC<ReceiverProps> = ({
disabled={isSubmittingTransaction}
aria-label="Transfer Amount"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder="Input amount to send"
/>} />
{receiverAccount && (<Accordion type="multiple" className="w-full flex flex-col gap-4">
@ -238,28 +239,28 @@ const Receiver: React.FC<ReceiverProps> = ({
readOnly
aria-label="Fee"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder={applyDecimals(receiverAccount?.data?.free, tokenDecimals, tokenSymbol)}
/>} />
<Row title={"Frozen"} element={<Input
readOnly
aria-label="Frozen"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder={applyDecimals(receiverAccount?.data?.frozen, tokenDecimals, tokenSymbol)}
/>} />
<Row title={"Reserved"} element={<Input
readOnly
aria-label="Reserved"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder={applyDecimals(receiverAccount?.data?.reserved, tokenDecimals, tokenSymbol)}
/>} />
<Row title={"Nonce"} element={<Input
readOnly
aria-label="Nonce"
type="text"
className="w-[300px]"
className="sm:w-[300px] w-full"
placeholder={receiverAccount?.nonce ? receiverAccount.nonce.toString() : ""}
/>} />
</AccordionContent>
@ -472,10 +473,10 @@ export const Transactions = () => {
])
return (
<div className="w-[500px] h-fit flex flex-col flex-1 gap-2 justify-center self-center rounded py-8">
<div className="sm:w-[500px] w-[85%] h-fit flex flex-col flex-1 gap-2 justify-center self-center rounded py-2">
<div className="bg-muted p-4 rounded flex flex-col gap-2">
<div className="w-full flex flex-row justify-between">
<div className="flex flex-row gap-2">
<div className="flex sm:flex-row flex-col gap-2">
<Button
type="button"
variant="ghost"
@ -502,6 +503,7 @@ export const Transactions = () => {
variant="ghost"
disabled={isSubmittingTransaction}
onClick={() => onActiveTabChanged("settings")}
className="sm:block hidden"
>
<Settings2 className="w-4 h-4 inline-block" />
</Button>
@ -581,17 +583,18 @@ export const Transactions = () => {
{transactionHistory.map((props: TransactionHistory) => (
<AccordionItem key={props.txHash} className="bg-muted rounded px-4" value={props.txHash ?? ""}>
<AccordionTrigger className="w-full hover:no-underline">
<div className="flex flex-row gap-2 items-center w-[90%] justify-between cursor-pointer">
<div className="flex sm:flex-row flex-col gap-2 items-center w-[90%] justify-between cursor-pointer">
<Input
readOnly
className="overflow-hidden whitespace-nowrap text-ellipsis w-[45%]"
className="overflow-hidden whitespace-nowrap text-ellipsis sm:w-[45%] w-full"
value={props.sender}
placeholder="Sender not found"
/>
<ArrowBigRightDash className="w-6 h-6" />
<ArrowBigRightDash className="w-6 h-6 sm:block hidden" />
<ArrowBigDownDash className="w-6 h-6 sm:hidden block" />
<Input
readOnly
className="overflow-hidden whitespace-nowrap text-ellipsis w-[45%]"
className="overflow-hidden whitespace-nowrap text-ellipsis sm:w-[45%] w-full"
value={props.receiver}
placeholder="Receiver not found"
/>
@ -613,28 +616,28 @@ export const Transactions = () => {
</span>
<hr className="my-4" />
<div className="flex flex-col gap-2">
<div className="flex flex-row justify-between items-center gap-2">
<div className="flex sm:flex-row flex-col justify-between sm:items-center items-left gap-2">
Tx hash:
<Input
readOnly
value={props.txHash}
className="text-accent w-[350px] h-[30px]"
className="text-accent sm:w-[350px] w-full h-[30px]"
/>
</div>
<div className="flex flex-row justify-between items-center gap-2">
<div className="flex sm:flex-row flex-col justify-between sm:items-center items-left gap-2">
Block hash:
<Input
readOnly
value={props.blockHash}
className="text-accent w-[350px] h-[30px]"
className="text-accent sm:w-[350px] w-full h-[30px]"
/>
</div>
<div className="flex flex-row justify-between items-center gap-2">
<div className="flex sm:flex-row flex-col justify-between sm:items-center items-left gap-2">
Calldata:
<Input
readOnly
value={props.calldata}
className="text-accent w-[350px] h-[30px]"
className="text-accent sm:w-[350px] w-full h-[30px]"
/>
</div>
</div>
@ -662,23 +665,23 @@ export const Transactions = () => {
)}
{activeTab === "settings" && (
<div className="min-h-[248px] text-sm flex flex-col gap-2">
<div className="flex flex-row gap-2 justify-between items-center">
<span className="pb-4">Max lifetime:</span>
<div className="w-[350px] flex flex-col">
<div className="flex sm:flex-row flex-col gap-2 justify-between sm:items-center items-left">
<span className="sm:pb-4 pb-0">Max lifetime:</span>
<div className="sm:w-[350px] w-full flex flex-col">
<Input
value={historyLifetimeDuration}
onChange={(e) => {
const newValue = +e.target.value
if (newValue) setHistoryLifetimeDuration(newValue)
}}
className="w-[350px]"
className="sm:w-[350px] w-full"
/>
<span className="text-xs text-accent my-2">
{convertedTimestamp({ timestamp: historyLifetimeDuration})}
</span>
</div>
</div>
<div className="flex flex-row gap-2 justify-between items-center">
<div className="flex sm:flex-row flex-col gap-2 justify-between sm:items-center items-left">
<span>Max records:</span>
<Input
value={historyMaxRecords}
@ -686,10 +689,10 @@ export const Transactions = () => {
const newValue = +e.target.value
if (newValue) setHistoryMaxRecords(newValue)
}}
className="w-[350px]"
className="sm:w-[350px] w-full"
/>
</div>
<div className="flex flex-row gap-2 justify-between items-center">
<div className="flex sm:flex-row flex-col gap-2 justify-between sm:items-center items-left">
<span>Default amount:</span>
<Input
value={defaultTransactAmount}
@ -697,7 +700,7 @@ export const Transactions = () => {
setDefaultTransactAmount(e.target.value)
setAmount(e.target.value)
}}
className="w-[350px]"
className="sm:w-[350px] w-full"
placeholder="Amount will be empty"
/>
</div>