Dashboard: Completely remove Chakra UI (#7755)
<!--
## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"
If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):
## Notes for the reviewer
Anything important to call out? Be sure to also clarify these in your comments.
## How to test
Unit tests, playground, etc.
-->
<!-- start pr-codex -->
---
## PR-Codex overview
This PR primarily focuses on removing the `@chakra-ui/react` library and its related components from the project, transitioning to a custom UI implementation.
### Detailed summary
- Deleted multiple `chakra` components and utility files.
- Removed `ChakraProviderSetup` usage from various components.
- Updated styles and layout in the `ContractPageLayout` and `ContractSplitPage`.
- Modified ESLint rules to disable chakra-specific restrictions.
- Updated `package.json` and `pnpm-lock.yaml` to remove `@chakra-ui` dependencies.
> The following files were skipped due to too many changes: `pnpm-lock.yaml`
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
This commit is contained in:
@@ -10,13 +10,6 @@ module.exports = {
|
||||
"plugin:storybook/recommended",
|
||||
],
|
||||
overrides: [
|
||||
// disable restricted imports in chakra
|
||||
{
|
||||
files: "src/chakra/**/*",
|
||||
rules: {
|
||||
"no-restricted-imports": ["off"],
|
||||
},
|
||||
},
|
||||
// allow direct PostHog imports inside analytics helpers
|
||||
{
|
||||
files: "src/@/analytics/**/*",
|
||||
@@ -91,60 +84,6 @@ module.exports = {
|
||||
"error",
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
// these are provided by chakra folder, so we don't want to import them from chakra directly
|
||||
importNames: [
|
||||
"Card",
|
||||
"Button",
|
||||
"Checkbox",
|
||||
"Badge",
|
||||
"Drawer",
|
||||
"Heading",
|
||||
"Text",
|
||||
"FormLabel",
|
||||
"FormHelperText",
|
||||
"FormErrorMessage",
|
||||
"MenuGroup",
|
||||
"VStack",
|
||||
"HStack",
|
||||
"AspectRatio",
|
||||
"useToast",
|
||||
"useClipboard",
|
||||
"Badge",
|
||||
"Stack",
|
||||
// also the types
|
||||
"ButtonProps",
|
||||
"BadgeProps",
|
||||
"DrawerProps",
|
||||
"HeadingProps",
|
||||
"TextProps",
|
||||
"FormLabelProps",
|
||||
"HelpTextProps",
|
||||
"MenuGroupProps",
|
||||
"MenuItemProps",
|
||||
"AspectRatioProps",
|
||||
"BadgeProps",
|
||||
"StackProps",
|
||||
],
|
||||
message:
|
||||
'import component from "chakra" folder instead if you have to use chakra component, But use shadcn component otherwise',
|
||||
name: "@chakra-ui/react",
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Import from `@chakra-ui/react` instead of `@chakra-ui/layout`.",
|
||||
name: "@chakra-ui/layout",
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Import from `@chakra-ui/react` instead of `@chakra-ui/button`.",
|
||||
name: "@chakra-ui/button",
|
||||
},
|
||||
{
|
||||
message:
|
||||
"Import from `@chakra-ui/react` instead of `@chakra-ui/menu`.",
|
||||
name: "@chakra-ui/menu",
|
||||
},
|
||||
{
|
||||
importNames: ["useRouter"],
|
||||
message:
|
||||
|
||||
@@ -20,11 +20,6 @@ const config: StorybookConfig = {
|
||||
name: getAbsolutePath("@storybook/nextjs"),
|
||||
options: {},
|
||||
},
|
||||
refs: {
|
||||
"@chakra-ui/react": {
|
||||
disable: true,
|
||||
},
|
||||
},
|
||||
staticDirs: ["../public"],
|
||||
features: {
|
||||
experimentalRSC: true,
|
||||
|
||||
@@ -115,9 +115,6 @@ const SENTRY_OPTIONS: SentryBuildOptions = {
|
||||
const FRAMER_ADDITIONAL_LANGUAGES = ["es"];
|
||||
|
||||
const baseNextConfig: NextConfig = {
|
||||
compiler: {
|
||||
emotion: true,
|
||||
},
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@chakra-ui/react": "^2.8.2",
|
||||
"@chakra-ui/styled-system": "^2.9.2",
|
||||
"@chakra-ui/theme-tools": "^2.1.2",
|
||||
"@emotion/react": "11.14.0",
|
||||
"@emotion/styled": "11.14.1",
|
||||
"@hookform/resolvers": "^3.9.1",
|
||||
"@marsidev/react-turnstile": "^1.1.0",
|
||||
"@radix-ui/react-accordion": "^1.2.11",
|
||||
@@ -36,11 +31,9 @@
|
||||
"abitype": "1.0.8",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"color": "5.0.0",
|
||||
"compare-versions": "^6.1.0",
|
||||
"date-fns": "4.1.0",
|
||||
"fast-xml-parser": "^5.2.5",
|
||||
"framer-motion": "12.23.0",
|
||||
"fuse.js": "7.1.0",
|
||||
"input-otp": "^1.4.1",
|
||||
"ioredis": "^5.6.1",
|
||||
@@ -85,7 +78,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.6",
|
||||
"@chakra-ui/cli": "^2.4.1",
|
||||
"@chromatic-com/storybook": "4.0.1",
|
||||
"@next/bundle-analyzer": "15.3.5",
|
||||
"@next/eslint-plugin-next": "15.3.5",
|
||||
@@ -127,12 +119,10 @@
|
||||
"dev": "next dev --turbopack",
|
||||
"fix": "biome check ./src --fix && eslint ./src --fix",
|
||||
"format": "biome format ./src --write",
|
||||
"gen:theme-typings": "chakra-cli tokens src/chakra/theme/index.ts",
|
||||
"knip": "knip",
|
||||
"lint": "biome check ./src && knip && eslint ./src",
|
||||
"playwright": "playwright test",
|
||||
"postbuild": "next-sitemap",
|
||||
"postinstall": "pnpm run gen:theme-typings",
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"start": "next start",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
@@ -140,4 +130,4 @@
|
||||
"update-checkly": "npx checkly deploy"
|
||||
},
|
||||
"version": "3.0.0"
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -1,5 +1,4 @@
|
||||
import { DeprecatedAlert } from "@app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/DeprecatedAlert";
|
||||
import { ChakraProviderSetup } from "chakra/ChakraProviderSetup";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import type { ChainMetadata } from "thirdweb/chains";
|
||||
import type { SidebarLink } from "@/components/blocks/Sidebar";
|
||||
@@ -36,7 +35,7 @@ export function ContractPageLayout(props: {
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<ChakraProviderSetup>
|
||||
<div>
|
||||
<div className="border-border border-b py-8">
|
||||
<div className="container flex flex-col gap-4">
|
||||
<div className="flex flex-col justify-between gap-4 md:flex-row">
|
||||
@@ -67,6 +66,6 @@ export function ContractPageLayout(props: {
|
||||
{props.children}
|
||||
<div className="h-20" />
|
||||
</SidebarLayout>
|
||||
</ChakraProviderSetup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+127
-123
@@ -1,16 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Flex,
|
||||
SimpleGrid,
|
||||
Spinner,
|
||||
Stat,
|
||||
StatLabel,
|
||||
StatNumber,
|
||||
} from "@chakra-ui/react";
|
||||
import { Card } from "chakra/card";
|
||||
import { Heading } from "chakra/heading";
|
||||
import { Text } from "chakra/text";
|
||||
import { useMemo } from "react";
|
||||
import {
|
||||
type ThirdwebContract,
|
||||
@@ -24,6 +13,17 @@ import {
|
||||
useReadContract,
|
||||
useWalletBalance,
|
||||
} from "thirdweb/react";
|
||||
import { WalletAddress } from "@/components/blocks/wallet-address";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { useAllChainsData } from "@/hooks/chains/allChains";
|
||||
import { useSplitBalances } from "@/hooks/useSplit";
|
||||
import { shortenIfAddress } from "@/utils/usedapp-external";
|
||||
@@ -42,10 +42,7 @@ interface SplitPageProps {
|
||||
isLoggedIn: boolean;
|
||||
}
|
||||
|
||||
export const ContractSplitPage: React.FC<SplitPageProps> = ({
|
||||
contract,
|
||||
isLoggedIn,
|
||||
}) => {
|
||||
export function ContractSplitPage({ contract, isLoggedIn }: SplitPageProps) {
|
||||
const address = useActiveAccount()?.address;
|
||||
const { idToChain } = useAllChainsData();
|
||||
const chainId = contract.chain.id;
|
||||
@@ -104,120 +101,127 @@ export const ContractSplitPage: React.FC<SplitPageProps> = ({
|
||||
);
|
||||
}, [allRecipientsPercentages, balances, address]);
|
||||
|
||||
const isPending = balanceQuery.isPending || nativeBalanceQuery.isPending;
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap={6}>
|
||||
<Flex align="center" direction="row" justify="space-between">
|
||||
<Heading size="title.sm">Balances</Heading>
|
||||
<Flex gap={4}>
|
||||
<DistributeButton
|
||||
balances={balances as Balance[]}
|
||||
balancesIsError={balanceQuery.isError && nativeBalanceQuery.isError}
|
||||
balancesIsPending={
|
||||
balanceQuery.isPending || nativeBalanceQuery.isPending
|
||||
}
|
||||
contract={contract}
|
||||
isLoggedIn={isLoggedIn}
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<div className="flex flex-col gap-8">
|
||||
<Flex flexDir="column" gap={4}>
|
||||
<SimpleGrid columns={{ base: 2, md: 4 }} spacing={{ base: 3, md: 6 }}>
|
||||
<Card as={Stat}>
|
||||
<StatLabel mb={{ base: 1, md: 0 }}>
|
||||
{nativeBalanceQuery.data?.symbol}
|
||||
</StatLabel>
|
||||
<StatNumber>{nativeBalanceQuery?.data?.displayValue}</StatNumber>
|
||||
{shareOfBalancesForConnectedWallet[ZERO_ADDRESS] && (
|
||||
<StatNumber>
|
||||
<Text size="body.md">
|
||||
<Text as="span" size="label.md">
|
||||
Your Share:
|
||||
</Text>{" "}
|
||||
{shareOfBalancesForConnectedWallet[ZERO_ADDRESS]}
|
||||
</Text>
|
||||
</StatNumber>
|
||||
)}
|
||||
</Card>
|
||||
{balanceQuery.isPending ? (
|
||||
<div className="flex items-center justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
(balanceQuery?.data || [])
|
||||
<div>
|
||||
{/* header */}
|
||||
<div className="flex flex-col gap-3 lg:flex-row lg:items-center justify-between mb-6 lg:mb-3">
|
||||
<h2 className="text-2xl font-semibold tracking-tight">Balances</h2>
|
||||
<DistributeButton
|
||||
balances={balances as Balance[]}
|
||||
balancesIsError={balanceQuery.isError && nativeBalanceQuery.isError}
|
||||
balancesIsPending={
|
||||
balanceQuery.isPending || nativeBalanceQuery.isPending
|
||||
}
|
||||
contract={contract}
|
||||
isLoggedIn={isLoggedIn}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* balances */}
|
||||
<div className="flex flex-col gap-4 mb-8">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3 md:gap-6">
|
||||
{isPending ? (
|
||||
new Array(4).fill(null).map((_, index) => (
|
||||
// biome-ignore lint/suspicious/noArrayIndexKey: ok
|
||||
<Skeleton key={index} className="h-[86px]" />
|
||||
))
|
||||
) : (
|
||||
<>
|
||||
<BalanceCard
|
||||
symbol={nativeBalanceQuery.data?.symbol || "Native Token"}
|
||||
displayValue={nativeBalanceQuery?.data?.displayValue || "0"}
|
||||
userShare={shareOfBalancesForConnectedWallet[ZERO_ADDRESS]}
|
||||
/>
|
||||
|
||||
{(balanceQuery?.data || [])
|
||||
?.filter((bl) => bl.name !== "Native Token")
|
||||
?.map((balance) => (
|
||||
<Card as={Stat} key={balance.token_address} maxWidth="2xs">
|
||||
<StatLabel as={Heading} size="label.lg">
|
||||
{balance.name === "Native Token"
|
||||
<BalanceCard
|
||||
key={balance.token_address}
|
||||
symbol={
|
||||
balance.name === "Native Token"
|
||||
? v4Chain?.nativeCurrency.symbol || "Native Token"
|
||||
: balance.symbol ||
|
||||
shortenIfAddress(balance.token_address)}
|
||||
</StatLabel>
|
||||
<StatNumber>
|
||||
<Text size="body.md">{balance.display_balance}</Text>
|
||||
</StatNumber>
|
||||
{shareOfBalancesForConnectedWallet[
|
||||
balance.token_address
|
||||
] && (
|
||||
<StatNumber>
|
||||
<Text size="body.md">
|
||||
<Text as="span" size="label.md">
|
||||
Your Share:
|
||||
</Text>{" "}
|
||||
{
|
||||
shareOfBalancesForConnectedWallet[
|
||||
balance.token_address
|
||||
]
|
||||
}
|
||||
</Text>
|
||||
</StatNumber>
|
||||
)}
|
||||
</Card>
|
||||
))
|
||||
)}
|
||||
</SimpleGrid>
|
||||
{balanceQuery.isError && (
|
||||
<Text color="red.500">
|
||||
{(balanceQuery?.error as Error).message === "Invalid chain!"
|
||||
? "Showing ERC20 balances for this network is not currently supported. You can distribute ERC20 funds from the Explorer tab."
|
||||
: "Error loading balances"}
|
||||
</Text>
|
||||
shortenIfAddress(balance.token_address)
|
||||
}
|
||||
displayValue={balance.display_balance}
|
||||
userShare={
|
||||
shareOfBalancesForConnectedWallet[balance.token_address]
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
<Text fontStyle="italic">
|
||||
The Split can receive funds in the native token or in any ERC20.
|
||||
Balances may take a couple of minutes to display after being
|
||||
received.
|
||||
<br />
|
||||
{/* We currently use Moralis and high chances are they don't recognize all ERC20 tokens in the contract */}
|
||||
If you are looking to distribute an ERC20 token and it's not being
|
||||
recognized on this page, you can manually call the `distribute`
|
||||
method in the Explorer page
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<Heading mb="8px" size="label.lg">
|
||||
Split Recipients
|
||||
</Heading>
|
||||
{(allRecipientsPercentages || []).map((split) => (
|
||||
<Card key={split.address}>
|
||||
<Text>
|
||||
<Text as="span" size="label.md">
|
||||
Address:
|
||||
</Text>{" "}
|
||||
{split.address}
|
||||
</Text>
|
||||
<Text>
|
||||
<Text as="span" size="label.md">
|
||||
Percentage:
|
||||
</Text>{" "}
|
||||
{split.splitPercentage}%
|
||||
</Text>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{balanceQuery.isError && (
|
||||
<p className="text-red-500">
|
||||
{(balanceQuery?.error as Error).message === "Invalid chain!"
|
||||
? "Showing ERC20 balances for this network is not currently supported. You can distribute ERC20 funds from the Explorer tab."
|
||||
: "Error loading balances"}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<p className="text-sm text-muted-foreground">
|
||||
The Split can receive funds in the native token or in any ERC20.
|
||||
Balances may take a couple of minutes to display after being received.
|
||||
<br />
|
||||
{/* We currently use Moralis and high chances are they don't recognize all ERC20 tokens in the contract */}
|
||||
If you are looking to distribute an ERC20 token and it's not being
|
||||
recognized on this page, you can manually call the `distribute` method
|
||||
in the Explorer page
|
||||
</p>
|
||||
</div>
|
||||
</Flex>
|
||||
|
||||
{/* recipients e */}
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold mb-2">Split Recipients</h3>
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Address</TableHead>
|
||||
<TableHead>Percentage</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{(allRecipientsPercentages || []).map((split) => (
|
||||
<TableRow key={split.address}>
|
||||
<TableCell>
|
||||
<WalletAddress
|
||||
address={split.address}
|
||||
client={contract.client}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>{split.splitPercentage}%</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function BalanceCard(props: {
|
||||
symbol: string;
|
||||
displayValue: string;
|
||||
userShare: string | undefined;
|
||||
}) {
|
||||
return (
|
||||
<div className="p-4 border rounded-lg bg-card space-y-1">
|
||||
<div className="text-xl font-semibold">
|
||||
{props.displayValue} {props.symbol}
|
||||
</div>
|
||||
{props.userShare && (
|
||||
<div className="text-sm">
|
||||
<span className="text-sm font-medium">Your Share:</span>{" "}
|
||||
{props.userShare}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+24
-23
@@ -1,28 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import { SplitIcon } from "lucide-react";
|
||||
import { useMemo } from "react";
|
||||
import { toast } from "sonner";
|
||||
import type { ThirdwebContract } from "thirdweb";
|
||||
import { TransactionButton } from "@/components/tx-button";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ToolTipLabel } from "@/components/ui/tooltip";
|
||||
import { useSplitDistributeFunds } from "@/hooks/useSplit";
|
||||
import { useTxNotifications } from "@/hooks/useTxNotifications";
|
||||
import { parseError } from "@/utils/errorParser";
|
||||
import type { Balance } from "../ContractSplitPage";
|
||||
|
||||
interface DistributeButtonProps {
|
||||
contract: ThirdwebContract;
|
||||
balances: Balance[];
|
||||
balancesIsPending: boolean;
|
||||
balancesIsError: boolean;
|
||||
isLoggedIn: boolean;
|
||||
}
|
||||
|
||||
export const DistributeButton: React.FC<DistributeButtonProps> = ({
|
||||
export const DistributeButton = ({
|
||||
contract,
|
||||
balances,
|
||||
balancesIsPending,
|
||||
balancesIsError,
|
||||
isLoggedIn,
|
||||
...restButtonProps
|
||||
}: {
|
||||
contract: ThirdwebContract;
|
||||
balances: Balance[];
|
||||
balancesIsPending: boolean;
|
||||
balancesIsError: boolean;
|
||||
isLoggedIn: boolean;
|
||||
}) => {
|
||||
const validBalances = balances.filter(
|
||||
(item) => item.balance !== "0" && item.balance !== "0.0",
|
||||
@@ -44,19 +44,16 @@ export const DistributeButton: React.FC<DistributeButtonProps> = ({
|
||||
|
||||
const mutation = useSplitDistributeFunds(contract);
|
||||
|
||||
const { onSuccess, onError } = useTxNotifications(
|
||||
"Funds splitted successfully",
|
||||
"Failed to process transaction",
|
||||
);
|
||||
|
||||
const distributeFunds = () => {
|
||||
mutation.mutate(undefined, {
|
||||
onError: (error) => {
|
||||
toast.error("Failed to process transaction", {
|
||||
description: parseError(error),
|
||||
});
|
||||
console.error(error);
|
||||
onError(error);
|
||||
},
|
||||
onSuccess: () => {
|
||||
onSuccess();
|
||||
toast.success("Funds splitted successfully");
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -71,7 +68,6 @@ export const DistributeButton: React.FC<DistributeButtonProps> = ({
|
||||
transactionCount={undefined}
|
||||
// if we fail to get the balances, we can't know how many transactions there are going to be
|
||||
txChainID={contract.chain.id}
|
||||
{...restButtonProps}
|
||||
>
|
||||
Distribute Funds
|
||||
</TransactionButton>
|
||||
@@ -80,9 +76,12 @@ export const DistributeButton: React.FC<DistributeButtonProps> = ({
|
||||
|
||||
if (numTransactions === 0) {
|
||||
return (
|
||||
<Button disabled variant="primary" {...restButtonProps}>
|
||||
Nothing to distribute
|
||||
</Button>
|
||||
<ToolTipLabel label="Nothing to distribute">
|
||||
<Button disabled variant="default" size="sm" className="gap-2">
|
||||
<SplitIcon className="size-3.5" />
|
||||
Distribute Funds
|
||||
</Button>
|
||||
</ToolTipLabel>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,9 +92,11 @@ export const DistributeButton: React.FC<DistributeButtonProps> = ({
|
||||
isPending={mutation.isPending}
|
||||
onClick={distributeFunds}
|
||||
transactionCount={numTransactions}
|
||||
{...restButtonProps}
|
||||
txChainID={contract.chain.id}
|
||||
variant="default"
|
||||
size="sm"
|
||||
>
|
||||
<SplitIcon className="size-3.5" />
|
||||
Distribute Funds
|
||||
</TransactionButton>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { ChakraProviderSetup } from "chakra/ChakraProviderSetup";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { fetchDeployMetadata } from "thirdweb/contract";
|
||||
@@ -74,22 +73,20 @@ export default async function PublishContractPage(
|
||||
|
||||
return (
|
||||
<div className="container flex max-w-[1130px] flex-col gap-8 py-8">
|
||||
<ChakraProviderSetup>
|
||||
<ContractPublishForm
|
||||
client={userThirdwebClient}
|
||||
isLoggedIn={!!token}
|
||||
onPublishSuccess={async () => {
|
||||
"use server";
|
||||
// we are pretty brutal here and simply invalidate ALL published contracts (for everyone!) and versions no matter what
|
||||
// TODO: we can be more granular here and only invalidate the specific contract and version etc
|
||||
revalidatePath(
|
||||
"/(dashboard)/published-contract/[publisher]/[contract_id]",
|
||||
"layout",
|
||||
);
|
||||
}}
|
||||
publishMetadata={publishMetadata}
|
||||
/>
|
||||
</ChakraProviderSetup>
|
||||
<ContractPublishForm
|
||||
client={userThirdwebClient}
|
||||
isLoggedIn={!!token}
|
||||
onPublishSuccess={async () => {
|
||||
"use server";
|
||||
// we are pretty brutal here and simply invalidate ALL published contracts (for everyone!) and versions no matter what
|
||||
// TODO: we can be more granular here and only invalidate the specific contract and version etc
|
||||
revalidatePath(
|
||||
"/(dashboard)/published-contract/[publisher]/[contract_id]",
|
||||
"layout",
|
||||
);
|
||||
}}
|
||||
publishMetadata={publishMetadata}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { ChakraProvider, useColorMode } from "@chakra-ui/react";
|
||||
import { useTheme } from "next-themes";
|
||||
import { useEffect } from "react";
|
||||
import chakraTheme from "./theme";
|
||||
|
||||
export function ChakraProviderSetup(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<ChakraProvider theme={chakraTheme}>
|
||||
{props.children}
|
||||
<SyncTheme />
|
||||
</ChakraProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function SyncTheme() {
|
||||
const { theme, setTheme } = useTheme();
|
||||
const { setColorMode } = useColorMode();
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
useEffect(() => {
|
||||
setColorMode(theme === "light" ? "light" : "dark");
|
||||
}, [setColorMode, theme]);
|
||||
|
||||
// handle dashboard with now old "system" set
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
useEffect(() => {
|
||||
if (theme === "system") {
|
||||
setTheme("dark");
|
||||
setColorMode("dark");
|
||||
}
|
||||
}, [theme, setTheme, setColorMode]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
# DO NOT ADD NEW THINGS INSIDE THIS FOLDER OR SUB_FOLDERS
|
||||
|
||||
This part of the dashboard is deprecated, and we are actively working on removing it. Please do not add new things here. If you need to add new things, please add them to the appropriate folder in the src folder.
|
||||
@@ -1,85 +0,0 @@
|
||||
import { Box, type BoxProps } from "@chakra-ui/react";
|
||||
|
||||
type DefaultedBoxProps = Pick<
|
||||
BoxProps,
|
||||
"shadow" | "py" | "px" | "borderRadius" | "borderWidth" | "borderColor"
|
||||
>;
|
||||
|
||||
const defaultBoxProps: Required<DefaultedBoxProps> = {
|
||||
borderColor: "borderColor",
|
||||
borderRadius: "xl",
|
||||
borderWidth: "1px",
|
||||
px: 4,
|
||||
py: 4,
|
||||
shadow: "sm",
|
||||
};
|
||||
|
||||
const borderRadiusMap = {
|
||||
"2xl": "xl",
|
||||
"3xl": "2xl",
|
||||
lg: "md",
|
||||
md: "sm",
|
||||
none: "none",
|
||||
sm: "none",
|
||||
xl: "lg",
|
||||
};
|
||||
|
||||
interface CardProps extends BoxProps {
|
||||
outlineBorder?: {
|
||||
gradient: string;
|
||||
width: string;
|
||||
};
|
||||
}
|
||||
|
||||
function getBorderRadius(
|
||||
borderRadius: BoxProps["borderRadius"],
|
||||
): BoxProps["borderRadius"] {
|
||||
try {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: FIXME
|
||||
return (borderRadiusMap as any)[borderRadius as any];
|
||||
} catch {
|
||||
return borderRadius;
|
||||
}
|
||||
}
|
||||
|
||||
export const Card: React.FC<CardProps> = ({
|
||||
children,
|
||||
outlineBorder,
|
||||
...requiredBoxProps
|
||||
}) => {
|
||||
const combinedProps = { ...{ ...defaultBoxProps, ...requiredBoxProps } };
|
||||
|
||||
return (
|
||||
<>
|
||||
{outlineBorder ? (
|
||||
<Box
|
||||
borderRadius={combinedProps.borderRadius}
|
||||
overflow="hidden"
|
||||
p={outlineBorder.width}
|
||||
position="relative"
|
||||
w={combinedProps.w || combinedProps.width}
|
||||
>
|
||||
<Box
|
||||
bgGradient={outlineBorder.gradient}
|
||||
h="full"
|
||||
left={0}
|
||||
position="absolute"
|
||||
top={0}
|
||||
w="full"
|
||||
zIndex={-1}
|
||||
/>
|
||||
|
||||
<Box
|
||||
{...combinedProps}
|
||||
borderRadius={getBorderRadius(combinedProps.borderRadius)}
|
||||
w="full"
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
) : (
|
||||
<Box {...combinedProps}>{children}</Box>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,35 +0,0 @@
|
||||
import {
|
||||
Heading as ChakraHeading,
|
||||
type HeadingProps as ChakraHeadingProps,
|
||||
} from "@chakra-ui/react";
|
||||
import {
|
||||
fontWeights,
|
||||
type HeadingBase,
|
||||
type HeadingSizes,
|
||||
letterSpacings,
|
||||
lineHeights,
|
||||
type TypographySize,
|
||||
} from "chakra/theme/typography";
|
||||
import type { ComponentWithChildren } from "@/types/component-with-children";
|
||||
import { convertFontSizeToCSSVar } from "./utils/typography";
|
||||
|
||||
interface HeadingProps extends Omit<ChakraHeadingProps, "size"> {
|
||||
size?: HeadingSizes;
|
||||
}
|
||||
|
||||
export const Heading: ComponentWithChildren<HeadingProps> = ({
|
||||
size = "title.lg",
|
||||
...restProps
|
||||
}) => {
|
||||
const [base] = size.split(".") as [HeadingBase, TypographySize];
|
||||
|
||||
return (
|
||||
<ChakraHeading
|
||||
fontSize={convertFontSizeToCSSVar(size)}
|
||||
fontWeight={fontWeights[base]}
|
||||
letterSpacing={letterSpacings[base]}
|
||||
lineHeight={lineHeights[base]}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1,35 +0,0 @@
|
||||
import {
|
||||
Text as ChakraText,
|
||||
type TextProps as ChakraTextProps,
|
||||
} from "@chakra-ui/react";
|
||||
import {
|
||||
fontWeights,
|
||||
letterSpacings,
|
||||
lineHeights,
|
||||
type TextBase,
|
||||
type TextSizes,
|
||||
type TypographySize,
|
||||
} from "chakra/theme/typography";
|
||||
import type { ComponentWithChildren } from "@/types/component-with-children";
|
||||
import { convertFontSizeToCSSVar } from "./utils/typography";
|
||||
|
||||
interface TextProps extends Omit<ChakraTextProps, "size"> {
|
||||
size?: TextSizes;
|
||||
}
|
||||
|
||||
export const Text: ComponentWithChildren<TextProps> = ({
|
||||
size = "body.md",
|
||||
...restProps
|
||||
}) => {
|
||||
const [base] = size.split(".") as [TextBase, TypographySize];
|
||||
|
||||
return (
|
||||
<ChakraText
|
||||
fontSize={convertFontSizeToCSSVar(size)}
|
||||
fontWeight={fontWeights[base]}
|
||||
letterSpacing={letterSpacings[base]}
|
||||
lineHeight={lineHeights[base]}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1,202 +0,0 @@
|
||||
import color from "color";
|
||||
|
||||
const config = {
|
||||
darkest: {
|
||||
lightness: 10,
|
||||
rotate: 0,
|
||||
saturate: 0,
|
||||
},
|
||||
lightest: {
|
||||
lightness: 95,
|
||||
rotate: 0,
|
||||
saturate: 0,
|
||||
},
|
||||
};
|
||||
|
||||
function createShades(centerColor: string): Record<number, string> {
|
||||
const _color = centerColor;
|
||||
const darkSteps = 4;
|
||||
const lightSteps = 5;
|
||||
|
||||
const lightnessStep = (config.lightest.lightness - 50) / lightSteps;
|
||||
const darknessStep = (50 - config.darkest.lightness) / darkSteps;
|
||||
|
||||
const lightRotateStep = config.lightest.rotate / lightSteps;
|
||||
const darkRotateStep = config.darkest.rotate / darkSteps;
|
||||
|
||||
const lightSaturateStep = config.lightest.saturate / lightSteps;
|
||||
const darkSaturateStep = config.darkest.saturate / darkSteps;
|
||||
|
||||
return {
|
||||
50: color(_color)
|
||||
.lightness(50 + lightnessStep * 5)
|
||||
.rotate(lightRotateStep * 5)
|
||||
.saturate(lightSaturateStep * 5)
|
||||
.hex(),
|
||||
100: color(_color)
|
||||
.lightness(50 + lightnessStep * 4)
|
||||
.rotate(lightRotateStep * 4)
|
||||
.saturate(lightSaturateStep * 4)
|
||||
.hex(),
|
||||
200: color(_color)
|
||||
.lightness(50 + lightnessStep * 3)
|
||||
.rotate(lightRotateStep * 3)
|
||||
.saturate(lightSaturateStep * 3)
|
||||
.hex(),
|
||||
300: color(_color)
|
||||
.lightness(50 + lightnessStep * 2)
|
||||
.rotate(lightRotateStep * 2)
|
||||
.saturate(lightSaturateStep * 2)
|
||||
.hex(),
|
||||
400: color(_color)
|
||||
.lightness(50 + Number(lightnessStep))
|
||||
.rotate(Number(lightRotateStep))
|
||||
.saturate(Number(lightSaturateStep))
|
||||
.hex(),
|
||||
500: centerColor,
|
||||
600: color(_color)
|
||||
.lightness(50 - Number(darknessStep))
|
||||
.rotate(Number(darkRotateStep))
|
||||
.saturate(Number(darkSaturateStep))
|
||||
.hex(),
|
||||
700: color(_color)
|
||||
.lightness(50 - darknessStep * 2)
|
||||
.rotate(darkRotateStep * 2)
|
||||
.saturate(darkSaturateStep * 2)
|
||||
.hex(),
|
||||
800: color(_color)
|
||||
.lightness(50 - darknessStep * 3)
|
||||
.rotate(darkRotateStep * 3)
|
||||
.saturate(darkSaturateStep * 3)
|
||||
.hex(),
|
||||
900: color(_color)
|
||||
.lightness(50 - darknessStep * 4)
|
||||
.rotate(darkRotateStep * 4)
|
||||
.saturate(darkSaturateStep * 4)
|
||||
.hex(),
|
||||
};
|
||||
}
|
||||
|
||||
const blue = {
|
||||
50: "#F0F9FF",
|
||||
100: "#E0F2FE",
|
||||
200: "#3385FF",
|
||||
300: "#4A92FE",
|
||||
400: "#4A92FE",
|
||||
500: "#3385FF",
|
||||
600: "#2D66BB",
|
||||
700: "#224A85",
|
||||
800: "#075985",
|
||||
900: "#0C4A6E",
|
||||
};
|
||||
|
||||
const themeColors = {
|
||||
blackAlpha: {
|
||||
50: "rgba(0,0,0,0.05)",
|
||||
100: "rgba(0,0,0,0.1)",
|
||||
200: "rgba(0,0,0,0.2)",
|
||||
300: "rgba(0,0,0,0.3)",
|
||||
400: "rgba(0,0,0,0.4)",
|
||||
500: "rgba(0,0,0,0.5)",
|
||||
600: "rgba(0,0,0,0.6)",
|
||||
700: "rgba(0,0,0,0.7)",
|
||||
800: "rgba(0,0,0,0.8)",
|
||||
900: "rgba(0,0,0,0.9)",
|
||||
},
|
||||
blue,
|
||||
cyan: blue,
|
||||
|
||||
gray: {
|
||||
50: "#F2F2F7",
|
||||
100: "#E5E5EA",
|
||||
200: "#E5E5EA",
|
||||
300: "#D1D1D6",
|
||||
400: "#C7C7CC",
|
||||
500: "#AEAEB2",
|
||||
600: "#8E8E93",
|
||||
700: "#636366",
|
||||
800: "#3A3A3C",
|
||||
900: "#1C1C1E",
|
||||
},
|
||||
green: {
|
||||
50: "#ECFDF5",
|
||||
100: "#D1FAE5",
|
||||
200: "#A7F3D0",
|
||||
300: "#6EE7B7",
|
||||
400: "#34D399",
|
||||
500: "#10B981",
|
||||
600: "#059669",
|
||||
700: "#047857",
|
||||
800: "#065F46",
|
||||
900: "#064E3B",
|
||||
},
|
||||
orange: {
|
||||
50: "#FFF7ED",
|
||||
100: "#FFEDD5",
|
||||
200: "#FED7AA",
|
||||
300: "#FDBA74",
|
||||
400: "#FB923C",
|
||||
500: "#F97316",
|
||||
600: "#EA580C",
|
||||
700: "#C2410C",
|
||||
800: "#9A3412",
|
||||
900: "#7C2D12",
|
||||
},
|
||||
pink: blue,
|
||||
purple: blue,
|
||||
red: {
|
||||
50: "#FEF2F2",
|
||||
100: "#FEE2E2",
|
||||
200: "#FECACA",
|
||||
300: "#FCA5A5",
|
||||
400: "#F87171",
|
||||
500: "#EF4444",
|
||||
600: "#DC2626",
|
||||
700: "#B91C1C",
|
||||
800: "#991B1B",
|
||||
900: "#7F1D1D",
|
||||
},
|
||||
teal: blue,
|
||||
transparent: "transparent",
|
||||
whiteAlpha: {
|
||||
50: "rgba(255,255,255,0.05)",
|
||||
100: "rgba(255,255,255,0.1)",
|
||||
200: "rgba(255,255,255,0.2)",
|
||||
300: "rgba(255,255,255,0.3)",
|
||||
400: "rgba(255,255,255,0.4)",
|
||||
500: "rgba(255,255,255,0.5)",
|
||||
600: "rgba(255,255,255,0.6)",
|
||||
700: "rgba(255,255,255,0.7)",
|
||||
800: "rgba(255,255,255,0.8)",
|
||||
900: "rgba(255,255,255,0.9)",
|
||||
},
|
||||
yellow: {
|
||||
50: "#FEFCE8",
|
||||
100: "#FEF9C3",
|
||||
200: "#FEF08A",
|
||||
300: "#FDE047",
|
||||
400: "#FACC15",
|
||||
500: "#EAB308",
|
||||
600: "#CA8A04",
|
||||
700: "#A16207",
|
||||
800: "#854D0E",
|
||||
900: "#713F12",
|
||||
},
|
||||
};
|
||||
|
||||
export const colors = {
|
||||
// generated
|
||||
discord: createShades("#314db5"),
|
||||
opensea: createShades("#3191e8"),
|
||||
|
||||
// theme colors
|
||||
...themeColors,
|
||||
backgroundDark: "#0E0E10",
|
||||
|
||||
// random
|
||||
backgroundLight: "#F5F6F8",
|
||||
|
||||
// blue: themeColors.primary,
|
||||
// purple: themeColors.primary,
|
||||
primary: themeColors.blue,
|
||||
};
|
||||
@@ -1,389 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { extendTheme, type Theme } from "@chakra-ui/react";
|
||||
import { getColor, mode } from "@chakra-ui/theme-tools";
|
||||
import { colors } from "./colors";
|
||||
import { skeletonTheme } from "./skeleton";
|
||||
import { fontWeights, letterSpacings, lineHeights } from "./typography";
|
||||
|
||||
const chakraTheme: Theme = extendTheme({
|
||||
colors,
|
||||
components: {
|
||||
Badge: {
|
||||
baseStyle: {
|
||||
backgroundColor: "badgeBg",
|
||||
},
|
||||
},
|
||||
Button: {
|
||||
baseStyle: {
|
||||
borderRadius: "md",
|
||||
},
|
||||
variants: {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: FIXME
|
||||
gradient: (props: any) => {
|
||||
const { theme, fromcolor, tocolor } = props;
|
||||
const lgFrom = getColor(theme, fromcolor);
|
||||
const lgTo = getColor(theme, tocolor);
|
||||
const bgColor = getColor(theme, mode("white", "gray.800")(props));
|
||||
|
||||
return {
|
||||
_hover: {
|
||||
"> *": {
|
||||
backgroundPosition: "right",
|
||||
},
|
||||
backgroundPosition: "right",
|
||||
opacity: 0.9,
|
||||
},
|
||||
"> *": {
|
||||
background: `linear-gradient(135deg, ${lgFrom}, ${lgTo}, ${lgFrom})`,
|
||||
backgroundClip: "text",
|
||||
backgroundSize: "200%",
|
||||
textFillColor: "transparent",
|
||||
transitionDuration: "slow",
|
||||
transitionProperty: "background",
|
||||
transitionTimingFunction: "easeOut",
|
||||
},
|
||||
background: `linear-gradient(${bgColor}, ${bgColor}) padding-box,
|
||||
linear-gradient(135deg, ${lgFrom}, ${lgTo}, ${lgFrom}) border-box`,
|
||||
backgroundSize: "200%",
|
||||
border: "3px solid",
|
||||
borderColor: "transparent",
|
||||
borderRadius: "md",
|
||||
transitionDuration: "slow",
|
||||
transitionProperty: "opacity, background",
|
||||
};
|
||||
},
|
||||
// biome-ignore lint/suspicious/noExplicitAny: FIXME
|
||||
highlighted: (props: any) => ({
|
||||
_hover: {
|
||||
boxShadow: "0 0 10px 2px rgba(51, 133, 255, 1)",
|
||||
transform: "scale(1.05)",
|
||||
},
|
||||
bg: "#151515",
|
||||
borderRadius: props.fullCircle ? "full" : "12px",
|
||||
size: "lg",
|
||||
}),
|
||||
inverted: {
|
||||
_disabled: {
|
||||
_hover: {
|
||||
bg: "bgBlack !important",
|
||||
},
|
||||
},
|
||||
_hover: {
|
||||
opacity: 0.8,
|
||||
},
|
||||
bg: "bgBlack",
|
||||
color: "bgWhite",
|
||||
},
|
||||
outline: {
|
||||
_hover: {
|
||||
bg: "transparent",
|
||||
borderColor: "inputBorderHover",
|
||||
},
|
||||
borderColor: "inputBorder",
|
||||
borderWidth: "1px",
|
||||
},
|
||||
},
|
||||
},
|
||||
Divider: {
|
||||
baseStyle: {
|
||||
borderColor: "borderColor",
|
||||
},
|
||||
},
|
||||
Drawer: {
|
||||
baseStyle: {
|
||||
dialog: {
|
||||
background: "backgroundHighlight",
|
||||
},
|
||||
overlay: {
|
||||
backdropFilter: "blur(5px)",
|
||||
},
|
||||
},
|
||||
},
|
||||
Heading: {
|
||||
baseStyle: {
|
||||
color: "heading",
|
||||
},
|
||||
},
|
||||
Input: {
|
||||
defaultProps: {
|
||||
variant: "filled",
|
||||
},
|
||||
sizes: {
|
||||
xl: {
|
||||
addon: {
|
||||
borderRadius: "md",
|
||||
fontSize: "lg",
|
||||
h: 14,
|
||||
px: 4,
|
||||
},
|
||||
field: {
|
||||
borderRadius: "md",
|
||||
fontSize: "lg",
|
||||
h: 14,
|
||||
px: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
filled: {
|
||||
field: {
|
||||
_focus: {
|
||||
borderColor: "blue.500",
|
||||
},
|
||||
_hover: {
|
||||
background: "transparent",
|
||||
borderColor: "inputBorderHover",
|
||||
},
|
||||
background: "transparent",
|
||||
borderColor: "inputBorder",
|
||||
borderWidth: "1px",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Menu: {
|
||||
baseStyle: {
|
||||
item: {
|
||||
_hover: {
|
||||
bg: "hsl(var(--muted))",
|
||||
},
|
||||
bg: "backgroundHighlight",
|
||||
py: 3,
|
||||
},
|
||||
list: {
|
||||
bg: "backgroundHighlight",
|
||||
borderColor: "borderColor",
|
||||
borderRadius: "lg",
|
||||
borderWidth: 1,
|
||||
overflow: "hidden",
|
||||
py: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
Modal: {
|
||||
baseStyle: {
|
||||
dialog: {
|
||||
background: "backgroundHighlight",
|
||||
},
|
||||
overlay: {
|
||||
backdropFilter: "blur(5px)",
|
||||
},
|
||||
},
|
||||
},
|
||||
NumberInput: {
|
||||
defaultProps: {
|
||||
variant: "filled",
|
||||
},
|
||||
sizes: {
|
||||
xl: {
|
||||
addon: {
|
||||
borderRadius: "md",
|
||||
fontSize: "lg",
|
||||
h: 14,
|
||||
px: 4,
|
||||
},
|
||||
field: {
|
||||
borderRadius: "md",
|
||||
fontSize: "lg",
|
||||
h: 14,
|
||||
px: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
variants: {
|
||||
filled: {
|
||||
field: {
|
||||
_hover: {
|
||||
background: "inputBgHover",
|
||||
borderColor: "blue.500",
|
||||
},
|
||||
_invalid: {
|
||||
borderColor: "inputBorder",
|
||||
},
|
||||
background: "inputBg",
|
||||
borderColor: "inputBorder",
|
||||
borderWidth: "1px",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Select: {
|
||||
defaultProps: {
|
||||
variant: "filled",
|
||||
},
|
||||
variants: {
|
||||
filled: {
|
||||
field: {
|
||||
_hover: {
|
||||
background: "inputBgHover",
|
||||
borderColor: "blue.500",
|
||||
},
|
||||
background: "inputBg",
|
||||
borderColor: "borderColor",
|
||||
borderWidth: "1px",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Skeleton: skeletonTheme,
|
||||
Table: {
|
||||
baseStyle: {
|
||||
cell: {
|
||||
borderColor: "borderColor",
|
||||
},
|
||||
tbody: {
|
||||
background: "backgroundHighlight",
|
||||
},
|
||||
thead: {
|
||||
background: "backgroundHighlight",
|
||||
borderBottomColor: "hsl(var(--border))",
|
||||
borderBottomWidth: 1,
|
||||
},
|
||||
},
|
||||
sizes: {
|
||||
md: {
|
||||
td: {
|
||||
borderBottom: "none",
|
||||
fontSize: "14px",
|
||||
px: 6,
|
||||
py: 2,
|
||||
},
|
||||
th: {
|
||||
borderBottom: "none",
|
||||
color: "faded",
|
||||
fontSize: "12px",
|
||||
fontWeight: "600",
|
||||
py: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Text: {
|
||||
baseStyle: {
|
||||
color: "paragraph",
|
||||
},
|
||||
},
|
||||
Textarea: {
|
||||
defaultProps: {
|
||||
variant: "filled",
|
||||
},
|
||||
variants: {
|
||||
filled: {
|
||||
_focus: {
|
||||
borderColor: "blue.500",
|
||||
},
|
||||
_hover: {
|
||||
background: "transparent",
|
||||
borderColor: "inputBorderHover",
|
||||
},
|
||||
background: "transparent",
|
||||
borderColor: "inputBorder",
|
||||
borderWidth: "1px",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
config: {
|
||||
initialColorMode: "dark",
|
||||
useSystemColorMode: false,
|
||||
} as Theme["config"],
|
||||
fontSizes: [],
|
||||
fonts: {
|
||||
body: "Inter, sans-serif",
|
||||
heading: "Inter, sans-serif",
|
||||
mono: "IBM Plex Mono, monospace",
|
||||
},
|
||||
fontWeights,
|
||||
letterSpacings,
|
||||
lineHeights,
|
||||
semanticTokens: {
|
||||
colors: {
|
||||
backgroundBody: {
|
||||
_dark: "hsl(var(--background))",
|
||||
default: "hsl(var(--background))",
|
||||
},
|
||||
backgroundCardHighlight: {
|
||||
_dark: "#0b0b0b",
|
||||
// equivalent to muted/50 but without transparency
|
||||
default: "#f8f8f8",
|
||||
},
|
||||
backgroundHighlight: {
|
||||
_dark: "#0b0b0b",
|
||||
// equivalent to muted/50 but without transparency
|
||||
default: "#f8f8f8",
|
||||
},
|
||||
|
||||
// other
|
||||
badgeBg: {
|
||||
_dark: "hsl(var(--background))",
|
||||
default: "hsl(var(--background))",
|
||||
},
|
||||
bgBlack: { _dark: "white", default: "black" },
|
||||
bgWhite: { _dark: "black", default: "#fff" },
|
||||
|
||||
borderColor: {
|
||||
_dark: "hsl(var(--border))",
|
||||
default: "hsl(var(--border))",
|
||||
},
|
||||
faded: {
|
||||
_dark: "hsl(var(--muted-foreground))",
|
||||
default: "hsl(var(--muted-foreground))",
|
||||
},
|
||||
heading: {
|
||||
_dark: "hsl(var(--foreground))",
|
||||
default: "hsl(var(--foreground))",
|
||||
},
|
||||
// inputs
|
||||
inputBg: { _dark: "hsl(var(--card))", default: "hsl(var(--card))" },
|
||||
inputBgHover: { _dark: "hsl(var(--card))", default: "hsl(var(--card))" },
|
||||
inputBorder: { _dark: "hsl(var(--input))", default: "hsl(var(--input))" },
|
||||
inputBorderHover: {
|
||||
_dark: "hsl(var(--input))",
|
||||
default: "hsl(var(--input))",
|
||||
},
|
||||
paragraph: {
|
||||
_dark: "hsl(var(--muted-foreground))",
|
||||
default: "hsl(var(--muted-foreground))",
|
||||
},
|
||||
secondaryCardHighlight: {
|
||||
_dark: "hsl(var(--background))",
|
||||
default: "hsl(var(--background))",
|
||||
},
|
||||
wordmark: {
|
||||
_dark: "hsl(var(--muted-foreground))",
|
||||
default: "hsl(var(--muted-foreground))",
|
||||
},
|
||||
},
|
||||
},
|
||||
sizes: {
|
||||
container: {
|
||||
hero: "1440px",
|
||||
page: "1170px",
|
||||
},
|
||||
},
|
||||
styles: {
|
||||
global: {
|
||||
"::-moz-selection": {
|
||||
backgroundColor: "#90cdf4",
|
||||
color: "#fefefe",
|
||||
},
|
||||
"::selection": {
|
||||
backgroundColor: "#90cdf4",
|
||||
color: "#fefefe",
|
||||
},
|
||||
body: {
|
||||
colorScheme: "dark",
|
||||
},
|
||||
"html, body": {
|
||||
background: "#000",
|
||||
fontFeatureSettings: `'zero' 1`,
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
scrollBehavior: "smooth",
|
||||
},
|
||||
},
|
||||
},
|
||||
}) as Theme;
|
||||
|
||||
export default chakraTheme;
|
||||
@@ -1,21 +0,0 @@
|
||||
import { cssVar, defineStyle, defineStyleConfig } from "@chakra-ui/react";
|
||||
|
||||
const $startColor = cssVar("skeleton-start-color");
|
||||
const $endColor = cssVar("skeleton-end-color");
|
||||
|
||||
const thirdweb = defineStyle({
|
||||
_dark: {
|
||||
[$startColor.variable]: "colors.gray.900",
|
||||
[$endColor.variable]: "colors.gray.800",
|
||||
},
|
||||
_light: {
|
||||
[$startColor.variable]: "colors.gray.100",
|
||||
[$endColor.variable]: "colors.gray.300",
|
||||
},
|
||||
});
|
||||
export const skeletonTheme = defineStyleConfig({
|
||||
defaultProps: {
|
||||
variant: "thirdweb",
|
||||
},
|
||||
variants: { thirdweb },
|
||||
});
|
||||
@@ -1,39 +0,0 @@
|
||||
export const fontWeights = {
|
||||
body: 400,
|
||||
display: 800,
|
||||
label: 600,
|
||||
subtitle: 500,
|
||||
title: 700,
|
||||
} as const;
|
||||
|
||||
export const lineHeights = {
|
||||
body: 1.6,
|
||||
display: 1.2,
|
||||
label: 1,
|
||||
subtitle: 1.6,
|
||||
title: 1.125,
|
||||
} as const;
|
||||
|
||||
export const letterSpacings = {
|
||||
body: "initial",
|
||||
display: -1.5,
|
||||
label: "initial",
|
||||
subtitle: 0.1,
|
||||
title: 0.15,
|
||||
} as const;
|
||||
|
||||
type TypographyBase = "display" | "title" | "subtitle" | "label" | "body";
|
||||
export type TypographySize = "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
|
||||
|
||||
export type TypographyFontSize = `${TypographyBase}.${TypographySize}`;
|
||||
|
||||
export type HeadingBase = Exclude<TypographyBase, "body">;
|
||||
|
||||
export type HeadingSizes = `${HeadingBase}.${TypographySize}`;
|
||||
|
||||
export type TextBase = Exclude<
|
||||
TypographyBase,
|
||||
"display" | "title" | "subtitle"
|
||||
>;
|
||||
|
||||
export type TextSizes = `${TextBase}.${TypographySize}`;
|
||||
@@ -1,11 +0,0 @@
|
||||
import type { TypographyFontSize } from "chakra/theme/typography";
|
||||
|
||||
const FONT_SIZE_CSS_VAR_PREFIX = "--tw-font-size-" as const;
|
||||
|
||||
function createCssVariable(size: TypographyFontSize) {
|
||||
return `${FONT_SIZE_CSS_VAR_PREFIX}${size.replace(/\./g, "-")}`;
|
||||
}
|
||||
|
||||
export function convertFontSizeToCSSVar(fontSize: TypographyFontSize) {
|
||||
return `var(${createCssVariable(fontSize)})`;
|
||||
}
|
||||
@@ -195,14 +195,6 @@ input:-webkit-autofill:active {
|
||||
text-decoration: var(--shiki-dark-text-decoration) !important;
|
||||
}
|
||||
|
||||
/* Remove this when chakra is removed */
|
||||
/* Make chakra modals have same z-index as shadcn dialog */
|
||||
body {
|
||||
--chakra-zIndices-modal: 50;
|
||||
--chakra-zIndices-overlay: 50;
|
||||
--chakra-colors-chakra-border-color: hsl(var(--border));
|
||||
}
|
||||
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: hsl(var(--muted)) transparent;
|
||||
|
||||
Generated
-1037
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user