Redesign and expose styling and theming (#25)
This commit is contained in:
parent
99a49ab334
commit
004938274b
|
@ -6,6 +6,7 @@
|
|||
"homepage": "https://github.com/project-serum/swap-ui",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@fontsource/roboto": "^4.3.0",
|
||||
"@project-serum/serum": "^0.13.34",
|
||||
"@project-serum/swap": "^0.1.0-alpha.14",
|
||||
"@solana/spl-token": "^0.1.4"
|
||||
|
|
|
@ -13,24 +13,18 @@ import { useSwapContext, useSwapFair } from "../context/Swap";
|
|||
import { useMint } from "../context/Token";
|
||||
import { useRoute, useMarketName, useBbo } from "../context/Dex";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
const useStyles = makeStyles(() => ({
|
||||
infoLabel: {
|
||||
marginTop: "10px",
|
||||
marginBottom: "10px",
|
||||
marginTop: "20px",
|
||||
marginBottom: "20px",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
marginLeft: "5px",
|
||||
marginRight: "5px",
|
||||
},
|
||||
fairPriceLabel: {
|
||||
marginRight: "10px",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
color: theme.palette.text.secondary,
|
||||
justifyContent: "flex-end",
|
||||
alignItems: "center",
|
||||
},
|
||||
infoButton: {
|
||||
marginLeft: "5px",
|
||||
padding: 0,
|
||||
fontSize: "14px",
|
||||
},
|
||||
}));
|
||||
|
||||
|
@ -47,17 +41,14 @@ export function InfoLabel() {
|
|||
|
||||
return (
|
||||
<div className={styles.infoLabel}>
|
||||
<Typography color="textSecondary"></Typography>
|
||||
<div style={{ display: "flex" }}>
|
||||
<div className={styles.fairPriceLabel}>
|
||||
{fair !== undefined && toTokenInfo && fromTokenInfo
|
||||
? `1 ${toTokenInfo.symbol} = ${fair.toFixed(
|
||||
fromMintInfo?.decimals
|
||||
)} ${fromTokenInfo.symbol}`
|
||||
: `-`}
|
||||
</div>
|
||||
<InfoButton />
|
||||
</div>
|
||||
<Typography color="textSecondary" style={{ fontSize: "14px" }}>
|
||||
{fair !== undefined && toTokenInfo && fromTokenInfo
|
||||
? `1 ${toTokenInfo.symbol} = ${fair.toFixed(
|
||||
fromMintInfo?.decimals
|
||||
)} ${fromTokenInfo.symbol}`
|
||||
: `-`}
|
||||
</Typography>
|
||||
<InfoButton />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -74,7 +65,7 @@ function InfoButton() {
|
|||
{...bindTrigger(popupState)}
|
||||
className={styles.infoButton}
|
||||
>
|
||||
<Info />
|
||||
<Info fontSize="small" />
|
||||
</IconButton>
|
||||
<Popover
|
||||
{...bindPopover(popupState)}
|
||||
|
|
|
@ -28,8 +28,8 @@ import { useMint, useOwnedTokenAccount } from "../context/Token";
|
|||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
table: {},
|
||||
closeAccountSwitchLabel: {
|
||||
color: theme.palette.text.secondary,
|
||||
closeAccount: {
|
||||
color: theme.palette.error.main,
|
||||
},
|
||||
}));
|
||||
|
||||
|
@ -40,6 +40,8 @@ export default function OpenOrdersDialog({
|
|||
open: boolean;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
maxWidth="lg"
|
||||
|
@ -51,30 +53,24 @@ export default function OpenOrdersDialog({
|
|||
},
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
onClick={onClose}
|
||||
style={{
|
||||
height: "24px",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
padding: 10,
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
onClick={onClose}
|
||||
style={{
|
||||
padding: 0,
|
||||
position: "absolute",
|
||||
right: "8px",
|
||||
top: "8px",
|
||||
}}
|
||||
>
|
||||
<Close />
|
||||
</IconButton>
|
||||
</div>
|
||||
<DialogContent style={{ paddingTop: 0 }}>
|
||||
<OpenOrdersAccounts />
|
||||
</DialogContent>
|
||||
<Close />
|
||||
</IconButton>
|
||||
</div>
|
||||
<DialogContent style={{ paddingTop: 0 }}>
|
||||
<OpenOrdersAccounts />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
@ -126,6 +122,8 @@ function OpenOrdersRow({
|
|||
market: PublicKey;
|
||||
openOrders: Array<OpenOrders>;
|
||||
}) {
|
||||
const styles = useStyles();
|
||||
|
||||
const [ooAccount, setOoAccount] = useState(openOrders[0]);
|
||||
const { swapClient } = useDexContext();
|
||||
const marketClient = useMarket(market);
|
||||
|
@ -235,9 +233,9 @@ function OpenOrdersRow({
|
|||
</TableCell>
|
||||
<TableCell align="center">
|
||||
<Button
|
||||
color="secondary"
|
||||
disabled={closeDisabled}
|
||||
onClick={closeOpenOrders}
|
||||
className={styles.closeAccount}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
FormControlLabel,
|
||||
FormGroup,
|
||||
} from "@material-ui/core";
|
||||
import { ToggleButton } from "@material-ui/lab";
|
||||
import { SettingsOutlined as Settings } from "@material-ui/icons";
|
||||
import PopupState, { bindTrigger, bindPopover } from "material-ui-popup-state";
|
||||
import { useSwapContext, useSwapFair } from "../context/Swap";
|
||||
|
@ -25,10 +24,27 @@ const useStyles = makeStyles((theme) => ({
|
|||
table: {},
|
||||
settingsButton: {
|
||||
padding: 0,
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
closeAccountSwitchLabel: {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
fairAutoSelected: {
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
padding: "3px 5px",
|
||||
borderRadius: "10px",
|
||||
color: theme.palette.primary.contrastText,
|
||||
fontWeight: 700,
|
||||
},
|
||||
fairAuto: {
|
||||
backgroundColor:
|
||||
theme.palette.type === "dark"
|
||||
? theme.palette.secondary.light
|
||||
: theme.palette.secondary.main,
|
||||
padding: "3px 5px",
|
||||
borderRadius: "10px",
|
||||
boxShadow: "none",
|
||||
},
|
||||
}));
|
||||
|
||||
export function SettingsButton() {
|
||||
|
@ -56,7 +72,12 @@ export function SettingsButton() {
|
|||
vertical: "top",
|
||||
horizontal: "right",
|
||||
}}
|
||||
PaperProps={{ style: { borderRadius: "10px" } }}
|
||||
PaperProps={{
|
||||
style: {
|
||||
borderRadius: "10px",
|
||||
boxShadow: "0px 0px 30px 5px rgba(0,0,0,0.075)",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SettingsDetails />
|
||||
</Popover>
|
||||
|
@ -68,6 +89,8 @@ export function SettingsButton() {
|
|||
}
|
||||
|
||||
function SettingsDetails() {
|
||||
const styles = useStyles();
|
||||
|
||||
const { slippage, setSlippage, fairOverride, setFairOverride } =
|
||||
useSwapContext();
|
||||
const [showSettingsDialog, setShowSettingsDialog] = useState(false);
|
||||
|
@ -80,12 +103,12 @@ function SettingsDetails() {
|
|||
|
||||
return (
|
||||
<div style={{ padding: "15px", width: "305px" }}>
|
||||
<Typography color="textSecondary" style={{ fontWeight: "bold" }}>
|
||||
Settings
|
||||
</Typography>
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
<div>
|
||||
<Typography color="textSecondary">Slippage tolerance</Typography>
|
||||
<Typography style={{ fontWeight: "bold" }}>Settings</Typography>
|
||||
<div>
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
<Typography color="textSecondary" style={{ fontSize: "12px" }}>
|
||||
Slippage tolerance
|
||||
</Typography>
|
||||
<TextField
|
||||
type="number"
|
||||
placeholder="Error tolerance percentage"
|
||||
|
@ -101,8 +124,10 @@ function SettingsDetails() {
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginTop: "5px" }}>
|
||||
<Typography color="textSecondary">Fair price</Typography>
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
<Typography color="textSecondary" style={{ fontSize: "12px" }}>
|
||||
Fair price
|
||||
</Typography>
|
||||
<div style={{ display: "flex" }}>
|
||||
<TextField
|
||||
type="number"
|
||||
|
@ -118,9 +143,9 @@ function SettingsDetails() {
|
|||
}}
|
||||
disabled={fairOverride === null}
|
||||
/>
|
||||
<ToggleButton
|
||||
value="bold"
|
||||
selected={fairOverride === null}
|
||||
<Button
|
||||
component="div"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
if (fair === undefined) {
|
||||
console.error("Fair is undefined");
|
||||
|
@ -132,27 +157,22 @@ function SettingsDetails() {
|
|||
setFairOverride(null);
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
paddingTop: "3px",
|
||||
paddingBottom: "3px",
|
||||
paddingLeft: "5px",
|
||||
paddingRight: "5px",
|
||||
borderRadius: "20px",
|
||||
}}
|
||||
className={
|
||||
fairOverride === null
|
||||
? styles.fairAutoSelected
|
||||
: styles.fairAuto
|
||||
}
|
||||
>
|
||||
Auto
|
||||
</ToggleButton>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ marginTop: "5px" }}>
|
||||
<div style={{ margin: "10px 0px" }}>
|
||||
<CloseNewAccountsSwitch />
|
||||
</div>
|
||||
<Button
|
||||
style={{
|
||||
width: "100%",
|
||||
marginTop: "10px",
|
||||
background: "#e0e0e0",
|
||||
}}
|
||||
variant="contained"
|
||||
fullWidth
|
||||
disabled={swapClient.program.provider.wallet.publicKey === null}
|
||||
onClick={() => setShowSettingsDialog(true)}
|
||||
>
|
||||
|
|
|
@ -5,11 +5,11 @@ import {
|
|||
makeStyles,
|
||||
Card,
|
||||
Button,
|
||||
Paper,
|
||||
Typography,
|
||||
TextField,
|
||||
useTheme,
|
||||
} from "@material-ui/core";
|
||||
import { ExpandMore } from "@material-ui/icons";
|
||||
import { ExpandMore, ImportExportRounded } from "@material-ui/icons";
|
||||
import { useSwapContext, useSwapFair } from "../context/Swap";
|
||||
import {
|
||||
useDexContext,
|
||||
|
@ -25,16 +25,12 @@ import TokenDialog from "./TokenDialog";
|
|||
import { SettingsButton } from "./Settings";
|
||||
import { InfoLabel } from "./Info";
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
card: {
|
||||
width: "450px",
|
||||
borderRadius: "10px",
|
||||
border: "solid 1pt #e0e0e0",
|
||||
},
|
||||
cardContent: {
|
||||
marginLeft: "6px",
|
||||
marginRight: "6px",
|
||||
marginBottom: "6px",
|
||||
borderRadius: "16px",
|
||||
boxShadow: "0px 0px 30px 5px rgba(0,0,0,0.075)",
|
||||
padding: "16px",
|
||||
},
|
||||
tab: {
|
||||
width: "50%",
|
||||
|
@ -44,30 +40,78 @@ const useStyles = makeStyles(() => ({
|
|||
},
|
||||
swapButton: {
|
||||
width: "100%",
|
||||
borderRadius: "15px",
|
||||
borderRadius: "10px",
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
color: theme.palette.primary.contrastText,
|
||||
fontSize: 16,
|
||||
fontWeight: 700,
|
||||
padding: "10px",
|
||||
},
|
||||
swapToFromButton: {
|
||||
display: "block",
|
||||
marginLeft: "auto",
|
||||
marginRight: "auto",
|
||||
margin: "10px auto 10px auto",
|
||||
cursor: "pointer",
|
||||
},
|
||||
amountInput: {
|
||||
fontSize: 22,
|
||||
fontWeight: 600,
|
||||
},
|
||||
input: {
|
||||
textAlign: "right",
|
||||
},
|
||||
swapTokenFormContainer: {
|
||||
borderRadius: "10px",
|
||||
boxShadow: "0px 0px 15px 2px rgba(33,150,243,0.1)",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
padding: "10px",
|
||||
},
|
||||
swapTokenSelectorContainer: {
|
||||
marginLeft: "5px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
},
|
||||
balanceContainer: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
fontSize: "14px",
|
||||
},
|
||||
maxButton: {
|
||||
marginLeft: 10,
|
||||
color: theme.palette.primary.main,
|
||||
fontWeight: 700,
|
||||
fontSize: "12px",
|
||||
cursor: "pointer",
|
||||
},
|
||||
tokenButton: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
cursor: "pointer",
|
||||
marginBottom: "10px",
|
||||
},
|
||||
}));
|
||||
|
||||
export default function SwapCard({ style }: { style?: any }) {
|
||||
export default function SwapCard({
|
||||
containerStyle,
|
||||
contentStyle,
|
||||
swapTokenContainerStyle,
|
||||
}: {
|
||||
containerStyle?: any;
|
||||
contentStyle?: any;
|
||||
swapTokenContainerStyle?: any;
|
||||
}) {
|
||||
const styles = useStyles();
|
||||
return (
|
||||
<div style={style}>
|
||||
<Card className={styles.card}>
|
||||
<SwapHeader />
|
||||
<div className={styles.cardContent}>
|
||||
<SwapFromForm />
|
||||
<ArrowButton />
|
||||
<SwapToForm />
|
||||
<InfoLabel />
|
||||
<SwapButton />
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
<Card className={styles.card} style={containerStyle}>
|
||||
<SwapHeader />
|
||||
<div style={contentStyle}>
|
||||
<SwapFromForm style={swapTokenContainerStyle} />
|
||||
<ArrowButton />
|
||||
<SwapToForm style={swapTokenContainerStyle} />
|
||||
<InfoLabel />
|
||||
<SwapButton />
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -77,18 +121,17 @@ function SwapHeader() {
|
|||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
margin: "8px",
|
||||
marginBottom: "20px",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
fontSize: 18,
|
||||
fontWeight: 700,
|
||||
fontFamily: "Roboto Condensed",
|
||||
}}
|
||||
>
|
||||
Swap
|
||||
SWAP
|
||||
</Typography>
|
||||
<SettingsButton />
|
||||
</div>
|
||||
|
@ -97,18 +140,24 @@ function SwapHeader() {
|
|||
|
||||
export function ArrowButton() {
|
||||
const styles = useStyles();
|
||||
const theme = useTheme();
|
||||
const { swapToFromMints } = useSwapContext();
|
||||
return (
|
||||
<Button className={styles.swapToFromButton} onClick={swapToFromMints}>
|
||||
⇅
|
||||
</Button>
|
||||
<ImportExportRounded
|
||||
className={styles.swapToFromButton}
|
||||
fontSize="large"
|
||||
htmlColor={theme.palette.primary.main}
|
||||
onClick={swapToFromMints}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function SwapFromForm() {
|
||||
function SwapFromForm({ style }: { style?: any }) {
|
||||
const { fromMint, setFromMint, fromAmount, setFromAmount } = useSwapContext();
|
||||
return (
|
||||
<SwapTokenForm
|
||||
from
|
||||
style={style}
|
||||
mint={fromMint}
|
||||
setMint={setFromMint}
|
||||
amount={fromAmount}
|
||||
|
@ -117,10 +166,12 @@ function SwapFromForm() {
|
|||
);
|
||||
}
|
||||
|
||||
function SwapToForm() {
|
||||
function SwapToForm({ style }: { style?: any }) {
|
||||
const { toMint, setToMint, toAmount, setToAmount } = useSwapContext();
|
||||
return (
|
||||
<SwapTokenForm
|
||||
from={false}
|
||||
style={style}
|
||||
mint={toMint}
|
||||
setMint={setToMint}
|
||||
amount={toAmount}
|
||||
|
@ -130,57 +181,75 @@ function SwapToForm() {
|
|||
}
|
||||
|
||||
function SwapTokenForm({
|
||||
from,
|
||||
style,
|
||||
mint,
|
||||
setMint,
|
||||
amount,
|
||||
setAmount,
|
||||
}: {
|
||||
from: boolean;
|
||||
style?: any;
|
||||
mint: PublicKey;
|
||||
setMint: (m: PublicKey) => void;
|
||||
amount: number;
|
||||
setAmount: (a: number) => void;
|
||||
}) {
|
||||
const styles = useStyles();
|
||||
|
||||
const [showTokenDialog, setShowTokenDialog] = useState(false);
|
||||
const tokenAccount = useOwnedTokenAccount(mint);
|
||||
const mintAccount = useMint(mint);
|
||||
|
||||
const balance =
|
||||
tokenAccount &&
|
||||
mintAccount &&
|
||||
tokenAccount.account.amount.toNumber() / 10 ** mintAccount.decimals;
|
||||
|
||||
const formattedAmount =
|
||||
mintAccount && amount
|
||||
? amount.toLocaleString("fullwide", {
|
||||
maximumFractionDigits: mintAccount.decimals,
|
||||
useGrouping: false,
|
||||
})
|
||||
: amount;
|
||||
|
||||
return (
|
||||
<Paper elevation={0} variant="outlined" style={{ borderRadius: "10px" }}>
|
||||
<div
|
||||
style={{
|
||||
height: "50px",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<div className={styles.swapTokenFormContainer} style={style}>
|
||||
<div className={styles.swapTokenSelectorContainer}>
|
||||
<TokenButton mint={mint} onClick={() => setShowTokenDialog(true)} />
|
||||
<TextField
|
||||
type="number"
|
||||
value={amount}
|
||||
onChange={(e) => setAmount(parseFloat(e.target.value))}
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginLeft: "10px", height: "30px" }}>
|
||||
<Typography color="textSecondary" style={{ fontSize: "14px" }}>
|
||||
<Typography color="textSecondary" className={styles.balanceContainer}>
|
||||
{tokenAccount && mintAccount
|
||||
? `Balance: ${(
|
||||
tokenAccount.account.amount.toNumber() /
|
||||
10 ** mintAccount.decimals
|
||||
).toFixed(mintAccount.decimals)}`
|
||||
? `Balance: ${balance?.toFixed(mintAccount.decimals)}`
|
||||
: `-`}
|
||||
{from && !!balance ? (
|
||||
<span
|
||||
className={styles.maxButton}
|
||||
onClick={() => setAmount(balance)}
|
||||
>
|
||||
MAX
|
||||
</span>
|
||||
) : null}
|
||||
</Typography>
|
||||
</div>
|
||||
<TextField
|
||||
type="number"
|
||||
value={formattedAmount}
|
||||
onChange={(e) => setAmount(parseFloat(e.target.value))}
|
||||
InputProps={{
|
||||
disableUnderline: true,
|
||||
classes: {
|
||||
root: styles.amountInput,
|
||||
input: styles.input,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<TokenDialog
|
||||
setMint={setMint}
|
||||
open={showTokenDialog}
|
||||
onClose={() => setShowTokenDialog(false)}
|
||||
/>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -191,12 +260,14 @@ function TokenButton({
|
|||
mint: PublicKey;
|
||||
onClick: () => void;
|
||||
}) {
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<Button onClick={onClick} style={{ minWidth: "116px" }}>
|
||||
<TokenIcon mint={mint} style={{ width: "25px", borderRadius: "13px" }} />
|
||||
<TokenName mint={mint} />
|
||||
<div onClick={onClick} className={styles.tokenButton}>
|
||||
<TokenIcon mint={mint} style={{ width: "30px" }} />
|
||||
<TokenName mint={mint} style={{ fontSize: 14, fontWeight: 700 }} />
|
||||
<ExpandMore />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -220,11 +291,13 @@ export function TokenIcon({ mint, style }: { mint: PublicKey; style: any }) {
|
|||
);
|
||||
}
|
||||
|
||||
function TokenName({ mint }: { mint: PublicKey }) {
|
||||
function TokenName({ mint, style }: { mint: PublicKey; style: any }) {
|
||||
const tokenMap = useTokenMap();
|
||||
let tokenInfo = tokenMap.get(mint.toString());
|
||||
return (
|
||||
<Typography style={{ marginLeft: "5px" }}>{tokenInfo?.symbol}</Typography>
|
||||
<Typography style={{ marginLeft: "10px", marginRight: "5px", ...style }}>
|
||||
{tokenInfo?.symbol}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,20 +17,25 @@ import {
|
|||
import { TokenIcon } from "./Swap";
|
||||
import { useSwappableTokens } from "../context/TokenList";
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
dialogContent: {
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
padding: 0,
|
||||
},
|
||||
textField: {
|
||||
width: "100%",
|
||||
border: "solid 1pt #ccc",
|
||||
borderRadius: "10px",
|
||||
marginBottom: "8px",
|
||||
},
|
||||
tab: {
|
||||
minWidth: "134px",
|
||||
},
|
||||
tabSelected: {
|
||||
color: theme.palette.primary.contrastText,
|
||||
fontWeight: 700,
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
borderRadius: "10px",
|
||||
},
|
||||
tabIndicator: {
|
||||
opacity: 0,
|
||||
},
|
||||
}));
|
||||
|
||||
export default function TokenDialog({
|
||||
|
@ -83,11 +88,9 @@ export default function TokenDialog({
|
|||
className={styles.textField}
|
||||
placeholder={"Search name"}
|
||||
value={tokenFilter}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
onChange={(e) => setTokenFilter(e.target.value)}
|
||||
InputProps={{
|
||||
disableUnderline: true,
|
||||
style: { padding: "10px" },
|
||||
}}
|
||||
/>
|
||||
</DialogTitle>
|
||||
<DialogContent className={styles.dialogContent} dividers={true}>
|
||||
|
@ -105,10 +108,31 @@ export default function TokenDialog({
|
|||
</List>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Tabs value={tabSelection} onChange={(e, v) => setTabSelection(v)}>
|
||||
<Tab value={0} className={styles.tab} label="Main" />
|
||||
<Tab value={1} className={styles.tab} label="Wormhole" />
|
||||
<Tab value={2} className={styles.tab} label="Sollet" />
|
||||
<Tabs
|
||||
value={tabSelection}
|
||||
onChange={(e, v) => setTabSelection(v)}
|
||||
classes={{
|
||||
indicator: styles.tabIndicator,
|
||||
}}
|
||||
>
|
||||
<Tab
|
||||
value={0}
|
||||
className={styles.tab}
|
||||
classes={{ selected: styles.tabSelected }}
|
||||
label="Main"
|
||||
/>
|
||||
<Tab
|
||||
value={1}
|
||||
className={styles.tab}
|
||||
classes={{ selected: styles.tabSelected }}
|
||||
label="Wormhole"
|
||||
/>
|
||||
<Tab
|
||||
value={2}
|
||||
className={styles.tab}
|
||||
classes={{ selected: styles.tabSelected }}
|
||||
label="Sollet"
|
||||
/>
|
||||
</Tabs>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
@ -124,7 +148,11 @@ function TokenListItem({
|
|||
}) {
|
||||
const mint = new PublicKey(tokenInfo.address);
|
||||
return (
|
||||
<ListItem button onClick={() => onClick(mint)}>
|
||||
<ListItem
|
||||
button
|
||||
onClick={() => onClick(mint)}
|
||||
style={{ padding: "10px 20px" }}
|
||||
>
|
||||
<TokenIcon mint={mint} style={{ width: "30px", borderRadius: "15px" }} />
|
||||
<TokenName tokenInfo={tokenInfo} />
|
||||
</ListItem>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
@import url("https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@300;400;700&display=swap");
|
|
@ -1,3 +1,5 @@
|
|||
import "@fontsource/roboto";
|
||||
import "./index.css";
|
||||
import { ReactElement } from "react";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { TokenListContainer } from "@solana/spl-token-registry";
|
||||
|
@ -8,6 +10,11 @@ import { DexContextProvider } from "./context/Dex";
|
|||
import { TokenListContextProvider } from "./context/TokenList";
|
||||
import { TokenContextProvider } from "./context/Token";
|
||||
import SwapCard from "./components/Swap";
|
||||
import {
|
||||
createMuiTheme,
|
||||
ThemeOptions,
|
||||
ThemeProvider,
|
||||
} from "@material-ui/core/styles";
|
||||
|
||||
/**
|
||||
* A`Swap` component that can be embedded into applications. To use,
|
||||
|
@ -26,7 +33,10 @@ import SwapCard from "./components/Swap";
|
|||
*/
|
||||
export function Swap(props: SwapProps): ReactElement {
|
||||
const {
|
||||
style,
|
||||
containerStyle,
|
||||
contentStyle,
|
||||
swapTokenContainerStyle,
|
||||
materialTheme,
|
||||
provider,
|
||||
tokenList,
|
||||
fromMint,
|
||||
|
@ -36,22 +46,45 @@ export function Swap(props: SwapProps): ReactElement {
|
|||
referral,
|
||||
} = props;
|
||||
const swapClient = new SwapClient(provider, tokenList);
|
||||
const theme = createMuiTheme(
|
||||
materialTheme || {
|
||||
palette: {
|
||||
primary: {
|
||||
main: "#2196F3",
|
||||
contrastText: "#FFFFFF",
|
||||
},
|
||||
secondary: {
|
||||
main: "#E0E0E0",
|
||||
light: "#595959",
|
||||
},
|
||||
error: {
|
||||
main: "#ff6b6b",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
return (
|
||||
<TokenListContextProvider tokenList={tokenList}>
|
||||
<TokenContextProvider provider={provider}>
|
||||
<DexContextProvider swapClient={swapClient}>
|
||||
<SwapContextProvider
|
||||
fromMint={fromMint}
|
||||
toMint={toMint}
|
||||
fromAmount={fromAmount}
|
||||
toAmount={toAmount}
|
||||
referral={referral}
|
||||
>
|
||||
<SwapCard style={style} />
|
||||
</SwapContextProvider>
|
||||
</DexContextProvider>
|
||||
</TokenContextProvider>
|
||||
</TokenListContextProvider>
|
||||
<ThemeProvider theme={theme}>
|
||||
<TokenListContextProvider tokenList={tokenList}>
|
||||
<TokenContextProvider provider={provider}>
|
||||
<DexContextProvider swapClient={swapClient}>
|
||||
<SwapContextProvider
|
||||
fromMint={fromMint}
|
||||
toMint={toMint}
|
||||
fromAmount={fromAmount}
|
||||
toAmount={toAmount}
|
||||
referral={referral}
|
||||
>
|
||||
<SwapCard
|
||||
containerStyle={containerStyle}
|
||||
contentStyle={contentStyle}
|
||||
swapTokenContainerStyle={swapTokenContainerStyle}
|
||||
/>
|
||||
</SwapContextProvider>
|
||||
</DexContextProvider>
|
||||
</TokenContextProvider>
|
||||
</TokenListContextProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -101,9 +134,24 @@ export type SwapProps = {
|
|||
toAmount?: number;
|
||||
|
||||
/**
|
||||
* Style properties to pass through to the component.
|
||||
* Provide custom material-ui theme.
|
||||
*/
|
||||
style?: any;
|
||||
materialTheme?: ThemeOptions;
|
||||
|
||||
/**
|
||||
* Styling properties for the main container.
|
||||
*/
|
||||
containerStyle?: any;
|
||||
|
||||
/**
|
||||
* Styling properties for the content container.
|
||||
*/
|
||||
contentStyle?: any;
|
||||
|
||||
/**
|
||||
* Styling properties for the from and to token containers.
|
||||
*/
|
||||
swapTokenContainerStyle?: any;
|
||||
};
|
||||
|
||||
export default Swap;
|
||||
|
|
|
@ -1255,6 +1255,11 @@
|
|||
minimatch "^3.0.4"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@fontsource/roboto@^4.3.0":
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@fontsource/roboto/-/roboto-4.3.0.tgz#00f1cceca43eff85bb0e1d424311751ee41f6aa6"
|
||||
integrity sha512-WeFWCWYutLWyEtRmBhn+bLbW4/km0l+HhTpR8wWDxJLiGiMOhVLO/Z0q5w6l20ZOkWnf6Z1rN3o3W2HjvYN6Rg==
|
||||
|
||||
"@hapi/address@2.x.x":
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5"
|
||||
|
|
Loading…
Reference in New Issue