From caeb355e8a0e8869a38f026a2c6783e358bd3233 Mon Sep 17 00:00:00 2001 From: Alissa Crane Date: Tue, 22 Apr 2025 16:05:18 -0700 Subject: [PATCH 01/70] initial --- packages/onchainkit/src/wallet/components/Wallet.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/onchainkit/src/wallet/components/Wallet.tsx b/packages/onchainkit/src/wallet/components/Wallet.tsx index 158ca60e06..f06138b346 100644 --- a/packages/onchainkit/src/wallet/components/Wallet.tsx +++ b/packages/onchainkit/src/wallet/components/Wallet.tsx @@ -27,6 +27,7 @@ const defaultWalletChildren = ( ); + export function Wallet({ children, className, From 3333f7257fc28b9beb005861f65af188c9a94959 Mon Sep 17 00:00:00 2001 From: Alissa Crane Date: Thu, 24 Apr 2025 12:06:22 -0700 Subject: [PATCH 02/70] chore: deprecate code (#2312) --- .../src/buy/components/BuyButton.tsx | 4 +- packages/onchainkit/src/core/types.ts | 10 - .../src/earn/components/DepositButton.tsx | 2 +- .../src/earn/components/WithdrawButton.tsx | 2 +- packages/onchainkit/src/index.ts | 2 - .../nft/components/NFTCardDefault.test.tsx | 6 +- .../src/nft/components/NFTCardDefault.tsx | 15 +- .../components/Transaction.test.tsx | 12 +- .../transaction/components/Transaction.tsx | 2 - .../components/TransactionDefault.test.tsx | 1 - .../components/TransactionDefault.tsx | 2 - .../components/TransactionProvider.test.tsx | 30 +-- .../components/TransactionProvider.tsx | 29 +-- packages/onchainkit/src/transaction/types.ts | 8 - .../wallet/components/ConnectButton.test.tsx | 13 +- .../src/wallet/components/ConnectButton.tsx | 8 +- .../wallet/components/ConnectWallet.test.tsx | 104 +++++--- .../src/wallet/components/ConnectWallet.tsx | 35 +-- .../components/ConnectWalletText.test.tsx | 21 -- .../wallet/components/ConnectWalletText.tsx | 16 -- .../src/wallet/components/Wallet.test.tsx | 60 +---- .../src/wallet/components/Wallet.tsx | 43 +--- .../wallet/components/WalletAdvanced.test.tsx | 229 ------------------ .../src/wallet/components/WalletAdvanced.tsx | 54 ----- packages/onchainkit/src/wallet/index.ts | 4 - packages/onchainkit/src/wallet/types.ts | 4 - .../components/demo/NFTCardDefault.tsx | 4 +- 27 files changed, 110 insertions(+), 610 deletions(-) delete mode 100644 packages/onchainkit/src/wallet/components/ConnectWalletText.test.tsx delete mode 100644 packages/onchainkit/src/wallet/components/ConnectWalletText.tsx delete mode 100644 packages/onchainkit/src/wallet/components/WalletAdvanced.test.tsx delete mode 100644 packages/onchainkit/src/wallet/components/WalletAdvanced.tsx diff --git a/packages/onchainkit/src/buy/components/BuyButton.tsx b/packages/onchainkit/src/buy/components/BuyButton.tsx index 0f89653c8e..6d3008487f 100644 --- a/packages/onchainkit/src/buy/components/BuyButton.tsx +++ b/packages/onchainkit/src/buy/components/BuyButton.tsx @@ -77,7 +77,9 @@ export function BuyButton() { }, [statusName, isDropdownOpen]); if (!isDisabled && !address) { - return ; + return ( + + ); } return ( diff --git a/packages/onchainkit/src/core/types.ts b/packages/onchainkit/src/core/types.ts index ad253b6e05..b081797cf2 100644 --- a/packages/onchainkit/src/core/types.ts +++ b/packages/onchainkit/src/core/types.ts @@ -63,11 +63,6 @@ export type IsBaseOptions = { isMainnetOnly?: boolean; }; -/** - * @deprecated Use IsBaseOptions instead - */ -export type isBaseOptions = IsBaseOptions; - /** * Note: exported as public Type */ @@ -78,11 +73,6 @@ export type IsEthereumOptions = { isMainnetOnly?: boolean; }; -/** - * @deprecated Use IsEthereumOptions instead - */ -export type isEthereumOptions = IsEthereumOptions; - export type Mode = 'auto' | 'light' | 'dark'; /** diff --git a/packages/onchainkit/src/earn/components/DepositButton.tsx b/packages/onchainkit/src/earn/components/DepositButton.tsx index bbc1504200..8c91bba363 100644 --- a/packages/onchainkit/src/earn/components/DepositButton.tsx +++ b/packages/onchainkit/src/earn/components/DepositButton.tsx @@ -67,7 +67,7 @@ export function DepositButton({ className }: DepositButtonReact) { return ( ); } diff --git a/packages/onchainkit/src/earn/components/WithdrawButton.tsx b/packages/onchainkit/src/earn/components/WithdrawButton.tsx index 8b0ff5d988..3adf1057b5 100644 --- a/packages/onchainkit/src/earn/components/WithdrawButton.tsx +++ b/packages/onchainkit/src/earn/components/WithdrawButton.tsx @@ -65,7 +65,7 @@ export function WithdrawButton({ className }: WithdrawButtonReact) { return ( ); } diff --git a/packages/onchainkit/src/index.ts b/packages/onchainkit/src/index.ts index f8e3c2e83c..3ebb998e36 100644 --- a/packages/onchainkit/src/index.ts +++ b/packages/onchainkit/src/index.ts @@ -14,8 +14,6 @@ export type { IsEthereumOptions, OnchainKitConfig, OnchainKitContextType, - isBaseOptions, - isEthereumOptions, } from './core/types'; export type { OnchainKitProviderReact } from './types'; diff --git a/packages/onchainkit/src/nft/components/NFTCardDefault.test.tsx b/packages/onchainkit/src/nft/components/NFTCardDefault.test.tsx index 14bf1dbb09..9dc3a94e97 100644 --- a/packages/onchainkit/src/nft/components/NFTCardDefault.test.tsx +++ b/packages/onchainkit/src/nft/components/NFTCardDefault.test.tsx @@ -26,10 +26,6 @@ describe('NFTCardDefault', () => { , ); - expect(getByTestId('nft-media')).toBeInTheDocument(); - expect(getByTestId('nft-title')).toBeInTheDocument(); - expect(getByTestId('nft-owner')).toBeInTheDocument(); - expect(getByTestId('nft-last-sold-price')).toBeInTheDocument(); - expect(getByTestId('nft-network')).toBeInTheDocument(); + expect(getByTestId('nft-card')).toBeInTheDocument(); }); }); diff --git a/packages/onchainkit/src/nft/components/NFTCardDefault.tsx b/packages/onchainkit/src/nft/components/NFTCardDefault.tsx index 1ce8904fc8..553f5eee4c 100644 --- a/packages/onchainkit/src/nft/components/NFTCardDefault.tsx +++ b/packages/onchainkit/src/nft/components/NFTCardDefault.tsx @@ -1,13 +1,6 @@ 'use client'; import type { NFTCardDefaultReact } from '@/nft/types'; import { NFTCard } from './NFTCard'; -import { - NFTLastSoldPrice, - NFTMedia, - NFTNetwork, - NFTOwner, - NFTTitle, -} from './view'; /** * @deprecated Use the `NFTCard` component instead with no 'children' props. @@ -28,12 +21,6 @@ export function NFTCardDefault({ onStatus={onStatus} onSuccess={onSuccess} onError={onError} - > - - - - - - + /> ); } diff --git a/packages/onchainkit/src/transaction/components/Transaction.test.tsx b/packages/onchainkit/src/transaction/components/Transaction.test.tsx index da7f6662d3..be6d73fb83 100644 --- a/packages/onchainkit/src/transaction/components/Transaction.test.tsx +++ b/packages/onchainkit/src/transaction/components/Transaction.test.tsx @@ -77,7 +77,7 @@ describe('Transaction', () => { capabilities={{}} chainId={123} className="test-class" - contracts={[]} + calls={[]} onError={vi.fn()} onSuccess={vi.fn()} > @@ -93,7 +93,7 @@ describe('Transaction', () => { capabilities={{}} chainId={123} className="test-class" - contracts={[]} + calls={[]} onError={vi.fn()} onSuccess={vi.fn()} > @@ -114,7 +114,7 @@ describe('Transaction', () => { capabilities={{}} chainId={123} className="test-class" - contracts={[]} + calls={[]} onError={onError} onStatus={onStatus} onSuccess={onSuccess} @@ -131,7 +131,7 @@ describe('Transaction', () => { @@ -147,7 +147,7 @@ describe('Transaction', () => { capabilities={{}} chainId={base.id} className="test-class" - contracts={[]} + calls={[]} onError={vi.fn()} onSuccess={vi.fn()} > @@ -163,7 +163,7 @@ describe('Transaction', () => { capabilities={{}} chainId={base.id} className="test-class" - contracts={[]} + calls={[]} onError={vi.fn()} onSuccess={vi.fn()} />, diff --git a/packages/onchainkit/src/transaction/components/Transaction.tsx b/packages/onchainkit/src/transaction/components/Transaction.tsx index 42459c03f1..9fba5a65c4 100644 --- a/packages/onchainkit/src/transaction/components/Transaction.tsx +++ b/packages/onchainkit/src/transaction/components/Transaction.tsx @@ -13,7 +13,6 @@ export function Transaction({ chainId, className, children, - contracts, disabled = false, isSponsored, onError, @@ -43,7 +42,6 @@ export function Transaction({ calls={calls} capabilities={capabilities} chainId={accountChainId} - contracts={contracts} isSponsored={isSponsored} onError={onError} onStatus={onStatus} diff --git a/packages/onchainkit/src/transaction/components/TransactionDefault.test.tsx b/packages/onchainkit/src/transaction/components/TransactionDefault.test.tsx index e78aaa6cb3..c221e156d1 100644 --- a/packages/onchainkit/src/transaction/components/TransactionDefault.test.tsx +++ b/packages/onchainkit/src/transaction/components/TransactionDefault.test.tsx @@ -55,7 +55,6 @@ describe('TransactionDefault Component', () => { const defaultProps: TransactionDefaultReact = { calls: [], - contracts: [], disabled: false, onError: mockOnError, onStatus: mockOnStatus, diff --git a/packages/onchainkit/src/transaction/components/TransactionDefault.tsx b/packages/onchainkit/src/transaction/components/TransactionDefault.tsx index dda994c2d2..4dae384433 100644 --- a/packages/onchainkit/src/transaction/components/TransactionDefault.tsx +++ b/packages/onchainkit/src/transaction/components/TransactionDefault.tsx @@ -9,7 +9,6 @@ export function TransactionDefault({ capabilities, chainId, className, - contracts, disabled, onError, onStatus, @@ -22,7 +21,6 @@ export function TransactionDefault({ chainId={chainId} className={className} disabled={disabled} - contracts={contracts} onError={onError} onStatus={onStatus} onSuccess={onSuccess} diff --git a/packages/onchainkit/src/transaction/components/TransactionProvider.test.tsx b/packages/onchainkit/src/transaction/components/TransactionProvider.test.tsx index 7a9b7db40f..11b6103731 100644 --- a/packages/onchainkit/src/transaction/components/TransactionProvider.test.tsx +++ b/packages/onchainkit/src/transaction/components/TransactionProvider.test.tsx @@ -767,7 +767,7 @@ describe('TransactionProvider', () => { , ); }).toThrowError( - 'Transaction: calls or contracts must be provided as a prop to the Transaction component.', + 'Transaction: calls must be provided as a prop to the Transaction component.', ); restore(); }); @@ -786,34 +786,6 @@ describe('TransactionProvider', () => { consoleError.mockRestore(); }); - it('should throw an error when both contracts and calls are provided', async () => { - const restore = silenceError(); - expect(() => { - render( - -
Test
-
, - ); - }).toThrowError( - 'Transaction: Only one of contracts or calls can be provided as a prop to the Transaction component.', - ); - restore(); - }); - it('should handle sponsored contract calls', async () => { const contracts = [ { to: '0alissa' as `0x${string}`, data: '0x' as `0x${string}` }, diff --git a/packages/onchainkit/src/transaction/components/TransactionProvider.tsx b/packages/onchainkit/src/transaction/components/TransactionProvider.tsx index 290e598909..5767b4f8d4 100644 --- a/packages/onchainkit/src/transaction/components/TransactionProvider.tsx +++ b/packages/onchainkit/src/transaction/components/TransactionProvider.tsx @@ -55,7 +55,6 @@ export function TransactionProvider({ capabilities: transactionCapabilities, chainId, children, - contracts, isSponsored, onError, onStatus, @@ -79,7 +78,6 @@ export function TransactionProvider({ number | undefined >(); const [transactionHashList, setTransactionHashList] = useState([]); - const transactions = calls || contracts; // Retrieve wallet capabilities const walletCapabilities = useCapabilitiesSafe({ @@ -89,16 +87,9 @@ export function TransactionProvider({ const { switchChainAsync } = useSwitchChain(); // Validate `calls` and `contracts` props - if (!contracts && !calls) { + if (!calls) { throw new Error( - 'Transaction: calls or contracts must be provided as a prop to the Transaction component.', - ); - } - - // Validate `calls` and `contracts` props - if (calls && contracts) { - throw new Error( - 'Transaction: Only one of contracts or calls can be provided as a prop to the Transaction component.', + 'Transaction: calls must be provided as a prop to the Transaction component.', ); } @@ -241,7 +232,6 @@ export function TransactionProvider({ } }, [receipt, resetAfter, resetSendCalls, resetSendCall]); - // When all transactions are successful, get the receipts const getTransactionLegacyReceipts = useCallback(async () => { const receipts = []; for (const hash of transactionHashList) { @@ -270,9 +260,10 @@ export function TransactionProvider({ }); }, [chainId, config, transactionHashList]); + // When all transactions are successful, get the receipts useEffect(() => { if ( - !transactions || + !calls || transactionHashList.length !== transactionCount || transactionCount < 2 ) { @@ -280,7 +271,7 @@ export function TransactionProvider({ } getTransactionLegacyReceipts(); }, [ - transactions, + calls, transactionCount, transactionHashList, getTransactionLegacyReceipts, @@ -304,9 +295,9 @@ export function TransactionProvider({ handleAnalytics(TransactionEvent.TransactionInitiated, { address: account.address, }); - const resolvedTransactions = await (typeof transactions === 'function' - ? transactions() - : Promise.resolve(transactions)); + const resolvedTransactions = await (typeof calls === 'function' + ? calls() + : Promise.resolve(calls)); setTransactionCount(resolvedTransactions?.length); return resolvedTransactions; } catch (err) { @@ -326,7 +317,7 @@ export function TransactionProvider({ }); return undefined; } - }, [transactions, handleAnalytics, account.address, errorCode]); + }, [calls, handleAnalytics, account.address, errorCode]); const handleSubmit = useCallback(async () => { setErrorMessage(''); @@ -364,7 +355,7 @@ export function TransactionProvider({ setIsToastVisible, setLifecycleStatus, setTransactionId, - transactions, + transactions: calls, transactionId, transactionHash: singleTransactionHash || batchedTransactionHash, transactionCount, diff --git a/packages/onchainkit/src/transaction/types.ts b/packages/onchainkit/src/transaction/types.ts index fc1eb69474..37545f2a71 100644 --- a/packages/onchainkit/src/transaction/types.ts +++ b/packages/onchainkit/src/transaction/types.ts @@ -165,10 +165,6 @@ export type TransactionProviderReact = { chainId: number; /** The child components to be rendered within the provider component */ children: ReactNode; - /** - * @deprecated Use `calls` instead. - */ - contracts?: Calls | Contracts | Array; /** Whether the transactions are sponsored (default: false) */ isSponsored?: boolean; /** An optional callback function that handles errors within the provider */ @@ -197,10 +193,6 @@ export type TransactionReact = { children?: ReactNode; /** An optional CSS class name for styling the component */ className?: string; - /** - * @deprecated Use `calls` instead. - */ - contracts?: Calls | Contracts | Array; /** Whether the transactions are sponsored (default: false) */ isSponsored?: boolean; /** An optional callback function that handles transaction errors */ diff --git a/packages/onchainkit/src/wallet/components/ConnectButton.test.tsx b/packages/onchainkit/src/wallet/components/ConnectButton.test.tsx index 536f437d02..7ed7bf6f27 100644 --- a/packages/onchainkit/src/wallet/components/ConnectButton.test.tsx +++ b/packages/onchainkit/src/wallet/components/ConnectButton.test.tsx @@ -1,16 +1,11 @@ import { render, screen } from '@testing-library/react'; import { describe, expect, it, vi } from 'vitest'; import { ConnectButton } from './ConnectButton'; -import { ConnectWalletText } from './ConnectWalletText'; describe('ConnectButton', () => { it('should render connect button', () => { render( - , + , ); const button = screen.getByTestId('ockConnectButton'); expect(button).toBeInTheDocument(); @@ -20,11 +15,8 @@ describe('ConnectButton', () => { it('should render connect button with custom text', () => { render( Connect Dope Wallet - } + connectWalletText="Connect Dope Wallet" onClick={vi.fn()} - text="text" />, ); const button = screen.getByTestId('ockConnectButton'); @@ -38,7 +30,6 @@ describe('ConnectButton', () => { className="custom-class" connectWalletText="Connect Dope Wallet" onClick={vi.fn()} - text="text" />, ); const button = screen.getByTestId('ockConnectButton'); diff --git a/packages/onchainkit/src/wallet/components/ConnectButton.tsx b/packages/onchainkit/src/wallet/components/ConnectButton.tsx index a23215bcfc..362a0a4e8b 100644 --- a/packages/onchainkit/src/wallet/components/ConnectButton.tsx +++ b/packages/onchainkit/src/wallet/components/ConnectButton.tsx @@ -13,8 +13,6 @@ export function ConnectButton({ className, connectWalletText, onClick, - // Text will be deprecated in the future - text, }: ConnectButtonReact) { return ( ); } diff --git a/packages/onchainkit/src/wallet/components/ConnectWallet.test.tsx b/packages/onchainkit/src/wallet/components/ConnectWallet.test.tsx index a409ce3c8c..d92e66e691 100644 --- a/packages/onchainkit/src/wallet/components/ConnectWallet.test.tsx +++ b/packages/onchainkit/src/wallet/components/ConnectWallet.test.tsx @@ -6,7 +6,6 @@ import { useAnalytics } from '../../core/analytics/hooks/useAnalytics'; import { WalletEvent } from '../../core/analytics/types'; import { useOnchainKit } from '../../useOnchainKit'; import { ConnectWallet } from './ConnectWallet'; -import { ConnectWalletText } from './ConnectWalletText'; import { useWalletContext } from './WalletProvider'; import type { Connector } from 'wagmi'; import type { UseAccountReturnType, UseConnectReturnType, Config } from 'wagmi'; @@ -136,7 +135,7 @@ describe('ConnectWallet', () => { }); it('should render connect button when disconnected', () => { - render(); + render(); const button = screen.getByTestId('ockConnectButton'); expect(button).toBeInTheDocument(); expect(button).toHaveTextContent('Connect Wallet'); @@ -173,7 +172,7 @@ describe('ConnectWallet', () => { connector: undefined, } as unknown as UseAccountReturnType); - render(); + render(); const spinner = screen.getByTestId('ockSpinner'); expect(spinner).toBeInTheDocument(); }); @@ -196,7 +195,7 @@ describe('ConnectWallet', () => { } as unknown as UseAccountReturnType); render( - +
Wallet Connected
, ); @@ -229,7 +228,7 @@ describe('ConnectWallet', () => { sendAnalytics: mockSendAnalytics, }); - render(); + render(); const button = screen.getByTestId('ockConnectButton'); fireEvent.click(button); @@ -307,7 +306,7 @@ describe('ConnectWallet', () => { } as unknown as WalletContextType); const { rerender } = render( - +
Wallet Connected
, ); @@ -329,7 +328,7 @@ describe('ConnectWallet', () => { } as unknown as WalletContextType); rerender( - +
Wallet Connected
, ); @@ -412,8 +411,7 @@ describe('ConnectWallet', () => { } as unknown as UseAccountReturnType); render( - - Not Render +
Wallet Ciao
, ); @@ -457,7 +455,12 @@ describe('ConnectWallet', () => { status: 'idle', } as unknown as UseConnectReturnType); - render(); + render( + , + ); const button = screen.getByTestId('ockConnectButton'); fireEvent.click(button); @@ -480,7 +483,12 @@ describe('ConnectWallet', () => { } as unknown as Connector, } as unknown as UseAccountReturnType); - render(); + render( + , + ); expect(onConnectMock).toHaveBeenCalledTimes(1); }); @@ -504,7 +512,12 @@ describe('ConnectWallet', () => { } as unknown as UseAccountReturnType); const onConnectMock = vi.fn(); - render(); + render( + , + ); expect(onConnectMock).toHaveBeenCalledTimes(0); }); @@ -568,7 +581,7 @@ describe('ConnectWallet', () => { handleClose: vi.fn(), } as unknown as WalletContextType); - render(); + render(); const button = screen.getByTestId('ockConnectButton'); fireEvent.click(button); @@ -596,7 +609,7 @@ describe('ConnectWallet', () => { status: 'idle', } as unknown as UseConnectReturnType); - render(); + render(); const connectButton = screen.getByTestId('ockConnectButton'); fireEvent.click(connectButton); @@ -632,11 +645,7 @@ describe('ConnectWallet', () => { connector: undefined, } as unknown as UseAccountReturnType); - render( - - Custom Connect Text - , - ); + render(); const button = screen.getByTestId('ockConnectButton'); expect(button).toHaveTextContent('Custom Connect Text'); @@ -689,7 +698,9 @@ describe('ConnectWallet', () => { handleClose: vi.fn(), } as unknown as WalletContextType); - render(); + render( + , + ); const button = screen.getByTestId('ockConnectButton'); fireEvent.click(button); @@ -758,7 +769,7 @@ describe('ConnectWallet', () => { handleClose: vi.fn(), } as unknown as WalletContextType); - render(); + render(); const connectButton = screen.getByTestId('ockConnectButton'); fireEvent.click(connectButton); @@ -807,7 +818,10 @@ describe('ConnectWallet', () => { } as unknown as UseConnectReturnType); const { rerender } = render( - , + , ); const button = screen.getByTestId('ockConnectButton'); @@ -833,13 +847,19 @@ describe('ConnectWallet', () => { } as unknown as UseAccountReturnType); rerender( - , + , ); expect(onConnectMock).toHaveBeenCalledTimes(1); rerender( - , + , ); expect(onConnectMock).toHaveBeenCalledTimes(1); }); @@ -891,7 +911,9 @@ describe('ConnectWallet', () => { handleClose: vi.fn(), } as unknown as WalletContextType); - render(); + render( + , + ); const button = screen.getByTestId('ockConnectButton'); fireEvent.click(button); @@ -965,7 +987,7 @@ describe('ConnectWallet', () => { } as unknown as WalletContextType); const { rerender } = render( - , + , ); const button = screen.getByTestId('ockConnectButton'); @@ -990,7 +1012,10 @@ describe('ConnectWallet', () => { } as unknown as UseAccountReturnType); rerender( - , + , ); expect(onConnectMock).toHaveBeenCalledTimes(1); @@ -1041,7 +1066,10 @@ describe('ConnectWallet', () => { } as unknown as UseAccountReturnType); const { rerender } = render( - , + , ); const button = screen.getByTestId('ockConnectButton'); @@ -1065,13 +1093,19 @@ describe('ConnectWallet', () => { } as unknown as UseAccountReturnType); rerender( - , + , ); expect(onConnectMock).toHaveBeenCalledTimes(1); rerender( - , + , ); expect(onConnectMock).toHaveBeenCalledTimes(1); }); @@ -1109,7 +1143,7 @@ describe('ConnectWallet', () => { status: 'idle', } as unknown as UseConnectReturnType); - render(); + render(); const button = screen.getByTestId('ockConnectButton'); fireEvent.click(button); @@ -1141,7 +1175,7 @@ describe('ConnectWallet', () => { status: 'idle', } as unknown as UseConnectReturnType); - render(); + render(); const button = screen.getByTestId('ockConnectButton'); fireEvent.click(button); @@ -1173,7 +1207,7 @@ describe('ConnectWallet', () => { status: 'idle', } as unknown as UseConnectReturnType); - render(); + render(); const button = screen.getByTestId('ockConnectButton'); fireEvent.click(button); @@ -1207,7 +1241,7 @@ describe('ConnectWallet', () => { status: 'idle', } as unknown as UseConnectReturnType); - render(); + render(); const button = screen.getByTestId('ockConnectButton'); fireEvent.click(button); @@ -1258,7 +1292,7 @@ describe('ConnectWallet', () => { } as unknown as Connector, } as unknown as UseAccountReturnType); - render(); + render(); expect(mockSendAnalytics).toHaveBeenCalledWith( WalletEvent.ConnectSuccess, diff --git a/packages/onchainkit/src/wallet/components/ConnectWallet.tsx b/packages/onchainkit/src/wallet/components/ConnectWallet.tsx index aa2fe374bb..03fe14b465 100644 --- a/packages/onchainkit/src/wallet/components/ConnectWallet.tsx +++ b/packages/onchainkit/src/wallet/components/ConnectWallet.tsx @@ -1,15 +1,13 @@ 'use client'; import { Avatar, Name } from '@/identity'; -import { Children, isValidElement, useCallback, useMemo } from 'react'; -import type { ReactNode } from 'react'; +import { useCallback } from 'react'; import { useEffect, useState } from 'react'; import { useAccount, useConnect } from 'wagmi'; import { useAnalytics } from '../../core/analytics/hooks/useAnalytics'; import { WalletEvent } from '../../core/analytics/types'; import { IdentityProvider } from '../../identity/components/IdentityProvider'; import { Spinner } from '../../internal/components/Spinner'; -import { findComponent } from '../../internal/utils/findComponent'; import { border, cn, @@ -20,7 +18,6 @@ import { import { useOnchainKit } from '../../useOnchainKit'; import type { ConnectWalletReact } from '../types'; import { ConnectButton } from './ConnectButton'; -import { ConnectWalletText } from './ConnectWalletText'; import { WalletModal } from './WalletModal'; import { useWalletContext } from './WalletProvider'; @@ -34,11 +31,8 @@ const connectWalletDefaultChildren = ( export function ConnectWallet({ children, className, - // In a few version we will officially deprecate this prop, - // but for now we will keep it for backward compatibility. - text = 'Connect Wallet', onConnect, - disconnectedLabel, + disconnectedLabel = 'Connect Wallet', }: ConnectWalletReact) { const { config = { wallet: { display: undefined } } } = useOnchainKit(); @@ -61,26 +55,6 @@ export function ConnectWallet({ const [hasClickedConnect, setHasClickedConnect] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false); // duplicate modal state because ConnectWallet not always within WalletProvider - // TODO: remove lines 57-74 after deprecating ConnectWalletText - // Get connectWalletText from children when present, - // this is used to customize the connect wallet button text - const { connectWalletText } = useMemo(() => { - const childrenArray = Children.toArray(children); - return { - connectWalletText: childrenArray.find(findComponent(ConnectWalletText)), - }; - }, [children]); - - // Remove connectWalletText from children if present - const childrenWithoutConnectWalletText = useMemo(() => { - return Children.map(children, (child: ReactNode) => { - if (isValidElement(child) && child.type === ConnectWalletText) { - return null; - } - return child; - }); - }, [children]); - // Wallet connect status const connector = accountConnector || connectors[0]; const isLoading = connectStatus === 'pending' || status === 'connecting'; @@ -190,9 +164,8 @@ export function ConnectWallet({
{config?.wallet?.display === 'modal' && ( @@ -241,7 +214,7 @@ export function ConnectWallet({ onClick={handleToggle} >
- {childrenWithoutConnectWalletText || connectWalletDefaultChildren} + {children || connectWalletDefaultChildren}
diff --git a/packages/onchainkit/src/wallet/components/ConnectWalletText.test.tsx b/packages/onchainkit/src/wallet/components/ConnectWalletText.test.tsx deleted file mode 100644 index 9b65abd7d8..0000000000 --- a/packages/onchainkit/src/wallet/components/ConnectWalletText.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import { describe, expect, it } from 'vitest'; -import { ConnectWalletText } from './ConnectWalletText'; - -describe('ConnectWalletText', () => { - it('should render text', () => { - render(Connect Dope Wallet); - const text = screen.getByText('Connect Dope Wallet'); - expect(text).toBeInTheDocument(); - }); - - it('should render text with className', () => { - render( - - Connect Dope Wallet - , - ); - const text = screen.getByText('Connect Dope Wallet'); - expect(text).toHaveClass('custom-class'); - }); -}); diff --git a/packages/onchainkit/src/wallet/components/ConnectWalletText.tsx b/packages/onchainkit/src/wallet/components/ConnectWalletText.tsx deleted file mode 100644 index f0d0a589d9..0000000000 --- a/packages/onchainkit/src/wallet/components/ConnectWalletText.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { cn, color, text as dsText } from '../../styles/theme'; -import type { ConnectWalletTextReact } from '../types'; - -/** - * @deprecated Use the `disconnectedLabel` prop on `ConnectWallet` instead. - */ -export function ConnectWalletText({ - children, - className, -}: ConnectWalletTextReact) { - return ( - - {children} - - ); -} diff --git a/packages/onchainkit/src/wallet/components/Wallet.test.tsx b/packages/onchainkit/src/wallet/components/Wallet.test.tsx index 5c22bf7d94..60500dace4 100644 --- a/packages/onchainkit/src/wallet/components/Wallet.test.tsx +++ b/packages/onchainkit/src/wallet/components/Wallet.test.tsx @@ -3,7 +3,6 @@ import { render, screen } from '@testing-library/react'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { ConnectWallet } from './ConnectWallet'; import { Wallet } from './Wallet'; -import { WalletAdvanced } from './WalletAdvanced'; import { WalletDropdown } from './WalletDropdown'; import { type WalletProviderReact, useWalletContext } from './WalletProvider'; @@ -169,57 +168,6 @@ describe('Wallet Component', () => { expect(mockHandleClose).not.toHaveBeenCalled(); }); - it('should log error and default to WalletDropdown when both WalletDropdown and WalletAdvanced are provided', () => { - const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); - (useWalletContext as ReturnType).mockReturnValue({ - isSubComponentOpen: true, - handleClose: mockHandleClose, - containerRef: { current: document.createElement('div') }, - address: '0x123', - breakpoint: 'md', - }); - - render( - - - -
Wallet Dropdown
-
- -
Wallet Advanced
-
-
, - ); - - expect(consoleSpy).toHaveBeenCalledWith( - 'Defaulted to WalletDropdown. Wallet cannot have both WalletDropdown and WalletAdvanced as children.', - ); - expect(screen.getByTestId('ockWalletDropdown')).toBeDefined(); - expect(screen.queryByTestId('wallet-advanced')).toBeNull(); - - consoleSpy.mockRestore(); - }); - - it('should render WalletAdvanced when WalletAdvanced is provided', () => { - (useWalletContext as ReturnType).mockReturnValue({ - isSubComponentOpen: true, - handleClose: mockHandleClose, - containerRef: { current: document.createElement('div') }, - }); - - render( - - - -
Wallet Advanced
-
-
, - ); - - expect(screen.getByTestId('wallet-advanced')).toBeDefined(); - expect(screen.queryByTestId('wallet-dropdown')).toBeNull(); - }); - it('should render Draggable when draggable prop is true', () => { (useWalletContext as ReturnType).mockReturnValue({ isSubComponentOpen: true, @@ -230,9 +178,9 @@ describe('Wallet Component', () => { render( - +
Wallet Advanced
-
+
, ); @@ -250,9 +198,9 @@ describe('Wallet Component', () => { render( - +
Wallet Advanced
-
+
, ); diff --git a/packages/onchainkit/src/wallet/components/Wallet.tsx b/packages/onchainkit/src/wallet/components/Wallet.tsx index f06138b346..5490dbc388 100644 --- a/packages/onchainkit/src/wallet/components/Wallet.tsx +++ b/packages/onchainkit/src/wallet/components/Wallet.tsx @@ -4,19 +4,11 @@ import { Draggable } from '@/internal/components/Draggable/Draggable'; import { useIsMounted } from '@/internal/hooks/useIsMounted'; import { useOutsideClick } from '@/internal/hooks/useOutsideClick'; import { useTheme } from '@/internal/hooks/useTheme'; -import { findComponent } from '@/internal/utils/findComponent'; import { cn } from '@/styles/theme'; -import { - Children, - type ReactNode, - isValidElement, - useMemo, - useRef, -} from 'react'; +import { useRef } from 'react'; import type { WalletReact } from '../types'; import { getWalletDraggableProps } from '../utils/getWalletDraggableProps'; import { ConnectWallet } from './ConnectWallet'; -import { WalletAdvanced } from './WalletAdvanced'; import { WalletDropdown } from './WalletDropdown'; import { WalletProvider, useWalletContext } from './WalletProvider'; @@ -35,6 +27,7 @@ export function Wallet({ draggableStartingPosition, }: WalletReact) { const componentTheme = useTheme(); + const isMounted = useIsMounted(); // prevents SSR hydration issue @@ -71,34 +64,6 @@ function WalletContent({ useOutsideClick(walletContainerRef, handleClose); - // Note: this can be removed after deprecating WalletAdvanced - const { dropdown, advanced } = useMemo(() => { - const childrenArray = Children.toArray(children); - return { - dropdown: childrenArray.find(findComponent(WalletDropdown)), - advanced: childrenArray.find(findComponent(WalletAdvanced)), - }; - }, [children]); - - // Note: this can be removed after deprecating WalletAdvanced - // cannot use advanced and dropdown, - // default to dropdown - const childrenToRender = useMemo(() => { - return Children.map(children, (child: ReactNode) => { - if (isValidElement(child) && child.type === WalletAdvanced && dropdown) { - return null; - } - return child; - }); - }, [dropdown, children]); - - // Note: this can be removed after deprecating WalletAdvanced - if (dropdown && advanced) { - console.error( - 'Defaulted to WalletDropdown. Wallet cannot have both WalletDropdown and WalletAdvanced as children.', - ); - } - // dragging should be disabled when the connect wallet modal is open // or when the subcomponent is open on mobile (because then we use bottom sheet) const disableDraggable = @@ -116,7 +81,7 @@ function WalletContent({ >
{/* Note: update childrenToRender to children after deprecating WalletAdvanced */} - {childrenToRender || defaultWalletChildren} + {children || defaultWalletChildren}
@@ -129,7 +94,7 @@ function WalletContent({ className={cn('relative w-fit shrink-0', className)} > {/* Note: update childrenToRender to children after deprecating WalletAdvanced */} -
{childrenToRender || defaultWalletChildren}
+
{children || defaultWalletChildren}
); } diff --git a/packages/onchainkit/src/wallet/components/WalletAdvanced.test.tsx b/packages/onchainkit/src/wallet/components/WalletAdvanced.test.tsx deleted file mode 100644 index 2fd14b1cdd..0000000000 --- a/packages/onchainkit/src/wallet/components/WalletAdvanced.test.tsx +++ /dev/null @@ -1,229 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { ConnectWallet } from './ConnectWallet'; -import { Wallet } from './Wallet'; -import { WalletAdvanced } from './WalletAdvanced'; -import { useWalletContext } from './WalletProvider'; - -vi.mock('@/internal/hooks/useTheme', () => ({ - useTheme: vi.fn(), -})); - -vi.mock('./ConnectWallet', () => ({ - ConnectWallet: () =>
Connect Wallet
, -})); - -vi.mock('./WalletDropdownContent', () => ({ - WalletDropdownContent: ({ children }: { children: React.ReactNode }) => ( -
{children}
- ), -})); - -vi.mock('./WalletAdvancedProvider', () => ({ - useWalletAdvancedContext: vi.fn(), - WalletAdvancedProvider: ({ children }: { children: React.ReactNode }) => ( - <>{children} - ), -})); - -vi.mock('./WalletProvider', () => ({ - useWalletContext: vi.fn(), - WalletProvider: ({ children }: { children: React.ReactNode }) => ( - <>{children} - ), -})); - -vi.mock('./WalletAdvancedWalletActions', () => ({ - WalletAdvancedWalletActions: () => ( -
Wallet Advanced
- ), -})); - -vi.mock('./WalletAdvancedAddressDetails', () => ({ - WalletAdvancedAddressDetails: () => ( -
Wallet Advanced
- ), -})); - -vi.mock('./WalletAdvancedTransactionActions', () => ({ - WalletAdvancedTransactionActions: () => ( -
Wallet Advanced
- ), -})); - -vi.mock('./WalletAdvancedTokenHoldings', () => ({ - WalletAdvancedTokenHoldings: () => ( -
Wallet Advanced
- ), -})); - -describe('WalletAdvanced', () => { - const mockUseWalletContext = useWalletContext as ReturnType; - - beforeEach(() => { - Object.defineProperty(window, 'matchMedia', { - writable: true, - value: vi.fn().mockImplementation((query) => ({ - matches: false, - media: query, - onchange: null, - addListener: vi.fn(), - removeListener: vi.fn(), - addEventListener: vi.fn(), - removeEventListener: vi.fn(), - dispatchEvent: vi.fn(), - })), - }); - - vi.clearAllMocks(); - }); - - it('should render WalletAdvanced right-aligned when there is not enough space on the right', () => { - Object.defineProperty(window, 'innerWidth', { - writable: true, - configurable: true, - value: 500, - }); - - (useWalletContext as ReturnType).mockReturnValue({ - isSubComponentOpen: true, - alignSubComponentRight: true, - }); - - render( - - - -
Wallet Advanced
-
-
, - ); - - expect(screen.getByTestId('ockWalletAdvancedContainer')).toHaveClass( - 'right-0', - ); - }); - - it('should render WalletAdvanced left-aligned when there is enough space on the right', () => { - Object.defineProperty(window, 'innerWidth', { - writable: true, - configurable: true, - value: 1000, - }); - - (useWalletContext as ReturnType).mockReturnValue({ - isSubComponentOpen: true, - }); - - render( - - - -
Wallet Advanced
-
-
, - ); - - expect(screen.getByTestId('ockWalletAdvancedContainer')).toHaveClass( - 'left-0', - ); - }); - - it('should render WalletAdvanced above ConnectWallet when there is not enough space on the bottom', () => { - Object.defineProperty(window, 'innerHeight', { - writable: true, - configurable: true, - value: 1000, - }); - - (useWalletContext as ReturnType).mockReturnValue({ - isSubComponentOpen: true, - showSubComponentAbove: true, - }); - - render( - - - -
Wallet Advanced
-
-
, - ); - - expect(screen.getByTestId('ockWalletAdvancedContainer')).toHaveClass( - 'bottom-full', - ); - }); - - it('should render WalletAdvanced below ConnectWallet when there is enough space on the bottom', () => { - Object.defineProperty(window, 'innerHeight', { - writable: true, - configurable: true, - value: 1000, - }); - - (useWalletContext as ReturnType).mockReturnValue({ - isSubComponentOpen: true, - }); - - render( - - - -
Wallet Advanced
-
-
, - ); - - expect(screen.getByTestId('ockWalletAdvancedContainer')).toHaveClass( - 'top-full', - ); - }); - - it('renders connect-wallet when isSubComponentOpen is false', () => { - mockUseWalletContext.mockReturnValue({ isSubComponentOpen: false }); - - render( - - - -
Some content
-
-
, - ); - - expect(screen.getByTestId('connect-wallet')).toBeDefined(); - expect(screen.queryByTestId('wallet-advanced-content')).toBeNull(); - expect(screen.queryByTestId('child-content')).toBeNull(); - }); - - it('renders wallet-advanced-content when isSubComponentOpen is true', () => { - mockUseWalletContext.mockReturnValue({ isSubComponentOpen: true }); - - render( - - - -
Some content
-
-
, - ); - - expect(screen.getByTestId('wallet-advanced-content')).toBeDefined(); - expect(screen.getByTestId('child-content')).toBeDefined(); - }); - - it('renders default children when no children are provided', () => { - mockUseWalletContext.mockReturnValue({ isSubComponentOpen: true }); - - render( - - - - , - ); - - expect(screen.getByTestId('WalletAdvancedWalletActions')).toBeDefined(); - expect(screen.getByTestId('WalletAdvancedAddressDetails')).toBeDefined(); - }); -}); diff --git a/packages/onchainkit/src/wallet/components/WalletAdvanced.tsx b/packages/onchainkit/src/wallet/components/WalletAdvanced.tsx deleted file mode 100644 index a63113566b..0000000000 --- a/packages/onchainkit/src/wallet/components/WalletAdvanced.tsx +++ /dev/null @@ -1,54 +0,0 @@ -'use client'; - -import { cn } from '@/styles/theme'; -import type { WalletAdvancedReact } from '../types'; -import { WalletAdvancedAddressDetails } from './WalletAdvancedAddressDetails'; -import { WalletAdvancedTokenHoldings } from './WalletAdvancedTokenHoldings'; -import { WalletAdvancedTransactionActions } from './WalletAdvancedTransactionActions'; -import { WalletAdvancedWalletActions } from './WalletAdvancedWalletActions'; -import { WalletDropdownContent } from './WalletDropdownContent'; -import { useWalletContext } from './WalletProvider'; - -const defaultWalletAdvancedChildren = ( - <> - - - - - -); - -/** - * @deprecated Use the `WalletDropdown` component instead. - */ - -export function WalletAdvanced({ - children, - classNames, - swappableTokens, -}: WalletAdvancedReact) { - const { isSubComponentOpen, showSubComponentAbove, alignSubComponentRight } = - useWalletContext(); - - if (!isSubComponentOpen) { - return null; - } - - return ( -
- - {children || defaultWalletAdvancedChildren} - -
- ); -} diff --git a/packages/onchainkit/src/wallet/index.ts b/packages/onchainkit/src/wallet/index.ts index c902de05ec..fde3469aa2 100644 --- a/packages/onchainkit/src/wallet/index.ts +++ b/packages/onchainkit/src/wallet/index.ts @@ -3,14 +3,12 @@ export { Wallet } from './components/Wallet'; export { WalletDefault } from './components/WalletDefault'; export { ConnectWallet } from './components/ConnectWallet'; -export { ConnectWalletText } from './components/ConnectWalletText'; export { WalletIsland } from './components/WalletIsland'; export { WalletDropdown } from './components/WalletDropdown'; export { WalletDropdownBasename } from './components/WalletDropdownBasename'; export { WalletDropdownDisconnect } from './components/WalletDropdownDisconnect'; export { WalletDropdownFundLink } from './components/WalletDropdownFundLink'; export { WalletDropdownLink } from './components/WalletDropdownLink'; -export { WalletAdvanced } from './components/WalletAdvanced'; export { WalletAdvancedDefault } from './components/WalletAdvancedDefault'; export { WalletAdvancedAddressDetails } from './components/WalletAdvancedAddressDetails'; export { WalletAdvancedTransactionActions } from './components/WalletAdvancedTransactionActions'; @@ -43,6 +41,4 @@ export type { WalletDropdownLinkReact, WalletDropdownReact, WalletReact, - WalletAdvancedReact, - WalletAdvancedContextType, } from './types'; diff --git a/packages/onchainkit/src/wallet/types.ts b/packages/onchainkit/src/wallet/types.ts index 5861761c74..d8a48cc7e3 100644 --- a/packages/onchainkit/src/wallet/types.ts +++ b/packages/onchainkit/src/wallet/types.ts @@ -14,8 +14,6 @@ export type ConnectButtonReact = { connectWalletText: ReactNode | null; /** Function to call when the button is clicked */ onClick: () => void; - /** Optional text override for button */ - text: string; }; /** @@ -26,8 +24,6 @@ export type ConnectWalletReact = { children?: React.ReactNode; /** Optional className override for button element */ className?: string; - /** @deprecated Prefer `ConnectWalletText component` */ - text?: string; /** Optional callback function to execute when the wallet is connected. */ onConnect?: () => void; /** Optional disconnected display override */ diff --git a/packages/playground/components/demo/NFTCardDefault.tsx b/packages/playground/components/demo/NFTCardDefault.tsx index 2305488d68..ad1d0f19fc 100644 --- a/packages/playground/components/demo/NFTCardDefault.tsx +++ b/packages/playground/components/demo/NFTCardDefault.tsx @@ -1,6 +1,6 @@ import { type LifecycleStatus, - NFTCardDefault, + NFTCard, type NFTError, } from '@coinbase/onchainkit/nft'; import { useCallback, useContext } from 'react'; @@ -30,7 +30,7 @@ function NFTCardDefaultDemo() { }, []); return ( - Date: Tue, 29 Apr 2025 16:08:18 -0700 Subject: [PATCH 03/70] feat: upgrade tailwind to v4 (#2313) --- .gitignore | 1 - .../templates/minikit-basic/app/globals.css | 41 +- .../templates/minikit-basic/app/layout.tsx | 2 +- .../templates/minikit-basic/app/theme.css | 6 +- .../templates/minikit-basic/package.json | 5 +- .../minikit-basic/postcss.config.mjs | 2 +- .../minikit-snake/app/components/snake.tsx | 4 +- .../templates/minikit-snake/app/globals.css | 40 +- .../templates/minikit-snake/app/layout.tsx | 2 +- .../templates/minikit-snake/package.json | 5 +- .../minikit-snake/postcss.config.mjs | 2 +- .../templates/next/app/globals.css | 29 +- .../templates/next/app/layout.tsx | 4 +- .../templates/next/app/page.tsx | 23 +- .../templates/next/package.json | 5 +- .../templates/next/postcss.config.mjs | 2 +- .../miniapp-manifest-generator/package.json | 2 +- packages/onchainkit/package.json | 8 +- .../src/styles/index-with-tailwind.css | 9 - packages/onchainkit/src/styles/index.css | 193 +----- .../src/styles/legacy-ock-styles.css | 184 ++++++ .../src/styles/tailwind-animate-v4.css | 298 ++++++++++ .../onchainkit/src/styles/tailwind-base.css | 43 +- packages/onchainkit/tailwind.config.js | 24 - packages/playground/app/globals.css | 172 ++++-- .../app/minikit/components/snake.tsx | 4 +- packages/playground/app/minikit/globals.css | 44 +- packages/playground/app/minikit/theme.css | 1 + packages/playground/components.json | 19 +- .../components/form/active-component.tsx | 2 +- packages/playground/components/form/chain.tsx | 2 +- .../components/form/component-mode.tsx | 2 +- .../components/form/component-theme.tsx | 2 +- packages/playground/components/ui/button.tsx | 63 +- .../components/ui/dropdown-menu.tsx | 405 +++++++------ packages/playground/components/ui/input.tsx | 36 +- packages/playground/components/ui/label.tsx | 32 +- .../playground/components/ui/radio-group.tsx | 54 +- packages/playground/components/ui/select.tsx | 305 +++++----- packages/playground/components/ui/switch.tsx | 43 +- packages/playground/components/ui/tabs.tsx | 102 ++-- packages/playground/package.json | 25 +- packages/playground/postcss.config.mjs | 2 +- pnpm-lock.yaml | 561 ++++++++++++------ 44 files changed, 1722 insertions(+), 1088 deletions(-) delete mode 100644 packages/onchainkit/src/styles/index-with-tailwind.css create mode 100644 packages/onchainkit/src/styles/legacy-ock-styles.css create mode 100644 packages/onchainkit/src/styles/tailwind-animate-v4.css delete mode 100644 packages/onchainkit/tailwind.config.js diff --git a/.gitignore b/.gitignore index d4c35e545d..8965c98bf4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ esm tmp /out-tsc src/styles.css -src/tailwind.css # dependencies node_modules diff --git a/packages/create-onchain/templates/minikit-basic/app/globals.css b/packages/create-onchain/templates/minikit-basic/app/globals.css index ddb9e40770..7a58612497 100644 --- a/packages/create-onchain/templates/minikit-basic/app/globals.css +++ b/packages/create-onchain/templates/minikit-basic/app/globals.css @@ -1,25 +1,32 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss"; +@custom-variant dark (&:where(.dark, .dark *)); :root { --background: #ffffff; - --foreground: #111111; + --foreground: #171717; } -@media (prefers-color-scheme: dark) { - :root { - --background: #111111; - --foreground: #ffffff; - } +.dark { + --background: #0a0a0a; + --foreground: #ededed; } -body { - color: var(--foreground); - background: var(--background); - font-family: "Geist", sans-serif; - font-optical-sizing: auto; - font-weight: 400; - font-style: normal; - font-size: 80%; +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); } + +@layer base { + body { + @apply bg-background text-foreground; + font-family: "Geist", sans-serif; + font-optical-sizing: auto; + font-weight: 400; + font-style: normal; + font-size: 80%; + } +} + +* { + touch-action: manipulation; +} \ No newline at end of file diff --git a/packages/create-onchain/templates/minikit-basic/app/layout.tsx b/packages/create-onchain/templates/minikit-basic/app/layout.tsx index 404c2b0535..23b81a1295 100644 --- a/packages/create-onchain/templates/minikit-basic/app/layout.tsx +++ b/packages/create-onchain/templates/minikit-basic/app/layout.tsx @@ -42,7 +42,7 @@ export default function RootLayout({ }>) { return ( - + {children} diff --git a/packages/create-onchain/templates/minikit-basic/app/theme.css b/packages/create-onchain/templates/minikit-basic/app/theme.css index d1524b5cff..1d8549471b 100644 --- a/packages/create-onchain/templates/minikit-basic/app/theme.css +++ b/packages/create-onchain/templates/minikit-basic/app/theme.css @@ -1,8 +1,6 @@ @import url("https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap"); -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss"; :root { --app-background: #ffffff; @@ -101,7 +99,7 @@ body { font-style: normal; } -@layer utilities { +@utility text-balance { .text-balance { text-wrap: balance; } diff --git a/packages/create-onchain/templates/minikit-basic/package.json b/packages/create-onchain/templates/minikit-basic/package.json index d292d48588..71138a731a 100644 --- a/packages/create-onchain/templates/minikit-basic/package.json +++ b/packages/create-onchain/templates/minikit-basic/package.json @@ -12,10 +12,13 @@ "@coinbase/onchainkit": "latest", "@farcaster/frame-sdk": "^0.0.35", "@upstash/redis": "^1.34.4", + "postcss": "^8.5.3", "next": "^14.2.15", "react": "^18", "react-dom": "^18", "@tanstack/react-query": "^5", + "tailwindcss": "^4.1.4", + "@tailwindcss/postcss": "^4.1.4", "viem": "^2.27.2", "wagmi": "^2.14.11" }, @@ -30,8 +33,6 @@ "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.2.0", "prettier": "^3.5.3", - "postcss": "^8", - "tailwindcss": "^3.4.1", "typescript": "^5" } } diff --git a/packages/create-onchain/templates/minikit-basic/postcss.config.mjs b/packages/create-onchain/templates/minikit-basic/postcss.config.mjs index 1a69fd2a45..5d6d8457f7 100644 --- a/packages/create-onchain/templates/minikit-basic/postcss.config.mjs +++ b/packages/create-onchain/templates/minikit-basic/postcss.config.mjs @@ -1,7 +1,7 @@ /** @type {import('postcss-load-config').Config} */ const config = { plugins: { - tailwindcss: {}, + '@tailwindcss/postcss': {}, }, }; diff --git a/packages/create-onchain/templates/minikit-snake/app/components/snake.tsx b/packages/create-onchain/templates/minikit-snake/app/components/snake.tsx index 2621e4f4fc..b32dca3118 100644 --- a/packages/create-onchain/templates/minikit-snake/app/components/snake.tsx +++ b/packages/create-onchain/templates/minikit-snake/app/components/snake.tsx @@ -1100,14 +1100,14 @@ const Sammy = () => { id="map" width={500} height={500} - className="absolute top-0 left-0 z-3" + className="absolute top-0 left-0 z-2" /> ) { return ( - + {children} diff --git a/packages/create-onchain/templates/minikit-snake/package.json b/packages/create-onchain/templates/minikit-snake/package.json index d292d48588..71138a731a 100644 --- a/packages/create-onchain/templates/minikit-snake/package.json +++ b/packages/create-onchain/templates/minikit-snake/package.json @@ -12,10 +12,13 @@ "@coinbase/onchainkit": "latest", "@farcaster/frame-sdk": "^0.0.35", "@upstash/redis": "^1.34.4", + "postcss": "^8.5.3", "next": "^14.2.15", "react": "^18", "react-dom": "^18", "@tanstack/react-query": "^5", + "tailwindcss": "^4.1.4", + "@tailwindcss/postcss": "^4.1.4", "viem": "^2.27.2", "wagmi": "^2.14.11" }, @@ -30,8 +33,6 @@ "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.2.0", "prettier": "^3.5.3", - "postcss": "^8", - "tailwindcss": "^3.4.1", "typescript": "^5" } } diff --git a/packages/create-onchain/templates/minikit-snake/postcss.config.mjs b/packages/create-onchain/templates/minikit-snake/postcss.config.mjs index 1a69fd2a45..5d6d8457f7 100644 --- a/packages/create-onchain/templates/minikit-snake/postcss.config.mjs +++ b/packages/create-onchain/templates/minikit-snake/postcss.config.mjs @@ -1,7 +1,7 @@ /** @type {import('postcss-load-config').Config} */ const config = { plugins: { - tailwindcss: {}, + '@tailwindcss/postcss': {}, }, }; diff --git a/packages/create-onchain/templates/next/app/globals.css b/packages/create-onchain/templates/next/app/globals.css index 13d40b8920..181704eea9 100644 --- a/packages/create-onchain/templates/next/app/globals.css +++ b/packages/create-onchain/templates/next/app/globals.css @@ -1,26 +1,29 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import 'tailwindcss'; +@custom-variant dark (&:where(.dark, .dark *)); :root { --background: #ffffff; --foreground: #171717; } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } +.dark { + --background: #0a0a0a; + --foreground: #ededed; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); } -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; +@layer base { + body { + @apply bg-background text-foreground; + font-family: Arial, Helvetica, sans-serif; + } } -@layer utilities { +@utility text-balance { .text-balance { text-wrap: balance; } diff --git a/packages/create-onchain/templates/next/app/layout.tsx b/packages/create-onchain/templates/next/app/layout.tsx index 1463d3a2fa..af024e187c 100644 --- a/packages/create-onchain/templates/next/app/layout.tsx +++ b/packages/create-onchain/templates/next/app/layout.tsx @@ -14,8 +14,8 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - + + {children} diff --git a/packages/create-onchain/templates/next/app/page.tsx b/packages/create-onchain/templates/next/app/page.tsx index e4a0d138ae..6d54e21b97 100644 --- a/packages/create-onchain/templates/next/app/page.tsx +++ b/packages/create-onchain/templates/next/app/page.tsx @@ -31,16 +31,19 @@ const components = [ const templates = [ { name: 'NFT', url: 'https://github.com/coinbase/onchain-app-template' }, - { name: 'Commerce', url: 'https://github.com/coinbase/onchain-commerce-template'}, + { + name: 'Commerce', + url: 'https://github.com/coinbase/onchain-commerce-template', + }, { name: 'Fund', url: 'https://github.com/fakepixels/fund-component' }, ]; export default function App() { return ( -
+
-
-
+
+
@@ -75,12 +78,14 @@ export default function App() {

Get started by editing - app/page.tsx. + + app/page.tsx +

@@ -94,7 +99,7 @@ export default function App() {
  • @@ -114,12 +119,12 @@ export default function App() {
  • {template.name} - +
  • ))} diff --git a/packages/create-onchain/templates/next/package.json b/packages/create-onchain/templates/next/package.json index 28d0ddf3eb..d4871802b5 100644 --- a/packages/create-onchain/templates/next/package.json +++ b/packages/create-onchain/templates/next/package.json @@ -10,10 +10,13 @@ }, "dependencies": { "@coinbase/onchainkit": "latest", + "postcss": "^8.5.3", "next": "14.2.15", "react": "^18", "react-dom": "^18", "@tanstack/react-query": "^5", + "tailwindcss": "^4.1.4", + "@tailwindcss/postcss": "^4.1.4", "viem": "^2.27.2", "wagmi": "^2.14.11" }, @@ -22,8 +25,6 @@ "@types/react": "^18", "@types/react-dom": "^18", "eslint-config-next": "14.2.15", - "postcss": "^8", - "tailwindcss": "^3.4.1", "typescript": "^5", "eslint": "^8" } diff --git a/packages/create-onchain/templates/next/postcss.config.mjs b/packages/create-onchain/templates/next/postcss.config.mjs index 1a69fd2a45..5d6d8457f7 100644 --- a/packages/create-onchain/templates/next/postcss.config.mjs +++ b/packages/create-onchain/templates/next/postcss.config.mjs @@ -1,7 +1,7 @@ /** @type {import('postcss-load-config').Config} */ const config = { plugins: { - tailwindcss: {}, + '@tailwindcss/postcss': {}, }, }; diff --git a/packages/miniapp-manifest-generator/package.json b/packages/miniapp-manifest-generator/package.json index 908a5fe6e0..656c0058a5 100644 --- a/packages/miniapp-manifest-generator/package.json +++ b/packages/miniapp-manifest-generator/package.json @@ -38,7 +38,7 @@ "eslint-plugin-react-refresh": "^0.4.19", "globals": "^15.15.0", "jsdom": "^24.1.0", - "tailwindcss": "^4.0.9", + "tailwindcss": "^4.1.4", "typescript": "~5.7.2", "typescript-eslint": "^8.24.1", "vite": "^6.2.0", diff --git a/packages/onchainkit/package.json b/packages/onchainkit/package.json index af51d30ffa..8485910a0e 100644 --- a/packages/onchainkit/package.json +++ b/packages/onchainkit/package.json @@ -12,8 +12,8 @@ "dev": "concurrently \"pnpm tailwind:dev\" \"pnpm bundle:dev\"", "bundle:dev": "NODE_ENV=development vite build --watch", "bundle:prod": "vite build", - "tailwind:dev": "tailwind -i ./src/styles/index-with-tailwind.css -o ./dist/styles.css --watch", - "tailwind:prod": "tailwindcss -i ./src/styles/index.css -o ./dist/tailwind.css --minify && tailwindcss -i ./src/styles/index-with-tailwind.css -o ./dist/styles.css --minify", + "tailwind:dev": "tailwindcss -i ./src/styles/index.css -o ./dist/styles.css --watch", + "tailwind:prod": "tailwindcss -i ./src/styles/index.css -o ./dist/styles.css --minify", "clean": "rm -rf dist esm", "lint": "eslint . --ext .ts,.tsx --max-warnings=0", "lint:fix": "eslint . --ext .ts,.tsx --fix", @@ -44,6 +44,7 @@ "wagmi": "^2.14.11" }, "devDependencies": { + "@tailwindcss/cli": "^4.1.4", "@testing-library/jest-dom": "6.4.7", "@testing-library/react": "^14.2.0", "@testing-library/user-event": "^14.6.1", @@ -70,7 +71,7 @@ "rimraf": "^5.0.5", "rollup-plugin-preserve-use-client": "^3.0.1", "storybook": "^8.2.9", - "tailwindcss": "^3.4.3", + "tailwindcss": "^4.1.4", "tailwindcss-animate": "^1.0.7", "tscpaths": "^0.0.9", "tsup": "^8.3.5", @@ -97,7 +98,6 @@ "exports": { "./package.json": "./package.json", "./styles.css": "./dist/styles.css", - "./tailwind.css": "./dist/tailwind.css", "./theme": "./dist/styles/theme.js", ".": { "types": "./dist/index.d.ts", diff --git a/packages/onchainkit/src/styles/index-with-tailwind.css b/packages/onchainkit/src/styles/index-with-tailwind.css deleted file mode 100644 index 0defc118ff..0000000000 --- a/packages/onchainkit/src/styles/index-with-tailwind.css +++ /dev/null @@ -1,9 +0,0 @@ -@import url("https://fonts.googleapis.com/css2?family=Inter&display=swap"); -@import url("https://fonts.googleapis.com/css2?family=Inter:wght@700&display=swap"); -@import url("https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz@0,9..40;1,9..40&display=swap"); -@import url("https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,700;1,9..40,700&display=swap"); -@import url("https://fonts.googleapis.com/css2?family=Oxanium:wght@200..800&display=swap"); -@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Mono:wght@100..900&display=swap'); -@import url("./index.css"); -@import url("./tailwind-base.css"); - diff --git a/packages/onchainkit/src/styles/index.css b/packages/onchainkit/src/styles/index.css index 4c8234a05f..40fb1ab41b 100644 --- a/packages/onchainkit/src/styles/index.css +++ b/packages/onchainkit/src/styles/index.css @@ -1,184 +1,9 @@ -/* Font */ -.ock-font-family { - font-family: var(--ock-font-family); -} - -/* Border */ -.ock-border-default { - border-color: var(--ock-bg-default); -} - -.ock-border-default-active { - border-color: var(--ock-bg-default-active); -} - -.ock-border-line-primary { - border-color: var(--ock-line-primary); -} - -.ock-border-line-default { - border-color: var(--ock-line-default); -} - -.ock-border-line-heavy { - border-color: var(--ock-line-heavy); -} - -.ock-border-line-inverse { - border-color: var(--ock-line-inverse); -} - -.ock-border-radius { - border-radius: var(--ock-border-radius); -} - -.ock-border-radius-inner { - border-radius: var(--ock-border-radius-inner); -} - -/* Fill */ -.ock-fill-default { - fill: var(--ock-bg-default); -} - -.ock-fill-default-reverse { - fill: var(--ock-bg-default-reverse); -} - -.ock-fill-alternate { - fill: var(--ock-bg-alternate); -} - -/* Icon */ -.ock-icon-color-primary { - fill: var(--ock-icon-color-primary); -} -.ock-icon-color-foreground { - fill: var(--ock-icon-color-foreground); -} -.ock-icon-color-foreground-muted { - fill: var(--ock-icon-color-foreground-muted); -} -.ock-icon-color-inverse { - fill: var(--ock-icon-color-inverse); -} -.ock-icon-color-error { - fill: var(--ock-icon-color-error); -} -.ock-icon-color-success { - fill: var(--ock-icon-color-success); -} -.ock-icon-color-warning { - fill: var(--ock-icon-color-warning); -} - -/* Placeholder */ -.placeholder-ock-default::placeholder { - color: var(--ock-text-foreground-muted); -} - -/* Scrollbar */ -.ock-scrollbar { - scrollbar-width: thin; - scrollbar-color: #d1d5db #ffffff; -} - -/* Shadow */ -.ock-shadow-default { - box-shadow: 0px 8px 12px 0px #5b616e1f; -} - -.dark .ock-shadow-default { - box-shadow: 0px 8px 12px 0px #5b616e1f; -} - -/* Text */ -.ock-text-inverse { - color: var(--ock-text-inverse); -} -.ock-text-foreground { - color: var(--ock-text-foreground); -} -.ock-text-foreground-muted { - color: var(--ock-text-foreground-muted); -} -.ock-text-error { - color: var(--ock-text-error); -} -.ock-text-primary { - color: var(--ock-text-primary); -} -.ock-text-success { - color: var(--ock-text-success); -} -.ock-text-warning { - color: var(--ock-text-warning); -} -.ock-text-disabled { - color: var(--ock-text-disabled); -} -/* Background */ -.ock-bg-default { - background-color: var(--ock-bg-default); -} -.ock-bg-default-hover { - background-color: var(--ock-bg-default-hover); -} -.ock-bg-default-active { - background-color: var(--ock-bg-default-active); -} -.ock-bg-alternate { - background-color: var(--ock-bg-alternate); -} -.ock-bg-alternate-hover { - background-color: var(--ock-bg-alternate-hover); -} -.ock-bg-alternate-active { - background-color: var(--ock-bg-alternate-active); -} -.ock-bg-inverse { - background-color: var(--ock-bg-inverse); -} -.ock-bg-inverse-hover { - background-color: var(--ock-bg-inverse-hover); -} -.ock-bg-inverse-active { - background-color: var(--ock-bg-inverse-active); -} -.ock-bg-primary { - background-color: var(--ock-bg-primary); -} -.ock-bg-primary-hover { - background-color: var(--ock-bg-primary-hover); -} -.ock-bg-primary-active { - background-color: var(--ock-bg-primary-active); -} -.ock-bg-secondary { - background-color: var(--ock-bg-secondary); -} -.ock-bg-secondary-hover { - background-color: var(--ock-bg-secondary-hover); -} -.ock-bg-secondary-active { - background-color: var(--ock-bg-secondary-active); -} -.ock-bg-error { - background-color: var(--ock-bg-error); -} -.ock-bg-warning { - background-color: var(--ock-bg-warning); -} -.ock-bg-success { - background-color: var(--ock-bg-success); -} -.ock-bg-default-reverse { - background-color: var(--ock-bg-default-reverse); -} -.ock-bg-primary-washed { - background-color: var(--ock-bg-primary-washed); -} -.ock-bg-primary-disabled { - background-color: var(--ock-bg-primary-disabled); -} - +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@700&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz@0,9..40;1,9..40&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,700;1,9..40,700&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Oxanium:wght@200..800&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Mono:wght@100..900&display=swap'); +@import './tailwind-base.css'; +@import './legacy-ock-styles.css'; +@import './tailwind-animate-v4.css'; diff --git a/packages/onchainkit/src/styles/legacy-ock-styles.css b/packages/onchainkit/src/styles/legacy-ock-styles.css new file mode 100644 index 0000000000..4c8234a05f --- /dev/null +++ b/packages/onchainkit/src/styles/legacy-ock-styles.css @@ -0,0 +1,184 @@ +/* Font */ +.ock-font-family { + font-family: var(--ock-font-family); +} + +/* Border */ +.ock-border-default { + border-color: var(--ock-bg-default); +} + +.ock-border-default-active { + border-color: var(--ock-bg-default-active); +} + +.ock-border-line-primary { + border-color: var(--ock-line-primary); +} + +.ock-border-line-default { + border-color: var(--ock-line-default); +} + +.ock-border-line-heavy { + border-color: var(--ock-line-heavy); +} + +.ock-border-line-inverse { + border-color: var(--ock-line-inverse); +} + +.ock-border-radius { + border-radius: var(--ock-border-radius); +} + +.ock-border-radius-inner { + border-radius: var(--ock-border-radius-inner); +} + +/* Fill */ +.ock-fill-default { + fill: var(--ock-bg-default); +} + +.ock-fill-default-reverse { + fill: var(--ock-bg-default-reverse); +} + +.ock-fill-alternate { + fill: var(--ock-bg-alternate); +} + +/* Icon */ +.ock-icon-color-primary { + fill: var(--ock-icon-color-primary); +} +.ock-icon-color-foreground { + fill: var(--ock-icon-color-foreground); +} +.ock-icon-color-foreground-muted { + fill: var(--ock-icon-color-foreground-muted); +} +.ock-icon-color-inverse { + fill: var(--ock-icon-color-inverse); +} +.ock-icon-color-error { + fill: var(--ock-icon-color-error); +} +.ock-icon-color-success { + fill: var(--ock-icon-color-success); +} +.ock-icon-color-warning { + fill: var(--ock-icon-color-warning); +} + +/* Placeholder */ +.placeholder-ock-default::placeholder { + color: var(--ock-text-foreground-muted); +} + +/* Scrollbar */ +.ock-scrollbar { + scrollbar-width: thin; + scrollbar-color: #d1d5db #ffffff; +} + +/* Shadow */ +.ock-shadow-default { + box-shadow: 0px 8px 12px 0px #5b616e1f; +} + +.dark .ock-shadow-default { + box-shadow: 0px 8px 12px 0px #5b616e1f; +} + +/* Text */ +.ock-text-inverse { + color: var(--ock-text-inverse); +} +.ock-text-foreground { + color: var(--ock-text-foreground); +} +.ock-text-foreground-muted { + color: var(--ock-text-foreground-muted); +} +.ock-text-error { + color: var(--ock-text-error); +} +.ock-text-primary { + color: var(--ock-text-primary); +} +.ock-text-success { + color: var(--ock-text-success); +} +.ock-text-warning { + color: var(--ock-text-warning); +} +.ock-text-disabled { + color: var(--ock-text-disabled); +} +/* Background */ +.ock-bg-default { + background-color: var(--ock-bg-default); +} +.ock-bg-default-hover { + background-color: var(--ock-bg-default-hover); +} +.ock-bg-default-active { + background-color: var(--ock-bg-default-active); +} +.ock-bg-alternate { + background-color: var(--ock-bg-alternate); +} +.ock-bg-alternate-hover { + background-color: var(--ock-bg-alternate-hover); +} +.ock-bg-alternate-active { + background-color: var(--ock-bg-alternate-active); +} +.ock-bg-inverse { + background-color: var(--ock-bg-inverse); +} +.ock-bg-inverse-hover { + background-color: var(--ock-bg-inverse-hover); +} +.ock-bg-inverse-active { + background-color: var(--ock-bg-inverse-active); +} +.ock-bg-primary { + background-color: var(--ock-bg-primary); +} +.ock-bg-primary-hover { + background-color: var(--ock-bg-primary-hover); +} +.ock-bg-primary-active { + background-color: var(--ock-bg-primary-active); +} +.ock-bg-secondary { + background-color: var(--ock-bg-secondary); +} +.ock-bg-secondary-hover { + background-color: var(--ock-bg-secondary-hover); +} +.ock-bg-secondary-active { + background-color: var(--ock-bg-secondary-active); +} +.ock-bg-error { + background-color: var(--ock-bg-error); +} +.ock-bg-warning { + background-color: var(--ock-bg-warning); +} +.ock-bg-success { + background-color: var(--ock-bg-success); +} +.ock-bg-default-reverse { + background-color: var(--ock-bg-default-reverse); +} +.ock-bg-primary-washed { + background-color: var(--ock-bg-primary-washed); +} +.ock-bg-primary-disabled { + background-color: var(--ock-bg-primary-disabled); +} + diff --git a/packages/onchainkit/src/styles/tailwind-animate-v4.css b/packages/onchainkit/src/styles/tailwind-animate-v4.css new file mode 100644 index 0000000000..e826b27de9 --- /dev/null +++ b/packages/onchainkit/src/styles/tailwind-animate-v4.css @@ -0,0 +1,298 @@ +@theme inline { + /* Predefined values */ + + --animation-delay-0: 0s; + --animation-delay-75: 75ms; + --animation-delay-100: 0.1s; + --animation-delay-150: 0.15s; + --animation-delay-200: 0.2s; + --animation-delay-300: 0.3s; + --animation-delay-500: 0.5s; + --animation-delay-700: 0.7s; + --animation-delay-1000: 1s; + + --animation-repeat-0: 0; + --animation-repeat-1: 1; + --animation-repeat-infinite: infinite; + + --animation-direction-normal: normal; + --animation-direction-reverse: reverse; + --animation-direction-alternate: alternate; + --animation-direction-alternate-reverse: alternate-reverse; + + --animation-fill-mode-none: none; + --animation-fill-mode-forwards: forwards; + --animation-fill-mode-backwards: backwards; + --animation-fill-mode-both: both; + + --percentage-0: 0; + --percentage-5: 0.05; + --percentage-10: 0.1; + --percentage-15: 0.15; + --percentage-20: 0.2; + --percentage-25: 0.25; + --percentage-30: 0.3; + --percentage-35: 0.35; + --percentage-40: 0.4; + --percentage-45: 0.45; + --percentage-50: 0.5; + --percentage-55: 0.55; + --percentage-60: 0.6; + --percentage-65: 0.65; + --percentage-70: 0.7; + --percentage-75: 0.75; + --percentage-80: 0.8; + --percentage-85: 0.85; + --percentage-90: 0.9; + --percentage-95: 0.95; + --percentage-100: 1; + --percentage-translate-full: 1; + + /* Animations and keyframes */ + + --animate-in: enter var(--tw-duration, 150ms) var(--tw-ease, var(--default-transition-timing-function)); + --animate-out: exit var(--tw-duration, 150ms) var(--tw-ease, var(--default-transition-timing-function)); + + @keyframes enter { + from { + opacity: var(--tw-enter-opacity, 1); + transform: translate3d(var(--tw-enter-translate-x, 0), var(--tw-enter-translate-y, 0), 0) + scale3d(var(--tw-enter-scale, 1), var(--tw-enter-scale, 1), var(--tw-enter-scale, 1)) + rotate(var(--tw-enter-rotate, 0)); + } + } + + @keyframes exit { + to { + opacity: var(--tw-exit-opacity, 1); + transform: translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0) + scale3d(var(--tw-exit-scale, 1), var(--tw-exit-scale, 1), var(--tw-exit-scale, 1)) + rotate(var(--tw-exit-rotate, 0)); + } + } + + /* + * Radix and Bits UI utilize CSS variables to define the height of Accordion and Collapsible + * content during open/close animations. The `--radix/bits-accordion-content-height` variables + * control the height of Accordion content, while collapsible variables are used for Collapsibles. + * + * The fallback value `auto` is used here, but it depends on the `interpolate-size: allow-keywords` + * property, which currently has limited browser support. For more details, see: + * + */ + + --animate-accordion-down: accordion-down var(--tw-duration, 200ms) ease-out; + --animate-accordion-up: accordion-up var(--tw-duration, 200ms) ease-out; + --animate-collapsible-down: collapsible-down var(--tw-duration, 200ms) ease-out; + --animate-collapsible-up: collapsible-up var(--tw-duration, 200ms) ease-out; + + @keyframes accordion-down { + from { + height: 0; + } + to { + height: var(--radix-accordion-content-height, var(--bits-accordion-content-height, auto)); + } + } + + @keyframes accordion-up { + from { + height: var(--radix-accordion-content-height, var(--bits-accordion-content-height, auto)); + } + to { + height: 0; + } + } + + @keyframes collapsible-down { + from { + height: 0; + } + to { + height: var(--radix-collapsible-content-height, var(--bits-collapsible-content-height, auto)); + } + } + + @keyframes collapsible-up { + from { + height: var(--radix-collapsible-content-height, var(--bits-collapsible-content-height, auto)); + } + to { + height: 0; + } + } + + --animate-caret-blink: caret-blink 1.25s ease-out infinite; + + @keyframes caret-blink { + 0%, + 70%, + 100% { + opacity: 1; + } + 20%, + 50% { + opacity: 0; + } + } + } + + /* Utility classes */ + + /* + * Tailwind's default `duration` utility sets the `--tw-duration` variable, so + * can set `animation-duration` directly in the animation definition in the + * `@theme` section above. Same goes for the `animation-timing-function`, set + * with `--tw-ease`. + */ + + @utility delay-* { + animation-delay: calc(--value(number) * 1ms); + animation-delay: --value(--animation-delay- *, [duration], "initial", [ *]); + } + + @utility repeat-* { + animation-iteration-count: --value(--animation-repeat- *, number, "initial", [ *]); + } + + @utility direction-* { + animation-direction: --value(--animation-direction- *, "initial", [ *]); + } + + @utility fill-mode-* { + animation-fill-mode: --value(--animation-fill-mode- *, "initial", [ *]); + } + + @utility running { + animation-play-state: running; + } + @utility paused { + animation-play-state: paused; + } + @utility play-state-* { + animation-play-state: --value("initial", [ *]); + } + + @utility fade-in { + --tw-enter-opacity: 0; + } + @utility fade-in-* { + --tw-enter-opacity: calc(--value(number) / 100); + --tw-enter-opacity: --value(--percentage- *, [ *]); + } + + @utility fade-out { + --tw-exit-opacity: 0; + } + @utility fade-out-* { + --tw-exit-opacity: calc(--value(number) / 100); + --tw-exit-opacity: --value(--percentage- *, [ *]); + } + + @utility zoom-in { + --tw-enter-scale: 0; + } + @utility zoom-in-* { + --tw-enter-scale: calc(--value([percentage]) / 100%); + --tw-enter-scale: calc(--value([ratio], [number])); + --tw-enter-scale: --value(--percentage- *); + } + + @utility zoom-out { + --tw-exit-scale: 0; + } + @utility zoom-out-* { + --tw-exit-scale: calc(--value([percentage]) / 100%); + --tw-exit-scale: calc(--value([ratio], [number])); + --tw-exit-scale: --value(--percentage- *); + } + + @utility spin-in { + --tw-enter-rotate: 30deg; + } + @utility spin-in-* { + --tw-enter-rotate: calc(--value(number) * 1deg); + --tw-enter-rotate: --value(--rotate- *, [angle]); + } + + @utility spin-out { + --tw-exit-rotate: 30deg; + } + @utility spin-out-* { + --tw-exit-rotate: calc(--value(number) * 1deg); + --tw-exit-rotate: --value(--rotate- *, [angle]); + } + + @utility slide-in-from-top { + --tw-enter-translate-y: -100%; + } + @utility slide-in-from-top-* { + --tw-enter-translate-y: calc(--value(integer) * var(--spacing) * -1); + --tw-enter-translate-y: calc(--value(--percentage- *, --percentage-translate- *) * -100%); + --tw-enter-translate-y: calc(--value(ratio) * -100%); + --tw-enter-translate-y: calc(--value(--translate- *, [percentage], [length]) * -1); + } + @utility slide-in-from-bottom { + --tw-enter-translate-y: 100%; + } + @utility slide-in-from-bottom-* { + --tw-enter-translate-y: calc(--value(integer) * var(--spacing)); + --tw-enter-translate-y: calc(--value(--percentage- *, --percentage-translate- *) * 100%); + --tw-enter-translate-y: calc(--value(ratio) * 100%); + --tw-enter-translate-y: --value(--translate- *, [percentage], [length]); + } + @utility slide-in-from-left { + --tw-enter-translate-x: -100%; + } + @utility slide-in-from-left-* { + --tw-enter-translate-x: calc(--value(integer) * var(--spacing) * -1); + --tw-enter-translate-x: calc(--value(--percentage- *, --percentage-translate- *) * -100%); + --tw-enter-translate-x: calc(--value(ratio) * 100%); + --tw-enter-translate-x: calc(--value(--translate- *, [percentage], [length]) * -1); + } + @utility slide-in-from-right { + --tw-enter-translate-x: 100%; + } + @utility slide-in-from-right-* { + --tw-enter-translate-x: calc(--value(integer) * var(--spacing)); + --tw-enter-translate-x: calc(--value(--percentage- *, --percentage-translate- *) * 100%); + --tw-enter-translate-x: calc(--value(ratio) * 100%); + --tw-enter-translate-x: --value(--translate- *, [percentage], [length]); + } + + @utility slide-out-to-top { + --tw-exit-translate-y: -100%; + } + @utility slide-out-to-top-* { + --tw-exit-translate-y: calc(--value(integer) * var(--spacing) * -1); + --tw-exit-translate-y: calc(--value(--percentage- *, --percentage-translate- *) * -100%); + --tw-exit-translate-y: calc(--value(ratio) * 100%); + --tw-exit-translate-y: calc(--value(--translate- *, [percentage], [length]) * -1); + } + @utility slide-out-to-bottom { + --tw-exit-translate-y: 100%; + } + @utility slide-out-to-bottom-* { + --tw-exit-translate-y: calc(--value(integer) * var(--spacing)); + --tw-exit-translate-y: calc(--value(--percentage- *, --percentage-translate- *) * 100%); + --tw-exit-translate-y: calc(--value(ratio) * 100%); + --tw-exit-translate-y: --value(--translate- *, [percentage], [length]); + } + @utility slide-out-to-left { + --tw-exit-translate-x: -100%; + } + @utility slide-out-to-left-* { + --tw-exit-translate-x: calc(--value(integer) * var(--spacing) * -1); + --tw-exit-translate-x: calc(--value(--percentage- *, --percentage-translate- *) * -100%); + --tw-exit-translate-x: calc(--value(ratio) * 100%); + --tw-exit-translate-x: calc(--value(--translate- *, [percentage], [length]) * -1); + } + @utility slide-out-to-right { + --tw-exit-translate-x: 100%; + } + @utility slide-out-to-right-* { + --tw-exit-translate-x: calc(--value(integer) * var(--spacing)); + --tw-exit-translate-x: calc(--value(--percentage- *, --percentage-translate- *) * 100%); + --tw-exit-translate-x: calc(--value(ratio) * 100%); + --tw-exit-translate-x: --value(--translate- *, [percentage], [length]); + } \ No newline at end of file diff --git a/packages/onchainkit/src/styles/tailwind-base.css b/packages/onchainkit/src/styles/tailwind-base.css index d1d86809c0..e3999e98db 100644 --- a/packages/onchainkit/src/styles/tailwind-base.css +++ b/packages/onchainkit/src/styles/tailwind-base.css @@ -1,4 +1,25 @@ -@tailwind base; +@import 'tailwindcss'; +@custom-variant dark (&:where(.dark, .dark *)); +@source inline("dark"); +@source inline("font-sans"); + +@theme { + --font-sans: 'Inter', sans-serif; + --font-display: 'DM Sans', sans-serif; + --spacing-88: 22rem; + --spacing-120: 30rem; +} + +@layer utilities { + .scrollbar-hidden::-webkit-scrollbar { + display: none; + } + + .scrollbar-hidden { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE and Edge */ + } +} @layer base { :root, @@ -299,7 +320,9 @@ } } -@layer components { +@reference "./tailwind-animate-v4.css"; +@layer utilities { + .animate-enterRight { @apply animate-in slide-in-from-right-8 fade-in duration-500; } @@ -312,19 +335,3 @@ @apply animate-in slide-in-from-top-8 fade-in duration-500; } } - -@tailwind utilities; - -@layer utilities { - /* Chrome, Safari and Opera */ - .scrollbar-hidden::-webkit-scrollbar { - display: none; - } - - .scrollbar-hidden { - scrollbar-width: none; /* Firefox */ - -ms-overflow-style: none; /* IE and Edge */ - } -} - -@tailwind components; diff --git a/packages/onchainkit/tailwind.config.js b/packages/onchainkit/tailwind.config.js deleted file mode 100644 index 90a38743b1..0000000000 --- a/packages/onchainkit/tailwind.config.js +++ /dev/null @@ -1,24 +0,0 @@ -/** @type {import('tailwindcss').Config} */ - -import tailwindcssAnimate from 'tailwindcss-animate'; - -export default { - content: ['./src/**/*.{ts,tsx}'], - darkMode: ['class'], - safelist: ['dark'], - theme: { - fontFamily: { - sans: ['Inter', 'sans-serif'], - }, - extend: { - spacing: { - 88: '22rem', - 120: '30rem', - }, - fontFamily: { - display: 'DM Sans, sans-serif', - }, - }, - }, - plugins: [tailwindcssAnimate], -}; diff --git a/packages/playground/app/globals.css b/packages/playground/app/globals.css index fb60fe5d76..4ca043b3b8 100644 --- a/packages/playground/app/globals.css +++ b/packages/playground/app/globals.css @@ -1,63 +1,5 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 224 71.4% 4.1%; - --card: 0 0% 100%; - --card-foreground: 224 71.4% 4.1%; - --popover: 0 0% 100%; - --popover-foreground: 224 71.4% 4.1%; - --primary: 220.9 39.3% 11%; - --primary-foreground: 210 20% 98%; - --secondary: 220 14.3% 95.9%; - --secondary-foreground: 220.9 39.3% 11%; - --muted: 220 14.3% 95.9%; - --muted-foreground: 220 8.9% 46.1%; - --accent: 220 14.3% 95.9%; - --accent-foreground: 220.9 39.3% 11%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 20% 98%; - --border: 220 13% 91%; - --input: 220 13% 91%; - --ring: 224 71.4% 4.1%; - --radius: 0.5rem; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - } - - .dark { - --background: 224 71.4% 4.1%; - --foreground: 210 20% 98%; - --card: 224 71.4% 4.1%; - --card-foreground: 210 20% 98%; - --popover: 224 71.4% 4.1%; - --popover-foreground: 210 20% 98%; - --primary: 210 20% 98%; - --primary-foreground: 220.9 39.3% 11%; - --secondary: 215 27.9% 16.9%; - --secondary-foreground: 210 20% 98%; - --muted: 215 27.9% 16.9%; - --muted-foreground: 217.9 10.6% 64.9%; - --accent: 215 27.9% 16.9%; - --accent-foreground: 210 20% 98%; - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 20% 98%; - --border: 215 27.9% 16.9%; - --input: 215 27.9% 16.9%; - --ring: 216 12.2% 83.9%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - } -} +@import "tailwindcss"; +@custom-variant dark (&:where(.dark, .dark *)); /* Customize existing Theme */ @@ -75,7 +17,6 @@ /* } } */ - /* Create your own custom Theme*/ /* Usage: @@ -146,9 +87,116 @@ Usage: --ock-line-inverse: #e5e7eb; } +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +:root { + --radius: 0.625rem; + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); +} + @layer base { * { - @apply border-border; + @apply border-border outline-ring/50; } body { @apply bg-background text-foreground; diff --git a/packages/playground/app/minikit/components/snake.tsx b/packages/playground/app/minikit/components/snake.tsx index 3c069b26ce..fcc20c4e7e 100644 --- a/packages/playground/app/minikit/components/snake.tsx +++ b/packages/playground/app/minikit/components/snake.tsx @@ -1081,14 +1081,14 @@ const Sammy = () => { id="map" width={500} height={500} - className="absolute top-0 left-0 z-3" + className="absolute top-0 left-0 z-2" /> - + diff --git a/packages/playground/components/form/chain.tsx b/packages/playground/components/form/chain.tsx index 5072a81497..3a8f73ee7a 100644 --- a/packages/playground/components/form/chain.tsx +++ b/packages/playground/components/form/chain.tsx @@ -21,7 +21,7 @@ export function Chain() { value ? setChainId?.(Number.parseInt(value)) : value } > - + diff --git a/packages/playground/components/form/component-mode.tsx b/packages/playground/components/form/component-mode.tsx index 0a1323612a..7bfae07325 100644 --- a/packages/playground/components/form/component-mode.tsx +++ b/packages/playground/components/form/component-mode.tsx @@ -28,7 +28,7 @@ export function ComponentMode() { return setComponentMode(value); }} > - + diff --git a/packages/playground/components/form/component-theme.tsx b/packages/playground/components/form/component-theme.tsx index 38e2c02cdc..5c767d7134 100644 --- a/packages/playground/components/form/component-theme.tsx +++ b/packages/playground/components/form/component-theme.tsx @@ -29,7 +29,7 @@ export function ComponentTheme() { setComponentTheme(value); }} > - + diff --git a/packages/playground/components/ui/button.tsx b/packages/playground/components/ui/button.tsx index efff7f670c..28691b2c76 100644 --- a/packages/playground/components/ui/button.tsx +++ b/packages/playground/components/ui/button.tsx @@ -1,29 +1,31 @@ +import * as React from 'react'; import { Slot } from '@radix-ui/react-slot'; -import { type VariantProps, cva } from 'class-variance-authority'; -import { forwardRef } from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; import { cn } from '@/lib/utils'; const buttonVariants = cva( - 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { - default: 'bg-primary text-primary-foreground hover:bg-primary/90', + default: + 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90', destructive: - 'bg-destructive text-destructive-foreground hover:bg-destructive/90', + 'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', outline: - 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', + 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50', secondary: - 'bg-secondary text-secondary-foreground hover:bg-secondary/80', - ghost: 'hover:bg-accent hover:text-accent-foreground', + 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80', + ghost: + 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', link: 'text-primary underline-offset-4 hover:underline', }, size: { - default: 'h-10 px-4 py-2', - sm: 'h-9 rounded-md px-3', - lg: 'h-11 rounded-md px-8', - icon: 'h-10 w-10', + default: 'h-9 px-4 py-2 has-[>svg]:px-3', + sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5', + lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', + icon: 'size-9', }, }, defaultVariants: { @@ -33,24 +35,25 @@ const buttonVariants = cva( }, ); -export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean; -} +function Button({ + className, + variant, + size, + asChild = false, + ...props +}: React.ComponentProps<'button'> & + VariantProps & { + asChild?: boolean; + }) { + const Comp = asChild ? Slot : 'button'; -const Button = forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : 'button'; - return ( - - ); - }, -); -Button.displayName = 'Button'; + return ( + + ); +} export { Button, buttonVariants }; diff --git a/packages/playground/components/ui/dropdown-menu.tsx b/packages/playground/components/ui/dropdown-menu.tsx index d278af5291..26027549db 100644 --- a/packages/playground/components/ui/dropdown-menu.tsx +++ b/packages/playground/components/ui/dropdown-menu.tsx @@ -1,208 +1,257 @@ 'use client'; -import { - CheckboxItem, - Content, - Group, - Item, - ItemIndicator, - Label, - Portal, - RadioGroup, - RadioItem, - Root, - Separator, - Sub, - SubContent, - SubTrigger, - Trigger, -} from '@radix-ui/react-dropdown-menu'; -import { Check, ChevronRight, Circle } from 'lucide-react'; -import { forwardRef } from 'react'; +import * as React from 'react'; +import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; +import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react'; import { cn } from '@/lib/utils'; -const DropdownMenu = Root; -const DropdownMenuTrigger = Trigger; -const DropdownMenuGroup = Group; -const DropdownMenuPortal = Portal; -const DropdownMenuSub = Sub; -const DropdownMenuRadioGroup = RadioGroup; - -const DropdownMenuSubTrigger = forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean; - } ->(({ className, inset, children, ...props }, ref) => ( - - {children} - - -)); -DropdownMenuSubTrigger.displayName = SubTrigger.displayName; - -const DropdownMenuSubContent = forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); -DropdownMenuSubContent.displayName = SubContent.displayName; - -const DropdownMenuContent = forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, sideOffset = 4, ...props }, ref) => ( - - ) { + return ; +} + +function DropdownMenuPortal({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuContent({ + className, + sideOffset = 4, + ...props +}: React.ComponentProps) { + return ( + + + + ); +} + +function DropdownMenuGroup({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuItem({ + className, + inset, + variant = 'default', + ...props +}: React.ComponentProps & { + inset?: boolean; + variant?: 'default' | 'destructive'; +}) { + return ( + + ); +} + +function DropdownMenuCheckboxItem({ + className, + children, + checked, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ); +} + +function DropdownMenuRadioGroup({ + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function DropdownMenuRadioItem({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ); +} + +function DropdownMenuLabel({ + className, + inset, + ...props +}: React.ComponentProps & { + inset?: boolean; +}) { + return ( + - -)); -DropdownMenuContent.displayName = Content.displayName; - -const DropdownMenuItem = forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean; - } ->(({ className, inset, ...props }, ref) => ( - -)); -DropdownMenuItem.displayName = Item.displayName; - -const DropdownMenuCheckboxItem = forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, checked, ...props }, ref) => ( - - - - - - - {children} - -)); -DropdownMenuCheckboxItem.displayName = CheckboxItem.displayName; - -const DropdownMenuRadioItem = forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)); -DropdownMenuRadioItem.displayName = RadioItem.displayName; - -const DropdownMenuLabel = forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean; - } ->(({ className, inset, ...props }, ref) => ( -