diff --git a/.changeset/silent-parrots-carry.md b/.changeset/silent-parrots-carry.md new file mode 100644 index 0000000000..a61bf76c0a --- /dev/null +++ b/.changeset/silent-parrots-carry.md @@ -0,0 +1,5 @@ +--- +'@penumbra-zone/ui': major +--- + +Refactor UI package from css-in-js to Tailwind diff --git a/apps/minifront/package.json b/apps/minifront/package.json index d3ab103531..27042606a6 100644 --- a/apps/minifront/package.json +++ b/apps/minifront/package.json @@ -31,7 +31,7 @@ "@penumbra-zone/protobuf": "workspace:*", "@penumbra-zone/transport-dom": "workspace:*", "@penumbra-zone/types": "workspace:*", - "@penumbra-zone/ui": "workspace:*", + "@penumbra-zone/ui-deprecated": "workspace:*", "@penumbra-zone/zquery": "workspace:*", "@radix-ui/react-dialog": "1.0.5", "@radix-ui/react-icons": "^1.3.0", @@ -66,6 +66,7 @@ "@types/react": "^18.3.2", "@types/react-dom": "^18.3.0", "@types/react-helmet": "^6.1.11", + "vite": "^5.2.11", "vitest": "^1.6.0" } } diff --git a/apps/minifront/postcss.config.js b/apps/minifront/postcss.config.js index 8e18cdcb77..2bdefa943e 100644 --- a/apps/minifront/postcss.config.js +++ b/apps/minifront/postcss.config.js @@ -1 +1 @@ -export { default } from '@penumbra-zone/ui/postcss.config.js'; +export { default } from '@penumbra-zone/ui-deprecated/postcss.config.js'; diff --git a/apps/minifront/src/components/dashboard/assets-table/equivalent-values.tsx b/apps/minifront/src/components/dashboard/assets-table/equivalent-values.tsx index 994efe2cd2..d47c939c9a 100644 --- a/apps/minifront/src/components/dashboard/assets-table/equivalent-values.tsx +++ b/apps/minifront/src/components/dashboard/assets-table/equivalent-values.tsx @@ -1,7 +1,7 @@ import { ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { asValueView } from '@penumbra-zone/getters/equivalent-value'; import { getDisplayDenomFromView, getEquivalentValues } from '@penumbra-zone/getters/value-view'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; export const EquivalentValues = ({ valueView }: { valueView?: ValueView }) => { const equivalentValuesAsValueViews = (getEquivalentValues.optional(valueView) ?? []).map( diff --git a/apps/minifront/src/components/dashboard/assets-table/index.tsx b/apps/minifront/src/components/dashboard/assets-table/index.tsx index a803a7ff42..76066f82da 100644 --- a/apps/minifront/src/components/dashboard/assets-table/index.tsx +++ b/apps/minifront/src/components/dashboard/assets-table/index.tsx @@ -1,6 +1,6 @@ import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; -import { AddressComponent, AddressIcon } from '@penumbra-zone/ui/components/ui/address'; -import { Button } from '@penumbra-zone/ui/components/ui/button'; +import { AddressComponent, AddressIcon } from '@penumbra-zone/ui-deprecated/components/ui/address'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; import { Table, TableBody, @@ -8,8 +8,8 @@ import { TableHead, TableHeader, TableRow, -} from '@penumbra-zone/ui/components/ui/table'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +} from '@penumbra-zone/ui-deprecated/components/ui/table'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; import { EquivalentValues } from './equivalent-values'; import { Fragment } from 'react'; import { PagePath } from '../../metadata/paths'; @@ -21,7 +21,7 @@ import { AbridgedZQueryState } from '@penumbra-zone/zquery/src/types'; import { shouldDisplay } from '../../../fetchers/balances/should-display'; import { sortByPriorityScore } from '../../../fetchers/balances/by-priority-score'; import { LineWave } from 'react-loader-spinner'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; const getTradeLink = (balance: BalancesResponse): string => { const metadata = getMetadataFromBalancesResponse.optional(balance); diff --git a/apps/minifront/src/components/dashboard/layout.tsx b/apps/minifront/src/components/dashboard/layout.tsx index 75be0a7667..5a9fef8e32 100644 --- a/apps/minifront/src/components/dashboard/layout.tsx +++ b/apps/minifront/src/components/dashboard/layout.tsx @@ -1,4 +1,4 @@ -import { Card } from '@penumbra-zone/ui/components/ui/card'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; import { dashboardTabs, dashboardTabsHelper } from './constants'; import { Outlet } from 'react-router-dom'; import { EduInfoCard } from '../shared/edu-panels/edu-info-card'; diff --git a/apps/minifront/src/components/dashboard/transaction-table.tsx b/apps/minifront/src/components/dashboard/transaction-table.tsx index 2853129fc2..e537dbf661 100644 --- a/apps/minifront/src/components/dashboard/transaction-table.tsx +++ b/apps/minifront/src/components/dashboard/transaction-table.tsx @@ -5,7 +5,7 @@ import { TableHead, TableHeader, TableRow, -} from '@penumbra-zone/ui/components/ui/table'; +} from '@penumbra-zone/ui-deprecated/components/ui/table'; import { Link } from 'react-router-dom'; import { shorten } from '@penumbra-zone/types/string'; import { memo } from 'react'; diff --git a/apps/minifront/src/components/extension-not-connected.tsx b/apps/minifront/src/components/extension-not-connected.tsx index 5882d69790..02b59cb260 100644 --- a/apps/minifront/src/components/extension-not-connected.tsx +++ b/apps/minifront/src/components/extension-not-connected.tsx @@ -1,11 +1,11 @@ import { useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useNavigate } from 'react-router-dom'; -import { Dialog } from '@penumbra-zone/ui/Dialog'; -import { Button } from '@penumbra-zone/ui/components/ui/button'; -import { Toaster } from '@penumbra-zone/ui/components/ui/toaster'; -import { SplashPage } from '@penumbra-zone/ui/components/ui/splash-page'; -import { errorToast, warningToast } from '@penumbra-zone/ui/lib/toast/presets'; +import { Dialog } from '@penumbra-zone/ui-deprecated/Dialog'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; +import { Toaster } from '@penumbra-zone/ui-deprecated/components/ui/toaster'; +import { SplashPage } from '@penumbra-zone/ui-deprecated/components/ui/splash-page'; +import { errorToast, warningToast } from '@penumbra-zone/ui-deprecated/lib/toast/presets'; import { PenumbraClient, PenumbraManifest, diff --git a/apps/minifront/src/components/extension-not-installed.tsx b/apps/minifront/src/components/extension-not-installed.tsx index efb91e725d..21ba60d40f 100644 --- a/apps/minifront/src/components/extension-not-installed.tsx +++ b/apps/minifront/src/components/extension-not-installed.tsx @@ -1,5 +1,5 @@ -import { Button } from '@penumbra-zone/ui/components/ui/button'; -import { SplashPage } from '@penumbra-zone/ui/components/ui/splash-page'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; +import { SplashPage } from '@penumbra-zone/ui-deprecated/components/ui/splash-page'; import { HeadTag } from './metadata/head-tag'; const CHROME_EXTENSION_ID = 'lkpmkhpnhknhmibgnmmhdhgdilepfghe'; diff --git a/apps/minifront/src/components/extension-transport-disconnected.tsx b/apps/minifront/src/components/extension-transport-disconnected.tsx index 62abfab944..99043cbaaf 100644 --- a/apps/minifront/src/components/extension-transport-disconnected.tsx +++ b/apps/minifront/src/components/extension-transport-disconnected.tsx @@ -1,6 +1,6 @@ -import { SplashPage } from '@penumbra-zone/ui/components/ui/splash-page'; +import { SplashPage } from '@penumbra-zone/ui-deprecated/components/ui/splash-page'; import { HeadTag } from './metadata/head-tag'; -import { Button } from '@penumbra-zone/ui/components/ui/button'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; export const ExtensionTransportDisconnected = () => { return ( diff --git a/apps/minifront/src/components/header/header.tsx b/apps/minifront/src/components/header/header.tsx index efe4411744..6a392d904d 100644 --- a/apps/minifront/src/components/header/header.tsx +++ b/apps/minifront/src/components/header/header.tsx @@ -1,6 +1,6 @@ -import { CondensedBlockSyncStatus } from '@penumbra-zone/ui/components/ui/block-sync-status'; -import { IncompatibleBrowserBanner } from '@penumbra-zone/ui/components/ui/incompatible-browser-banner'; -import { TestnetBanner } from '@penumbra-zone/ui/components/ui/testnet-banner'; +import { CondensedBlockSyncStatus } from '@penumbra-zone/ui-deprecated/components/ui/block-sync-status'; +import { IncompatibleBrowserBanner } from '@penumbra-zone/ui-deprecated/components/ui/incompatible-browser-banner'; +import { TestnetBanner } from '@penumbra-zone/ui-deprecated/components/ui/testnet-banner'; import { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; import { getChainId } from '../../fetchers/chain-id'; diff --git a/apps/minifront/src/components/header/menu/desktop-nav.tsx b/apps/minifront/src/components/header/menu/desktop-nav.tsx index 546bdc607d..90f989195f 100644 --- a/apps/minifront/src/components/header/menu/desktop-nav.tsx +++ b/apps/minifront/src/components/header/menu/desktop-nav.tsx @@ -1,4 +1,4 @@ -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; import * as NavigationMenu from '@radix-ui/react-navigation-menu'; import { usePagePath } from '../../../fetchers/page-path'; import { dashboardLink, headerLinks } from '../constants'; diff --git a/apps/minifront/src/components/header/menu/menu.tsx b/apps/minifront/src/components/header/menu/menu.tsx index 64d2d62dc1..b0142f1a91 100644 --- a/apps/minifront/src/components/header/menu/menu.tsx +++ b/apps/minifront/src/components/header/menu/menu.tsx @@ -1,4 +1,4 @@ -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; import { DesktopNav } from './desktop-nav'; import { MobileNav } from './mobile-nav'; import { ProviderMenu } from './provider'; diff --git a/apps/minifront/src/components/header/menu/mobile-nav.tsx b/apps/minifront/src/components/header/menu/mobile-nav.tsx index 4f41ce40f2..74c8e8f18b 100644 --- a/apps/minifront/src/components/header/menu/mobile-nav.tsx +++ b/apps/minifront/src/components/header/menu/mobile-nav.tsx @@ -3,7 +3,7 @@ import { SheetContent, SheetHeader, SheetTrigger, -} from '@penumbra-zone/ui/components/ui/sheet'; +} from '@penumbra-zone/ui-deprecated/components/ui/sheet'; import { HamburgerMenuIcon } from '@radix-ui/react-icons'; import { headerLinks } from '../constants'; import { Link } from 'react-router-dom'; diff --git a/apps/minifront/src/components/header/menu/provider.tsx b/apps/minifront/src/components/header/menu/provider.tsx index 5244950e35..ef82caa262 100644 --- a/apps/minifront/src/components/header/menu/provider.tsx +++ b/apps/minifront/src/components/header/menu/provider.tsx @@ -1,4 +1,4 @@ -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; import * as NavigationMenu from '@radix-ui/react-navigation-menu'; import { getChainId } from '../../../fetchers/chain-id'; import { useEffect, useState } from 'react'; diff --git a/apps/minifront/src/components/header/menu/tablet-nav.tsx b/apps/minifront/src/components/header/menu/tablet-nav.tsx index a812c9fadf..42695c749a 100644 --- a/apps/minifront/src/components/header/menu/tablet-nav.tsx +++ b/apps/minifront/src/components/header/menu/tablet-nav.tsx @@ -1,4 +1,4 @@ -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; import * as NavigationMenu from '@radix-ui/react-navigation-menu'; import { usePagePath } from '../../../fetchers/page-path'; import { dashboardLink, headerLinks } from '../constants'; diff --git a/apps/minifront/src/components/ibc/ibc-in/assets-table.tsx b/apps/minifront/src/components/ibc/ibc-in/assets-table.tsx index ac6392df9d..c5b59b8190 100644 --- a/apps/minifront/src/components/ibc/ibc-in/assets-table.tsx +++ b/apps/minifront/src/components/ibc/ibc-in/assets-table.tsx @@ -8,9 +8,9 @@ import { TableHead, TableHeader, TableRow, -} from '@penumbra-zone/ui/components/ui/table'; -import { Avatar, AvatarImage } from '@penumbra-zone/ui/components/ui/avatar'; -import { Identicon } from '@penumbra-zone/ui/components/ui/identicon'; +} from '@penumbra-zone/ui-deprecated/components/ui/table'; +import { Avatar, AvatarImage } from '@penumbra-zone/ui-deprecated/components/ui/avatar'; +import { Identicon } from '@penumbra-zone/ui-deprecated/components/ui/identicon'; import { LineWave } from 'react-loader-spinner'; import { getIconWithUmFallback } from './asset-utils.tsx'; diff --git a/apps/minifront/src/components/ibc/ibc-in/chain-dropdown.tsx b/apps/minifront/src/components/ibc/ibc-in/chain-dropdown.tsx index 889dc31587..0edfb05114 100644 --- a/apps/minifront/src/components/ibc/ibc-in/chain-dropdown.tsx +++ b/apps/minifront/src/components/ibc/ibc-in/chain-dropdown.tsx @@ -1,7 +1,11 @@ import * as React from 'react'; import { useMemo } from 'react'; import { useManager } from '@cosmos-kit/react'; -import { Popover, PopoverContent, PopoverTrigger } from '@penumbra-zone/ui/components/ui/popover'; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from '@penumbra-zone/ui-deprecated/components/ui/popover'; import { ChevronsUpDown } from 'lucide-react'; import { Command, @@ -9,12 +13,12 @@ import { CommandGroup, CommandInput, CommandItem, -} from '@penumbra-zone/ui/components/ui/command'; -import { Button } from '@penumbra-zone/ui/components/ui/button'; +} from '@penumbra-zone/ui-deprecated/components/ui/command'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; import { ibcInSelector } from '../../../state/ibc-in'; import { useStore } from '../../../state'; -import { Avatar, AvatarImage } from '@penumbra-zone/ui/components/ui/avatar'; -import { Identicon } from '@penumbra-zone/ui/components/ui/identicon'; +import { Avatar, AvatarImage } from '@penumbra-zone/ui-deprecated/components/ui/avatar'; +import { Identicon } from '@penumbra-zone/ui-deprecated/components/ui/identicon'; export interface ChainInfo { chainName: string; diff --git a/apps/minifront/src/components/ibc/ibc-in/destination-addr.tsx b/apps/minifront/src/components/ibc/ibc-in/destination-addr.tsx index e365c8eda4..148020e2e5 100644 --- a/apps/minifront/src/components/ibc/ibc-in/destination-addr.tsx +++ b/apps/minifront/src/components/ibc/ibc-in/destination-addr.tsx @@ -1,7 +1,7 @@ import { AllSlices } from '../../../state'; import { useStoreShallow } from '../../../utils/use-store-shallow'; -import { AccountSwitcher } from '@penumbra-zone/ui/components/ui/account-switcher'; -import { CopyToClipboard } from '@penumbra-zone/ui/components/ui/copy-to-clipboard'; +import { AccountSwitcher } from '@penumbra-zone/ui-deprecated/components/ui/account-switcher'; +import { CopyToClipboard } from '@penumbra-zone/ui-deprecated/components/ui/copy-to-clipboard'; import { useEffect } from 'react'; const addrsSelector = ({ ibcIn }: AllSlices) => ({ diff --git a/apps/minifront/src/components/ibc/ibc-in/ibc-in-request.tsx b/apps/minifront/src/components/ibc/ibc-in/ibc-in-request.tsx index aef1ba0d0b..624c9b7ebd 100644 --- a/apps/minifront/src/components/ibc/ibc-in/ibc-in-request.tsx +++ b/apps/minifront/src/components/ibc/ibc-in/ibc-in-request.tsx @@ -7,11 +7,11 @@ import { SelectItem, SelectTrigger, SelectValue, -} from '@penumbra-zone/ui/components/ui/select'; -import { Avatar, AvatarImage } from '@penumbra-zone/ui/components/ui/avatar'; -import { Identicon } from '@penumbra-zone/ui/components/ui/identicon'; +} from '@penumbra-zone/ui-deprecated/components/ui/select'; +import { Avatar, AvatarImage } from '@penumbra-zone/ui-deprecated/components/ui/avatar'; +import { Identicon } from '@penumbra-zone/ui-deprecated/components/ui/identicon'; import { DestinationAddr } from './destination-addr'; -import { Button } from '@penumbra-zone/ui/components/ui/button'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; import { LockClosedIcon } from '@radix-ui/react-icons'; import { NumberInput } from '../../shared/number-input'; import { getIconWithUmFallback } from './asset-utils.tsx'; diff --git a/apps/minifront/src/components/ibc/ibc-in/wallet-addr-card.tsx b/apps/minifront/src/components/ibc/ibc-in/wallet-addr-card.tsx index 3c34414c6e..72f05e7114 100644 --- a/apps/minifront/src/components/ibc/ibc-in/wallet-addr-card.tsx +++ b/apps/minifront/src/components/ibc/ibc-in/wallet-addr-card.tsx @@ -1,4 +1,4 @@ -import { Identicon } from '@penumbra-zone/ui/components/ui/identicon'; +import { Identicon } from '@penumbra-zone/ui-deprecated/components/ui/identicon'; interface UserInfoProps { address: string; diff --git a/apps/minifront/src/components/ibc/ibc-in/wallet-connect-button.tsx b/apps/minifront/src/components/ibc/ibc-in/wallet-connect-button.tsx index 89b0b1fb26..6af0511d2a 100644 --- a/apps/minifront/src/components/ibc/ibc-in/wallet-connect-button.tsx +++ b/apps/minifront/src/components/ibc/ibc-in/wallet-connect-button.tsx @@ -1,11 +1,11 @@ import { WalletStatus } from 'cosmos-kit'; -import { WalletIcon } from '@penumbra-zone/ui/components/ui/icons/wallet'; +import { WalletIcon } from '@penumbra-zone/ui-deprecated/components/ui/icons/wallet'; import { MouseEventHandler } from 'react'; import { useStore } from '../../../state'; import { ibcInSelector } from '../../../state/ibc-in'; import { useChainConnector } from './hooks'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; export const ConnectWalletButton = () => { const { connect, openView, status } = useChainConnector(); diff --git a/apps/minifront/src/components/ibc/ibc-out/chain-selector.tsx b/apps/minifront/src/components/ibc/ibc-out/chain-selector.tsx index 5b75ff3937..a031a4c646 100644 --- a/apps/minifront/src/components/ibc/ibc-out/chain-selector.tsx +++ b/apps/minifront/src/components/ibc/ibc-out/chain-selector.tsx @@ -4,8 +4,8 @@ import { SelectItem, SelectTrigger, SelectValue, -} from '@penumbra-zone/ui/components/ui/select'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +} from '@penumbra-zone/ui-deprecated/components/ui/select'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; import { AllSlices } from '../../../state'; import { Chain } from '@penumbra-labs/registry'; import { useStoreShallow } from '../../../utils/use-store-shallow'; diff --git a/apps/minifront/src/components/ibc/ibc-out/ibc-out-form.tsx b/apps/minifront/src/components/ibc/ibc-out/ibc-out-form.tsx index a66e359faa..e9cef8aa39 100644 --- a/apps/minifront/src/components/ibc/ibc-out/ibc-out-form.tsx +++ b/apps/minifront/src/components/ibc/ibc-out/ibc-out-form.tsx @@ -1,5 +1,5 @@ -import { Button } from '@penumbra-zone/ui/components/ui/button'; -import { Input } from '@penumbra-zone/ui/components/ui/input'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; +import { Input } from '@penumbra-zone/ui-deprecated/components/ui/input'; import { ChainSelector } from './chain-selector'; import { useStore } from '../../../state'; import { diff --git a/apps/minifront/src/components/ibc/layout.tsx b/apps/minifront/src/components/ibc/layout.tsx index 06c0bfb385..fee64a9a56 100644 --- a/apps/minifront/src/components/ibc/layout.tsx +++ b/apps/minifront/src/components/ibc/layout.tsx @@ -1,4 +1,4 @@ -import { Card } from '@penumbra-zone/ui/components/ui/card'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; import { IbcOutForm } from './ibc-out/ibc-out-form'; import { InterchainUi } from './ibc-in/interchain-ui'; import { LongArrowIcon } from './long-arrow'; diff --git a/apps/minifront/src/components/layout.tsx b/apps/minifront/src/components/layout.tsx index 9f3fcc79c9..063cb1be10 100644 --- a/apps/minifront/src/components/layout.tsx +++ b/apps/minifront/src/components/layout.tsx @@ -1,10 +1,10 @@ import { Outlet } from 'react-router-dom'; import { HeadTag } from './metadata/head-tag'; import { Header } from './header/header'; -import { Toaster } from '@penumbra-zone/ui/components/ui/toaster'; +import { Toaster } from '@penumbra-zone/ui-deprecated/components/ui/toaster'; import { Footer } from './footer/footer'; import { SyncingDialog } from './syncing-dialog'; -import '@penumbra-zone/ui/styles/globals.css'; +import '@penumbra-zone/ui-deprecated/styles/globals.css'; export const Layout = () => { return ( diff --git a/apps/minifront/src/components/not-found.tsx b/apps/minifront/src/components/not-found.tsx index e15f3e3e57..383bc1dd12 100644 --- a/apps/minifront/src/components/not-found.tsx +++ b/apps/minifront/src/components/not-found.tsx @@ -1,4 +1,4 @@ -import { SplashPage } from '@penumbra-zone/ui/components/ui/splash-page'; +import { SplashPage } from '@penumbra-zone/ui-deprecated/components/ui/splash-page'; export const NotFound = () => { return That page could not be found. ; diff --git a/apps/minifront/src/components/send/layout.tsx b/apps/minifront/src/components/send/layout.tsx index 56f99ef69a..4137dd96d9 100644 --- a/apps/minifront/src/components/send/layout.tsx +++ b/apps/minifront/src/components/send/layout.tsx @@ -1,4 +1,4 @@ -import { Card } from '@penumbra-zone/ui/components/ui/card'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; import { sendTabs, sendTabsHelper } from './constants'; import { SendTab } from './types'; import { usePagePath } from '../../fetchers/page-path'; diff --git a/apps/minifront/src/components/send/receive.tsx b/apps/minifront/src/components/send/receive.tsx index f4723d8dce..a83377d310 100644 --- a/apps/minifront/src/components/send/receive.tsx +++ b/apps/minifront/src/components/send/receive.tsx @@ -1,4 +1,4 @@ -import { SelectAccount } from '@penumbra-zone/ui/components/ui/select'; +import { SelectAccount } from '@penumbra-zone/ui-deprecated/components/ui/select'; import { getAddrByIndex } from '../../fetchers/address'; export const Receive = () => { diff --git a/apps/minifront/src/components/send/send-form/index.tsx b/apps/minifront/src/components/send/send-form/index.tsx index ec3ce2fa26..1a6e40d06d 100644 --- a/apps/minifront/src/components/send/send-form/index.tsx +++ b/apps/minifront/src/components/send/send-form/index.tsx @@ -1,5 +1,5 @@ -import { Button } from '@penumbra-zone/ui/components/ui/button'; -import { Input } from '@penumbra-zone/ui/components/ui/input'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; +import { Input } from '@penumbra-zone/ui-deprecated/components/ui/input'; import { useStore } from '../../../state'; import { sendSelector, sendValidationErrors } from '../../../state/send'; import { InputBlock } from '../../shared/input-block'; diff --git a/apps/minifront/src/components/shared/edu-panels/edu-info-card.tsx b/apps/minifront/src/components/shared/edu-panels/edu-info-card.tsx index 74204548fc..8d2c6dd159 100644 --- a/apps/minifront/src/components/shared/edu-panels/edu-info-card.tsx +++ b/apps/minifront/src/components/shared/edu-panels/edu-info-card.tsx @@ -1,6 +1,6 @@ -import { Card } from '@penumbra-zone/ui/components/ui/card'; -import { cn } from '@penumbra-zone/ui/lib/utils'; -import { GradientHeader } from '@penumbra-zone/ui/components/ui/gradient-header'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; +import { GradientHeader } from '@penumbra-zone/ui-deprecated/components/ui/gradient-header'; import { EduPanel, eduPanelContent } from './content'; import { motion } from 'framer-motion'; diff --git a/apps/minifront/src/components/shared/error-boundary.tsx b/apps/minifront/src/components/shared/error-boundary.tsx index dac1007ba9..fc2a3bae98 100644 --- a/apps/minifront/src/components/shared/error-boundary.tsx +++ b/apps/minifront/src/components/shared/error-boundary.tsx @@ -4,7 +4,7 @@ import { PenumbraNotInstalledError, PenumbraProviderNotConnectedError, } from '@penumbra-zone/client'; -import { SplashPage } from '@penumbra-zone/ui/components/ui/splash-page'; +import { SplashPage } from '@penumbra-zone/ui-deprecated/components/ui/splash-page'; import { NotFound } from '../not-found'; import { ExtensionTransportDisconnected } from '../extension-transport-disconnected'; import { ExtensionNotInstalled } from '../extension-not-installed'; diff --git a/apps/minifront/src/components/shared/gas-fee.tsx b/apps/minifront/src/components/shared/gas-fee.tsx index a34dfebd9b..6191671355 100644 --- a/apps/minifront/src/components/shared/gas-fee.tsx +++ b/apps/minifront/src/components/shared/gas-fee.tsx @@ -2,9 +2,9 @@ import { Fee, FeeTier_Tier } from '@penumbra-zone/protobuf/penumbra/core/compone import { SegmentedPicker, SegmentedPickerOption, -} from '@penumbra-zone/ui/components/ui/segmented-picker'; +} from '@penumbra-zone/ui-deprecated/components/ui/segmented-picker'; import { InputBlock } from './input-block'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; import { Metadata, ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; const FEE_TIER_OPTIONS: SegmentedPickerOption[] = [ diff --git a/apps/minifront/src/components/shared/input-block.tsx b/apps/minifront/src/components/shared/input-block.tsx index 2061f7add5..4538d37628 100644 --- a/apps/minifront/src/components/shared/input-block.tsx +++ b/apps/minifront/src/components/shared/input-block.tsx @@ -1,7 +1,7 @@ -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; import { Validation, validationResult } from './validation-result'; import { ReactNode } from 'react'; -import { Box } from '@penumbra-zone/ui/components/ui/box'; +import { Box } from '@penumbra-zone/ui-deprecated/components/ui/box'; interface InputBlockProps { label: string; diff --git a/apps/minifront/src/components/shared/input-token.tsx b/apps/minifront/src/components/shared/input-token.tsx index a20659b195..f42484ed71 100644 --- a/apps/minifront/src/components/shared/input-token.tsx +++ b/apps/minifront/src/components/shared/input-token.tsx @@ -1,6 +1,6 @@ import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; -import { BalanceValueView } from '@penumbra-zone/ui/components/ui/balance-value-view'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { BalanceValueView } from '@penumbra-zone/ui-deprecated/components/ui/balance-value-view'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; import BalanceSelector from './selectors/balance-selector'; import { Validation } from './validation-result'; import { InputBlock } from './input-block'; diff --git a/apps/minifront/src/components/shared/number-input/index.tsx b/apps/minifront/src/components/shared/number-input/index.tsx index ac1c591374..b40ed18660 100644 --- a/apps/minifront/src/components/shared/number-input/index.tsx +++ b/apps/minifront/src/components/shared/number-input/index.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import { Input, InputProps } from '@penumbra-zone/ui/components/ui/input'; +import { Input, InputProps } from '@penumbra-zone/ui-deprecated/components/ui/input'; import { useWheelPrevent } from './use-wheel-prevent'; export const NumberInput: FC = props => { diff --git a/apps/minifront/src/components/shared/selectors/asset-selector.tsx b/apps/minifront/src/components/shared/selectors/asset-selector.tsx index a3a3549d40..fb28335064 100644 --- a/apps/minifront/src/components/shared/selectors/asset-selector.tsx +++ b/apps/minifront/src/components/shared/selectors/asset-selector.tsx @@ -3,19 +3,24 @@ import { DialogClose, DialogContent, DialogHeader, -} from '@penumbra-zone/ui/components/ui/dialog'; -import { AssetIcon } from '@penumbra-zone/ui/components/ui/asset-icon'; +} from '@penumbra-zone/ui-deprecated/components/ui/dialog'; +import { AssetIcon } from '@penumbra-zone/ui-deprecated/components/ui/asset-icon'; import { Metadata, ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; import { useCallback, useEffect, useId, useMemo, useState } from 'react'; -import { IconInput } from '@penumbra-zone/ui/components/ui/icon-input'; +import { IconInput } from '@penumbra-zone/ui-deprecated/components/ui/icon-input'; import { MagnifyingGlassIcon } from '@radix-ui/react-icons'; -import { Box } from '@penumbra-zone/ui/components/ui/box'; +import { Box } from '@penumbra-zone/ui-deprecated/components/ui/box'; import { motion } from 'framer-motion'; import { metadataBySearch } from './search-filters'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; import { LoadingIndicator } from './loading-indicator'; -import { Table, TableBody, TableCell, TableRow } from '@penumbra-zone/ui/components/ui/table'; +import { + Table, + TableBody, + TableCell, + TableRow, +} from '@penumbra-zone/ui-deprecated/components/ui/table'; interface AssetSelectorProps { assets: Metadata[]; diff --git a/apps/minifront/src/components/shared/selectors/balance-item.tsx b/apps/minifront/src/components/shared/selectors/balance-item.tsx index d68f3ef6b1..f8a4e5f95a 100644 --- a/apps/minifront/src/components/shared/selectors/balance-item.tsx +++ b/apps/minifront/src/components/shared/selectors/balance-item.tsx @@ -2,11 +2,11 @@ import { BalanceOrMetadata, isBalance, isMetadata } from './helpers'; import { getAddressIndex } from '@penumbra-zone/getters/address-view'; import { getMetadataFromBalancesResponse } from '@penumbra-zone/getters/balances-response'; import { useMemo } from 'react'; -import { DialogClose } from '@penumbra-zone/ui/components/ui/dialog'; -import { cn } from '@penumbra-zone/ui/lib/utils'; -import { AssetIcon } from '@penumbra-zone/ui/components/ui/asset-icon'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; -import { TableCell, TableRow } from '@penumbra-zone/ui/components/ui/table'; +import { DialogClose } from '@penumbra-zone/ui-deprecated/components/ui/dialog'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; +import { AssetIcon } from '@penumbra-zone/ui-deprecated/components/ui/asset-icon'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; +import { TableCell, TableRow } from '@penumbra-zone/ui-deprecated/components/ui/table'; import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; interface BalanceItemProps { diff --git a/apps/minifront/src/components/shared/selectors/balance-selector.tsx b/apps/minifront/src/components/shared/selectors/balance-selector.tsx index ac03176f43..845d1618f6 100644 --- a/apps/minifront/src/components/shared/selectors/balance-selector.tsx +++ b/apps/minifront/src/components/shared/selectors/balance-selector.tsx @@ -1,10 +1,14 @@ import { MagnifyingGlassIcon } from '@radix-ui/react-icons'; import { useId, useState } from 'react'; -import { IconInput } from '@penumbra-zone/ui/components/ui/icon-input'; -import { Dialog, DialogContent, DialogHeader } from '@penumbra-zone/ui/components/ui/dialog'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +import { IconInput } from '@penumbra-zone/ui-deprecated/components/ui/icon-input'; +import { + Dialog, + DialogContent, + DialogHeader, +} from '@penumbra-zone/ui-deprecated/components/ui/dialog'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; -import { Box } from '@penumbra-zone/ui/components/ui/box'; +import { Box } from '@penumbra-zone/ui-deprecated/components/ui/box'; import { motion } from 'framer-motion'; import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { emptyBalanceResponse } from '../../../utils/empty-balance-response'; @@ -16,7 +20,7 @@ import { useSyncSelectedBalance, } from './helpers'; import { BalanceItem } from './balance-item'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; import { LoadingIndicator } from './loading-indicator'; import { Table, @@ -24,7 +28,7 @@ import { TableHead, TableHeader, TableRow, -} from '@penumbra-zone/ui/components/ui/table'; +} from '@penumbra-zone/ui-deprecated/components/ui/table'; interface BalanceSelectorProps { value: BalancesResponse | undefined; diff --git a/apps/minifront/src/components/shared/tabs.tsx b/apps/minifront/src/components/shared/tabs.tsx index 2a0488bf2f..3804684d3a 100644 --- a/apps/minifront/src/components/shared/tabs.tsx +++ b/apps/minifront/src/components/shared/tabs.tsx @@ -1,6 +1,6 @@ import { PagePath } from '../metadata/paths'; import { useNavigate } from 'react-router-dom'; -import { SegmentedPicker } from '@penumbra-zone/ui/components/ui/segmented-picker'; +import { SegmentedPicker } from '@penumbra-zone/ui-deprecated/components/ui/segmented-picker'; import { ComponentProps } from 'react'; export interface Tab { diff --git a/apps/minifront/src/components/staking/account/delegation-value-view/index.tsx b/apps/minifront/src/components/staking/account/delegation-value-view/index.tsx index 4d3b61027a..b14e23b032 100644 --- a/apps/minifront/src/components/staking/account/delegation-value-view/index.tsx +++ b/apps/minifront/src/components/staking/account/delegation-value-view/index.tsx @@ -1,6 +1,6 @@ import { ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { ValidatorInfoComponent } from './validator-info-component'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; import { StakingActions } from './staking-actions'; import { memo, useMemo } from 'react'; import { diff --git a/apps/minifront/src/components/staking/account/delegation-value-view/staking-actions/form-dialog.tsx b/apps/minifront/src/components/staking/account/delegation-value-view/staking-actions/form-dialog.tsx index 0c5f9f6537..b7e5fd5f6b 100644 --- a/apps/minifront/src/components/staking/account/delegation-value-view/staking-actions/form-dialog.tsx +++ b/apps/minifront/src/components/staking/account/delegation-value-view/staking-actions/form-dialog.tsx @@ -1,18 +1,18 @@ -import { Button } from '@penumbra-zone/ui/components/ui/button'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; import { Dialog, DialogClose, DialogContent, DialogHeader, -} from '@penumbra-zone/ui/components/ui/dialog'; -import { IdentityKeyComponent } from '@penumbra-zone/ui/components/ui/identity-key-component'; +} from '@penumbra-zone/ui-deprecated/components/ui/dialog'; +import { IdentityKeyComponent } from '@penumbra-zone/ui-deprecated/components/ui/identity-key-component'; import { InputBlock } from '../../../../shared/input-block'; import { Validator } from '@penumbra-zone/protobuf/penumbra/core/component/stake/v1/stake_pb'; import { ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { FormEvent } from 'react'; import { getIdentityKey } from '@penumbra-zone/getters/validator'; import { getFormattedAmtFromValueView } from '@penumbra-zone/types/value-view'; -import { BalanceValueView } from '@penumbra-zone/ui/components/ui/balance-value-view'; +import { BalanceValueView } from '@penumbra-zone/ui-deprecated/components/ui/balance-value-view'; import { NumberInput } from '../../../../shared/number-input'; import { CircleAlert } from 'lucide-react'; import { useStoreShallow } from '../../../../../utils/use-store-shallow.ts'; diff --git a/apps/minifront/src/components/staking/account/delegation-value-view/staking-actions/index.tsx b/apps/minifront/src/components/staking/account/delegation-value-view/staking-actions/index.tsx index 3009e061c8..84a6651a9f 100644 --- a/apps/minifront/src/components/staking/account/delegation-value-view/staking-actions/index.tsx +++ b/apps/minifront/src/components/staking/account/delegation-value-view/staking-actions/index.tsx @@ -1,4 +1,4 @@ -import { Button } from '@penumbra-zone/ui/components/ui/button'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; import { ValidatorInfo } from '@penumbra-zone/protobuf/penumbra/core/component/stake/v1/stake_pb'; import { ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { FormDialog } from './form-dialog'; diff --git a/apps/minifront/src/components/staking/account/delegation-value-view/validator-info-component.tsx b/apps/minifront/src/components/staking/account/delegation-value-view/validator-info-component.tsx index c217018f4f..cb1554b22a 100644 --- a/apps/minifront/src/components/staking/account/delegation-value-view/validator-info-component.tsx +++ b/apps/minifront/src/components/staking/account/delegation-value-view/validator-info-component.tsx @@ -1,11 +1,11 @@ import { ValidatorInfo } from '@penumbra-zone/protobuf/penumbra/core/component/stake/v1/stake_pb'; -import { IdentityKeyComponent } from '@penumbra-zone/ui/components/ui/identity-key-component'; +import { IdentityKeyComponent } from '@penumbra-zone/ui-deprecated/components/ui/identity-key-component'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, -} from '@penumbra-zone/ui/components/ui/tooltip'; +} from '@penumbra-zone/ui-deprecated/components/ui/tooltip'; import { useStore } from '../../../../state'; import { getIdentityKeyFromValidatorInfo, @@ -14,7 +14,7 @@ import { } from '@penumbra-zone/getters/validator-info'; import { calculateCommissionAsPercentage } from '@penumbra-zone/types/staking'; import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; -import { AssetIcon } from '@penumbra-zone/ui/components/ui/asset-icon'; +import { AssetIcon } from '@penumbra-zone/ui-deprecated/components/ui/asset-icon'; import { ValidatorStateLabel } from './validator-state-label.tsx'; /** diff --git a/apps/minifront/src/components/staking/account/delegation-value-view/validator-state-label.tsx b/apps/minifront/src/components/staking/account/delegation-value-view/validator-state-label.tsx index ed41aa0722..3b4da9900e 100644 --- a/apps/minifront/src/components/staking/account/delegation-value-view/validator-state-label.tsx +++ b/apps/minifront/src/components/staking/account/delegation-value-view/validator-state-label.tsx @@ -1,5 +1,5 @@ import { ValidatorState_ValidatorStateEnum } from '@penumbra-zone/protobuf/penumbra/core/component/stake/v1/stake_pb'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; interface LabelInfo { label: string; diff --git a/apps/minifront/src/components/staking/account/header/index.tsx b/apps/minifront/src/components/staking/account/header/index.tsx index 16ba56d540..0d730c0de5 100644 --- a/apps/minifront/src/components/staking/account/header/index.tsx +++ b/apps/minifront/src/components/staking/account/header/index.tsx @@ -1,7 +1,7 @@ -import { Button } from '@penumbra-zone/ui/components/ui/button'; -import { Card, CardContent } from '@penumbra-zone/ui/components/ui/card'; -import { AccountSwitcher } from '@penumbra-zone/ui/components/ui/account-switcher'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; +import { Card, CardContent } from '@penumbra-zone/ui-deprecated/components/ui/card'; +import { AccountSwitcher } from '@penumbra-zone/ui-deprecated/components/ui/account-switcher'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; import { Stat } from './stat'; import { AllSlices } from '../../../../state'; import { UnbondingTokens } from './unbonding-tokens'; diff --git a/apps/minifront/src/components/staking/account/header/unbonding-tokens.tsx b/apps/minifront/src/components/staking/account/header/unbonding-tokens.tsx index 712e15d8ed..a33a7f052e 100644 --- a/apps/minifront/src/components/staking/account/header/unbonding-tokens.tsx +++ b/apps/minifront/src/components/staking/account/header/unbonding-tokens.tsx @@ -5,8 +5,8 @@ import { Tooltip, TooltipTrigger, TooltipContent, -} from '@penumbra-zone/ui/components/ui/tooltip'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +} from '@penumbra-zone/ui-deprecated/components/ui/tooltip'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; import { ReactNode } from 'react'; import { zeroValueView } from '../../../../utils/zero-value-view'; diff --git a/apps/minifront/src/components/staking/layout.tsx b/apps/minifront/src/components/staking/layout.tsx index 90ca2c5c85..c127c401a1 100644 --- a/apps/minifront/src/components/staking/layout.tsx +++ b/apps/minifront/src/components/staking/layout.tsx @@ -1,6 +1,11 @@ import { useEffect } from 'react'; import { AllSlices } from '../../state'; -import { Card, CardContent, CardHeader, CardTitle } from '@penumbra-zone/ui/components/ui/card'; +import { + Card, + CardContent, + CardHeader, + CardTitle, +} from '@penumbra-zone/ui-deprecated/components/ui/card'; import { Header } from './account/header'; import { Delegations } from './account/delegations'; import { useStoreShallow } from '../../utils/use-store-shallow'; diff --git a/apps/minifront/src/components/staking/validator-info-row.tsx b/apps/minifront/src/components/staking/validator-info-row.tsx index 3c15f2a670..06b1070eab 100644 --- a/apps/minifront/src/components/staking/validator-info-row.tsx +++ b/apps/minifront/src/components/staking/validator-info-row.tsx @@ -1,5 +1,5 @@ import { ValidatorInfo } from '@penumbra-zone/protobuf/penumbra/core/component/stake/v1/stake_pb'; -import { TableCell, TableRow } from '@penumbra-zone/ui/components/ui/table'; +import { TableCell, TableRow } from '@penumbra-zone/ui-deprecated/components/ui/table'; import { ReactNode } from 'react'; import { Oval } from 'react-loader-spinner'; import { getValidator } from '@penumbra-zone/getters/validator-info'; diff --git a/apps/minifront/src/components/staking/validators-table.tsx b/apps/minifront/src/components/staking/validators-table.tsx index e38cce5014..ab88cd16b7 100644 --- a/apps/minifront/src/components/staking/validators-table.tsx +++ b/apps/minifront/src/components/staking/validators-table.tsx @@ -5,7 +5,7 @@ import { TableHead, TableHeader, TableRow, -} from '@penumbra-zone/ui/components/ui/table'; +} from '@penumbra-zone/ui-deprecated/components/ui/table'; import { Oval } from 'react-loader-spinner'; import { ValidatorInfoRow } from './validator-info-row'; import { ValidatorInfo } from '@penumbra-zone/protobuf/penumbra/core/component/stake/v1/stake_pb'; diff --git a/apps/minifront/src/components/swap/auction-list/end-or-withdraw-all-button.tsx b/apps/minifront/src/components/swap/auction-list/end-or-withdraw-all-button.tsx index a6152e2b40..f2e0ec5a33 100644 --- a/apps/minifront/src/components/swap/auction-list/end-or-withdraw-all-button.tsx +++ b/apps/minifront/src/components/swap/auction-list/end-or-withdraw-all-button.tsx @@ -1,6 +1,6 @@ import { useAuctionInfos } from '../../../state/swap/dutch-auction'; import { AddressIndex } from '@penumbra-zone/protobuf/penumbra/core/keys/v1/keys_pb'; -import { Button } from '@penumbra-zone/ui/components/ui/button'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; import { AllSlices } from '../../../state'; import { useStoreShallow } from '../../../utils/use-store-shallow.ts'; import { filterWithLimit } from './helpers.ts'; @@ -9,7 +9,7 @@ import { TooltipContent, TooltipProvider, TooltipTrigger, -} from '@penumbra-zone/ui/components/ui/tooltip'; +} from '@penumbra-zone/ui-deprecated/components/ui/tooltip'; import { AuctionInfo } from '../../../fetchers/auction-infos.ts'; const endOrWithdrawAllButtonSelector = (state: AllSlices) => ({ diff --git a/apps/minifront/src/components/swap/auction-list/filters.tsx b/apps/minifront/src/components/swap/auction-list/filters.tsx index a9f58f70b2..7b85ec6a5d 100644 --- a/apps/minifront/src/components/swap/auction-list/filters.tsx +++ b/apps/minifront/src/components/swap/auction-list/filters.tsx @@ -1,7 +1,7 @@ import { ListFilter } from 'lucide-react'; import { AllSlices } from '../../../state'; import { useStoreShallow } from '../../../utils/use-store-shallow'; -import { PopoverMenu, PopoverMenuItem } from '@penumbra-zone/ui/components/ui/popover'; +import { PopoverMenu, PopoverMenuItem } from '@penumbra-zone/ui-deprecated/components/ui/popover'; import type { Filter as TFilter } from '../../../state/swap/dutch-auction'; const filtersSelector = (state: AllSlices) => ({ diff --git a/apps/minifront/src/components/swap/auction-list/index.tsx b/apps/minifront/src/components/swap/auction-list/index.tsx index 4a480b80d0..2707f96a69 100644 --- a/apps/minifront/src/components/swap/auction-list/index.tsx +++ b/apps/minifront/src/components/swap/auction-list/index.tsx @@ -1,10 +1,10 @@ import { AllSlices } from '../../../state'; -import { DutchAuctionComponent } from '@penumbra-zone/ui/components/ui/dutch-auction-component'; +import { DutchAuctionComponent } from '@penumbra-zone/ui-deprecated/components/ui/dutch-auction-component'; import { useStoreShallow } from '../../../utils/use-store-shallow'; import { AuctionId } from '@penumbra-zone/protobuf/penumbra/core/component/auction/v1/auction_pb'; -import { GradientHeader } from '@penumbra-zone/ui/components/ui/gradient-header'; +import { GradientHeader } from '@penumbra-zone/ui-deprecated/components/ui/gradient-header'; import { QueryLatestStateButton } from './query-latest-state-button'; -import { Card } from '@penumbra-zone/ui/components/ui/card'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; import { bech32mAuctionId } from '@penumbra-zone/bech32m/pauctid'; import { useMemo } from 'react'; import { getFilteredAuctionInfos } from './get-filtered-auction-infos'; diff --git a/apps/minifront/src/components/swap/auction-list/query-latest-state-button.tsx b/apps/minifront/src/components/swap/auction-list/query-latest-state-button.tsx index 868e764293..42668b1cac 100644 --- a/apps/minifront/src/components/swap/auction-list/query-latest-state-button.tsx +++ b/apps/minifront/src/components/swap/auction-list/query-latest-state-button.tsx @@ -3,10 +3,10 @@ import { TooltipContent, TooltipProvider, TooltipTrigger, -} from '@penumbra-zone/ui/components/ui/tooltip'; +} from '@penumbra-zone/ui-deprecated/components/ui/tooltip'; import { ReloadIcon } from '@radix-ui/react-icons'; import { useAuctionInfos, useRevalidateAuctionInfos } from '../../../state/swap/dutch-auction'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; export const QueryLatestStateButton = () => { const { loading } = useAuctionInfos(); diff --git a/apps/minifront/src/components/swap/duration-slider.tsx b/apps/minifront/src/components/swap/duration-slider.tsx index 9fcd59bc2c..1b239de3d7 100644 --- a/apps/minifront/src/components/swap/duration-slider.tsx +++ b/apps/minifront/src/components/swap/duration-slider.tsx @@ -1,4 +1,4 @@ -import { Slider } from '@penumbra-zone/ui/components/ui/slider'; +import { Slider } from '@penumbra-zone/ui-deprecated/components/ui/slider'; import { DURATION_OPTIONS, GDA_RECIPES } from '../../state/swap/constants'; import { useStoreShallow } from '../../utils/use-store-shallow'; import { AllSlices } from '../../state'; diff --git a/apps/minifront/src/components/swap/lp-positions.tsx b/apps/minifront/src/components/swap/lp-positions.tsx index 161e4e4219..93ec9629f1 100644 --- a/apps/minifront/src/components/swap/lp-positions.tsx +++ b/apps/minifront/src/components/swap/lp-positions.tsx @@ -1,5 +1,5 @@ -import { Card } from '@penumbra-zone/ui/components/ui/card'; -import { GradientHeader } from '@penumbra-zone/ui/components/ui/gradient-header'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; +import { GradientHeader } from '@penumbra-zone/ui-deprecated/components/ui/gradient-header'; import { useOwnedPositions } from '../../state/swap/lp-positions.ts'; import { bech32mPositionId } from '@penumbra-zone/bech32m/plpid'; diff --git a/apps/minifront/src/components/swap/swap-form/estimate-button.tsx b/apps/minifront/src/components/swap/swap-form/estimate-button.tsx index 602852bc9b..fc06eeee5f 100644 --- a/apps/minifront/src/components/swap/swap-form/estimate-button.tsx +++ b/apps/minifront/src/components/swap/swap-form/estimate-button.tsx @@ -1,11 +1,11 @@ -import { buttonVariants } from '@penumbra-zone/ui/components/ui/button'; +import { buttonVariants } from '@penumbra-zone/ui-deprecated/components/ui/button'; import { Tooltip, TooltipProvider, TooltipTrigger, TooltipContent, -} from '@penumbra-zone/ui/components/ui/tooltip'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +} from '@penumbra-zone/ui-deprecated/components/ui/tooltip'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; export const EstimateButton = ({ disabled, diff --git a/apps/minifront/src/components/swap/swap-form/index.tsx b/apps/minifront/src/components/swap/swap-form/index.tsx index c61b45d4ff..3c914c2154 100644 --- a/apps/minifront/src/components/swap/swap-form/index.tsx +++ b/apps/minifront/src/components/swap/swap-form/index.tsx @@ -1,11 +1,11 @@ -import { Button } from '@penumbra-zone/ui/components/ui/button'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; import { AllSlices } from '../../../state'; import { TokenSwapInput } from './token-swap-input'; import { useStoreShallow } from '../../../utils/use-store-shallow'; import { DurationSlider } from '../duration-slider'; import { InputBlock } from '../../shared/input-block'; import { Output } from './output'; -import { Card } from '@penumbra-zone/ui/components/ui/card'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; import { SimulateSwap } from './simulate-swap'; import { LayoutGroup } from 'framer-motion'; import { useId } from 'react'; diff --git a/apps/minifront/src/components/swap/swap-form/output/index.tsx b/apps/minifront/src/components/swap/swap-form/output/index.tsx index 0569f48ae1..b044c2b9a3 100644 --- a/apps/minifront/src/components/swap/swap-form/output/index.tsx +++ b/apps/minifront/src/components/swap/swap-form/output/index.tsx @@ -1,4 +1,4 @@ -import { Box } from '@penumbra-zone/ui/components/ui/box'; +import { Box } from '@penumbra-zone/ui-deprecated/components/ui/box'; import { AllSlices } from '../../../../state'; import { useStoreShallow } from '../../../../utils/use-store-shallow'; import { EstimateButton } from '../estimate-button'; diff --git a/apps/minifront/src/components/swap/swap-form/price-history.tsx b/apps/minifront/src/components/swap/swap-form/price-history.tsx index d143245b90..f590c481fa 100644 --- a/apps/minifront/src/components/swap/swap-form/price-history.tsx +++ b/apps/minifront/src/components/swap/swap-form/price-history.tsx @@ -1,7 +1,7 @@ import { getMetadataFromBalancesResponse } from '@penumbra-zone/getters/balances-response'; import { AbridgedZQueryState } from '@penumbra-zone/zquery/src/types'; -import { Box } from '@penumbra-zone/ui/components/ui/box'; -import { CandlestickPlot } from '@penumbra-zone/ui/components/ui/candlestick-plot'; +import { Box } from '@penumbra-zone/ui-deprecated/components/ui/box'; +import { CandlestickPlot } from '@penumbra-zone/ui-deprecated/components/ui/candlestick-plot'; import { useEffect, useMemo, useState } from 'react'; import { getBlockDate } from '../../../fetchers/block-date'; import { AllSlices } from '../../../state'; @@ -9,7 +9,7 @@ import { useStatus } from '../../../state/status'; import { combinedCandlestickDataSelector } from '../../../state/swap/helpers'; import { useCandles, useRevalidateCandles } from '../../../state/swap/price-history'; import { useStoreShallow } from '../../../utils/use-store-shallow'; -import { Button } from '@penumbra-zone/ui/components/ui/button'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; const priceHistorySelector = (state: AllSlices) => ({ startMetadata: getMetadataFromBalancesResponse.optional(state.swap.assetIn), diff --git a/apps/minifront/src/components/swap/swap-form/simulate-swap-result/index.tsx b/apps/minifront/src/components/swap/swap-form/simulate-swap-result/index.tsx index b019e4636c..488ace2644 100644 --- a/apps/minifront/src/components/swap/swap-form/simulate-swap-result/index.tsx +++ b/apps/minifront/src/components/swap/swap-form/simulate-swap-result/index.tsx @@ -1,4 +1,4 @@ -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; import { PriceImpact } from './price-impact'; import { motion } from 'framer-motion'; import { SimulateSwapResult as TSimulateSwapResult } from '../../../../state/swap'; diff --git a/apps/minifront/src/components/swap/swap-form/simulate-swap-result/price-impact.tsx b/apps/minifront/src/components/swap/swap-form/simulate-swap-result/price-impact.tsx index 5d7790c250..76a951f054 100644 --- a/apps/minifront/src/components/swap/swap-form/simulate-swap-result/price-impact.tsx +++ b/apps/minifront/src/components/swap/swap-form/simulate-swap-result/price-impact.tsx @@ -1,6 +1,6 @@ import { formatNumber } from '@penumbra-zone/types/amount'; -import { Pill } from '@penumbra-zone/ui/components/ui/pill'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { Pill } from '@penumbra-zone/ui-deprecated/components/ui/pill'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; // The price hit the user takes as a consequence of moving the market with the size of their trade export const PriceImpact = ({ amount = 0 }: { amount?: number }) => { diff --git a/apps/minifront/src/components/swap/swap-form/simulate-swap-result/traces/index.tsx b/apps/minifront/src/components/swap/swap-form/simulate-swap-result/traces/index.tsx index 4fa15e8c39..bae3cac392 100644 --- a/apps/minifront/src/components/swap/swap-form/simulate-swap-result/traces/index.tsx +++ b/apps/minifront/src/components/swap/swap-form/simulate-swap-result/traces/index.tsx @@ -1,7 +1,7 @@ import { SwapExecution_Trace } from '@penumbra-zone/protobuf/penumbra/core/component/dex/v1/dex_pb'; import { Trace } from './trace'; import { Metadata, ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; import { ArrowDown, ArrowUp } from 'lucide-react'; export const Traces = ({ diff --git a/apps/minifront/src/components/swap/swap-form/simulate-swap-result/traces/trace/index.tsx b/apps/minifront/src/components/swap/swap-form/simulate-swap-result/traces/trace/index.tsx index 7fa47652ed..0b554e3dc3 100644 --- a/apps/minifront/src/components/swap/swap-form/simulate-swap-result/traces/trace/index.tsx +++ b/apps/minifront/src/components/swap/swap-form/simulate-swap-result/traces/trace/index.tsx @@ -5,7 +5,7 @@ import { } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { SwapExecution_Trace } from '@penumbra-zone/protobuf/penumbra/core/component/dex/v1/dex_pb'; import { bech32mAssetId } from '@penumbra-zone/bech32m/passet'; -import { ValueViewComponent } from '@penumbra-zone/ui/components/ui/value'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/components/ui/value'; import { Price } from './price'; const getValueView = (metadataByAssetId: Record, { amount, assetId }: Value) => diff --git a/apps/minifront/src/components/swap/swap-form/simulate-swap.tsx b/apps/minifront/src/components/swap/swap-form/simulate-swap.tsx index af71b85950..ef44742e22 100644 --- a/apps/minifront/src/components/swap/swap-form/simulate-swap.tsx +++ b/apps/minifront/src/components/swap/swap-form/simulate-swap.tsx @@ -1,4 +1,4 @@ -import { Box } from '@penumbra-zone/ui/components/ui/box'; +import { Box } from '@penumbra-zone/ui-deprecated/components/ui/box'; import { SimulateSwapResult } from './simulate-swap-result'; import { AllSlices } from '../../../state'; import { useStoreShallow } from '../../../utils/use-store-shallow'; diff --git a/apps/minifront/src/components/swap/swap-form/token-swap-input.tsx b/apps/minifront/src/components/swap/swap-form/token-swap-input.tsx index 24e0c7a161..4afbd4add5 100644 --- a/apps/minifront/src/components/swap/swap-form/token-swap-input.tsx +++ b/apps/minifront/src/components/swap/swap-form/token-swap-input.tsx @@ -1,7 +1,7 @@ -import { BalanceValueView } from '@penumbra-zone/ui/components/ui/balance-value-view'; +import { BalanceValueView } from '@penumbra-zone/ui-deprecated/components/ui/balance-value-view'; import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; -import { Box } from '@penumbra-zone/ui/components/ui/box'; +import { Box } from '@penumbra-zone/ui-deprecated/components/ui/box'; import { joinLoHiAmount } from '@penumbra-zone/types/amount'; import { getAmount, getBalanceView } from '@penumbra-zone/getters/balances-response'; import { ArrowRight } from 'lucide-react'; diff --git a/apps/minifront/src/components/swap/unclaimed-swaps.tsx b/apps/minifront/src/components/swap/unclaimed-swaps.tsx index b2c5bb001f..d1805eaac5 100644 --- a/apps/minifront/src/components/swap/unclaimed-swaps.tsx +++ b/apps/minifront/src/components/swap/unclaimed-swaps.tsx @@ -1,11 +1,11 @@ -import { Button } from '@penumbra-zone/ui/components/ui/button'; -import { Card } from '@penumbra-zone/ui/components/ui/card'; -import { AssetIcon } from '@penumbra-zone/ui/components/ui/asset-icon'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; +import { AssetIcon } from '@penumbra-zone/ui-deprecated/components/ui/asset-icon'; import { AllSlices } from '../../state'; import { useUnclaimedSwaps } from '../../state/unclaimed-swaps'; import { getSwapRecordCommitment } from '@penumbra-zone/getters/swap-record'; import { uint8ArrayToBase64 } from '@penumbra-zone/types/base64'; -import { GradientHeader } from '@penumbra-zone/ui/components/ui/gradient-header'; +import { GradientHeader } from '@penumbra-zone/ui-deprecated/components/ui/gradient-header'; import { useStoreShallow } from '../../utils/use-store-shallow'; import { useState } from 'react'; import { SwapRecord } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; diff --git a/apps/minifront/src/components/syncing-dialog/index.tsx b/apps/minifront/src/components/syncing-dialog/index.tsx index 72e8383ecb..7bb4e55d8f 100644 --- a/apps/minifront/src/components/syncing-dialog/index.tsx +++ b/apps/minifront/src/components/syncing-dialog/index.tsx @@ -1,9 +1,9 @@ -import { Dialog } from '@penumbra-zone/ui/Dialog'; +import { Dialog } from '@penumbra-zone/ui-deprecated/Dialog'; import { statusSelector, useStatus } from '../../state/status'; import { SyncAnimation } from './sync-animation'; -import { Text } from '@penumbra-zone/ui/Text'; +import { Text } from '@penumbra-zone/ui-deprecated/Text'; import { useEffect, useState } from 'react'; -import { useSyncProgress } from '@penumbra-zone/ui/components/ui/block-sync-status'; +import { useSyncProgress } from '@penumbra-zone/ui-deprecated/components/ui/block-sync-status'; export const SyncingDialog = () => { const status = useStatus({ diff --git a/apps/minifront/src/components/tx-details/index.tsx b/apps/minifront/src/components/tx-details/index.tsx index 0d14e980f2..62ad74738d 100644 --- a/apps/minifront/src/components/tx-details/index.tsx +++ b/apps/minifront/src/components/tx-details/index.tsx @@ -1,5 +1,5 @@ -import { Card } from '@penumbra-zone/ui/components/ui/card'; -import { FadeTransition } from '@penumbra-zone/ui/components/ui/fade-transition'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; +import { FadeTransition } from '@penumbra-zone/ui-deprecated/components/ui/fade-transition'; import { TxViewer } from './tx-viewer'; import { EduInfoCard } from '../shared/edu-panels/edu-info-card'; import { EduPanel } from '../shared/edu-panels/content'; diff --git a/apps/minifront/src/components/tx-details/tx-viewer.tsx b/apps/minifront/src/components/tx-details/tx-viewer.tsx index a62b738513..3285f04e51 100644 --- a/apps/minifront/src/components/tx-details/tx-viewer.tsx +++ b/apps/minifront/src/components/tx-details/tx-viewer.tsx @@ -1,9 +1,12 @@ -import { JsonViewer } from '@penumbra-zone/ui/components/ui/json-viewer'; -import { MetadataFetchFn, TransactionViewComponent } from '@penumbra-zone/ui/components/ui/tx'; +import { JsonViewer } from '@penumbra-zone/ui-deprecated/components/ui/json-viewer'; +import { + MetadataFetchFn, + TransactionViewComponent, +} from '@penumbra-zone/ui-deprecated/components/ui/tx'; import { TransactionInfo } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; import type { Jsonified } from '@penumbra-zone/types/jsonified'; import { useState } from 'react'; -import { SegmentedPicker } from '@penumbra-zone/ui/components/ui/segmented-picker'; +import { SegmentedPicker } from '@penumbra-zone/ui-deprecated/components/ui/segmented-picker'; import { asPublicTransactionView } from '@penumbra-zone/perspective/translators/transaction-view'; import { typeRegistry, ViewService } from '@penumbra-zone/protobuf'; import { useQuery } from '@tanstack/react-query'; diff --git a/apps/minifront/src/components/v2/dashboard-layout/assets-card-title.tsx b/apps/minifront/src/components/v2/dashboard-layout/assets-card-title.tsx index 4bfef44535..8a234d0434 100644 --- a/apps/minifront/src/components/v2/dashboard-layout/assets-card-title.tsx +++ b/apps/minifront/src/components/v2/dashboard-layout/assets-card-title.tsx @@ -1,7 +1,7 @@ -import { Button } from '@penumbra-zone/ui/Button'; -import { CharacterTransition } from '@penumbra-zone/ui/CharacterTransition'; -import { Dialog } from '@penumbra-zone/ui/Dialog'; -import { Text } from '@penumbra-zone/ui/Text'; +import { Button } from '@penumbra-zone/ui-deprecated/Button'; +import { CharacterTransition } from '@penumbra-zone/ui-deprecated/CharacterTransition'; +import { Dialog } from '@penumbra-zone/ui-deprecated/Dialog'; +import { Text } from '@penumbra-zone/ui-deprecated/Text'; import { Info } from 'lucide-react'; import { useId } from 'react'; diff --git a/apps/minifront/src/components/v2/dashboard-layout/assets-page/equivalent-values.tsx b/apps/minifront/src/components/v2/dashboard-layout/assets-page/equivalent-values.tsx index db172933e7..9ff11d9c22 100644 --- a/apps/minifront/src/components/v2/dashboard-layout/assets-page/equivalent-values.tsx +++ b/apps/minifront/src/components/v2/dashboard-layout/assets-page/equivalent-values.tsx @@ -1,7 +1,7 @@ import { ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { asValueView } from '@penumbra-zone/getters/equivalent-value'; import { getDisplayDenomFromView, getEquivalentValues } from '@penumbra-zone/getters/value-view'; -import { ValueViewComponent } from '@penumbra-zone/ui/ValueViewComponent'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/ValueViewComponent'; export const EquivalentValues = ({ valueView }: { valueView?: ValueView }) => { const equivalentValuesAsValueViews = (getEquivalentValues.optional(valueView) ?? []).map( diff --git a/apps/minifront/src/components/v2/dashboard-layout/assets-page/index.tsx b/apps/minifront/src/components/v2/dashboard-layout/assets-page/index.tsx index 8ad96547cb..6ad65bc09e 100644 --- a/apps/minifront/src/components/v2/dashboard-layout/assets-page/index.tsx +++ b/apps/minifront/src/components/v2/dashboard-layout/assets-page/index.tsx @@ -1,5 +1,5 @@ -import { Density } from '@penumbra-zone/ui/Density'; -import { Table } from '@penumbra-zone/ui/Table'; +import { Density } from '@penumbra-zone/ui-deprecated/Density'; +import { Table } from '@penumbra-zone/ui-deprecated/Table'; import { BalancesByAccount, groupByAccount, useBalancesResponses } from '../../../../state/shared'; import { shouldDisplay } from '../../../../fetchers/balances/should-display'; import { sortByPriorityScore } from '../../../../fetchers/balances/by-priority-score'; @@ -8,14 +8,14 @@ import { getMetadataFromBalancesResponse } from '@penumbra-zone/getters/balances import { PagePath } from '../../../metadata/paths'; import { getAddressIndex } from '@penumbra-zone/getters/address-view'; import { AbridgedZQueryState } from '@penumbra-zone/zquery/src/types'; -import { ValueViewComponent } from '@penumbra-zone/ui/ValueViewComponent'; +import { ValueViewComponent } from '@penumbra-zone/ui-deprecated/ValueViewComponent'; import { EquivalentValues } from './equivalent-values'; import { TableTitle } from './table-title'; import { Link } from 'react-router-dom'; -import { Button } from '@penumbra-zone/ui/Button'; +import { Button } from '@penumbra-zone/ui-deprecated/Button'; import { ArrowRightLeft } from 'lucide-react'; -import { useAnimationDeferredValue } from '@penumbra-zone/ui/hooks/useAnimationDeferredValue'; -import { ConditionalWrap } from '@penumbra-zone/ui/ConditionalWrap'; +import { useAnimationDeferredValue } from '@penumbra-zone/ui-deprecated/hooks/useAnimationDeferredValue'; +import { ConditionalWrap } from '@penumbra-zone/ui-deprecated/ConditionalWrap'; import { LayoutGroup } from 'framer-motion'; const getTradeLink = (balance: BalancesResponse): string => { diff --git a/apps/minifront/src/components/v2/dashboard-layout/assets-page/table-title.tsx b/apps/minifront/src/components/v2/dashboard-layout/assets-page/table-title.tsx index 17c0737b28..bc71dd6f29 100644 --- a/apps/minifront/src/components/v2/dashboard-layout/assets-page/table-title.tsx +++ b/apps/minifront/src/components/v2/dashboard-layout/assets-page/table-title.tsx @@ -1,4 +1,4 @@ -import { AddressViewComponent } from '@penumbra-zone/ui/AddressViewComponent'; +import { AddressViewComponent } from '@penumbra-zone/ui-deprecated/AddressViewComponent'; import { BalancesByAccount } from '../../../../state/shared'; import { AddressView } from '@penumbra-zone/protobuf/penumbra/core/keys/v1/keys_pb'; import { useMemo } from 'react'; diff --git a/apps/minifront/src/components/v2/dashboard-layout/index.tsx b/apps/minifront/src/components/v2/dashboard-layout/index.tsx index 5f94517895..4e5c5859a7 100644 --- a/apps/minifront/src/components/v2/dashboard-layout/index.tsx +++ b/apps/minifront/src/components/v2/dashboard-layout/index.tsx @@ -1,7 +1,7 @@ -import { Card } from '@penumbra-zone/ui/Card'; +import { Card } from '@penumbra-zone/ui-deprecated/Card'; import { Outlet, useNavigate } from 'react-router-dom'; -import { Grid } from '@penumbra-zone/ui/Grid'; -import { Tabs } from '@penumbra-zone/ui/Tabs'; +import { Grid } from '@penumbra-zone/ui-deprecated/Grid'; +import { Tabs } from '@penumbra-zone/ui-deprecated/Tabs'; import { usePagePath } from '../../../fetchers/page-path'; import { PagePath } from '../../metadata/paths'; import { AssetsCardTitle } from './assets-card-title'; diff --git a/apps/minifront/src/components/v2/dashboard-layout/transactions-card-title.tsx b/apps/minifront/src/components/v2/dashboard-layout/transactions-card-title.tsx index b4f03d3a1c..72f76c53c1 100644 --- a/apps/minifront/src/components/v2/dashboard-layout/transactions-card-title.tsx +++ b/apps/minifront/src/components/v2/dashboard-layout/transactions-card-title.tsx @@ -1,7 +1,7 @@ -import { Button } from '@penumbra-zone/ui/Button'; -import { CharacterTransition } from '@penumbra-zone/ui/CharacterTransition'; -import { Dialog } from '@penumbra-zone/ui/Dialog'; -import { Text } from '@penumbra-zone/ui/Text'; +import { Button } from '@penumbra-zone/ui-deprecated/Button'; +import { CharacterTransition } from '@penumbra-zone/ui-deprecated/CharacterTransition'; +import { Dialog } from '@penumbra-zone/ui-deprecated/Dialog'; +import { Text } from '@penumbra-zone/ui-deprecated/Text'; import { Info } from 'lucide-react'; import { useId } from 'react'; diff --git a/apps/minifront/src/components/v2/dashboard-layout/transactions-page/index.tsx b/apps/minifront/src/components/v2/dashboard-layout/transactions-page/index.tsx index 3e87a6e2a8..ecaca48c5a 100644 --- a/apps/minifront/src/components/v2/dashboard-layout/transactions-page/index.tsx +++ b/apps/minifront/src/components/v2/dashboard-layout/transactions-page/index.tsx @@ -1,10 +1,10 @@ -import { Table } from '@penumbra-zone/ui/Table'; +import { Table } from '@penumbra-zone/ui-deprecated/Table'; import { useSummaries } from '../../../../state/transactions'; -import { Text } from '@penumbra-zone/ui/Text'; +import { Text } from '@penumbra-zone/ui-deprecated/Text'; import { Link } from 'react-router-dom'; import { SquareArrowOutUpRight } from 'lucide-react'; -import { Button } from '@penumbra-zone/ui/Button'; -import { useAnimationDeferredValue } from '@penumbra-zone/ui/hooks/useAnimationDeferredValue'; +import { Button } from '@penumbra-zone/ui-deprecated/Button'; +import { useAnimationDeferredValue } from '@penumbra-zone/ui-deprecated/hooks/useAnimationDeferredValue'; import { LayoutGroup } from 'framer-motion'; export const TransactionsPage = () => { diff --git a/apps/minifront/src/components/v2/header/desktop-nav.tsx b/apps/minifront/src/components/v2/header/desktop-nav.tsx index 8c4d9cfb52..b04c91fb09 100644 --- a/apps/minifront/src/components/v2/header/desktop-nav.tsx +++ b/apps/minifront/src/components/v2/header/desktop-nav.tsx @@ -1,6 +1,6 @@ import { useNavigate } from 'react-router-dom'; -import { Tabs } from '@penumbra-zone/ui/Tabs'; -import { Density } from '@penumbra-zone/ui/Density'; +import { Tabs } from '@penumbra-zone/ui-deprecated/Tabs'; +import { Density } from '@penumbra-zone/ui-deprecated/Density'; import { getV2Link } from '../get-v2-link.ts'; import { usePagePath } from '../../../fetchers/page-path.ts'; import { HEADER_LINKS } from './links.ts'; diff --git a/apps/minifront/src/components/v2/header/index.tsx b/apps/minifront/src/components/v2/header/index.tsx index 87013fdfc4..30fd93130e 100644 --- a/apps/minifront/src/components/v2/header/index.tsx +++ b/apps/minifront/src/components/v2/header/index.tsx @@ -1,4 +1,4 @@ -import { Density } from '@penumbra-zone/ui/Density'; +import { Density } from '@penumbra-zone/ui-deprecated/Density'; import { HeaderLogo } from './logo.tsx'; import { ProviderPopover } from './provider-popover.tsx'; import { StatusPopover } from './status-popover.tsx'; diff --git a/apps/minifront/src/components/v2/header/mobile-nav.tsx b/apps/minifront/src/components/v2/header/mobile-nav.tsx index 53781128b3..fdfdacc067 100644 --- a/apps/minifront/src/components/v2/header/mobile-nav.tsx +++ b/apps/minifront/src/components/v2/header/mobile-nav.tsx @@ -1,8 +1,8 @@ import { Menu, X } from 'lucide-react'; -import { Button } from '@penumbra-zone/ui/Button'; -import { Dialog } from '@penumbra-zone/ui/Dialog'; -import { Display } from '@penumbra-zone/ui/Display'; -import { MenuItem } from '@penumbra-zone/ui/MenuItem'; +import { Button } from '@penumbra-zone/ui-deprecated/Button'; +import { Dialog } from '@penumbra-zone/ui-deprecated/Dialog'; +import { Display } from '@penumbra-zone/ui-deprecated/Display'; +import { MenuItem } from '@penumbra-zone/ui-deprecated/MenuItem'; import { StatusPopover } from './status-popover.tsx'; import { ProviderPopover } from './provider-popover.tsx'; import { HeaderLogo } from './logo.tsx'; diff --git a/apps/minifront/src/components/v2/header/provider-popover.tsx b/apps/minifront/src/components/v2/header/provider-popover.tsx index 1f8fa4b046..d92540c46c 100644 --- a/apps/minifront/src/components/v2/header/provider-popover.tsx +++ b/apps/minifront/src/components/v2/header/provider-popover.tsx @@ -1,8 +1,8 @@ import { useEffect, useMemo, useState } from 'react'; import { Link2Off } from 'lucide-react'; -import { Popover } from '@penumbra-zone/ui/Popover'; -import { Button } from '@penumbra-zone/ui/Button'; -import { Text } from '@penumbra-zone/ui/Text'; +import { Popover } from '@penumbra-zone/ui-deprecated/Popover'; +import { Button } from '@penumbra-zone/ui-deprecated/Button'; +import { Text } from '@penumbra-zone/ui-deprecated/Text'; import { penumbra } from '../../../penumbra.ts'; import { PenumbraManifest } from '@penumbra-zone/client'; diff --git a/apps/minifront/src/components/v2/header/status-popover.tsx b/apps/minifront/src/components/v2/header/status-popover.tsx index f9305643f1..2a628ec0d7 100644 --- a/apps/minifront/src/components/v2/header/status-popover.tsx +++ b/apps/minifront/src/components/v2/header/status-popover.tsx @@ -1,9 +1,9 @@ import { Blocks } from 'lucide-react'; -import { Popover, PopoverContext } from '@penumbra-zone/ui/Popover'; -import { Button } from '@penumbra-zone/ui/Button'; -import { Density } from '@penumbra-zone/ui/Density'; -import { Pill } from '@penumbra-zone/ui/Pill'; -import { Text } from '@penumbra-zone/ui/Text'; +import { Popover, PopoverContext } from '@penumbra-zone/ui-deprecated/Popover'; +import { Button } from '@penumbra-zone/ui-deprecated/Button'; +import { Density } from '@penumbra-zone/ui-deprecated/Density'; +import { Pill } from '@penumbra-zone/ui-deprecated/Pill'; +import { Text } from '@penumbra-zone/ui-deprecated/Text'; import { statusSelector, useStatus } from '../../../state/status.ts'; import { useMemo } from 'react'; diff --git a/apps/minifront/src/components/v2/header/sync-bar.tsx b/apps/minifront/src/components/v2/header/sync-bar.tsx index 83e8df2fe4..5415a0d4d2 100644 --- a/apps/minifront/src/components/v2/header/sync-bar.tsx +++ b/apps/minifront/src/components/v2/header/sync-bar.tsx @@ -1,5 +1,5 @@ import { statusSelector, useStatus } from '../../../state/status.ts'; -import { Progress } from '@penumbra-zone/ui/Progress'; +import { Progress } from '@penumbra-zone/ui-deprecated/Progress'; export const SyncBar = () => { const status = useStatus({ diff --git a/apps/minifront/src/components/v2/layout.tsx b/apps/minifront/src/components/v2/layout.tsx index 45ab15ac59..1d5d7f3123 100644 --- a/apps/minifront/src/components/v2/layout.tsx +++ b/apps/minifront/src/components/v2/layout.tsx @@ -1,7 +1,6 @@ -import { Display } from '@penumbra-zone/ui/Display'; +import { Display } from '@penumbra-zone/ui-deprecated/Display'; import { HeadTag } from '../metadata/head-tag'; import { Outlet } from 'react-router-dom'; -import { Toaster } from '@penumbra-zone/ui/components/ui/toaster'; import { SyncingDialog } from '../syncing-dialog'; import { Header } from './header'; import { SyncBar } from './header/sync-bar.tsx'; @@ -14,7 +13,6 @@ export const Layout = () => (
- ); diff --git a/apps/minifront/src/components/v2/transfer-layout/index.tsx b/apps/minifront/src/components/v2/transfer-layout/index.tsx index b590c94994..76068561af 100644 --- a/apps/minifront/src/components/v2/transfer-layout/index.tsx +++ b/apps/minifront/src/components/v2/transfer-layout/index.tsx @@ -1,7 +1,7 @@ -import { Card } from '@penumbra-zone/ui/Card'; +import { Card } from '@penumbra-zone/ui-deprecated/Card'; import { Outlet, useNavigate } from 'react-router-dom'; -import { Grid } from '@penumbra-zone/ui/Grid'; -import { Tabs } from '@penumbra-zone/ui/Tabs'; +import { Grid } from '@penumbra-zone/ui-deprecated/Grid'; +import { Tabs } from '@penumbra-zone/ui-deprecated/Tabs'; import { usePagePath } from '../../../fetchers/page-path'; import { PagePath } from '../../metadata/paths'; import { motion } from 'framer-motion'; diff --git a/apps/minifront/src/components/v2/transfer-layout/receive-page/index.tsx b/apps/minifront/src/components/v2/transfer-layout/receive-page/index.tsx index a3808b2147..9cccb5f88f 100644 --- a/apps/minifront/src/components/v2/transfer-layout/receive-page/index.tsx +++ b/apps/minifront/src/components/v2/transfer-layout/receive-page/index.tsx @@ -1,6 +1,6 @@ -import { AccountSelector } from '@penumbra-zone/ui/AccountSelector'; -import { Card } from '@penumbra-zone/ui/Card'; -import { FormField } from '@penumbra-zone/ui/FormField'; +import { AccountSelector } from '@penumbra-zone/ui-deprecated/AccountSelector'; +import { Card } from '@penumbra-zone/ui-deprecated/Card'; +import { FormField } from '@penumbra-zone/ui-deprecated/FormField'; import { getAddrByIndex } from '../../../../fetchers/address'; export const ReceivePage = () => { diff --git a/apps/minifront/src/components/v2/transfer-layout/send-page/index.tsx b/apps/minifront/src/components/v2/transfer-layout/send-page/index.tsx index 53b9837d7b..847dd638d3 100644 --- a/apps/minifront/src/components/v2/transfer-layout/send-page/index.tsx +++ b/apps/minifront/src/components/v2/transfer-layout/send-page/index.tsx @@ -1,11 +1,11 @@ -import { Card } from '@penumbra-zone/ui/Card'; -import { FormField } from '@penumbra-zone/ui/FormField'; -import { SegmentedControl } from '@penumbra-zone/ui/SegmentedControl'; -import { TextInput } from '@penumbra-zone/ui/TextInput'; +import { Card } from '@penumbra-zone/ui-deprecated/Card'; +import { FormField } from '@penumbra-zone/ui-deprecated/FormField'; +import { SegmentedControl } from '@penumbra-zone/ui-deprecated/SegmentedControl'; +import { TextInput } from '@penumbra-zone/ui-deprecated/TextInput'; import { AllSlices } from '../../../../state'; import { sendValidationErrors } from '../../../../state/send'; import { FeeTier_Tier } from '@penumbra-zone/protobuf/penumbra/core/component/fee/v1/fee_pb'; -import { Button } from '@penumbra-zone/ui/Button'; +import { Button } from '@penumbra-zone/ui-deprecated/Button'; import { ArrowUpFromDot } from 'lucide-react'; import { useMemo } from 'react'; import { useStoreShallow } from '../../../../utils/use-store-shallow'; diff --git a/apps/minifront/src/icons/box.tsx b/apps/minifront/src/icons/box.tsx index e4422bc14f..e840e8f3f0 100644 --- a/apps/minifront/src/icons/box.tsx +++ b/apps/minifront/src/icons/box.tsx @@ -1,4 +1,4 @@ -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; export const BoxIcon = ({ stroke = '#BDB8B8', diff --git a/apps/minifront/src/icons/drag-handle-dots.tsx b/apps/minifront/src/icons/drag-handle-dots.tsx index f5c45a3bf3..5dcd44729e 100644 --- a/apps/minifront/src/icons/drag-handle-dots.tsx +++ b/apps/minifront/src/icons/drag-handle-dots.tsx @@ -1,4 +1,4 @@ -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; export const DragHandleDotsIcon = ({ stroke = '#BDB8B8', diff --git a/apps/minifront/src/icons/swap.tsx b/apps/minifront/src/icons/swap.tsx index f8564e0179..788a62df48 100644 --- a/apps/minifront/src/icons/swap.tsx +++ b/apps/minifront/src/icons/swap.tsx @@ -1,4 +1,4 @@ -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; export const SwapIcon = ({ stroke = '#BDB8B8', diff --git a/apps/minifront/src/main.tsx b/apps/minifront/src/main.tsx index bfbb86a17c..beccd56fc7 100644 --- a/apps/minifront/src/main.tsx +++ b/apps/minifront/src/main.tsx @@ -9,7 +9,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useState } from 'react'; import { RouterProvider } from 'react-router-dom'; import { rootRouter } from './components/root-router'; -import { PenumbraUIProvider } from '@penumbra-zone/ui/PenumbraUIProvider'; +import { PenumbraUIProvider } from '@penumbra-zone/ui-deprecated/PenumbraUIProvider'; const Main = () => { const [queryClient] = useState(() => new QueryClient()); diff --git a/apps/minifront/src/state/helpers.ts b/apps/minifront/src/state/helpers.ts index 79e33e0200..385acf6895 100644 --- a/apps/minifront/src/state/helpers.ts +++ b/apps/minifront/src/state/helpers.ts @@ -16,7 +16,7 @@ import { } from '@penumbra-zone/protobuf/penumbra/core/transaction/v1/transaction_pb'; import { TransactionId } from '@penumbra-zone/protobuf/penumbra/core/txhash/v1/txhash_pb'; import { PartialMessage } from '@bufbuild/protobuf'; -import { TransactionToast } from '@penumbra-zone/ui/lib/toast/transaction-toast'; +import { TransactionToast } from '@penumbra-zone/ui-deprecated/lib/toast/transaction-toast'; import { TransactionClassification } from '@penumbra-zone/perspective/transaction/classification'; import { uint8ArrayToHex } from '@penumbra-zone/types/hex'; import { fromValueView } from '@penumbra-zone/types/amount'; diff --git a/apps/minifront/src/state/ibc-in/index.tsx b/apps/minifront/src/state/ibc-in/index.tsx index 783b1490c6..e7530c2efc 100644 --- a/apps/minifront/src/state/ibc-in/index.tsx +++ b/apps/minifront/src/state/ibc-in/index.tsx @@ -4,7 +4,7 @@ import { ChainWalletContext } from '@cosmos-kit/core'; import { AllSlices, SliceCreator } from '..'; import { getAddrByIndex } from '../../fetchers/address'; import { bech32mAddress } from '@penumbra-zone/bech32m/penumbra'; -import { Toast } from '@penumbra-zone/ui/lib/toast/toast'; +import { Toast } from '@penumbra-zone/ui-deprecated/lib/toast/toast'; import { shorten } from '@penumbra-zone/types/string'; import { Address } from '@penumbra-zone/protobuf/penumbra/core/keys/v1/keys_pb'; import { bech32CompatAddress } from '@penumbra-zone/bech32m/penumbracompat1'; diff --git a/apps/minifront/src/state/ibc-out.ts b/apps/minifront/src/state/ibc-out.ts index 24b7d068fc..5a37e29c26 100644 --- a/apps/minifront/src/state/ibc-out.ts +++ b/apps/minifront/src/state/ibc-out.ts @@ -17,7 +17,7 @@ import { amountMoreThanBalance, isIncorrectDecimal, planBuildBroadcast } from '. import { getAssetId } from '@penumbra-zone/getters/metadata'; import { assetPatterns } from '@penumbra-zone/types/assets'; import { bech32, bech32m } from 'bech32'; -import { errorToast } from '@penumbra-zone/ui/lib/toast/presets'; +import { errorToast } from '@penumbra-zone/ui-deprecated/lib/toast/presets'; import { Chain } from '@penumbra-labs/registry'; import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { Channel } from '@penumbra-zone/protobuf/ibc/core/channel/v1/channel_pb'; diff --git a/apps/minifront/src/state/swap/dutch-auction/index.ts b/apps/minifront/src/state/swap/dutch-auction/index.ts index b3bdff1e21..40d436f871 100644 --- a/apps/minifront/src/state/swap/dutch-auction/index.ts +++ b/apps/minifront/src/state/swap/dutch-auction/index.ts @@ -11,7 +11,7 @@ import { sendSimulateTradeRequest } from '../helpers'; import { fromBaseUnitAmount, isZero, multiplyAmountByNumber } from '@penumbra-zone/types/amount'; import { getDisplayDenomExponent } from '@penumbra-zone/getters/metadata'; import { Amount } from '@penumbra-zone/protobuf/penumbra/core/num/v1/num_pb'; -import { errorToast } from '@penumbra-zone/ui/lib/toast/presets'; +import { errorToast } from '@penumbra-zone/ui-deprecated/lib/toast/presets'; import { ZQueryState, createZQuery } from '@penumbra-zone/zquery'; import { AuctionInfo, getAuctionInfos } from '../../../fetchers/auction-infos'; import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; diff --git a/apps/minifront/src/state/swap/instant-swap.ts b/apps/minifront/src/state/swap/instant-swap.ts index 10092acf63..b55dd6fe02 100644 --- a/apps/minifront/src/state/swap/instant-swap.ts +++ b/apps/minifront/src/state/swap/instant-swap.ts @@ -10,7 +10,7 @@ import { import { BigNumber } from 'bignumber.js'; import { getAddressByIndex } from '../../fetchers/address'; import { StateCommitment } from '@penumbra-zone/protobuf/penumbra/crypto/tct/v1/tct_pb'; -import { errorToast } from '@penumbra-zone/ui/lib/toast/presets'; +import { errorToast } from '@penumbra-zone/ui-deprecated/lib/toast/presets'; import { SwapExecution, SwapExecution_Trace, diff --git a/apps/node-status/package.json b/apps/node-status/package.json index fa169f2712..94360020d8 100644 --- a/apps/node-status/package.json +++ b/apps/node-status/package.json @@ -19,7 +19,7 @@ "@penumbra-zone/crypto-web": "workspace:*", "@penumbra-zone/protobuf": "workspace:*", "@penumbra-zone/types": "workspace:*", - "@penumbra-zone/ui": "workspace:*", + "@penumbra-zone/ui-deprecated": "workspace:*", "date-fns": "^3.6.0", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/apps/node-status/postcss.config.js b/apps/node-status/postcss.config.js index 8e18cdcb77..2bdefa943e 100644 --- a/apps/node-status/postcss.config.js +++ b/apps/node-status/postcss.config.js @@ -1 +1 @@ -export { default } from '@penumbra-zone/ui/postcss.config.js'; +export { default } from '@penumbra-zone/ui-deprecated/postcss.config.js'; diff --git a/apps/node-status/src/components/error-boundary.tsx b/apps/node-status/src/components/error-boundary.tsx index 3110463191..fdec27f87e 100644 --- a/apps/node-status/src/components/error-boundary.tsx +++ b/apps/node-status/src/components/error-boundary.tsx @@ -1,4 +1,4 @@ -import { SplashPage } from '@penumbra-zone/ui/components/ui/splash-page'; +import { SplashPage } from '@penumbra-zone/ui-deprecated/components/ui/splash-page'; import { useRouteError } from 'react-router-dom'; export const ErrorBoundary = () => { diff --git a/apps/node-status/src/components/frontend-referral.tsx b/apps/node-status/src/components/frontend-referral.tsx index cffca9789a..675339ca68 100644 --- a/apps/node-status/src/components/frontend-referral.tsx +++ b/apps/node-status/src/components/frontend-referral.tsx @@ -1,4 +1,4 @@ -import { Button } from '@penumbra-zone/ui/components/ui/button'; +import { Button } from '@penumbra-zone/ui-deprecated/components/ui/button'; import { devFrontend, prodFrontend } from '../constants'; export const FrontendReferral = () => { diff --git a/apps/node-status/src/components/header.tsx b/apps/node-status/src/components/header.tsx index 7581827bac..d63b5f0510 100644 --- a/apps/node-status/src/components/header.tsx +++ b/apps/node-status/src/components/header.tsx @@ -1,6 +1,6 @@ import { Link } from 'react-router-dom'; import { LineWave } from 'react-loader-spinner'; -import { cn } from '@penumbra-zone/ui/lib/utils'; +import { cn } from '@penumbra-zone/ui-deprecated/lib/utils'; import { useDelayedIsLoading } from '../fetching/refetch-hook'; export const Header = () => { diff --git a/apps/node-status/src/components/node-info.tsx b/apps/node-status/src/components/node-info.tsx index 2060b8a881..4dc1897856 100644 --- a/apps/node-status/src/components/node-info.tsx +++ b/apps/node-status/src/components/node-info.tsx @@ -1,6 +1,6 @@ import { useLoaderData } from 'react-router-dom'; -import { Card } from '@penumbra-zone/ui/components/ui/card'; -import { Identicon } from '@penumbra-zone/ui/components/ui/identicon'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; +import { Identicon } from '@penumbra-zone/ui-deprecated/components/ui/identicon'; import { IndexLoaderResponse } from '../fetching/loader'; import { uint8ArrayToString } from '@penumbra-zone/types/string'; diff --git a/apps/node-status/src/components/sync-info.tsx b/apps/node-status/src/components/sync-info.tsx index c3c3db2a77..a3745391bd 100644 --- a/apps/node-status/src/components/sync-info.tsx +++ b/apps/node-status/src/components/sync-info.tsx @@ -1,6 +1,6 @@ import { useLoaderData } from 'react-router-dom'; import { IndexLoaderResponse } from '../fetching/loader'; -import { Card } from '@penumbra-zone/ui/components/ui/card'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; import { format } from 'date-fns'; import { SyncInfo as SyncInfoProto } from '@penumbra-zone/protobuf/penumbra/util/tendermint_proxy/v1/tendermint_proxy_pb'; diff --git a/apps/node-status/src/components/validator-info.tsx b/apps/node-status/src/components/validator-info.tsx index d8f6a3d248..6b7018201d 100644 --- a/apps/node-status/src/components/validator-info.tsx +++ b/apps/node-status/src/components/validator-info.tsx @@ -1,5 +1,5 @@ import { useLoaderData } from 'react-router-dom'; -import { Card } from '@penumbra-zone/ui/components/ui/card'; +import { Card } from '@penumbra-zone/ui-deprecated/components/ui/card'; import { IndexLoaderResponse } from '../fetching/loader'; import { PublicKey } from '@penumbra-zone/protobuf/tendermint/crypto/keys_pb'; import { uint8ArrayToHex } from '@penumbra-zone/types/hex'; diff --git a/apps/node-status/src/main.tsx b/apps/node-status/src/main.tsx index df941faf75..05300b73df 100644 --- a/apps/node-status/src/main.tsx +++ b/apps/node-status/src/main.tsx @@ -3,7 +3,7 @@ import { createRoot } from 'react-dom/client'; import { RouterProvider } from 'react-router-dom'; import { router } from './components/router'; -import '@penumbra-zone/ui/styles/globals.css'; +import '@penumbra-zone/ui-deprecated/styles/globals.css'; const Main = () => ( diff --git a/packages/tailwind-config/index.js b/packages/tailwind-config/index.js index e78a25dddb..b374bf2d8e 100644 --- a/packages/tailwind-config/index.js +++ b/packages/tailwind-config/index.js @@ -2,7 +2,7 @@ import plugin from 'tailwindcss/plugin'; import tailwindCssAnimatePlugin from 'tailwindcss-animate'; // TODO: Replace the theme to v2 instead of partially using it -import { tailwindConfig as v2TailwindConfig } from '@penumbra-zone/ui/tailwind'; +import { tailwindConfig as v2TailwindConfig } from '@penumbra-zone/ui-deprecated/tailwind'; /** @type {import('tailwindcss').Config} */ export default { @@ -11,7 +11,8 @@ export default { './components/**/*.{ts,tsx}', './app/**/*.{ts,tsx}', './src/**/*.{ts,tsx}', - '../../packages/ui/components/**/*.{ts,tsx}', + '../../packages/ui-deprecated/components/**/*.{ts,tsx}', + './node_modules/@penumbra-zone/ui-deprecated/components/**/*.{ts,tsx}', './shared/**/*.{ts,tsx}', ], theme: { diff --git a/packages/tailwind-config/package.json b/packages/tailwind-config/package.json index 52b9ea25a6..5573bac1ff 100644 --- a/packages/tailwind-config/package.json +++ b/packages/tailwind-config/package.json @@ -5,7 +5,7 @@ "license": "(MIT OR Apache-2.0)", "main": "index.js", "dependencies": { - "@penumbra-zone/ui": "workspace:*", + "@penumbra-zone/ui-deprecated": "workspace:*", "tailwindcss": "^3.4.3", "tailwindcss-animate": "^1.0.7" } diff --git a/packages/ui/.storybook/main.js b/packages/ui-deprecated/.storybook/main.js similarity index 100% rename from packages/ui/.storybook/main.js rename to packages/ui-deprecated/.storybook/main.js diff --git a/packages/ui/.storybook/manager.js b/packages/ui-deprecated/.storybook/manager.js similarity index 100% rename from packages/ui/.storybook/manager.js rename to packages/ui-deprecated/.storybook/manager.js diff --git a/packages/ui/.storybook/penumbraTheme.js b/packages/ui-deprecated/.storybook/penumbraTheme.js similarity index 100% rename from packages/ui/.storybook/penumbraTheme.js rename to packages/ui-deprecated/.storybook/penumbraTheme.js diff --git a/packages/ui/.storybook/preview.jsx b/packages/ui-deprecated/.storybook/preview.jsx similarity index 100% rename from packages/ui/.storybook/preview.jsx rename to packages/ui-deprecated/.storybook/preview.jsx diff --git a/packages/ui-tailwind/.storybook/public/logo.svg b/packages/ui-deprecated/.storybook/public/logo.svg similarity index 100% rename from packages/ui-tailwind/.storybook/public/logo.svg rename to packages/ui-deprecated/.storybook/public/logo.svg diff --git a/packages/ui/CHANGELOG.md b/packages/ui-deprecated/CHANGELOG.md similarity index 100% rename from packages/ui/CHANGELOG.md rename to packages/ui-deprecated/CHANGELOG.md diff --git a/packages/ui-deprecated/README.md b/packages/ui-deprecated/README.md new file mode 100644 index 0000000000..8cacdb531d --- /dev/null +++ b/packages/ui-deprecated/README.md @@ -0,0 +1,364 @@ +# Penumbra UI + +The Penumbra UI library is a set of UI components purpose-built for the Penumbra ecosystem. Use these components to get rendering of various Penumbra data types out of the box, and to create a UI that is consistent with other Penumbra UIs' look and feel. + +## Storybook + +All Penumbra UI components (except some deprecated ones) in the latest tagged release can be found at the Penumbra UI Storybook site: https://ui.penumbra.zone/ + +To view the latest components merged to `main` (even if they are not yet in a tagged release), check out the Storybook Preview site: https://preview.ui.penumbra.zone/ + +## Set up + +First, install the library: + +```bash +npm install @penumbra-zone/ui +``` + +Then, use components by importing them from their specific files: + +```tsx +import { ValueViewComponent } from '@penumbra-zone/ui/ValueViewComponent'; +``` + +## Usage + +### Density + +Many Penumbra UI components come in two densities: `sparse` and `compact`. This feature allows Penumbra UI consumers to choose how to present data based on the context. For example, a table with dozens or hundreds of rows would be well suited to a `compact` density, while an interactive form could use the `sparse` density. + +To control density, use the `` component with either the `sparse` or `compact` prop: + +```tsx + + {/* ... */}
+
+``` + +In the example above, the `` (and all Penumbra UI components inside of it that have density variants) will use the `compact` variant, ensuring consistency throughout the layout. + +To enable density variants in your own components and layouts, import and use the `useDensity()` hook: + +```tsx +const MyComponent = () => { + const density = useDensity(); + + return
{/* ... */}
; +}; +``` + +That way, `` will have looser padding when wrapped with ``, and tighter when wrapped with ``. + +## Development + +These guidelines are for maintainers of the components in the Penumbra UI library. + +### Guiding principles + +To ensure consistency in the code design of the Penumbra UI components, and to maintain an optimal developer experience, developers should adhere to these guidelines. + +#### Keep design decisions to a minimum for Penumbra UI consumers. + +Penumbra UI aims to take as much as possible of the design-related decision-making out of developers' hands. Developers using Penumbra UI should be freed up to focus on _functionality_, rather than needing to think about what colors would "look nice" or what spacing would "feel right." Specifically: + +##### Props and their values should be named to indicate their _use_, rather than their _effect on appearance_. + +For example, buttons have a `priority` prop to determine whether a given button is `primary` or `secondary`. This allows consumers to set the prop based on how the button is _used_: if it's the "Confirm" button for a popup dialog, it would obviously have a `primary` priority. If it's a "Cancel" button underneath the "Confirm" button, it would have a `secondary` priority. + +It just so happens that the primary button has a filled-in, solid-color background, while the secondary button has a transparent background and a subtle border. Notice, though, that Penumbra UI buttons don't accept `backgroundColor` or `borderColor` props. Nor do they accept `className` props that would allow consumers to customize their appearance in any number of other ways (that would be even worse!). For that matter, they don't even have a `variant` prop with values like `filled` vs. `outlined`. Why not? Because if they did, two developers working on the same app might end up using those visual styles in inconsistent ways, resulting in a disjointed UI. + +Instead, the `priority` prop is so named to indicate that it should be set based on how the button is used. Then, Penumbra UI itself makes the right decision about how to style it based on that use case. + +##### Components must not accept `className` or `style` props. + +This ensures that each component is internally responsible for its own styling. + +Any variations of the component's appearance must be controlled via props like `state`, `priority` etc. — not by kitchen-sink props like `className` and `style`, which allow arbitrary changes to be made that could interfere with the internal structure of the component and cause visual inconsistencies between instances of Penumbra UI components. + +##### Components should not define external margins or absolute/fixed positioning. + +Components may only define their internal spacing and layout — never external spacing and layout. This ensures that components can be reused in any context. + +External spacing and positioning is the responsibility of parent components, and can be achieved in the parent via, e.g., wrapper `
`s that position components appropriately. + +(Note that absolute positioning _is_ acceptable for elements who have a higher-level relative-positioned element in the same component, since that means that the absolute-positioned element is still contained within the component's layout. There also a few exceptions to this rule, such as for tooltips and dropdown menus, as well as for page-level components that absolutely position a child component via a wrapper.) + +###### Correct + +```tsx +// BackgroundAnimation/index.tsx +export function BackgroundAnimation() { + return ; +} + +// SplashPage/index.tsx +export function SplashPage() { + return ( + // ✅ CORRECT: position the background animation in the center of the screen + // using a wrapper div in the parent +
+ +
+ ); +} +``` + +###### Incorrect + +```tsx +// BackgroundAnimation/index.tsx +export function BackgroundAnimation() { + return ( + // ❌ INCORRECT: do not absolute-position elements in a non-page-level + // component +
+ ; +
+ ); +} + +// SplashPage/index.tsx +export function SplashPage() { + return ; +} +``` + +###### Correct + +```tsx +// AssetIcon/index.tsx +export interface AssetIconProps { + display: string; + src: string; +} + +export function AssetIcon({ display, src }: AssetIconProps) { + return {`Icon; +} + +// ValueComponent/index.tsx +export interface ValueComponentProps { + value: Value; + metadata: Metadata; +} + +export function ValueComponent({ value, metadata }: ValueComponentProps) { + return ( + + // ✅ CORRECT: define space around components using wrapper divs +
+ + + {metadata.display} +
+
+ ); +} +``` + +###### Incorrect + +```tsx +// AssetIcon/index.tsx +export interface AssetIconProps { + display: string; + src: string; +} + +export function AssetIcon({ display, src }: AssetIconProps) { + return ( + {`Icon + ); +} + +// ValueComponent/index.tsx +export interface ValueComponentProps { + value: Value; + metadata: Metadata; +} + +export function ValueComponent({ value, metadata }: ValueComponentProps) { + return ( + + + {metadata.display} + + ); +} +``` + +#### Document and test Penumbra UI components thoroughly. + +Penumbra UI is a public package available for anyone in the Penumbra ecosystem to use. As such, its documentation and tests should be given first-class treatment. Specifically: + +##### Components should include Storybook stories. + +[Storybook stories](https://storybook.js.org/docs/react/writing-stories/introduction) are pages in Storybook that showcase a particular component, usually with controls that allow the user to edit its props. + +Storybook stories should be located next to the component they apply to, and have a file suffix of `.stories.ts(x)`. For example, a component located at `src/Button/index.tsx` should have stories at `src/Button/index.stories.tsx`. + +When writing stories, make sure to tag your stories with [`autodocs`](https://storybook.js.org/docs/react/writing-docs/autodocs). This is a Storybook feature that analyzes your component code to auto-generate documentation for your component, including a code sample, controls for each of the props, etc. + +##### Documentation of component props should be written with JSDoc syntax. + +[JSDoc-style comments](https://jsdoc.app/about-getting-started.html#adding-documentation-comments-to-your-code) (`/** ... */`) should be written before any props that need to be documented so that A) IDEs can pull them in for tooltips, and B) Storybook can use them in the Storybook UI. + +##### Components' rendering logic should be covered via unit tests. + +```tsx +// FooBarAndMaybeBaz/index.tsx +export interface FooBarAndMaybeBazProps { + baz?: boolean; +} + +export function FooBarAndMaybeBaz({ baz }: FooBarAndMaybeBazProps) { + return ( +
    +
  • Foo
  • +
  • Bar
  • + {baz &&
  • Baz
  • } +
+ ); +} + +// FooBarAndMaybeBaz/index.test.tsx +import { render } from '@testing-library/react'; + +describe('', () => { + it('renders `baz` when the `baz` prop is `true`', () => { + const { queryByText } = render(); + + expect(queryByText('Baz')).not.toBeNull(); + }); + + it('does not render `baz` when the `baz` prop is falsy', () => { + const { queryByText } = render(); + + expect(queryByText('Baz')).toBeNull(); + }); +}); +``` + +Note that we do not use unit tests to test the visual appearance of components; that's a job better suited to screenshot testing, which we may implement in the future. + +### Code style and file organization guidelines + +#### Components must be located at `./components/v2//index.tsx`. + +This ensures that the Penumbra UI `package.json` `exports` field works as intended, so that components can be imported via `@penumbra-zone/ui/`. + +Note that `` should be replaced with the `UpperCamelCase` component name — e.g., `./components/v2/LoadingIndicator/index.tsx`. + +#### Internal-use components that are only used within a parent component must sit in the parent component's directory, rather than be a sibling of the parent directory. + +This guideline only applies to components that are _not_ intended to be used externally, but are only to be used as dependencies of other Penumbra UI library components. + +``` +- src/components/ + - HeaderWithDropdown/ + - index.tsx + - Dropdown.tsx ✅ Correct, if Dropdown is only ever used inside HeaderWithDropdown +``` + +``` +- src/components/ + - Dropdown.tsx ❌ Wrong, if Dropdown is only ever used inside HeaderWithDropdown + - HeaderWithDropdown/ + - index.tsx +``` + +(One exception to this rule: if you're developing a component that will eventually be used by multiple other components, and just happens to be a child of only a single component at the moment, you can leave it as a sibling of its parent.) + +#### Internal-use components should be located at the most specific possible directory level. + +This guideline only applies to components that are _not_ intended to be used externally, but are only to be used as dependencies of other Penumbra UI library components. + +For example, if the `Dropdown` component is used by both `HeaderWithDropdown` and `Menu` components, `Dropdown` should be placed in the lowest-level directory that contains both `HeaderWithDropdown` and `Menu`: + +``` +- src/components/ + - SomeCommonParentOfBothHeaderWithDropdownAndMenu/ + - index.tsx + - HeaderWithDropdown/ + - index.tsx + - index.test.tsx + - Menu/ + - index.tsx + - index.test.tsx + - Dropdown.tsx ✅ Correct - Dropdown is used by both Menu and HeaderWithDropdown, so it's a sibling to both +``` + +This, as opposed to e.g., placing it inside the `HeaderWithDropdown` directory (and then importing it from there in `Menu`), or inside a root-level directory. This way, components are nested as closely to the components using them as possible. + +``` +- src/components/ + - SomeCommonParentOfBothHeaderWithDropdownAndMenu/ + - index.tsx + - HeaderWithDropdown/ + - index.tsx + - index.test.tsx + - Dropdown.tsx ❌ Wrong - Menu shouldn't be importing a child of HeaderWithDropdown + - Menu/ + - index.tsx + - index.test.tsx +``` + +#### Component props must be exported from the component file as `Props`. + +For example: + +```tsx +export interface MyComponentProps { + color: Color; +} + +export function MyComponent({ color }: MyComponentProps) { + // ... +} +``` + +#### Components built for Protobuf types must be suffixed with `Component` to avoid naming collisions. + +For example, a component designed to render a `ValueView` must be named `ValueViewComponent`, rather than `ValueView`, to avoid awkward naming collisions for consumers: + +```tsx +// ValueViewComponent/index.tsx +import { ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; + +export interface ValueViewComponentProps { + valueView: ValueView; +} + +export function ValueViewComponent({ valueView }: ValueViewComponentProps) { + // ... +} + +// SomeConsumer.tsx +// ✅ Now, there is no naming conflict between these two imports. +import { ValueView } from 'penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; +import { ValueViewComponent } from '@penumbra-zone/ui/ValueViewComponent'; +``` + +#### Use the `useDensity()` hook to control component density. + +Components should never accept a `density` prop to control their density. This ensures that all components in a given density context will be rendered with the same density. + +##### Using density with Storybook + +If you're creating a component that has density variants, use the `density` tag for your Storybook stories: + +```ts +const meta: Meta = { + component: MyComponent, + tags: ['density'], + // ... +}; +``` + +Storybook will then add a control for density, so that density can be controlled via context. diff --git a/packages/ui/components.json b/packages/ui-deprecated/components.json similarity index 100% rename from packages/ui/components.json rename to packages/ui-deprecated/components.json diff --git a/packages/ui/components/README.md b/packages/ui-deprecated/components/README.md similarity index 100% rename from packages/ui/components/README.md rename to packages/ui-deprecated/components/README.md diff --git a/packages/ui/components/readme.mdx b/packages/ui-deprecated/components/readme.mdx similarity index 100% rename from packages/ui/components/readme.mdx rename to packages/ui-deprecated/components/readme.mdx diff --git a/packages/ui/components/ui/account-switcher/account-switcher.test.tsx b/packages/ui-deprecated/components/ui/account-switcher/account-switcher.test.tsx similarity index 100% rename from packages/ui/components/ui/account-switcher/account-switcher.test.tsx rename to packages/ui-deprecated/components/ui/account-switcher/account-switcher.test.tsx diff --git a/packages/ui/components/ui/account-switcher/index.tsx b/packages/ui-deprecated/components/ui/account-switcher/index.tsx similarity index 100% rename from packages/ui/components/ui/account-switcher/index.tsx rename to packages/ui-deprecated/components/ui/account-switcher/index.tsx diff --git a/packages/ui/components/ui/address-view/address-view.stories.tsx b/packages/ui-deprecated/components/ui/address-view/address-view.stories.tsx similarity index 100% rename from packages/ui/components/ui/address-view/address-view.stories.tsx rename to packages/ui-deprecated/components/ui/address-view/address-view.stories.tsx diff --git a/packages/ui/components/ui/address-view/address-view.test.tsx b/packages/ui-deprecated/components/ui/address-view/address-view.test.tsx similarity index 100% rename from packages/ui/components/ui/address-view/address-view.test.tsx rename to packages/ui-deprecated/components/ui/address-view/address-view.test.tsx diff --git a/packages/ui/components/ui/address-view/index.tsx b/packages/ui-deprecated/components/ui/address-view/index.tsx similarity index 100% rename from packages/ui/components/ui/address-view/index.tsx rename to packages/ui-deprecated/components/ui/address-view/index.tsx diff --git a/packages/ui/components/ui/address/address-component.test.tsx b/packages/ui-deprecated/components/ui/address/address-component.test.tsx similarity index 100% rename from packages/ui/components/ui/address/address-component.test.tsx rename to packages/ui-deprecated/components/ui/address/address-component.test.tsx diff --git a/packages/ui/components/ui/address/address-component.tsx b/packages/ui-deprecated/components/ui/address/address-component.tsx similarity index 100% rename from packages/ui/components/ui/address/address-component.tsx rename to packages/ui-deprecated/components/ui/address/address-component.tsx diff --git a/packages/ui/components/ui/address/address-icon.tsx b/packages/ui-deprecated/components/ui/address/address-icon.tsx similarity index 100% rename from packages/ui/components/ui/address/address-icon.tsx rename to packages/ui-deprecated/components/ui/address/address-icon.tsx diff --git a/packages/ui/components/ui/address/index.tsx b/packages/ui-deprecated/components/ui/address/index.tsx similarity index 100% rename from packages/ui/components/ui/address/index.tsx rename to packages/ui-deprecated/components/ui/address/index.tsx diff --git a/packages/ui/components/ui/asset-icon/asset-icon.stories.tsx b/packages/ui-deprecated/components/ui/asset-icon/asset-icon.stories.tsx similarity index 100% rename from packages/ui/components/ui/asset-icon/asset-icon.stories.tsx rename to packages/ui-deprecated/components/ui/asset-icon/asset-icon.stories.tsx diff --git a/packages/ui/components/ui/asset-icon/delegation-token-icon.tsx b/packages/ui-deprecated/components/ui/asset-icon/delegation-token-icon.tsx similarity index 100% rename from packages/ui/components/ui/asset-icon/delegation-token-icon.tsx rename to packages/ui-deprecated/components/ui/asset-icon/delegation-token-icon.tsx diff --git a/packages/ui/components/ui/asset-icon/index.tsx b/packages/ui-deprecated/components/ui/asset-icon/index.tsx similarity index 100% rename from packages/ui/components/ui/asset-icon/index.tsx rename to packages/ui-deprecated/components/ui/asset-icon/index.tsx diff --git a/packages/ui/components/ui/asset-icon/unbonding-token-icon.tsx b/packages/ui-deprecated/components/ui/asset-icon/unbonding-token-icon.tsx similarity index 100% rename from packages/ui/components/ui/asset-icon/unbonding-token-icon.tsx rename to packages/ui-deprecated/components/ui/asset-icon/unbonding-token-icon.tsx diff --git a/packages/ui/components/ui/auction-id-component/index.tsx b/packages/ui-deprecated/components/ui/auction-id-component/index.tsx similarity index 100% rename from packages/ui/components/ui/auction-id-component/index.tsx rename to packages/ui-deprecated/components/ui/auction-id-component/index.tsx diff --git a/packages/ui/components/ui/avatar/avatar.stories.tsx b/packages/ui-deprecated/components/ui/avatar/avatar.stories.tsx similarity index 100% rename from packages/ui/components/ui/avatar/avatar.stories.tsx rename to packages/ui-deprecated/components/ui/avatar/avatar.stories.tsx diff --git a/packages/ui/components/ui/avatar/index.tsx b/packages/ui-deprecated/components/ui/avatar/index.tsx similarity index 100% rename from packages/ui/components/ui/avatar/index.tsx rename to packages/ui-deprecated/components/ui/avatar/index.tsx diff --git a/packages/ui/components/ui/balance-value-view/balance-value-view.test.tsx b/packages/ui-deprecated/components/ui/balance-value-view/balance-value-view.test.tsx similarity index 100% rename from packages/ui/components/ui/balance-value-view/balance-value-view.test.tsx rename to packages/ui-deprecated/components/ui/balance-value-view/balance-value-view.test.tsx diff --git a/packages/ui/components/ui/balance-value-view/index.tsx b/packages/ui-deprecated/components/ui/balance-value-view/index.tsx similarity index 100% rename from packages/ui/components/ui/balance-value-view/index.tsx rename to packages/ui-deprecated/components/ui/balance-value-view/index.tsx diff --git a/packages/ui/components/ui/banner/banner.test.tsx b/packages/ui-deprecated/components/ui/banner/banner.test.tsx similarity index 100% rename from packages/ui/components/ui/banner/banner.test.tsx rename to packages/ui-deprecated/components/ui/banner/banner.test.tsx diff --git a/packages/ui/components/ui/banner/index.tsx b/packages/ui-deprecated/components/ui/banner/index.tsx similarity index 100% rename from packages/ui/components/ui/banner/index.tsx rename to packages/ui-deprecated/components/ui/banner/index.tsx diff --git a/packages/ui/components/ui/block-sync-status/block-sync-status.tsx b/packages/ui-deprecated/components/ui/block-sync-status/block-sync-status.tsx similarity index 100% rename from packages/ui/components/ui/block-sync-status/block-sync-status.tsx rename to packages/ui-deprecated/components/ui/block-sync-status/block-sync-status.tsx diff --git a/packages/ui/components/ui/block-sync-status/ewma.test.ts b/packages/ui-deprecated/components/ui/block-sync-status/ewma.test.ts similarity index 100% rename from packages/ui/components/ui/block-sync-status/ewma.test.ts rename to packages/ui-deprecated/components/ui/block-sync-status/ewma.test.ts diff --git a/packages/ui/components/ui/block-sync-status/ewma.ts b/packages/ui-deprecated/components/ui/block-sync-status/ewma.ts similarity index 100% rename from packages/ui/components/ui/block-sync-status/ewma.ts rename to packages/ui-deprecated/components/ui/block-sync-status/ewma.ts diff --git a/packages/ui/components/ui/block-sync-status/hooks.ts b/packages/ui-deprecated/components/ui/block-sync-status/hooks.ts similarity index 100% rename from packages/ui/components/ui/block-sync-status/hooks.ts rename to packages/ui-deprecated/components/ui/block-sync-status/hooks.ts diff --git a/packages/ui/components/ui/block-sync-status/index.tsx b/packages/ui-deprecated/components/ui/block-sync-status/index.tsx similarity index 100% rename from packages/ui/components/ui/block-sync-status/index.tsx rename to packages/ui-deprecated/components/ui/block-sync-status/index.tsx diff --git a/packages/ui/components/ui/box/box.stories.tsx b/packages/ui-deprecated/components/ui/box/box.stories.tsx similarity index 100% rename from packages/ui/components/ui/box/box.stories.tsx rename to packages/ui-deprecated/components/ui/box/box.stories.tsx diff --git a/packages/ui/components/ui/box/index.tsx b/packages/ui-deprecated/components/ui/box/index.tsx similarity index 100% rename from packages/ui/components/ui/box/index.tsx rename to packages/ui-deprecated/components/ui/box/index.tsx diff --git a/packages/ui/components/ui/button/button.stories.tsx b/packages/ui-deprecated/components/ui/button/button.stories.tsx similarity index 100% rename from packages/ui/components/ui/button/button.stories.tsx rename to packages/ui-deprecated/components/ui/button/button.stories.tsx diff --git a/packages/ui/components/ui/button/index.tsx b/packages/ui-deprecated/components/ui/button/index.tsx similarity index 100% rename from packages/ui/components/ui/button/index.tsx rename to packages/ui-deprecated/components/ui/button/index.tsx diff --git a/packages/ui/components/ui/candlestick-plot/index.tsx b/packages/ui-deprecated/components/ui/candlestick-plot/index.tsx similarity index 100% rename from packages/ui/components/ui/candlestick-plot/index.tsx rename to packages/ui-deprecated/components/ui/candlestick-plot/index.tsx diff --git a/packages/ui/components/ui/card/card.stories.tsx b/packages/ui-deprecated/components/ui/card/card.stories.tsx similarity index 100% rename from packages/ui/components/ui/card/card.stories.tsx rename to packages/ui-deprecated/components/ui/card/card.stories.tsx diff --git a/packages/ui/components/ui/card/index.tsx b/packages/ui-deprecated/components/ui/card/index.tsx similarity index 100% rename from packages/ui/components/ui/card/index.tsx rename to packages/ui-deprecated/components/ui/card/index.tsx diff --git a/packages/ui/components/ui/command/index.tsx b/packages/ui-deprecated/components/ui/command/index.tsx similarity index 100% rename from packages/ui/components/ui/command/index.tsx rename to packages/ui-deprecated/components/ui/command/index.tsx diff --git a/packages/ui/components/ui/copy-to-clipboard/copy-to-clipboard-icon-button.tsx b/packages/ui-deprecated/components/ui/copy-to-clipboard/copy-to-clipboard-icon-button.tsx similarity index 100% rename from packages/ui/components/ui/copy-to-clipboard/copy-to-clipboard-icon-button.tsx rename to packages/ui-deprecated/components/ui/copy-to-clipboard/copy-to-clipboard-icon-button.tsx diff --git a/packages/ui/components/ui/copy-to-clipboard/copy-to-clipboard.tsx b/packages/ui-deprecated/components/ui/copy-to-clipboard/copy-to-clipboard.tsx similarity index 100% rename from packages/ui/components/ui/copy-to-clipboard/copy-to-clipboard.tsx rename to packages/ui-deprecated/components/ui/copy-to-clipboard/copy-to-clipboard.tsx diff --git a/packages/ui/components/ui/copy-to-clipboard/index.tsx b/packages/ui-deprecated/components/ui/copy-to-clipboard/index.tsx similarity index 100% rename from packages/ui/components/ui/copy-to-clipboard/index.tsx rename to packages/ui-deprecated/components/ui/copy-to-clipboard/index.tsx diff --git a/packages/ui/components/ui/dialog/dialog.stories.tsx b/packages/ui-deprecated/components/ui/dialog/dialog.stories.tsx similarity index 100% rename from packages/ui/components/ui/dialog/dialog.stories.tsx rename to packages/ui-deprecated/components/ui/dialog/dialog.stories.tsx diff --git a/packages/ui/components/ui/dialog/index.tsx b/packages/ui-deprecated/components/ui/dialog/index.tsx similarity index 100% rename from packages/ui/components/ui/dialog/index.tsx rename to packages/ui-deprecated/components/ui/dialog/index.tsx diff --git a/packages/ui/components/ui/dutch-auction-component/expanded-details/get-price.test.ts b/packages/ui-deprecated/components/ui/dutch-auction-component/expanded-details/get-price.test.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/expanded-details/get-price.test.ts rename to packages/ui-deprecated/components/ui/dutch-auction-component/expanded-details/get-price.test.ts diff --git a/packages/ui/components/ui/dutch-auction-component/expanded-details/get-price.ts b/packages/ui-deprecated/components/ui/dutch-auction-component/expanded-details/get-price.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/expanded-details/get-price.ts rename to packages/ui-deprecated/components/ui/dutch-auction-component/expanded-details/get-price.ts diff --git a/packages/ui/components/ui/dutch-auction-component/expanded-details/get-step-index.test.ts b/packages/ui-deprecated/components/ui/dutch-auction-component/expanded-details/get-step-index.test.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/expanded-details/get-step-index.test.ts rename to packages/ui-deprecated/components/ui/dutch-auction-component/expanded-details/get-step-index.test.ts diff --git a/packages/ui/components/ui/dutch-auction-component/expanded-details/get-step-index.ts b/packages/ui-deprecated/components/ui/dutch-auction-component/expanded-details/get-step-index.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/expanded-details/get-step-index.ts rename to packages/ui-deprecated/components/ui/dutch-auction-component/expanded-details/get-step-index.ts diff --git a/packages/ui/components/ui/dutch-auction-component/expanded-details/index.tsx b/packages/ui-deprecated/components/ui/dutch-auction-component/expanded-details/index.tsx similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/expanded-details/index.tsx rename to packages/ui-deprecated/components/ui/dutch-auction-component/expanded-details/index.tsx diff --git a/packages/ui/components/ui/dutch-auction-component/index.tsx b/packages/ui-deprecated/components/ui/dutch-auction-component/index.tsx similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/index.tsx rename to packages/ui-deprecated/components/ui/dutch-auction-component/index.tsx diff --git a/packages/ui/components/ui/dutch-auction-component/progress-bar/get-human-readable-interval.test.ts b/packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/get-human-readable-interval.test.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/progress-bar/get-human-readable-interval.test.ts rename to packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/get-human-readable-interval.test.ts diff --git a/packages/ui/components/ui/dutch-auction-component/progress-bar/get-human-readable-interval.ts b/packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/get-human-readable-interval.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/progress-bar/get-human-readable-interval.ts rename to packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/get-human-readable-interval.ts diff --git a/packages/ui/components/ui/dutch-auction-component/progress-bar/helpers.ts b/packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/helpers.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/progress-bar/helpers.ts rename to packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/helpers.ts diff --git a/packages/ui/components/ui/dutch-auction-component/progress-bar/index.tsx b/packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/index.tsx similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/progress-bar/index.tsx rename to packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/index.tsx diff --git a/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.test.ts b/packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.test.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.test.ts rename to packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.test.ts diff --git a/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.ts b/packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.ts similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.ts rename to packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/indicator/get-progress.ts diff --git a/packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/index.tsx b/packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/indicator/index.tsx similarity index 100% rename from packages/ui/components/ui/dutch-auction-component/progress-bar/indicator/index.tsx rename to packages/ui-deprecated/components/ui/dutch-auction-component/progress-bar/indicator/index.tsx diff --git a/packages/ui/components/ui/fade-in/index.tsx b/packages/ui-deprecated/components/ui/fade-in/index.tsx similarity index 100% rename from packages/ui/components/ui/fade-in/index.tsx rename to packages/ui-deprecated/components/ui/fade-in/index.tsx diff --git a/packages/ui/components/ui/fade-transition/index.tsx b/packages/ui-deprecated/components/ui/fade-transition/index.tsx similarity index 100% rename from packages/ui/components/ui/fade-transition/index.tsx rename to packages/ui-deprecated/components/ui/fade-transition/index.tsx diff --git a/packages/ui/components/ui/gradient-header/index.tsx b/packages/ui-deprecated/components/ui/gradient-header/index.tsx similarity index 100% rename from packages/ui/components/ui/gradient-header/index.tsx rename to packages/ui-deprecated/components/ui/gradient-header/index.tsx diff --git a/packages/ui/components/ui/icon-input/index.tsx b/packages/ui-deprecated/components/ui/icon-input/index.tsx similarity index 100% rename from packages/ui/components/ui/icon-input/index.tsx rename to packages/ui-deprecated/components/ui/icon-input/index.tsx diff --git a/packages/ui/components/ui/icons/back-icon.tsx b/packages/ui-deprecated/components/ui/icons/back-icon.tsx similarity index 100% rename from packages/ui/components/ui/icons/back-icon.tsx rename to packages/ui-deprecated/components/ui/icons/back-icon.tsx diff --git a/packages/ui/components/ui/icons/incognito.tsx b/packages/ui-deprecated/components/ui/icons/incognito.tsx similarity index 100% rename from packages/ui/components/ui/icons/incognito.tsx rename to packages/ui-deprecated/components/ui/icons/incognito.tsx diff --git a/packages/ui/components/ui/icons/wallet.tsx b/packages/ui-deprecated/components/ui/icons/wallet.tsx similarity index 100% rename from packages/ui/components/ui/icons/wallet.tsx rename to packages/ui-deprecated/components/ui/icons/wallet.tsx diff --git a/packages/ui-tailwind/src/Identicon/generate.ts b/packages/ui-deprecated/components/ui/identicon/generate.ts similarity index 100% rename from packages/ui-tailwind/src/Identicon/generate.ts rename to packages/ui-deprecated/components/ui/identicon/generate.ts diff --git a/packages/ui/components/ui/identicon/index.tsx b/packages/ui-deprecated/components/ui/identicon/index.tsx similarity index 100% rename from packages/ui/components/ui/identicon/index.tsx rename to packages/ui-deprecated/components/ui/identicon/index.tsx diff --git a/packages/ui/components/ui/identicon/types.ts b/packages/ui-deprecated/components/ui/identicon/types.ts similarity index 100% rename from packages/ui/components/ui/identicon/types.ts rename to packages/ui-deprecated/components/ui/identicon/types.ts diff --git a/packages/ui/components/ui/identity-key-component/index.tsx b/packages/ui-deprecated/components/ui/identity-key-component/index.tsx similarity index 100% rename from packages/ui/components/ui/identity-key-component/index.tsx rename to packages/ui-deprecated/components/ui/identity-key-component/index.tsx diff --git a/packages/ui/components/ui/incompatible-browser-banner/get-compatibility.ts b/packages/ui-deprecated/components/ui/incompatible-browser-banner/get-compatibility.ts similarity index 100% rename from packages/ui/components/ui/incompatible-browser-banner/get-compatibility.ts rename to packages/ui-deprecated/components/ui/incompatible-browser-banner/get-compatibility.ts diff --git a/packages/ui/components/ui/incompatible-browser-banner/incompatible-browser-banner.test.tsx b/packages/ui-deprecated/components/ui/incompatible-browser-banner/incompatible-browser-banner.test.tsx similarity index 100% rename from packages/ui/components/ui/incompatible-browser-banner/incompatible-browser-banner.test.tsx rename to packages/ui-deprecated/components/ui/incompatible-browser-banner/incompatible-browser-banner.test.tsx diff --git a/packages/ui/components/ui/incompatible-browser-banner/index.tsx b/packages/ui-deprecated/components/ui/incompatible-browser-banner/index.tsx similarity index 100% rename from packages/ui/components/ui/incompatible-browser-banner/index.tsx rename to packages/ui-deprecated/components/ui/incompatible-browser-banner/index.tsx diff --git a/packages/ui/components/ui/input/index.tsx b/packages/ui-deprecated/components/ui/input/index.tsx similarity index 100% rename from packages/ui/components/ui/input/index.tsx rename to packages/ui-deprecated/components/ui/input/index.tsx diff --git a/packages/ui/components/ui/json-viewer/index.tsx b/packages/ui-deprecated/components/ui/json-viewer/index.tsx similarity index 100% rename from packages/ui/components/ui/json-viewer/index.tsx rename to packages/ui-deprecated/components/ui/json-viewer/index.tsx diff --git a/packages/ui/components/ui/logo/animated-penumbra.tsx b/packages/ui-deprecated/components/ui/logo/animated-penumbra.tsx similarity index 100% rename from packages/ui/components/ui/logo/animated-penumbra.tsx rename to packages/ui-deprecated/components/ui/logo/animated-penumbra.tsx diff --git a/packages/ui/components/ui/logo/animation-logic.ts b/packages/ui-deprecated/components/ui/logo/animation-logic.ts similarity index 100% rename from packages/ui/components/ui/logo/animation-logic.ts rename to packages/ui-deprecated/components/ui/logo/animation-logic.ts diff --git a/packages/ui/components/ui/logo/original-animated-penumbra.svg b/packages/ui-deprecated/components/ui/logo/original-animated-penumbra.svg similarity index 100% rename from packages/ui/components/ui/logo/original-animated-penumbra.svg rename to packages/ui-deprecated/components/ui/logo/original-animated-penumbra.svg diff --git a/packages/ui/components/ui/logo/perlin-noise.ts b/packages/ui-deprecated/components/ui/logo/perlin-noise.ts similarity index 100% rename from packages/ui/components/ui/logo/perlin-noise.ts rename to packages/ui-deprecated/components/ui/logo/perlin-noise.ts diff --git a/packages/ui/components/ui/logo/static.tsx b/packages/ui-deprecated/components/ui/logo/static.tsx similarity index 100% rename from packages/ui/components/ui/logo/static.tsx rename to packages/ui-deprecated/components/ui/logo/static.tsx diff --git a/packages/ui/components/ui/pill/index.tsx b/packages/ui-deprecated/components/ui/pill/index.tsx similarity index 100% rename from packages/ui/components/ui/pill/index.tsx rename to packages/ui-deprecated/components/ui/pill/index.tsx diff --git a/packages/ui/components/ui/pill/pill.stories.tsx b/packages/ui-deprecated/components/ui/pill/pill.stories.tsx similarity index 100% rename from packages/ui/components/ui/pill/pill.stories.tsx rename to packages/ui-deprecated/components/ui/pill/pill.stories.tsx diff --git a/packages/ui/components/ui/popover/index.tsx b/packages/ui-deprecated/components/ui/popover/index.tsx similarity index 100% rename from packages/ui/components/ui/popover/index.tsx rename to packages/ui-deprecated/components/ui/popover/index.tsx diff --git a/packages/ui/components/ui/popover/popover-menu.stories.tsx b/packages/ui-deprecated/components/ui/popover/popover-menu.stories.tsx similarity index 100% rename from packages/ui/components/ui/popover/popover-menu.stories.tsx rename to packages/ui-deprecated/components/ui/popover/popover-menu.stories.tsx diff --git a/packages/ui/components/ui/popover/popover-menu.tsx b/packages/ui-deprecated/components/ui/popover/popover-menu.tsx similarity index 100% rename from packages/ui/components/ui/popover/popover-menu.tsx rename to packages/ui-deprecated/components/ui/popover/popover-menu.tsx diff --git a/packages/ui/components/ui/popover/popover.tsx b/packages/ui-deprecated/components/ui/popover/popover.tsx similarity index 100% rename from packages/ui/components/ui/popover/popover.tsx rename to packages/ui-deprecated/components/ui/popover/popover.tsx diff --git a/packages/ui/components/ui/progress/index.tsx b/packages/ui-deprecated/components/ui/progress/index.tsx similarity index 100% rename from packages/ui/components/ui/progress/index.tsx rename to packages/ui-deprecated/components/ui/progress/index.tsx diff --git a/packages/ui/components/ui/segmented-picker/index.tsx b/packages/ui-deprecated/components/ui/segmented-picker/index.tsx similarity index 100% rename from packages/ui/components/ui/segmented-picker/index.tsx rename to packages/ui-deprecated/components/ui/segmented-picker/index.tsx diff --git a/packages/ui/components/ui/segmented-picker/segmented-picker.stories.tsx b/packages/ui-deprecated/components/ui/segmented-picker/segmented-picker.stories.tsx similarity index 100% rename from packages/ui/components/ui/segmented-picker/segmented-picker.stories.tsx rename to packages/ui-deprecated/components/ui/segmented-picker/segmented-picker.stories.tsx diff --git a/packages/ui/components/ui/segmented-picker/segmented-picker.test.tsx b/packages/ui-deprecated/components/ui/segmented-picker/segmented-picker.test.tsx similarity index 100% rename from packages/ui/components/ui/segmented-picker/segmented-picker.test.tsx rename to packages/ui-deprecated/components/ui/segmented-picker/segmented-picker.test.tsx diff --git a/packages/ui/components/ui/select/index.tsx b/packages/ui-deprecated/components/ui/select/index.tsx similarity index 100% rename from packages/ui/components/ui/select/index.tsx rename to packages/ui-deprecated/components/ui/select/index.tsx diff --git a/packages/ui/components/ui/select/select-account.tsx b/packages/ui-deprecated/components/ui/select/select-account.tsx similarity index 100% rename from packages/ui/components/ui/select/select-account.tsx rename to packages/ui-deprecated/components/ui/select/select-account.tsx diff --git a/packages/ui/components/ui/select/select-list.stories.tsx b/packages/ui-deprecated/components/ui/select/select-list.stories.tsx similarity index 100% rename from packages/ui/components/ui/select/select-list.stories.tsx rename to packages/ui-deprecated/components/ui/select/select-list.stories.tsx diff --git a/packages/ui/components/ui/select/select-list.tsx b/packages/ui-deprecated/components/ui/select/select-list.tsx similarity index 100% rename from packages/ui/components/ui/select/select-list.tsx rename to packages/ui-deprecated/components/ui/select/select-list.tsx diff --git a/packages/ui/components/ui/select/select.tsx b/packages/ui-deprecated/components/ui/select/select.tsx similarity index 100% rename from packages/ui/components/ui/select/select.tsx rename to packages/ui-deprecated/components/ui/select/select.tsx diff --git a/packages/ui/components/ui/separator/index.tsx b/packages/ui-deprecated/components/ui/separator/index.tsx similarity index 100% rename from packages/ui/components/ui/separator/index.tsx rename to packages/ui-deprecated/components/ui/separator/index.tsx diff --git a/packages/ui/components/ui/sheet/index.tsx b/packages/ui-deprecated/components/ui/sheet/index.tsx similarity index 100% rename from packages/ui/components/ui/sheet/index.tsx rename to packages/ui-deprecated/components/ui/sheet/index.tsx diff --git a/packages/ui/components/ui/slider/index.stories.tsx b/packages/ui-deprecated/components/ui/slider/index.stories.tsx similarity index 100% rename from packages/ui/components/ui/slider/index.stories.tsx rename to packages/ui-deprecated/components/ui/slider/index.stories.tsx diff --git a/packages/ui/components/ui/slider/index.tsx b/packages/ui-deprecated/components/ui/slider/index.tsx similarity index 100% rename from packages/ui/components/ui/slider/index.tsx rename to packages/ui-deprecated/components/ui/slider/index.tsx diff --git a/packages/ui/components/ui/slider/thumbs.tsx b/packages/ui-deprecated/components/ui/slider/thumbs.tsx similarity index 100% rename from packages/ui/components/ui/slider/thumbs.tsx rename to packages/ui-deprecated/components/ui/slider/thumbs.tsx diff --git a/packages/ui/components/ui/splash-page/index.tsx b/packages/ui-deprecated/components/ui/splash-page/index.tsx similarity index 100% rename from packages/ui/components/ui/splash-page/index.tsx rename to packages/ui-deprecated/components/ui/splash-page/index.tsx diff --git a/packages/ui/components/ui/switch/index.tsx b/packages/ui-deprecated/components/ui/switch/index.tsx similarity index 100% rename from packages/ui/components/ui/switch/index.tsx rename to packages/ui-deprecated/components/ui/switch/index.tsx diff --git a/packages/ui/components/ui/table/index.tsx b/packages/ui-deprecated/components/ui/table/index.tsx similarity index 100% rename from packages/ui/components/ui/table/index.tsx rename to packages/ui-deprecated/components/ui/table/index.tsx diff --git a/packages/ui/components/ui/table/table.stories.tsx b/packages/ui-deprecated/components/ui/table/table.stories.tsx similarity index 100% rename from packages/ui/components/ui/table/table.stories.tsx rename to packages/ui-deprecated/components/ui/table/table.stories.tsx diff --git a/packages/ui/components/ui/tabs/index.tsx b/packages/ui-deprecated/components/ui/tabs/index.tsx similarity index 100% rename from packages/ui/components/ui/tabs/index.tsx rename to packages/ui-deprecated/components/ui/tabs/index.tsx diff --git a/packages/ui/components/ui/tabs/tabs.stories.tsx b/packages/ui-deprecated/components/ui/tabs/tabs.stories.tsx similarity index 100% rename from packages/ui/components/ui/tabs/tabs.stories.tsx rename to packages/ui-deprecated/components/ui/tabs/tabs.stories.tsx diff --git a/packages/ui/components/ui/testnet-banner/index.tsx b/packages/ui-deprecated/components/ui/testnet-banner/index.tsx similarity index 100% rename from packages/ui/components/ui/testnet-banner/index.tsx rename to packages/ui-deprecated/components/ui/testnet-banner/index.tsx diff --git a/packages/ui/components/ui/testnet-banner/testnet-banner.test.tsx b/packages/ui-deprecated/components/ui/testnet-banner/testnet-banner.test.tsx similarity index 100% rename from packages/ui/components/ui/testnet-banner/testnet-banner.test.tsx rename to packages/ui-deprecated/components/ui/testnet-banner/testnet-banner.test.tsx diff --git a/packages/ui/components/ui/toaster/index.tsx b/packages/ui-deprecated/components/ui/toaster/index.tsx similarity index 100% rename from packages/ui/components/ui/toaster/index.tsx rename to packages/ui-deprecated/components/ui/toaster/index.tsx diff --git a/packages/ui/components/ui/toaster/toaster.css b/packages/ui-deprecated/components/ui/toaster/toaster.css similarity index 100% rename from packages/ui/components/ui/toaster/toaster.css rename to packages/ui-deprecated/components/ui/toaster/toaster.css diff --git a/packages/ui/components/ui/toaster/toaster.stories.tsx b/packages/ui-deprecated/components/ui/toaster/toaster.stories.tsx similarity index 100% rename from packages/ui/components/ui/toaster/toaster.stories.tsx rename to packages/ui-deprecated/components/ui/toaster/toaster.stories.tsx diff --git a/packages/ui/components/ui/toggle/index.tsx b/packages/ui-deprecated/components/ui/toggle/index.tsx similarity index 100% rename from packages/ui/components/ui/toggle/index.tsx rename to packages/ui-deprecated/components/ui/toggle/index.tsx diff --git a/packages/ui/components/ui/tooltip/index.tsx b/packages/ui-deprecated/components/ui/tooltip/index.tsx similarity index 100% rename from packages/ui/components/ui/tooltip/index.tsx rename to packages/ui-deprecated/components/ui/tooltip/index.tsx diff --git a/packages/ui/components/ui/tx/action-view.tsx b/packages/ui-deprecated/components/ui/tx/action-view.tsx similarity index 100% rename from packages/ui/components/ui/tx/action-view.tsx rename to packages/ui-deprecated/components/ui/tx/action-view.tsx diff --git a/packages/ui/components/ui/tx/actions-views/action-details.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/action-details.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/action-details.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/action-details.tsx diff --git a/packages/ui/components/ui/tx/actions-views/action-dutch-auction-end.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/action-dutch-auction-end.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/action-dutch-auction-end.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/action-dutch-auction-end.tsx diff --git a/packages/ui/components/ui/tx/actions-views/action-dutch-auction-schedule-view.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/action-dutch-auction-schedule-view.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/action-dutch-auction-schedule-view.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/action-dutch-auction-schedule-view.tsx diff --git a/packages/ui/components/ui/tx/actions-views/action-dutch-auction-withdraw-view.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/action-dutch-auction-withdraw-view.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/action-dutch-auction-withdraw-view.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/action-dutch-auction-withdraw-view.tsx diff --git a/packages/ui/components/ui/tx/actions-views/delegate.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/delegate.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/delegate.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/delegate.tsx diff --git a/packages/ui/components/ui/tx/actions-views/delegator-vote.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/delegator-vote.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/delegator-vote.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/delegator-vote.tsx diff --git a/packages/ui/components/ui/tx/actions-views/ibc-relay.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/ibc-relay.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/ibc-relay.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/ibc-relay.tsx diff --git a/packages/ui/components/ui/tx/actions-views/isc20-withdrawal.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/isc20-withdrawal.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/isc20-withdrawal.tsx diff --git a/packages/ui/components/ui/tx/actions-views/output.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/output.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/output.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/output.tsx diff --git a/packages/ui/components/ui/tx/actions-views/position-close.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/position-close.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/position-close.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/position-close.tsx diff --git a/packages/ui/components/ui/tx/actions-views/position-open.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/position-open.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/position-open.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/position-open.tsx diff --git a/packages/ui/components/ui/tx/actions-views/position-withdraw.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/position-withdraw.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/position-withdraw.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/position-withdraw.tsx diff --git a/packages/ui/components/ui/tx/actions-views/spend.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/spend.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/spend.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/spend.tsx diff --git a/packages/ui/components/ui/tx/actions-views/swap/index.test.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/swap/index.test.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/swap/index.test.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/swap/index.test.tsx diff --git a/packages/ui/components/ui/tx/actions-views/swap/index.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/swap/index.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/swap/index.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/swap/index.tsx diff --git a/packages/ui/components/ui/tx/actions-views/swap/one-way-swap.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/swap/one-way-swap.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/swap/one-way-swap.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/swap/one-way-swap.tsx diff --git a/packages/ui/components/ui/tx/actions-views/swap/swap-claim.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/swap/swap-claim.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/swap/swap-claim.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/swap/swap-claim.tsx diff --git a/packages/ui/components/ui/tx/actions-views/swap/transaction-id.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/swap/transaction-id.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/swap/transaction-id.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/swap/transaction-id.tsx diff --git a/packages/ui/components/ui/tx/actions-views/undelegate-claim.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/undelegate-claim.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/undelegate-claim.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/undelegate-claim.tsx diff --git a/packages/ui/components/ui/tx/actions-views/undelegate.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/undelegate.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/undelegate.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/undelegate.tsx diff --git a/packages/ui/components/ui/tx/actions-views/unimplemented-view.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/unimplemented-view.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/unimplemented-view.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/unimplemented-view.tsx diff --git a/packages/ui/components/ui/tx/actions-views/validator-vote.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/validator-vote.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/validator-vote.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/validator-vote.tsx diff --git a/packages/ui/components/ui/tx/actions-views/value-with-address.tsx b/packages/ui-deprecated/components/ui/tx/actions-views/value-with-address.tsx similarity index 100% rename from packages/ui/components/ui/tx/actions-views/value-with-address.tsx rename to packages/ui-deprecated/components/ui/tx/actions-views/value-with-address.tsx diff --git a/packages/ui/components/ui/tx/index.tsx b/packages/ui-deprecated/components/ui/tx/index.tsx similarity index 100% rename from packages/ui/components/ui/tx/index.tsx rename to packages/ui-deprecated/components/ui/tx/index.tsx diff --git a/packages/ui/components/ui/tx/memo-view.tsx b/packages/ui-deprecated/components/ui/tx/memo-view.tsx similarity index 100% rename from packages/ui/components/ui/tx/memo-view.tsx rename to packages/ui-deprecated/components/ui/tx/memo-view.tsx diff --git a/packages/ui/components/ui/tx/transaction.stories.tsx b/packages/ui-deprecated/components/ui/tx/transaction.stories.tsx similarity index 100% rename from packages/ui/components/ui/tx/transaction.stories.tsx rename to packages/ui-deprecated/components/ui/tx/transaction.stories.tsx diff --git a/packages/ui/components/ui/tx/viewbox.tsx b/packages/ui-deprecated/components/ui/tx/viewbox.tsx similarity index 100% rename from packages/ui/components/ui/tx/viewbox.tsx rename to packages/ui-deprecated/components/ui/tx/viewbox.tsx diff --git a/packages/ui/components/ui/value/index.test.tsx b/packages/ui-deprecated/components/ui/value/index.test.tsx similarity index 100% rename from packages/ui/components/ui/value/index.test.tsx rename to packages/ui-deprecated/components/ui/value/index.test.tsx diff --git a/packages/ui/components/ui/value/index.tsx b/packages/ui-deprecated/components/ui/value/index.tsx similarity index 100% rename from packages/ui/components/ui/value/index.tsx rename to packages/ui-deprecated/components/ui/value/index.tsx diff --git a/packages/ui/components/ui/value/value.stories.tsx b/packages/ui-deprecated/components/ui/value/value.stories.tsx similarity index 100% rename from packages/ui/components/ui/value/value.stories.tsx rename to packages/ui-deprecated/components/ui/value/value.stories.tsx diff --git a/packages/ui/components/ui/value/value.tsx b/packages/ui-deprecated/components/ui/value/value.tsx similarity index 100% rename from packages/ui/components/ui/value/value.tsx rename to packages/ui-deprecated/components/ui/value/value.tsx diff --git a/packages/ui/fonts/Devanagari-Sangam-Bold.woff2 b/packages/ui-deprecated/fonts/Devanagari-Sangam-Bold.woff2 similarity index 100% rename from packages/ui/fonts/Devanagari-Sangam-Bold.woff2 rename to packages/ui-deprecated/fonts/Devanagari-Sangam-Bold.woff2 diff --git a/packages/ui/fonts/Devanagari-Sangam-Regular.woff2 b/packages/ui-deprecated/fonts/Devanagari-Sangam-Regular.woff2 similarity index 100% rename from packages/ui/fonts/Devanagari-Sangam-Regular.woff2 rename to packages/ui-deprecated/fonts/Devanagari-Sangam-Regular.woff2 diff --git a/packages/ui/fonts/Faktum-Bold.woff2 b/packages/ui-deprecated/fonts/Faktum-Bold.woff2 similarity index 100% rename from packages/ui/fonts/Faktum-Bold.woff2 rename to packages/ui-deprecated/fonts/Faktum-Bold.woff2 diff --git a/packages/ui/fonts/Faktum-Medium.woff2 b/packages/ui-deprecated/fonts/Faktum-Medium.woff2 similarity index 100% rename from packages/ui/fonts/Faktum-Medium.woff2 rename to packages/ui-deprecated/fonts/Faktum-Medium.woff2 diff --git a/packages/ui/fonts/Faktum-SemiBold.woff2 b/packages/ui-deprecated/fonts/Faktum-SemiBold.woff2 similarity index 100% rename from packages/ui/fonts/Faktum-SemiBold.woff2 rename to packages/ui-deprecated/fonts/Faktum-SemiBold.woff2 diff --git a/packages/ui/fonts/iosevka-term-ss03-italic.woff2 b/packages/ui-deprecated/fonts/iosevka-term-ss03-italic.woff2 similarity index 100% rename from packages/ui/fonts/iosevka-term-ss03-italic.woff2 rename to packages/ui-deprecated/fonts/iosevka-term-ss03-italic.woff2 diff --git a/packages/ui/fonts/iosevka-term-ss03-regular.woff2 b/packages/ui-deprecated/fonts/iosevka-term-ss03-regular.woff2 similarity index 100% rename from packages/ui/fonts/iosevka-term-ss03-regular.woff2 rename to packages/ui-deprecated/fonts/iosevka-term-ss03-regular.woff2 diff --git a/packages/ui/lib/toast/presets.ts b/packages/ui-deprecated/lib/toast/presets.ts similarity index 100% rename from packages/ui/lib/toast/presets.ts rename to packages/ui-deprecated/lib/toast/presets.ts diff --git a/packages/ui/lib/toast/toast.test.ts b/packages/ui-deprecated/lib/toast/toast.test.ts similarity index 100% rename from packages/ui/lib/toast/toast.test.ts rename to packages/ui-deprecated/lib/toast/toast.test.ts diff --git a/packages/ui/lib/toast/toast.ts b/packages/ui-deprecated/lib/toast/toast.ts similarity index 100% rename from packages/ui/lib/toast/toast.ts rename to packages/ui-deprecated/lib/toast/toast.ts diff --git a/packages/ui/lib/toast/transaction-toast.test.tsx b/packages/ui-deprecated/lib/toast/transaction-toast.test.tsx similarity index 100% rename from packages/ui/lib/toast/transaction-toast.test.tsx rename to packages/ui-deprecated/lib/toast/transaction-toast.test.tsx diff --git a/packages/ui/lib/toast/transaction-toast.tsx b/packages/ui-deprecated/lib/toast/transaction-toast.tsx similarity index 100% rename from packages/ui/lib/toast/transaction-toast.tsx rename to packages/ui-deprecated/lib/toast/transaction-toast.tsx diff --git a/packages/ui/lib/utils.ts b/packages/ui-deprecated/lib/utils.ts similarity index 100% rename from packages/ui/lib/utils.ts rename to packages/ui-deprecated/lib/utils.ts diff --git a/packages/ui-deprecated/package.json b/packages/ui-deprecated/package.json new file mode 100644 index 0000000000..3ad2996fa1 --- /dev/null +++ b/packages/ui-deprecated/package.json @@ -0,0 +1,150 @@ +{ + "name": "@penumbra-zone/ui-deprecated", + "version": "12.4.0", + "private": true, + "license": "(MIT OR Apache-2.0)", + "description": "UI components for Penumbra", + "type": "module", + "engine": { + "node": ">=22" + }, + "scripts": { + "build": "vite build", + "build-storybook": "storybook build", + "dev:pack": "VITE_WATCH=true vite build --watch", + "lint": "eslint components lib src", + "lint:fix": "eslint components lib src --fix", + "lint:strict": "tsc --noEmit && eslint components lib src --max-warnings 0", + "storybook": "storybook dev -p 6006", + "test": "vitest run" + }, + "files": [ + "dist", + "components", + "lib", + "styles", + "postcss.config.js" + ], + "exports": { + "./components/ui/icons/*": "./components/ui/icons/*.tsx", + "./components/ui/*": "./components/ui/*/index.tsx", + "./lib/toast/*": "./lib/toast/*.ts", + "./lib/toast/transaction-toast": "./lib/toast/transaction-toast.tsx", + "./lib/utils": "./lib/utils.ts", + "./tailwind": "./src/tailwindConfig.ts", + "./postcss.config.js": "./postcss.config.js", + "./styles/*": "./styles/*", + "./theme": "./src/PenumbraUIProvider/theme.ts", + "./utils/*": "./src/utils/*.ts", + "./hooks/*": "./src/hooks/*/index.ts", + "./*": "./src/*/index.tsx" + }, + "publishConfig": { + "exports": { + "./tailwind": { + "types": "./dist/src/tailwindConfig.d.ts", + "default": "./dist/src/tailwindConfig.js" + }, + "./components/*": { + "types": "./dist/components/ui/*.d.ts", + "default": "./dist/components/ui/*.js" + }, + "./utils/typography": { + "types": "./dist/src/utils/typography.d.ts", + "default": "./dist/src/utils/typography.js" + }, + "./*": { + "types": "./dist/src/*/index.d.ts", + "default": "./dist/src/*/index.js" + } + } + }, + "dependencies": { + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@penumbra-zone/bech32m": "workspace:*", + "@penumbra-zone/perspective": "workspace:*", + "@penumbra-zone/types": "workspace:*", + "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-checkbox": "^1.0.4", + "@radix-ui/react-dialog": "1.0.5", + "@radix-ui/react-dropdown-menu": "^2.1.1", + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-navigation-menu": "^1.1.4", + "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-progress": "^1.0.3", + "@radix-ui/react-radio-group": "^1.2.0", + "@radix-ui/react-select": "^2.1.1", + "@radix-ui/react-slider": "^1.1.2", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-switch": "^1.0.3", + "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-toast": "^1.1.5", + "@radix-ui/react-toggle": "^1.0.3", + "@radix-ui/react-tooltip": "^1.0.7", + "@textea/json-viewer": "^3.4.1", + "@visx/axis": "^3.10.1", + "@visx/curve": "^3.3.0", + "@visx/grid": "^3.5.0", + "@visx/group": "^3.3.0", + "@visx/responsive": "^3.10.2", + "@visx/scale": "^3.5.0", + "@visx/shape": "^3.5.0", + "@visx/stats": "^3.5.0", + "@visx/threshold": "^3.5.0", + "@visx/tooltip": "^3.3.0", + "bignumber.js": "^9.1.2", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "cmdk": "0.2.0", + "framer-motion": "^11.2.4", + "humanize-duration": "^3.32.0", + "lucide-react": "^0.378.0", + "murmurhash3js": "^3.0.1", + "react-dom": "^18.3.1", + "react-loader-spinner": "^6.1.6", + "react-router-dom": "^6.23.1", + "sonner": "1.4.3", + "styled-components": "^6.1.11", + "tailwind-merge": "^2.3.0", + "tinycolor2": "^1.6.0", + "ua-parser-js": "^1.0.38" + }, + "devDependencies": { + "@penumbra-zone/getters": "workspace:*", + "@penumbra-zone/protobuf": "workspace:*", + "@storybook/addon-essentials": "^8.4.2", + "@storybook/addon-interactions": "^8.4.2", + "@storybook/addon-links": "^8.1.1", + "@storybook/addon-postcss": "^2.0.0", + "@storybook/blocks": "^8.4.2", + "@storybook/manager-api": "^8.1.11", + "@storybook/preview-api": "^8.1.1", + "@storybook/react": "^8.4.2", + "@storybook/react-vite": "^8.4.2", + "@storybook/theming": "^8.1.11", + "@testing-library/user-event": "^14.5.2", + "@types/humanize-duration": "^3.27.4", + "@types/murmurhash3js": "^3.0.7", + "@types/react": "^18.3.2", + "@types/react-dom": "^18.3.0", + "@types/styled-components": "^5.1.34", + "@types/tinycolor2": "^1.4.6", + "@types/ua-parser-js": "^0.7.39", + "execa": "^9.5.1", + "prop-types": "^15.8.1", + "storybook": "^8.4.2", + "vite": "^5.2.11", + "vite-plugin-dts": "^4.0.3" + }, + "peerDependencies": { + "@bufbuild/protobuf": "^1.10.0", + "@penumbra-zone/protobuf": "workspace:*", + "framer-motion": "^11.2.4", + "lucide-react": "^0.378.0", + "postcss": "^8.4.38", + "react": "^18.3.1", + "styled-components": "^6.1.11", + "tailwindcss": "^3.4.3" + } +} diff --git a/packages/ui-tailwind/postcss.config.js b/packages/ui-deprecated/postcss.config.js similarity index 100% rename from packages/ui-tailwind/postcss.config.js rename to packages/ui-deprecated/postcss.config.js diff --git a/packages/ui/src/AccountSelector/AccountSelectorAddress.tsx b/packages/ui-deprecated/src/AccountSelector/AccountSelectorAddress.tsx similarity index 100% rename from packages/ui/src/AccountSelector/AccountSelectorAddress.tsx rename to packages/ui-deprecated/src/AccountSelector/AccountSelectorAddress.tsx diff --git a/packages/ui/src/AccountSelector/IbcDepositToggle.tsx b/packages/ui-deprecated/src/AccountSelector/IbcDepositToggle.tsx similarity index 100% rename from packages/ui/src/AccountSelector/IbcDepositToggle.tsx rename to packages/ui-deprecated/src/AccountSelector/IbcDepositToggle.tsx diff --git a/packages/ui/src/AccountSelector/index.stories.tsx b/packages/ui-deprecated/src/AccountSelector/index.stories.tsx similarity index 100% rename from packages/ui/src/AccountSelector/index.stories.tsx rename to packages/ui-deprecated/src/AccountSelector/index.stories.tsx diff --git a/packages/ui/src/AccountSelector/index.tsx b/packages/ui-deprecated/src/AccountSelector/index.tsx similarity index 100% rename from packages/ui/src/AccountSelector/index.tsx rename to packages/ui-deprecated/src/AccountSelector/index.tsx diff --git a/packages/ui/src/AccountSelector/useAccountSelector.ts b/packages/ui-deprecated/src/AccountSelector/useAccountSelector.ts similarity index 100% rename from packages/ui/src/AccountSelector/useAccountSelector.ts rename to packages/ui-deprecated/src/AccountSelector/useAccountSelector.ts diff --git a/packages/ui-tailwind/src/AddressView/AddressIcon.tsx b/packages/ui-deprecated/src/AddressViewComponent/AddressIcon.tsx similarity index 100% rename from packages/ui-tailwind/src/AddressView/AddressIcon.tsx rename to packages/ui-deprecated/src/AddressViewComponent/AddressIcon.tsx diff --git a/packages/ui/src/AddressViewComponent/index.stories.tsx b/packages/ui-deprecated/src/AddressViewComponent/index.stories.tsx similarity index 100% rename from packages/ui/src/AddressViewComponent/index.stories.tsx rename to packages/ui-deprecated/src/AddressViewComponent/index.stories.tsx diff --git a/packages/ui/src/AddressViewComponent/index.test.tsx b/packages/ui-deprecated/src/AddressViewComponent/index.test.tsx similarity index 100% rename from packages/ui/src/AddressViewComponent/index.test.tsx rename to packages/ui-deprecated/src/AddressViewComponent/index.test.tsx diff --git a/packages/ui/src/AddressViewComponent/index.tsx b/packages/ui-deprecated/src/AddressViewComponent/index.tsx similarity index 100% rename from packages/ui/src/AddressViewComponent/index.tsx rename to packages/ui-deprecated/src/AddressViewComponent/index.tsx diff --git a/packages/ui-tailwind/src/AssetIcon/DelegationTokenIcon.tsx b/packages/ui-deprecated/src/AssetIcon/DelegationTokenIcon.tsx similarity index 91% rename from packages/ui-tailwind/src/AssetIcon/DelegationTokenIcon.tsx rename to packages/ui-deprecated/src/AssetIcon/DelegationTokenIcon.tsx index f81f006418..58dd68ce9d 100644 --- a/packages/ui-tailwind/src/AssetIcon/DelegationTokenIcon.tsx +++ b/packages/ui-deprecated/src/AssetIcon/DelegationTokenIcon.tsx @@ -1,4 +1,15 @@ import { assetPatterns } from '@penumbra-zone/types/assets'; +import { styled } from 'styled-components'; + +const Svg = styled.svg.attrs({ + id: 'delegation', + xmlns: 'http://www.w3.org/2000/svg', + xmlnsXlink: 'http://www.w3.org/1999/xlink', + viewBox: '0 0 32 32', +})` + display: block; + border-radius: ${props => props.theme.borderRadius.full}; +`; const getFirstEightCharactersOfValidatorId = (displayDenom = ''): [string, string] => { const id = (assetPatterns.delegationToken.capture(displayDenom)?.id ?? '').substring(0, 8); @@ -17,13 +28,7 @@ export const DelegationTokenIcon = ({ displayDenom }: DelegationTokenIconProps) const [firstFour, lastFour] = getFirstEightCharactersOfValidatorId(displayDenom); return ( - + - + ); }; diff --git a/packages/ui-tailwind/src/AssetIcon/UnbondingTokenIcon.tsx b/packages/ui-deprecated/src/AssetIcon/UnbondingTokenIcon.tsx similarity index 91% rename from packages/ui-tailwind/src/AssetIcon/UnbondingTokenIcon.tsx rename to packages/ui-deprecated/src/AssetIcon/UnbondingTokenIcon.tsx index 5ebd251ef1..58b302bf09 100644 --- a/packages/ui-tailwind/src/AssetIcon/UnbondingTokenIcon.tsx +++ b/packages/ui-deprecated/src/AssetIcon/UnbondingTokenIcon.tsx @@ -1,4 +1,15 @@ import { assetPatterns } from '@penumbra-zone/types/assets'; +import { styled } from 'styled-components'; + +const Svg = styled.svg.attrs({ + id: 'unbonding', + xmlns: 'http://www.w3.org/2000/svg', + xmlnsXlink: 'http://www.w3.org/1999/xlink', + viewBox: '0 0 32 32', +})` + display: block; + border-radius: ${props => props.theme.borderRadius.full}; +`; const getFirstEightCharactersOfValidatorId = (displayDenom = ''): [string, string] => { const id = (assetPatterns.unbondingToken.capture(displayDenom)?.id ?? '').substring(0, 8); @@ -17,13 +28,7 @@ export const UnbondingTokenIcon = ({ displayDenom }: UnbondingTokenIconProps) => const [firstFour, lastFour] = getFirstEightCharactersOfValidatorId(displayDenom); return ( - + strokeWidth='.75' /> - + ); }; diff --git a/packages/ui-tailwind/src/AssetIcon/index.stories.tsx b/packages/ui-deprecated/src/AssetIcon/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/AssetIcon/index.stories.tsx rename to packages/ui-deprecated/src/AssetIcon/index.stories.tsx diff --git a/packages/ui-tailwind/src/AssetIcon/index.tsx b/packages/ui-deprecated/src/AssetIcon/index.tsx similarity index 72% rename from packages/ui-tailwind/src/AssetIcon/index.tsx rename to packages/ui-deprecated/src/AssetIcon/index.tsx index cf7a1cf222..b54e3abbab 100644 --- a/packages/ui-tailwind/src/AssetIcon/index.tsx +++ b/packages/ui-deprecated/src/AssetIcon/index.tsx @@ -1,20 +1,36 @@ import { ReactNode } from 'react'; +import { styled } from 'styled-components'; import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { getDisplay } from '@penumbra-zone/getters/metadata'; import { assetPatterns } from '@penumbra-zone/types/assets'; import { Identicon } from '../Identicon'; import { DelegationTokenIcon } from './DelegationTokenIcon'; import { UnbondingTokenIcon } from './UnbondingTokenIcon'; -import cn from 'clsx'; type Size = 'lg' | 'md' | 'sm'; -const sizeMap: Record = { - lg: cn('w-8 h-8'), - md: cn('w-6 h-6'), - sm: cn('w-4 h-4'), +const sizeMap: Record = { + lg: 32, + md: 24, + sm: 16, }; +const BorderWrapper = styled.div<{ $size: Size }>` + width: ${props => sizeMap[props.$size]}px; + height: ${props => sizeMap[props.$size]}px; + border-radius: ${props => props.theme.borderRadius.full}; + overflow: hidden; + + & > * { + width: 100%; + height: 100%; + } +`; + +const IconImg = styled.img` + display: block; +`; + export interface AssetIconProps { size?: Size; metadata?: Metadata; @@ -29,7 +45,7 @@ export const AssetIcon = ({ metadata, size = 'md' }: AssetIconProps) => { let assetIcon: ReactNode; if (icon) { - assetIcon = Asset icon; + assetIcon = ; } else if (isDelegationToken) { assetIcon = ; } else if (isUnbondingToken) { @@ -42,9 +58,5 @@ export const AssetIcon = ({ metadata, size = 'md' }: AssetIconProps) => { assetIcon = ; } - return ( -
*]:w-full [&>*]:h-full')}> - {assetIcon} -
- ); + return {assetIcon}; }; diff --git a/packages/ui/src/AssetIcon/shared.ts b/packages/ui-deprecated/src/AssetIcon/shared.ts similarity index 100% rename from packages/ui/src/AssetIcon/shared.ts rename to packages/ui-deprecated/src/AssetIcon/shared.ts diff --git a/packages/ui-tailwind/src/AssetSelector/Custom.tsx b/packages/ui-deprecated/src/AssetSelector/Custom.tsx similarity index 68% rename from packages/ui-tailwind/src/AssetSelector/Custom.tsx rename to packages/ui-deprecated/src/AssetSelector/Custom.tsx index f9df9516b8..77da9b165b 100644 --- a/packages/ui-tailwind/src/AssetSelector/Custom.tsx +++ b/packages/ui-deprecated/src/AssetSelector/Custom.tsx @@ -1,10 +1,18 @@ import { ReactNode, useId, useState } from 'react'; +import { styled } from 'styled-components'; import { Dialog } from '../Dialog'; -import { getHash } from './shared/helpers'; -import { AssetSelectorContext } from './shared/Context'; -import { AssetSelectorSearchFilter } from './SearchFilter'; -import { AssetSelectorTrigger } from './Trigger'; -import { AssetSelectorBaseProps } from './shared/types'; +import { IsAnimatingProvider } from '../IsAnimatingProvider'; +import { getHash } from './shared/helpers.ts'; +import { AssetSelectorContext } from './shared/Context.tsx'; +import { AssetSelectorSearchFilter } from './SearchFilter.tsx'; +import { AssetSelectorTrigger } from './Trigger.tsx'; +import { AssetSelectorBaseProps } from './shared/types.ts'; + +const OptionsWrapper = styled.div` + display: flex; + flex-direction: column; + gap: ${props => props.theme.spacing(1)}; +`; interface ChildrenArguments { onClose: VoidFunction; @@ -104,22 +112,28 @@ export const AssetSelectorCustom = ({ onClick={() => setIsOpen(true)} /> - - ) - } - > - -
- {typeof children === 'function' - ? children({ onClose, getKeyHash: getHash }) - : children} -
-
-
+ + {props => ( + + ) + } + > + + + {typeof children === 'function' + ? children({ onClose, getKeyHash: getHash }) + : children} + + + + )} + ); diff --git a/packages/ui-tailwind/src/AssetSelector/SearchFilter.tsx b/packages/ui-deprecated/src/AssetSelector/SearchFilter.tsx similarity index 94% rename from packages/ui-tailwind/src/AssetSelector/SearchFilter.tsx rename to packages/ui-deprecated/src/AssetSelector/SearchFilter.tsx index 7b179303a7..3d79e60b43 100644 --- a/packages/ui-tailwind/src/AssetSelector/SearchFilter.tsx +++ b/packages/ui-deprecated/src/AssetSelector/SearchFilter.tsx @@ -12,7 +12,7 @@ export const AssetSelectorSearchFilter = ({ value, onChange }: AssetSelectorSear return ( } + startAdornment={ color.text.primary} />} value={value ?? ''} onChange={handleSearch} placeholder='Search...' diff --git a/packages/ui-tailwind/src/AssetSelector/SelectItem.tsx b/packages/ui-deprecated/src/AssetSelector/SelectItem.tsx similarity index 74% rename from packages/ui-tailwind/src/AssetSelector/SelectItem.tsx rename to packages/ui-deprecated/src/AssetSelector/SelectItem.tsx index 8f17139c83..b7dcba0997 100644 --- a/packages/ui-tailwind/src/AssetSelector/SelectItem.tsx +++ b/packages/ui-deprecated/src/AssetSelector/SelectItem.tsx @@ -1,3 +1,4 @@ +import { styled } from 'styled-components'; import { AssetIcon } from '../AssetIcon'; import { Text } from '../Text'; import { getFormattedAmtFromValueView } from '@penumbra-zone/types/value-view'; @@ -6,12 +7,32 @@ import { getBalanceView, getMetadataFromBalancesResponse, } from '@penumbra-zone/getters/balances-response'; -import { ActionType } from '../utils/action-type'; +import { ActionType } from '../utils/ActionType'; import { AssetSelectorValue } from './shared/types'; +import { media } from '../utils/media'; import { getHash, isBalancesResponse } from './shared/helpers'; import { RadioItem } from '../Dialog/RadioItem'; import { useAssetsSelector } from './shared/Context'; +const AssetTitleText = styled(Text)` + display: inline-block; + max-width: 100px; + + ${media.tablet` + max-width: 300px; + `} + + ${media.lg` + max-width: 400px; + `} +`; + +const Balance = styled.div` + display: flex; + flex-direction: column; + align-items: flex-end; +`; + export interface AssetSelectorItemProps { /** * A `BalancesResponse` or `Metadata` protobuf message type. Renders the asset @@ -56,27 +77,25 @@ export const Item = ({ value, disabled, actionType = 'default' }: AssetSelectorI title={ <> {balance?.valueView && ( - + {getFormattedAmtFromValueView(balance.valueView, true)}{' '} )} - - - {metadata?.symbol ?? 'Unknown'} - - + + {metadata?.symbol ?? 'Unknown'} + } endAdornment={ balance?.addressIndexAccount !== undefined && ( -
- + + color.text.secondary}> #{balance.addressIndexAccount} - + color.text.secondary}> Account -
+ ) } /> diff --git a/packages/ui-deprecated/src/AssetSelector/Trigger.tsx b/packages/ui-deprecated/src/AssetSelector/Trigger.tsx new file mode 100644 index 0000000000..c5acc88a4f --- /dev/null +++ b/packages/ui-deprecated/src/AssetSelector/Trigger.tsx @@ -0,0 +1,127 @@ +import { forwardRef, MouseEventHandler } from 'react'; +import { styled, css } from 'styled-components'; +import { ChevronsUpDownIcon } from 'lucide-react'; +import { motion } from 'framer-motion'; +import { getMetadataFromBalancesResponse } from '@penumbra-zone/getters/balances-response'; +import { ActionType, getOutlineColorByActionType } from '../utils/ActionType.ts'; +import { Density } from '../types/Density.ts'; +import { useDensity } from '../hooks/useDensity'; +import { asTransientProps } from '../utils/asTransientProps.ts'; +import { Icon } from '../Icon'; +import { Text } from '../Text'; +import { AssetIcon } from '../AssetIcon'; +import { isMetadata } from './shared/helpers.ts'; +import { Dialog } from '../Dialog/index.tsx'; +import { AssetSelectorValue } from './shared/types.ts'; + +const SparseButton = css` + height: ${props => props.theme.spacing(12)}; + padding: 0 ${props => props.theme.spacing(3)}; +`; + +const CompactButton = css` + height: ${props => props.theme.spacing(8)}; + padding: 0 ${props => props.theme.spacing(2)}; +`; + +const Trigger = styled(motion.button)<{ $density: Density; $actionType: ActionType }>` + display: flex; + justify-content: space-between; + align-items: center; + gap: ${props => props.theme.spacing(1)}; + min-width: ${props => props.theme.spacing(20)}; + border-radius: ${props => props.theme.borderRadius.none}; + background: ${props => props.theme.color.other.tonalFill5}; + transition: + background 0.15s, + outline 0.15s; + + ${props => (props.$density === 'sparse' ? SparseButton : CompactButton)}; + + &:hover { + background-color: ${props => props.theme.color.action.hoverOverlay}; + } + + &:focus { + color: ${props => props.theme.color.text.secondary}; + background: ${props => props.theme.color.other.tonalFill5}; + outline: 2px solid ${props => getOutlineColorByActionType(props.theme, props.$actionType)}; + } + + &:disabled { + background: linear-gradient( + 0deg, + ${props => props.theme.color.action.disabledOverlay} 0%, + ${props => props.theme.color.action.disabledOverlay} 100% + ), + ${props => props.theme.color.other.tonalFill10}; + } +`; + +const Value = styled.div<{ $density: Density; $actionType: ActionType }>` + display: flex; + align-items: center; + gap: ${props => props.theme.spacing(props.$density === 'sparse' ? 2 : 1)}; +`; + +const IconAdornment = styled.i<{ $disabled?: boolean }>` + display: flex; + align-items: center; + justify-content: center; + padding: ${props => props.theme.spacing(1)}; + width: ${props => props.theme.spacing(6)}; + height: ${props => props.theme.spacing(6)}; + border-radius: ${props => props.theme.borderRadius.full}; + background-color: ${props => + props.$disabled ? props.theme.color.action.disabledOverlay : 'transparent'}; +`; + +export interface AssetSelectorTriggerProps { + value?: AssetSelectorValue; + actionType?: ActionType; + disabled?: boolean; + onClick?: MouseEventHandler; + layoutId?: string; +} + +export const AssetSelectorTrigger = forwardRef( + ({ value, actionType = 'default', disabled, onClick, layoutId }, ref) => { + const density = useDensity(); + + const metadata = isMetadata(value) ? value : getMetadataFromBalancesResponse.optional(value); + + return ( + + + {!value ? ( + (disabled ? color.text.muted : color.text.primary)}> + Asset + + ) : ( + + + (disabled ? color.text.muted : color.text.primary)}> + {metadata?.symbol ?? 'Unknown'} + + + )} + + + (disabled ? color.text.muted : color.text.primary)} + /> + + + + ); + }, +); +AssetSelectorTrigger.displayName = 'AssetSelectorTrigger'; diff --git a/packages/ui-tailwind/src/AssetSelector/index.stories.tsx b/packages/ui-deprecated/src/AssetSelector/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/AssetSelector/index.stories.tsx rename to packages/ui-deprecated/src/AssetSelector/index.stories.tsx diff --git a/packages/ui-tailwind/src/AssetSelector/index.tsx b/packages/ui-deprecated/src/AssetSelector/index.tsx similarity index 86% rename from packages/ui-tailwind/src/AssetSelector/index.tsx rename to packages/ui-deprecated/src/AssetSelector/index.tsx index c249155751..6ee71f2de1 100644 --- a/packages/ui-tailwind/src/AssetSelector/index.tsx +++ b/packages/ui-deprecated/src/AssetSelector/index.tsx @@ -1,14 +1,27 @@ import { useMemo, useState } from 'react'; +import { styled } from 'styled-components'; import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; -import { isBalancesResponse, isMetadata } from './shared/helpers'; -import { filterMetadataOrBalancesResponseByText } from './shared/filterMetadataOrBalancesResponseByText'; -import { AssetSelectorBaseProps, AssetSelectorValue } from './shared/types'; -import { AssetSelectorCustom, AssetSelectorCustomProps } from './Custom'; -import { Item, AssetSelectorItemProps } from './SelectItem'; +import { isBalancesResponse, isMetadata } from './shared/helpers.ts'; +import { filterMetadataOrBalancesResponseByText } from './shared/filterMetadataOrBalancesResponseByText.ts'; +import { AssetSelectorBaseProps, AssetSelectorValue } from './shared/types.ts'; +import { AssetSelectorCustom, AssetSelectorCustomProps } from './Custom.tsx'; +import { Item, AssetSelectorItemProps } from './SelectItem.tsx'; import { Text } from '../Text'; -import { filterAssets, groupAndSortBalances } from './shared/groupAndSort'; +import { filterAssets, groupAndSortBalances } from './shared/groupAndSort.ts'; + +const ListItemGroup = styled.div` + display: flex; + flex-direction: column; + gap: ${props => props.theme.spacing(1)}; +`; + +const SelectorList = styled.div` + display: flex; + flex-direction: column; + gap: ${props => props.theme.spacing(4)}; +`; export interface AssetSelectorProps extends AssetSelectorBaseProps { /** @@ -110,23 +123,23 @@ export const AssetSelector = ({ onChange={onChange} > {({ getKeyHash }) => ( -
+ {!!filteredBalances.length && ( - + color.text.secondary}> Your Tokens )} {filteredBalances.map(([account, balances]) => ( -
+ {balances.map(balance => ( ))} -
+ ))} {!!filteredAssets.length && ( - + color.text.secondary}> All Tokens )} @@ -134,7 +147,7 @@ export const AssetSelector = ({ {filteredAssets.map(asset => ( ))} -
+ )} ); diff --git a/packages/ui-tailwind/src/AssetSelector/shared/Context.tsx b/packages/ui-deprecated/src/AssetSelector/shared/Context.tsx similarity index 100% rename from packages/ui-tailwind/src/AssetSelector/shared/Context.tsx rename to packages/ui-deprecated/src/AssetSelector/shared/Context.tsx diff --git a/packages/ui/src/AssetSelector/shared/filterMetadataOrBalancesResponseByText.test.ts b/packages/ui-deprecated/src/AssetSelector/shared/filterMetadataOrBalancesResponseByText.test.ts similarity index 100% rename from packages/ui/src/AssetSelector/shared/filterMetadataOrBalancesResponseByText.test.ts rename to packages/ui-deprecated/src/AssetSelector/shared/filterMetadataOrBalancesResponseByText.test.ts diff --git a/packages/ui-tailwind/src/AssetSelector/shared/filterMetadataOrBalancesResponseByText.ts b/packages/ui-deprecated/src/AssetSelector/shared/filterMetadataOrBalancesResponseByText.ts similarity index 100% rename from packages/ui-tailwind/src/AssetSelector/shared/filterMetadataOrBalancesResponseByText.ts rename to packages/ui-deprecated/src/AssetSelector/shared/filterMetadataOrBalancesResponseByText.ts diff --git a/packages/ui-tailwind/src/AssetSelector/shared/groupAndSort.ts b/packages/ui-deprecated/src/AssetSelector/shared/groupAndSort.ts similarity index 100% rename from packages/ui-tailwind/src/AssetSelector/shared/groupAndSort.ts rename to packages/ui-deprecated/src/AssetSelector/shared/groupAndSort.ts diff --git a/packages/ui-tailwind/src/AssetSelector/shared/helpers.ts b/packages/ui-deprecated/src/AssetSelector/shared/helpers.ts similarity index 100% rename from packages/ui-tailwind/src/AssetSelector/shared/helpers.ts rename to packages/ui-deprecated/src/AssetSelector/shared/helpers.ts diff --git a/packages/ui-tailwind/src/AssetSelector/shared/types.ts b/packages/ui-deprecated/src/AssetSelector/shared/types.ts similarity index 94% rename from packages/ui-tailwind/src/AssetSelector/shared/types.ts rename to packages/ui-deprecated/src/AssetSelector/shared/types.ts index cd328b6f64..b214ff7042 100644 --- a/packages/ui-tailwind/src/AssetSelector/shared/types.ts +++ b/packages/ui-deprecated/src/AssetSelector/shared/types.ts @@ -1,6 +1,6 @@ import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; -import { ActionType } from '../../utils/action-type'; +import { ActionType } from '../../utils/ActionType.ts'; export type AssetSelectorValue = BalancesResponse | Metadata; diff --git a/packages/ui/src/Button/helpers.test.ts b/packages/ui-deprecated/src/Button/helpers.test.ts similarity index 100% rename from packages/ui/src/Button/helpers.test.ts rename to packages/ui-deprecated/src/Button/helpers.test.ts diff --git a/packages/ui/src/Button/helpers.ts b/packages/ui-deprecated/src/Button/helpers.ts similarity index 100% rename from packages/ui/src/Button/helpers.ts rename to packages/ui-deprecated/src/Button/helpers.ts diff --git a/packages/ui-tailwind/src/Button/index.stories.tsx b/packages/ui-deprecated/src/Button/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/Button/index.stories.tsx rename to packages/ui-deprecated/src/Button/index.stories.tsx diff --git a/packages/ui/src/Button/index.test.tsx b/packages/ui-deprecated/src/Button/index.test.tsx similarity index 100% rename from packages/ui/src/Button/index.test.tsx rename to packages/ui-deprecated/src/Button/index.test.tsx diff --git a/packages/ui-tailwind/src/Button/index.tsx b/packages/ui-deprecated/src/Button/index.tsx similarity index 50% rename from packages/ui-tailwind/src/Button/index.tsx rename to packages/ui-deprecated/src/Button/index.tsx index 1963a51c18..70a7626307 100644 --- a/packages/ui-tailwind/src/Button/index.tsx +++ b/packages/ui-deprecated/src/Button/index.tsx @@ -1,17 +1,99 @@ import { FC, forwardRef, MouseEventHandler, ReactNode } from 'react'; -import { LucideIcon } from 'lucide-react'; -import cn from 'clsx'; -import { getOutlineColorByActionType, ActionType } from '../utils/action-type'; -import { Priority, buttonBase, getBackground, getFocusOutline, getOverlays } from '../utils/button'; +import { styled, css, DefaultTheme } from 'styled-components'; +import { asTransientProps } from '../utils/asTransientProps'; +import { Priority, focusOutline, overlays, buttonBase } from '../utils/button'; +import { getBackgroundColor } from './helpers'; import { button } from '../utils/typography'; -import { useDensity } from '../utils/density'; +import { LucideIcon } from 'lucide-react'; +import { Density } from '../types/Density'; +import { useDensity } from '../hooks/useDensity'; +import { ActionType } from '../utils/ActionType'; +import { MotionProp } from '../utils/MotionProp'; +import { motion } from 'framer-motion'; + +const iconOnlyAdornment = css` + border-radius: ${props => props.theme.borderRadius.full}; + padding: ${props => props.theme.spacing(1)}; + width: max-content; +`; + +const sparse = css` + border-radius: ${props => props.theme.borderRadius.sm}; + padding-left: ${props => (props.$iconOnly ? 'none' : props.theme.spacing(4))}; + padding-right: ${props => (props.$iconOnly ? 'none' : props.theme.spacing(4))}; + height: 48px; + width: ${props => (props.$iconOnly ? '48px' : '100%')}; + ${props => props.$iconOnly && 'min-width: 48px;'} +`; + +const compact = css` + border-radius: ${props => props.theme.borderRadius.full}; + padding-left: ${props => props.theme.spacing(props.$iconOnly ? 2 : 4)}; + padding-right: ${props => props.theme.spacing(props.$iconOnly ? 2 : 4)}; + height: 32px; + min-width: 32px; + width: max-content; +`; + +const outlineColorByActionType: Record = { + default: 'neutralFocusOutline', + accent: 'primaryFocusOutline', + unshield: 'unshieldFocusOutline', + destructive: 'destructiveFocusOutline', +}; -const iconOnlyAdornment = cn('rounded-full p-1 w-max'); -const sparse = (iconOnly?: boolean | 'adornment') => - cn('rounded-sm h-12', iconOnly ? 'w-12 min-w-12 pl-0 pr-0' : 'w-full pl-4 pr-4'); +const borderColorByActionType: Record< + ActionType, + 'neutral' | 'primary' | 'unshield' | 'destructive' +> = { + default: 'neutral', + accent: 'primary', + unshield: 'unshield', + destructive: 'destructive', +}; -const compact = (iconOnly?: boolean | 'adornment') => - cn('rounded-full h-8 min-w-8 w-max', iconOnly ? 'pl-2 pr-2' : 'pl-4 pr-4'); +interface StyledButtonProps { + $iconOnly?: boolean | 'adornment'; + $actionType: ActionType; + $priority: Priority; + $density: Density; + $getFocusOutlineColor: (theme: DefaultTheme) => string; + $getFocusOutlineOffset?: (theme: DefaultTheme) => string | undefined; + $getBorderRadius: (theme: DefaultTheme) => string; +} + +const StyledButton = styled(motion.button)` + ${buttonBase} + ${button} + + background-color: ${props => + getBackgroundColor(props.$actionType, props.$priority, props.theme, props.$iconOnly)}; + outline: ${props => + props.$priority === 'secondary' + ? `1px solid ${props.theme.color[borderColorByActionType[props.$actionType]].main}` + : 'none'}; + outline-offset: -1px; + display: flex; + gap: ${props => props.theme.spacing(2)}; + align-items: center; + justify-content: center; + color: ${props => props.theme.color.neutral.contrast}; + position: relative; + + ${props => + // eslint-disable-next-line no-nested-ternary -- readable ternary + props.$iconOnly === 'adornment' + ? iconOnlyAdornment + : props.$density === 'sparse' + ? sparse + : compact} + &::after { + outline-offset: -2px; + } + + ${focusOutline} + ${overlays} +`; interface BaseButtonProps { type?: HTMLButtonElement['type']; @@ -80,7 +162,7 @@ interface RegularProps { icon?: LucideIcon | FC; } -export type ButtonProps = BaseButtonProps & (IconOnlyProps | RegularProps); +export type ButtonProps = BaseButtonProps & (IconOnlyProps | RegularProps) & MotionProp; /** * A component for all your button needs! @@ -102,53 +184,40 @@ export const Button = forwardRef( actionType = 'default', type = 'button', priority = 'primary', - ...attrs + motion, // needed for the Radix's `asChild` prop to work correctly // https://www.radix-ui.com/primitives/docs/guides/composition#composing-with-your-own-react-components + ...props }, ref, ) => { const density = useDensity(); return ( - + ); }, ); diff --git a/packages/ui/src/ButtonGroup/index.stories.tsx b/packages/ui-deprecated/src/ButtonGroup/index.stories.tsx similarity index 100% rename from packages/ui/src/ButtonGroup/index.stories.tsx rename to packages/ui-deprecated/src/ButtonGroup/index.stories.tsx diff --git a/packages/ui/src/ButtonGroup/index.test.tsx b/packages/ui-deprecated/src/ButtonGroup/index.test.tsx similarity index 100% rename from packages/ui/src/ButtonGroup/index.test.tsx rename to packages/ui-deprecated/src/ButtonGroup/index.test.tsx diff --git a/packages/ui/src/ButtonGroup/index.tsx b/packages/ui-deprecated/src/ButtonGroup/index.tsx similarity index 100% rename from packages/ui/src/ButtonGroup/index.tsx rename to packages/ui-deprecated/src/ButtonGroup/index.tsx diff --git a/packages/ui/src/Card/Title.tsx b/packages/ui-deprecated/src/Card/Title.tsx similarity index 100% rename from packages/ui/src/Card/Title.tsx rename to packages/ui-deprecated/src/Card/Title.tsx diff --git a/packages/ui-tailwind/src/Card/index.stories.tsx b/packages/ui-deprecated/src/Card/index.stories.tsx similarity index 68% rename from packages/ui-tailwind/src/Card/index.stories.tsx rename to packages/ui-deprecated/src/Card/index.stories.tsx index cbefd33980..3edbfc4bcb 100644 --- a/packages/ui-tailwind/src/Card/index.stories.tsx +++ b/packages/ui-deprecated/src/Card/index.stories.tsx @@ -2,24 +2,39 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Card } from '.'; -// import storiesBg from './storiesBg.jpg'; +import storiesBg from './storiesBg.jpg'; +import { styled } from 'styled-components'; import { Text } from '../Text'; +import { FormField } from '../FormField'; +import { TextInput } from '../TextInput'; import { useState } from 'react'; import { Button } from '../Button'; import { Tabs } from '../Tabs'; import { Send } from 'lucide-react'; +const BgWrapper = styled.div` + padding: ${props => props.theme.spacing(20)}; + position: relative; + + &::before { + content: ''; + background: url(${storiesBg}) center / cover; + opacity: 0.6; + filter: blur(4px); + position: absolute; + inset: 0; + z-index: -1; + } +`; + const meta: Meta = { component: Card, tags: ['autodocs', '!dev'], decorators: [ Story => ( -
+ -
+ ), ], argTypes: { @@ -40,7 +55,7 @@ export const Basic: Story = { render: function Render({ as, title }) { const [tab, setTab] = useState('one'); - // const [textInput, setTextInput] = useState(''); + const [textInput, setTextInput] = useState(''); return ( @@ -75,6 +90,18 @@ export const Basic: Story = { in a <Card.Section />.
+ + + + + + + + + )} + + + + + + + + + ); +}; diff --git a/packages/ui-tailwind/src/Dialog/Context.tsx b/packages/ui-deprecated/src/Dialog/Context.tsx similarity index 100% rename from packages/ui-tailwind/src/Dialog/Context.tsx rename to packages/ui-deprecated/src/Dialog/Context.tsx diff --git a/packages/ui-deprecated/src/Dialog/EmptyContent.tsx b/packages/ui-deprecated/src/Dialog/EmptyContent.tsx new file mode 100644 index 0000000000..87ac9ab2cc --- /dev/null +++ b/packages/ui-deprecated/src/Dialog/EmptyContent.tsx @@ -0,0 +1,51 @@ +import { ReactNode } from 'react'; +import { + Overlay as RadixDialogOverlay, + Portal as RadixDialogPortal, + Content as RadixDialogContent, +} from '@radix-ui/react-dialog'; +import { styled } from 'styled-components'; + +const Overlay = styled(RadixDialogOverlay)` + backdrop-filter: blur(${props => props.theme.blur.xs}); + background-color: ${props => props.theme.color.other.overlay}; + position: fixed; + inset: 0; + z-index: auto; +`; + +/** + * We make a full-screen wrapper around the dialog's content so that we can + * correctly position it using the same ``/`` as the + * underlying page uses. Note that we use a `styled.div` here, rather than + * `styled(RadixDialog.Content)`, because Radix adds an inline `pointer-events: + * auto` style to that element. We need to make sure there _aren't_ pointer + * events on the dialog content, because of the aforementioned full-screen + * wrapper that appears over the ``. We want to make sure that clicks + * on the full-screen wrapper pass through to the underlying ``, so + * that the dialog closes when the user clicks there. + */ +const DialogContent = styled.div<{ $zIndex?: number }>` + position: fixed; + inset: 0; + pointer-events: none; + ${props => props.$zIndex && `z-index: ${props.$zIndex};`} +`; + +export interface DialogEmptyContentProps { + children?: ReactNode; + /** @deprecated this prop will be removed in the future */ + zIndex?: number; +} + +export const EmptyContent = ({ children, zIndex }: DialogEmptyContentProps) => { + return ( + + + + + {children} + + + ); +}; diff --git a/packages/ui-deprecated/src/Dialog/RadioItem.tsx b/packages/ui-deprecated/src/Dialog/RadioItem.tsx new file mode 100644 index 0000000000..85cec2658d --- /dev/null +++ b/packages/ui-deprecated/src/Dialog/RadioItem.tsx @@ -0,0 +1,151 @@ +import React, { ReactNode, useMemo } from 'react'; +import { RadioGroupItem } from '@radix-ui/react-radio-group'; +import { styled } from 'styled-components'; +import { motion } from 'framer-motion'; +import { Text } from '../Text'; +import { ActionType, getOutlineColorByActionType } from '../utils/ActionType'; +import { asTransientProps } from '../utils/asTransientProps'; + +const Root = styled(motion.button)<{ + $actionType: ActionType; + $disabled?: boolean; +}>` + border-radius: ${props => props.theme.borderRadius.sm}; + background-color: ${props => props.theme.color.other.tonalFill5}; + padding: ${props => props.theme.spacing(3)}; + + display: flex; + justify-content: space-between; + align-items: center; + text-align: left; + transition: + background 0.15s, + outline 0.15s; + + &:hover { + background: linear-gradient( + 0deg, + ${props => props.theme.color.action.hoverOverlay} 0%, + ${props => props.theme.color.action.hoverOverlay} 100% + ), + ${props => props.theme.color.other.tonalFill5}; + } + + &:focus { + background: linear-gradient( + 0deg, + ${props => props.theme.color.action.hoverOverlay} 0%, + ${props => props.theme.color.action.hoverOverlay} 100% + ), + ${props => props.theme.color.other.tonalFill5}; + outline: 2px solid ${props => getOutlineColorByActionType(props.theme, props.$actionType)}; + } + + &[aria-checked='true'] { + outline: 2px solid ${props => getOutlineColorByActionType(props.theme, props.$actionType)}; + } + + &:disabled { + background: linear-gradient( + 0deg, + ${props => props.theme.color.action.disabledOverlay} 0%, + ${props => props.theme.color.action.disabledOverlay} 100% + ), + ${props => props.theme.color.other.tonalFill5}; + } +`; + +const Info = styled.div` + display: flex; + gap: ${props => props.theme.spacing(2)}; + align-items: center; +`; + +const Title = styled.div` + display: flex; + align-items: center; + white-space: nowrap; + gap: ${props => props.theme.spacing(1)}; +`; + +export interface DialogRadioItemProps { + /** A required unique string value defining the radio item */ + value: string; + title: ReactNode; + description?: ReactNode; + /** A component rendered on the left side of the item */ + endAdornment?: ReactNode; + /** A component rendered on the right side of the item */ + startAdornment?: ReactNode; + disabled?: boolean; + actionType?: ActionType; + /** A function that closes the dialog on select of the item */ + onClose?: VoidFunction; + /** Fires when the item is clicked or focused using the keyboard */ + onSelect?: VoidFunction; +} + +/** A radio button that selects an asset or a balance from the `AssetSelector` */ +export const RadioItem = ({ + value, + title, + description, + startAdornment, + endAdornment, + disabled, + actionType = 'default', + onClose, + onSelect, +}: DialogRadioItemProps) => { + const handleClick = (event: React.MouseEvent) => { + // Is a click and not an arrow key up/down + if (event.detail > 0) { + onSelect?.(); + onClose?.(); + } + }; + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + onSelect?.(); + onClose?.(); + } + }; + + const descriptionText = useMemo(() => { + if (!description) { + return null; + } + + if (typeof description === 'string') { + return ( + color.text.secondary} as='div'> + {description} + + ); + } + + return description; + }, [description]); + + return ( + + + + {startAdornment} +
+ {title} + {descriptionText} +
+
+ + {endAdornment} +
+
+ ); +}; diff --git a/packages/ui-tailwind/src/Dialog/RadioItemGroup.tsx b/packages/ui-deprecated/src/Dialog/RadioItemGroup.tsx similarity index 100% rename from packages/ui-tailwind/src/Dialog/RadioItemGroup.tsx rename to packages/ui-deprecated/src/Dialog/RadioItemGroup.tsx diff --git a/packages/ui-tailwind/src/Dialog/Trigger.tsx b/packages/ui-deprecated/src/Dialog/Trigger.tsx similarity index 100% rename from packages/ui-tailwind/src/Dialog/Trigger.tsx rename to packages/ui-deprecated/src/Dialog/Trigger.tsx diff --git a/packages/ui-tailwind/src/Dialog/index.stories.tsx b/packages/ui-deprecated/src/Dialog/index.stories.tsx similarity index 80% rename from packages/ui-tailwind/src/Dialog/index.stories.tsx rename to packages/ui-deprecated/src/Dialog/index.stories.tsx index 6442007ddc..b67cc659fd 100644 --- a/packages/ui-tailwind/src/Dialog/index.stories.tsx +++ b/packages/ui-deprecated/src/Dialog/index.stories.tsx @@ -5,9 +5,21 @@ import { Button } from '../Button'; import { ComponentType } from 'react'; import { Text } from '../Text'; import { AssetIcon } from '../AssetIcon'; +import { styled } from 'styled-components'; import { Ban, Handshake, ThumbsUp } from 'lucide-react'; import { OSMO_METADATA, PENUMBRA_METADATA, PIZZA_METADATA } from '../utils/bufs'; +const WhiteTextWrapper = styled.div` + color: ${props => props.theme.color.text.primary}; +`; + +const Column = styled.div` + display: flex; + flex-direction: column; + gap: ${props => props.theme.spacing(1)}; + padding-top: ${props => props.theme.spacing(1)}; +`; + const meta: Meta = { component: Dialog, tags: ['autodocs', '!dev'], @@ -36,21 +48,16 @@ export const Basic: Story = { - - - - - } + buttonGroupProps={{ + buttons: [ + { label: 'Primary CTA', icon: ThumbsUp }, + { label: 'Secondary CTA', icon: Handshake }, + { label: 'Another secondary CTA', icon: Ban }, + ], + hasPrimaryButton: true, + }} > -
+ This is a subheading @@ -66,7 +73,7 @@ export const Basic: Story = { elit. Ut et massa mi. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut et massa mi. -
+
); @@ -83,7 +90,7 @@ export const WithRadioItems: Story = { -
+ } /> -
+
diff --git a/packages/ui/src/Dialog/index.test.tsx b/packages/ui-deprecated/src/Dialog/index.test.tsx similarity index 100% rename from packages/ui/src/Dialog/index.test.tsx rename to packages/ui-deprecated/src/Dialog/index.test.tsx diff --git a/packages/ui-tailwind/src/Dialog/index.tsx b/packages/ui-deprecated/src/Dialog/index.tsx similarity index 100% rename from packages/ui-tailwind/src/Dialog/index.tsx rename to packages/ui-deprecated/src/Dialog/index.tsx diff --git a/packages/ui-tailwind/src/Display/index.stories.tsx b/packages/ui-deprecated/src/Display/index.stories.tsx similarity index 73% rename from packages/ui-tailwind/src/Display/index.stories.tsx rename to packages/ui-deprecated/src/Display/index.stories.tsx index fab620c930..00265605b3 100644 --- a/packages/ui-tailwind/src/Display/index.stories.tsx +++ b/packages/ui-deprecated/src/Display/index.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Display } from '.'; +import { styled } from 'styled-components'; import { Text } from '../Text'; const meta: Meta = { @@ -11,9 +12,9 @@ const meta: Meta = { }, decorators: [ Story => ( -
+ -
+ ), ], }; @@ -21,10 +22,20 @@ export default meta; type Story = StoryObj; +const OuterWidthIndicator = styled.div` + border: 1px solid ${props => props.theme.color.base.white}; +`; + +const InnerWidthIndicator = styled.div` + background: ${props => props.theme.color.base.white}; + color: ${props => props.theme.color.base.black}; + padding: ${props => props.theme.spacing(2)}; +`; + export const FullWidth: Story = { args: { children: ( -
+ The white background that this text sits inside of represents the{' '} inside width of the <Display />{' '} @@ -40,7 +51,7 @@ export const FullWidth: Story = { To test <Display /> at full width, click the "Full Width" item in the left sidebar, and try resizing your browser. -
+ ), }, }; diff --git a/packages/ui-tailwind/src/Display/index.tsx b/packages/ui-deprecated/src/Display/index.tsx similarity index 57% rename from packages/ui-tailwind/src/Display/index.tsx rename to packages/ui-deprecated/src/Display/index.tsx index f428f9d2f7..758831e7bc 100644 --- a/packages/ui-tailwind/src/Display/index.tsx +++ b/packages/ui-deprecated/src/Display/index.tsx @@ -1,4 +1,19 @@ import { ReactNode } from 'react'; +import { styled } from 'styled-components'; +import { media } from '../utils/media'; + +const Root = styled.section` + padding: 0 ${props => props.theme.spacing(4)}; + + ${props => media.desktop` + padding: 0 ${props.theme.spacing(8)}; + `} +`; + +const ContentsWrapper = styled.div` + max-width: 1600px; + margin: 0 auto; +`; export interface DisplayProps { children?: ReactNode; @@ -20,8 +35,8 @@ export interface DisplayProps { */ export const Display = ({ children }: DisplayProps) => { return ( -
-
{children}
-
+ + {children} + ); }; diff --git a/packages/ui-tailwind/src/DropdownMenu/CheckboxItem.tsx b/packages/ui-deprecated/src/DropdownMenu/CheckboxItem.tsx similarity index 80% rename from packages/ui-tailwind/src/DropdownMenu/CheckboxItem.tsx rename to packages/ui-deprecated/src/DropdownMenu/CheckboxItem.tsx index 8b215708ba..6dbd6d1bef 100644 --- a/packages/ui-tailwind/src/DropdownMenu/CheckboxItem.tsx +++ b/packages/ui-deprecated/src/DropdownMenu/CheckboxItem.tsx @@ -4,8 +4,9 @@ import { } from '@radix-ui/react-dropdown-menu'; import { ReactNode } from 'react'; import { Check } from 'lucide-react'; +import { asTransientProps } from '../utils/asTransientProps.ts'; import { Text } from '../Text'; -import { DropdownMenuItemBase, getMenuItem } from '../utils/menu-item.ts'; +import { DropdownMenuItemBase, MenuItem } from '../utils/menuItem.ts'; export interface DropdownMenuCheckboxItemProps extends DropdownMenuItemBase { children?: ReactNode; @@ -22,18 +23,18 @@ export const CheckboxItem = ({ }: DropdownMenuCheckboxItemProps) => { return ( -
+ {children} -
+
); }; diff --git a/packages/ui-tailwind/src/DropdownMenu/Content.tsx b/packages/ui-deprecated/src/DropdownMenu/Content.tsx similarity index 64% rename from packages/ui-tailwind/src/DropdownMenu/Content.tsx rename to packages/ui-deprecated/src/DropdownMenu/Content.tsx index c0b0c3a825..8243d165ec 100644 --- a/packages/ui-tailwind/src/DropdownMenu/Content.tsx +++ b/packages/ui-deprecated/src/DropdownMenu/Content.tsx @@ -1,10 +1,11 @@ import { ReactNode } from 'react'; +import { useTheme } from 'styled-components'; import { Content as RadixDropdownMenuContent, Portal as RadixDropdownMenuPortal, DropdownMenuContentProps as RadixDropdownMenuContentProps, } from '@radix-ui/react-dropdown-menu'; -import { getPopoverContent, PopoverContext } from '../utils/popover.ts'; +import { PopoverContent, PopoverContext } from '../utils/popover.ts'; export interface DropdownMenuContentProps { children?: ReactNode; @@ -19,10 +20,17 @@ export const Content = ({ align, context = 'default', }: DropdownMenuContentProps) => { + const theme = useTheme(); + return ( - -
{children}
+ + {children}
); diff --git a/packages/ui-tailwind/src/DropdownMenu/Item.tsx b/packages/ui-deprecated/src/DropdownMenu/Item.tsx similarity index 71% rename from packages/ui-tailwind/src/DropdownMenu/Item.tsx rename to packages/ui-deprecated/src/DropdownMenu/Item.tsx index bb6f6dbe71..78aeec15a9 100644 --- a/packages/ui-tailwind/src/DropdownMenu/Item.tsx +++ b/packages/ui-deprecated/src/DropdownMenu/Item.tsx @@ -1,7 +1,8 @@ import { ReactNode } from 'react'; import { Item as RadixDropdownMenuItem } from '@radix-ui/react-dropdown-menu'; +import { asTransientProps } from '../utils/asTransientProps.ts'; import { Text } from '../Text'; -import { DropdownMenuItemBase, getMenuItem } from '../utils/menu-item.ts'; +import { DropdownMenuItemBase, MenuItem } from '../utils/menuItem.ts'; export interface DropdownMenuItemProps extends DropdownMenuItemBase { children?: ReactNode; @@ -18,10 +19,10 @@ export const Item = ({ }: DropdownMenuItemProps) => { return ( -
+ {icon} {children} -
+
); }; diff --git a/packages/ui-tailwind/src/DropdownMenu/RadioGroup.tsx b/packages/ui-deprecated/src/DropdownMenu/RadioGroup.tsx similarity index 100% rename from packages/ui-tailwind/src/DropdownMenu/RadioGroup.tsx rename to packages/ui-deprecated/src/DropdownMenu/RadioGroup.tsx diff --git a/packages/ui-tailwind/src/DropdownMenu/RadioItem.tsx b/packages/ui-deprecated/src/DropdownMenu/RadioItem.tsx similarity index 77% rename from packages/ui-tailwind/src/DropdownMenu/RadioItem.tsx rename to packages/ui-deprecated/src/DropdownMenu/RadioItem.tsx index 47f0187d9c..63633d4977 100644 --- a/packages/ui-tailwind/src/DropdownMenu/RadioItem.tsx +++ b/packages/ui-deprecated/src/DropdownMenu/RadioItem.tsx @@ -4,8 +4,9 @@ import { } from '@radix-ui/react-dropdown-menu'; import { ReactNode } from 'react'; import { Check } from 'lucide-react'; +import { asTransientProps } from '../utils/asTransientProps.ts'; import { Text } from '../Text'; -import { DropdownMenuItemBase, getMenuItem } from '../utils/menu-item.ts'; +import { DropdownMenuItemBase, MenuItem } from '../utils/menuItem.ts'; export interface DropdownMenuRadioItemProps extends DropdownMenuItemBase { children?: ReactNode; @@ -20,13 +21,13 @@ export const RadioItem = ({ }: DropdownMenuRadioItemProps) => { return ( -
+ {children} -
+
); }; diff --git a/packages/ui-tailwind/src/DropdownMenu/Root.tsx b/packages/ui-deprecated/src/DropdownMenu/Root.tsx similarity index 100% rename from packages/ui-tailwind/src/DropdownMenu/Root.tsx rename to packages/ui-deprecated/src/DropdownMenu/Root.tsx diff --git a/packages/ui-tailwind/src/DropdownMenu/Trigger.tsx b/packages/ui-deprecated/src/DropdownMenu/Trigger.tsx similarity index 100% rename from packages/ui-tailwind/src/DropdownMenu/Trigger.tsx rename to packages/ui-deprecated/src/DropdownMenu/Trigger.tsx diff --git a/packages/ui-tailwind/src/DropdownMenu/index.stories.tsx b/packages/ui-deprecated/src/DropdownMenu/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/DropdownMenu/index.stories.tsx rename to packages/ui-deprecated/src/DropdownMenu/index.stories.tsx diff --git a/packages/ui/src/DropdownMenu/index.test.tsx b/packages/ui-deprecated/src/DropdownMenu/index.test.tsx similarity index 100% rename from packages/ui/src/DropdownMenu/index.test.tsx rename to packages/ui-deprecated/src/DropdownMenu/index.test.tsx diff --git a/packages/ui-tailwind/src/DropdownMenu/index.tsx b/packages/ui-deprecated/src/DropdownMenu/index.tsx similarity index 100% rename from packages/ui-tailwind/src/DropdownMenu/index.tsx rename to packages/ui-deprecated/src/DropdownMenu/index.tsx diff --git a/packages/ui/src/FormField/index.stories.tsx b/packages/ui-deprecated/src/FormField/index.stories.tsx similarity index 100% rename from packages/ui/src/FormField/index.stories.tsx rename to packages/ui-deprecated/src/FormField/index.stories.tsx diff --git a/packages/ui/src/FormField/index.tsx b/packages/ui-deprecated/src/FormField/index.tsx similarity index 100% rename from packages/ui/src/FormField/index.tsx rename to packages/ui-deprecated/src/FormField/index.tsx diff --git a/packages/ui-tailwind/src/Grid/index.stories.tsx b/packages/ui-deprecated/src/Grid/index.stories.tsx similarity index 76% rename from packages/ui-tailwind/src/Grid/index.stories.tsx rename to packages/ui-deprecated/src/Grid/index.stories.tsx index a69f42c628..68ae46aaa0 100644 --- a/packages/ui-tailwind/src/Grid/index.stories.tsx +++ b/packages/ui-deprecated/src/Grid/index.stories.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Grid } from '.'; +import { styled } from 'styled-components'; import { Text } from '../Text'; const meta: Meta = { @@ -20,23 +21,31 @@ export default meta; type Story = StoryObj; +const Item = styled.div` + background-color: ${props => props.theme.color.neutral.main}; + display: flex; + align-items: center; + justify-content: center; + padding: ${props => props.theme.spacing(2)}; +`; + export const Demo: Story = { render: function Render() { return ( -
+ mobile=12 -
+
{Array(2) .fill(null) .map((_, index) => ( -
+ mobile=12 tablet=6 -
+
))} @@ -44,9 +53,9 @@ export const Demo: Story = { .fill(null) .map((_, index) => ( -
+ mobile=6 tablet=6 desktop=3 -
+
))} @@ -54,9 +63,9 @@ export const Demo: Story = { .fill(null) .map((_, index) => ( -
+ lg=1 -
+
))}
diff --git a/packages/ui-tailwind/src/Grid/index.tsx b/packages/ui-deprecated/src/Grid/index.tsx similarity index 56% rename from packages/ui-tailwind/src/Grid/index.tsx rename to packages/ui-deprecated/src/Grid/index.tsx index 3a9abb0f20..3444298f91 100644 --- a/packages/ui-tailwind/src/Grid/index.tsx +++ b/packages/ui-deprecated/src/Grid/index.tsx @@ -1,5 +1,7 @@ import { PropsWithChildren } from 'react'; -import cn from 'clsx'; +import { styled } from 'styled-components'; +import { AsTransientProps, asTransientProps } from '../utils/asTransientProps'; +import { media } from '../utils/media'; type GridElement = 'div' | 'main' | 'section'; @@ -28,7 +30,7 @@ interface GridItemProps extends BaseGridProps { * The number of columns this grid item should span on mobile. * * The mobile grid layout can only be split in half, so you can only set a - * grid item to 6 or 12 columns on mobile. 0 hides the container from mobile screens. + * grid item to 6 or 12 columns on mobile. */ mobile?: 0 | 6 | 12; /** @@ -45,71 +47,43 @@ interface GridItemProps extends BaseGridProps { xl?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; } -const MOBILE_MAP: Record['mobile'], string> = { - 0: 'hidden', - 6: 'col-span-6', - 12: 'col-span-12', -}; +export type GridProps = PropsWithChildren; -const TABLET_MAP: Record['tablet'], string> = { - 0: 'tablet:hidden', - 2: 'tablet:col-span-2', - 4: 'tablet:col-span-4', - 6: 'tablet:col-span-6', - 8: 'tablet:col-span-8', - 10: 'tablet:col-span-10', - 12: 'tablet:col-span-12', -}; +const Container = styled.div` + display: grid; + grid-template-columns: repeat(12, 1fr); + gap: ${props => props.theme.spacing(4)}; +`; -const DESKTOP_MAP: Record['desktop'], string> = { - 0: 'desktop:hidden', - 1: 'desktop:col-span-1', - 2: 'desktop:col-span-2', - 3: 'desktop:col-span-3', - 4: 'desktop:col-span-4', - 5: 'desktop:col-span-5', - 6: 'desktop:col-span-6', - 7: 'desktop:col-span-7', - 8: 'desktop:col-span-8', - 9: 'desktop:col-span-9', - 10: 'desktop:col-span-10', - 11: 'desktop:col-span-11', - 12: 'desktop:col-span-12', -}; +const Item = styled.div>>` + ${props => media.mobile` + grid-column: span ${props.$mobile ?? 12}; + `} -const LG_MAP: Record['lg'], string> = { - 0: 'lg:hidden', - 1: 'lg:col-span-1', - 2: 'lg:col-span-2', - 3: 'lg:col-span-3', - 4: 'lg:col-span-4', - 5: 'lg:col-span-5', - 6: 'lg:col-span-6', - 7: 'lg:col-span-7', - 8: 'lg:col-span-8', - 9: 'lg:col-span-9', - 10: 'lg:col-span-10', - 11: 'lg:col-span-11', - 12: 'lg:col-span-12', -}; + ${props => + props.$tablet && + media.tablet` + grid-column: span ${props.$tablet}; + `} -const XL_MAP: Record['xl'], string> = { - 0: 'xl:hidden', - 1: 'xl:col-span-1', - 2: 'xl:col-span-2', - 3: 'xl:col-span-3', - 4: 'xl:col-span-4', - 5: 'xl:col-span-5', - 6: 'xl:col-span-6', - 7: 'xl:col-span-7', - 8: 'xl:col-span-8', - 9: 'xl:col-span-9', - 10: 'xl:col-span-10', - 11: 'xl:col-span-11', - 12: 'xl:col-span-12', -}; + ${props => + props.$desktop && + media.desktop` + grid-column: span ${props.$desktop}; + `} -export type GridProps = PropsWithChildren; + ${props => + props.$lg && + media.lg` + grid-column: span ${props.$lg}; + `} + + ${props => + props.$xl && + media.xl` + grid-column: span ${props.$xl}; + `} +`; /** * A responsive grid component that makes 12-column layouts super easy to build. @@ -151,19 +125,11 @@ export type GridProps = PropsWithChildren; *
* ``` */ -export const Grid = ({ container, children, as: Container = 'div', ...props }: GridProps) => +export const Grid = ({ container, children, as = 'div', ...props }: GridProps) => container ? ( - {children} + {children} ) : ( - + {children} - + ); diff --git a/packages/ui-tailwind/src/Icon/index.stories.ts b/packages/ui-deprecated/src/Icon/index.stories.ts similarity index 92% rename from packages/ui-tailwind/src/Icon/index.stories.ts rename to packages/ui-deprecated/src/Icon/index.stories.ts index b7f494b781..f7dd4137f9 100644 --- a/packages/ui-tailwind/src/Icon/index.stories.ts +++ b/packages/ui-deprecated/src/Icon/index.stories.ts @@ -20,6 +20,6 @@ export const Basic: StoryObj = { args: { IconComponent: ArrowRightLeft, size: 'sm', - color: 'text.primary', + color: color => color.text.primary, }, }; diff --git a/packages/ui-tailwind/src/Icon/index.tsx b/packages/ui-deprecated/src/Icon/index.tsx similarity index 66% rename from packages/ui-tailwind/src/Icon/index.tsx rename to packages/ui-deprecated/src/Icon/index.tsx index 9746156fab..0de23de0c2 100644 --- a/packages/ui-tailwind/src/Icon/index.tsx +++ b/packages/ui-deprecated/src/Icon/index.tsx @@ -1,7 +1,6 @@ import { LucideIcon } from 'lucide-react'; import { ComponentProps, FC } from 'react'; -import { ThemeColor, getThemeColorClass } from '../utils/color'; -import cn from 'clsx'; +import { DefaultTheme, useTheme } from 'styled-components'; export type IconSize = 'sm' | 'md' | 'lg'; @@ -21,8 +20,12 @@ export interface IconProps { * - `lg`: 32px square */ size: IconSize; - /** A string representing the color key from the Tailwind theme (e.g. 'primary.light') */ - color?: ThemeColor; + /** + * A function that takes the `color` object of `theme`, and returns a CSS color to render + * the icon with. If left undefined, will default to the parent's text color + * (`currentColor` in SVG terms). + */ + color?: (color: DefaultTheme['color']) => string; } const PROPS_BY_SIZE: Record> = { @@ -50,17 +53,13 @@ const PROPS_BY_SIZE: Record> = { * color.primary.main} * /> * ``` */ export const Icon = ({ IconComponent, size = 'sm', color }: IconProps) => { - return ( - - ); + const theme = useTheme(); + const resolvedColor = color ? color(theme.color) : 'currentColor'; + + return ; }; diff --git a/packages/ui/components/ui/identicon/generate.ts b/packages/ui-deprecated/src/Identicon/generate.ts similarity index 100% rename from packages/ui/components/ui/identicon/generate.ts rename to packages/ui-deprecated/src/Identicon/generate.ts diff --git a/packages/ui-tailwind/src/Identicon/index.stories.tsx b/packages/ui-deprecated/src/Identicon/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/Identicon/index.stories.tsx rename to packages/ui-deprecated/src/Identicon/index.stories.tsx diff --git a/packages/ui-tailwind/src/Identicon/index.tsx b/packages/ui-deprecated/src/Identicon/index.tsx similarity index 79% rename from packages/ui-tailwind/src/Identicon/index.tsx rename to packages/ui-deprecated/src/Identicon/index.tsx index fb518243e2..89671bd9d9 100644 --- a/packages/ui-tailwind/src/Identicon/index.tsx +++ b/packages/ui-deprecated/src/Identicon/index.tsx @@ -1,5 +1,6 @@ import { useMemo } from 'react'; import { generateGradient, generateSolidColor } from './generate'; +import { styled } from 'styled-components'; /** * The view box size is separate from the passed-in `size` prop. @@ -10,6 +11,22 @@ import { generateGradient, generateSolidColor } from './generate'; */ const VIEW_BOX_SIZE = 24; +const Svg = styled.svg.attrs<{ $size: number }>(props => ({ + width: props.$size, + height: props.$size, + viewBox: `0 0 ${VIEW_BOX_SIZE} ${VIEW_BOX_SIZE}`, + version: '1.1', + xmlns: 'http://www.w3.org/2000/svg', +}))` + display: block; + border-radius: ${props => props.theme.borderRadius.full}; +`; + +const SvgText = styled.text` + text-transform: uppercase; + font-family: ${props => props.theme.font.default}; +`; + export interface IdenticonProps { /** * The ID or other string representation of the object you want an identicon @@ -46,14 +63,7 @@ const IdenticonGradient = ({ uniqueIdentifier, size = 120 }: IdenticonProps) => const gradientId = useMemo(() => `gradient-${uniqueIdentifier}`, [uniqueIdentifier]); return ( - + @@ -69,7 +79,7 @@ const IdenticonGradient = ({ uniqueIdentifier, size = 120 }: IdenticonProps) => height={VIEW_BOX_SIZE} /> - + ); }; @@ -77,18 +87,11 @@ const IdenticonSolid = ({ uniqueIdentifier, size = 120 }: IdenticonProps) => { const color = useMemo(() => generateSolidColor(uniqueIdentifier), [uniqueIdentifier]); return ( - + - + {uniqueIdentifier[0]} - - + + ); }; diff --git a/packages/ui/src/IsAnimatingProvider/index.tsx b/packages/ui-deprecated/src/IsAnimatingProvider/index.tsx similarity index 100% rename from packages/ui/src/IsAnimatingProvider/index.tsx rename to packages/ui-deprecated/src/IsAnimatingProvider/index.tsx diff --git a/packages/ui-tailwind/src/MenuItem/index.stories.tsx b/packages/ui-deprecated/src/MenuItem/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/MenuItem/index.stories.tsx rename to packages/ui-deprecated/src/MenuItem/index.stories.tsx diff --git a/packages/ui-deprecated/src/MenuItem/index.tsx b/packages/ui-deprecated/src/MenuItem/index.tsx new file mode 100644 index 0000000000..96341d4ff1 --- /dev/null +++ b/packages/ui-deprecated/src/MenuItem/index.tsx @@ -0,0 +1,48 @@ +import type { LucideIcon } from 'lucide-react'; +import type { FC, MouseEventHandler } from 'react'; +import { MenuItem as SharedMenuItem, DropdownMenuItemBase } from '../utils/menuItem'; +import { Text } from '../Text'; +import { styled } from 'styled-components'; +import { asTransientProps } from '../utils/asTransientProps.ts'; + +const IconAdornment = styled.i` + display: flex; + align-items: center; + justify-content: center; + padding: ${props => props.theme.spacing(1)}; + width: ${props => props.theme.spacing(6)}; + height: ${props => props.theme.spacing(6)}; +`; + +export interface MenuItemProps extends DropdownMenuItemBase { + label: string; + icon?: LucideIcon | FC; + onClick?: MouseEventHandler; +} + +/** + * A button generally used in menus or selectable lists + */ +export const MenuItem = ({ + actionType = 'default', + icon: IconComponent, + label, + onClick, + disabled, +}: MenuItemProps) => { + return ( + + {IconComponent && ( + + + + )} + {label} + + ); +}; diff --git a/packages/ui/src/PenumbraUIProvider/FontFaces.tsx b/packages/ui-deprecated/src/PenumbraUIProvider/FontFaces.tsx similarity index 100% rename from packages/ui/src/PenumbraUIProvider/FontFaces.tsx rename to packages/ui-deprecated/src/PenumbraUIProvider/FontFaces.tsx diff --git a/packages/ui/src/PenumbraUIProvider/fonts.d.ts b/packages/ui-deprecated/src/PenumbraUIProvider/fonts.d.ts similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts.d.ts rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts.d.ts diff --git a/packages/ui-tailwind/src/theme/fonts/IosevkaTerm-Regular.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/IosevkaTerm-Regular.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/IosevkaTerm-Regular.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/IosevkaTerm-Regular.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/Poppins-Italic-LatinExt.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Italic-LatinExt.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/Poppins-Italic-LatinExt.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Italic-LatinExt.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/Poppins-Italic.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Italic.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/Poppins-Italic.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Italic.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/Poppins-Medium-LatinExt.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Medium-LatinExt.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/Poppins-Medium-LatinExt.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Medium-LatinExt.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/Poppins-Medium.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Medium.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/Poppins-Medium.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Medium.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/Poppins-MediumItalic-LatinExt.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-MediumItalic-LatinExt.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/Poppins-MediumItalic-LatinExt.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-MediumItalic-LatinExt.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/Poppins-MediumItalic.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-MediumItalic.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/Poppins-MediumItalic.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-MediumItalic.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/Poppins-Regular-LatinExt.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Regular-LatinExt.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/Poppins-Regular-LatinExt.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Regular-LatinExt.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/Poppins-Regular.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Regular.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/Poppins-Regular.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/Poppins-Regular.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/WorkSans-Medium-LatinExt.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/WorkSans-Medium-LatinExt.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/WorkSans-Medium-LatinExt.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/WorkSans-Medium-LatinExt.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/WorkSans-Medium-Vietnamese.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/WorkSans-Medium-Vietnamese.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/WorkSans-Medium-Vietnamese.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/WorkSans-Medium-Vietnamese.woff2 diff --git a/packages/ui-tailwind/src/theme/fonts/WorkSans-Medium.woff2 b/packages/ui-deprecated/src/PenumbraUIProvider/fonts/WorkSans-Medium.woff2 similarity index 100% rename from packages/ui-tailwind/src/theme/fonts/WorkSans-Medium.woff2 rename to packages/ui-deprecated/src/PenumbraUIProvider/fonts/WorkSans-Medium.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/index.tsx b/packages/ui-deprecated/src/PenumbraUIProvider/index.tsx similarity index 100% rename from packages/ui/src/PenumbraUIProvider/index.tsx rename to packages/ui-deprecated/src/PenumbraUIProvider/index.tsx diff --git a/packages/ui/src/PenumbraUIProvider/theme.ts b/packages/ui-deprecated/src/PenumbraUIProvider/theme.ts similarity index 100% rename from packages/ui/src/PenumbraUIProvider/theme.ts rename to packages/ui-deprecated/src/PenumbraUIProvider/theme.ts diff --git a/packages/ui-tailwind/src/Pill/index.stories.tsx b/packages/ui-deprecated/src/Pill/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/Pill/index.stories.tsx rename to packages/ui-deprecated/src/Pill/index.stories.tsx diff --git a/packages/ui/src/Pill/index.test.tsx b/packages/ui-deprecated/src/Pill/index.test.tsx similarity index 100% rename from packages/ui/src/Pill/index.test.tsx rename to packages/ui-deprecated/src/Pill/index.test.tsx diff --git a/packages/ui-deprecated/src/Pill/index.tsx b/packages/ui-deprecated/src/Pill/index.tsx new file mode 100644 index 0000000000..41947b357f --- /dev/null +++ b/packages/ui-deprecated/src/Pill/index.tsx @@ -0,0 +1,94 @@ +import { styled, DefaultTheme } from 'styled-components'; +import { asTransientProps } from '../utils/asTransientProps'; +import { ReactNode } from 'react'; +import { body, technical, detail, detailTechnical } from '../utils/typography'; +import { Density } from '../types/Density'; +import { useDensity } from '../hooks/useDensity'; + +type Priority = 'primary' | 'secondary'; +type Context = + | 'default' + | 'technical-default' + | 'technical-success' + | 'technical-caution' + | 'technical-destructive'; + +const getFont = (context: Context, density: Density) => { + if (context === 'default') { + return density === 'sparse' ? body : detail; + } + return density === 'sparse' ? technical : detailTechnical; +}; + +const getXPadding = (priority: Priority, density: Density) => { + let padding = density === 'sparse' ? 3 : 2; + if (priority === 'secondary') { + padding = padding - 0.5; + } + return padding; +}; + +const getBackgroundColor = (theme: DefaultTheme, priority: Priority, context: Context) => { + if (priority === 'secondary') { + return 'transparent'; + } + const colorMap: Record = { + default: theme.color.other.tonalFill10, + 'technical-default': theme.color.other.tonalFill10, + 'technical-success': theme.color.secondary.light, + 'technical-caution': theme.color.caution.light, + 'technical-destructive': theme.color.destructive.light, + }; + return colorMap[context]; +}; + +const getColor = (theme: DefaultTheme, priority: Priority, context: Context) => { + if (priority === 'primary') { + return context === 'default' || context === 'technical-default' + ? theme.color.text.primary + : theme.color.secondary.dark; + } + + const colorMap: Record = { + default: theme.color.text.primary, + 'technical-default': theme.color.text.primary, + 'technical-success': theme.color.secondary.light, + 'technical-caution': theme.color.caution.light, + 'technical-destructive': theme.color.destructive.light, + }; + return colorMap[context]; +}; + +const Root = styled.span<{ $density: Density; $priority: Priority; $context: Context }>` + box-sizing: border-box; + + border: ${props => + props.$priority === 'secondary' ? `2px dashed ${props.theme.color.other.tonalStroke}` : 'none'}; + border-radius: ${props => props.theme.borderRadius.full}; + + display: inline-block; + max-width: 100%; + width: max-content; + + padding-top: ${props => props.theme.spacing(props.$priority === 'secondary' ? 0.5 : 1)}; + padding-bottom: ${props => props.theme.spacing(props.$priority === 'secondary' ? 0.5 : 1)}; + + padding-left: ${props => props.theme.spacing(getXPadding(props.$priority, props.$density))}; + padding-right: ${props => props.theme.spacing(getXPadding(props.$priority, props.$density))}; + + ${props => getFont(props.$context, props.$density)}; + color: ${props => getColor(props.theme, props.$priority, props.$context)}; + background-color: ${props => getBackgroundColor(props.theme, props.$priority, props.$context)}; +`; + +export interface PillProps { + children: ReactNode; + priority?: Priority; + context?: Context; +} + +export const Pill = ({ children, priority = 'primary', context = 'default' }: PillProps) => { + const density = useDensity(); + + return {children}; +}; diff --git a/packages/ui-tailwind/src/Popover/index.stories.tsx b/packages/ui-deprecated/src/Popover/index.stories.tsx similarity index 86% rename from packages/ui-tailwind/src/Popover/index.stories.tsx rename to packages/ui-deprecated/src/Popover/index.stories.tsx index 8bb09f83cf..70719d36c5 100644 --- a/packages/ui-tailwind/src/Popover/index.stories.tsx +++ b/packages/ui-deprecated/src/Popover/index.stories.tsx @@ -4,9 +4,17 @@ import { Popover } from '.'; import { Button } from '../Button'; import { ComponentType, useState } from 'react'; import { Text } from '../Text'; +import { styled } from 'styled-components'; import { Shield } from 'lucide-react'; import { Density } from '../Density'; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: ${props => props.theme.spacing(4)}; + color: ${props => props.theme.color.text.primary}; +`; + const meta: Meta = { component: Popover, tags: ['autodocs', '!dev'], @@ -36,7 +44,7 @@ export const Basic: Story = { -
+ This is a heading @@ -51,7 +59,7 @@ export const Basic: Story = {
-
+ ); diff --git a/packages/ui/src/Popover/index.test.tsx b/packages/ui-deprecated/src/Popover/index.test.tsx similarity index 100% rename from packages/ui/src/Popover/index.test.tsx rename to packages/ui-deprecated/src/Popover/index.test.tsx diff --git a/packages/ui-tailwind/src/Popover/index.tsx b/packages/ui-deprecated/src/Popover/index.tsx similarity index 91% rename from packages/ui-tailwind/src/Popover/index.tsx rename to packages/ui-deprecated/src/Popover/index.tsx index c19f573f2a..db403b93ff 100644 --- a/packages/ui-tailwind/src/Popover/index.tsx +++ b/packages/ui-deprecated/src/Popover/index.tsx @@ -1,7 +1,8 @@ import { ReactNode } from 'react'; import * as RadixPopover from '@radix-ui/react-popover'; import type { PopoverContentProps as RadixPopoverContentProps } from '@radix-ui/react-popover'; -import { getPopoverContent, PopoverContext } from '../utils/popover.ts'; +import { useTheme } from 'styled-components'; +import { PopoverContent, PopoverContext } from '../utils/popover.ts'; interface ControlledPopoverProps { /** @@ -114,10 +115,17 @@ export interface PopoverContentProps { * `side` and `align` props. */ const Content = ({ children, side, align, context = 'default' }: PopoverContentProps) => { + const theme = useTheme(); + return ( - -
{children}
+ + {children}
); diff --git a/packages/ui-tailwind/src/Progress/index.stories.tsx b/packages/ui-deprecated/src/Progress/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/Progress/index.stories.tsx rename to packages/ui-deprecated/src/Progress/index.stories.tsx diff --git a/packages/ui-deprecated/src/Progress/index.tsx b/packages/ui-deprecated/src/Progress/index.tsx new file mode 100644 index 0000000000..3c13381b6d --- /dev/null +++ b/packages/ui-deprecated/src/Progress/index.tsx @@ -0,0 +1,85 @@ +import * as ProgressPrimitive from '@radix-ui/react-progress'; +import { styled, type DefaultTheme, keyframes } from 'styled-components'; + +export const infiniteLoading = keyframes` + from { + left: -20%; + } + to { + left: 100%; + } +`; + +const Root = styled(ProgressPrimitive.Root)<{ $error: boolean }>` + position: relative; + width: 100%; + height: ${props => props.theme.spacing(1)}; + background-color: ${props => + props.$error ? props.theme.color.destructive.light : props.theme.color.other.tonalFill5}; + transition: background-color 0.15s; + overflow: hidden; +`; + +export const getIndicatorColor = (theme: DefaultTheme, value: number, error: boolean): string => { + if (error) { + return theme.color.destructive.light; + } + + if (value === 1) { + return theme.color.secondary.light; + } + + return theme.color.caution.light; +}; + +const Indicator = styled.div<{ $value: number; $error: boolean }>` + height: 100%; + width: 100%; + background-color: ${props => getIndicatorColor(props.theme, props.$value, props.$error)}; + transition: + transform 0.5s cubic-bezier(0.65, 0, 0.35, 1), + background-color 0.15s; + overflow: hidden; +`; + +const Loading = styled.div` + position: absolute; + top: 0; + left: -20%; + width: 20%; + height: 100%; + filter: blur(2px); + background: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0%, + #fff 50%, + rgba(255, 255, 255, 0) 100% + ); + animation: ${infiniteLoading} 1s linear infinite; +`; + +export interface ProgressProps { + /** Percentage value from 0 to 1 */ + value: number; + /** Displays the skeleton-like moving shade */ + loading?: boolean; + /** Renders red indicator while the progress continues */ + error?: boolean; +} + +/** + * Progress bar with loading and error states + */ +export const Progress = ({ value, loading, error = false }: ProgressProps) => ( + + + + {loading && } + + + +); diff --git a/packages/ui/src/SegmentedControl/index.stories.tsx b/packages/ui-deprecated/src/SegmentedControl/index.stories.tsx similarity index 100% rename from packages/ui/src/SegmentedControl/index.stories.tsx rename to packages/ui-deprecated/src/SegmentedControl/index.stories.tsx diff --git a/packages/ui/src/SegmentedControl/index.test.tsx b/packages/ui-deprecated/src/SegmentedControl/index.test.tsx similarity index 100% rename from packages/ui/src/SegmentedControl/index.test.tsx rename to packages/ui-deprecated/src/SegmentedControl/index.test.tsx diff --git a/packages/ui/src/SegmentedControl/index.tsx b/packages/ui-deprecated/src/SegmentedControl/index.tsx similarity index 100% rename from packages/ui/src/SegmentedControl/index.tsx rename to packages/ui-deprecated/src/SegmentedControl/index.tsx diff --git a/packages/ui/src/Slider/index.stories.tsx b/packages/ui-deprecated/src/Slider/index.stories.tsx similarity index 100% rename from packages/ui/src/Slider/index.stories.tsx rename to packages/ui-deprecated/src/Slider/index.stories.tsx diff --git a/packages/ui/src/Slider/index.test.tsx b/packages/ui-deprecated/src/Slider/index.test.tsx similarity index 100% rename from packages/ui/src/Slider/index.test.tsx rename to packages/ui-deprecated/src/Slider/index.test.tsx diff --git a/packages/ui/src/Slider/index.tsx b/packages/ui-deprecated/src/Slider/index.tsx similarity index 100% rename from packages/ui/src/Slider/index.tsx rename to packages/ui-deprecated/src/Slider/index.tsx diff --git a/packages/ui/src/SwapInput/index.stories.tsx b/packages/ui-deprecated/src/SwapInput/index.stories.tsx similarity index 100% rename from packages/ui/src/SwapInput/index.stories.tsx rename to packages/ui-deprecated/src/SwapInput/index.stories.tsx diff --git a/packages/ui/src/SwapInput/index.tsx b/packages/ui-deprecated/src/SwapInput/index.tsx similarity index 100% rename from packages/ui/src/SwapInput/index.tsx rename to packages/ui-deprecated/src/SwapInput/index.tsx diff --git a/packages/ui-tailwind/src/Table/index.stories.tsx b/packages/ui-deprecated/src/Table/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/Table/index.stories.tsx rename to packages/ui-deprecated/src/Table/index.stories.tsx diff --git a/packages/ui/src/Table/index.test.tsx b/packages/ui-deprecated/src/Table/index.test.tsx similarity index 100% rename from packages/ui/src/Table/index.test.tsx rename to packages/ui-deprecated/src/Table/index.test.tsx diff --git a/packages/ui-deprecated/src/Table/index.tsx b/packages/ui-deprecated/src/Table/index.tsx new file mode 100644 index 0000000000..b3ce822426 --- /dev/null +++ b/packages/ui-deprecated/src/Table/index.tsx @@ -0,0 +1,219 @@ +import { PropsWithChildren, ReactNode } from 'react'; +import { styled, css } from 'styled-components'; +import { tableHeading, tableItem } from '../utils/typography'; +import { Density } from '../types/Density'; +import { useDensity } from '../hooks/useDensity'; +import { ConditionalWrap } from '../ConditionalWrap'; +import { motion } from 'framer-motion'; +import { MotionProp } from '../utils/MotionProp'; + +const FIVE_PERCENT_OPACITY_IN_HEX = '0d'; + +// So named to avoid naming conflicts with `
` +const StyledTable = styled(motion.table)<{ $tableLayout?: 'fixed' | 'auto' }>` + width: 100%; + background-color: ${props => props.theme.color.neutral.contrast + FIVE_PERCENT_OPACITY_IN_HEX}; + padding-left: ${props => props.theme.spacing(3)}; + padding-right: ${props => props.theme.spacing(3)}; + border-radius: ${props => props.theme.borderRadius.sm}; + table-layout: ${props => props.$tableLayout ?? 'auto'}; +`; + +const TitleAndTableWrapper = styled.div` + display: flex; + flex-direction: column; +`; + +const TitleWrapper = styled.div` + padding: ${props => props.theme.spacing(3)}; +`; + +export interface TableProps extends MotionProp { + /** Content that will appear above the table. */ + title?: ReactNode; + children: ReactNode; + /** Which CSS `table-layout` property to use. */ + tableLayout?: 'fixed' | 'auto'; +} + +/** + * A styled HTML table. + * + * To build a table, you only need to import the `
` component. All + * other components are properties on `Table`. + * + * ```tsx + *
+ * + * + * Header cell + * Header cell 2 + * + * + * + * + * Body cell + * Body cell 2 + * + * + *
+ * ``` + * + * By design, `` elements have limited props. No styling or + * customization is permitted. This ensures that all tables look consistent + * throughout the Penumbra UI. + * + * To render title content above the table, pass a `title` prop: + * + * ```tsx + * + * ... + *
+ * + * // or... + * + * Here is some rich table title content}> + * ... + *
+ * ``` + */ +export const Table = ({ title, children, tableLayout }: TableProps) => ( + ( + + {title} + {children} + + )} + > + + {children} + + +); + +const Thead = ({ children }: PropsWithChildren) => {children}; +Table.Thead = Thead; + +const StyledTbody = styled.tbody``; // Needs to be a styled component for `StyledTd` below +const Tbody = ({ children }: PropsWithChildren) => {children}; +Table.Tbody = Tbody; + +const StyledTr = styled(motion.tr)``; // Needs to be a styled component for `StyledTd` below +const Tr = ({ children, motion }: PropsWithChildren) => ( + {children} +); +Table.Tr = Tr; + +type HAlign = 'left' | 'center' | 'right'; +type VAlign = 'top' | 'middle' | 'bottom'; +interface CellStyledProps { + $density: Density; + $width?: string; + $hAlign?: HAlign; + $vAlign?: VAlign; +} + +const cell = css` + box-sizing: border-box; + + padding-left: ${props => props.theme.spacing(3)}; + padding-right: ${props => props.theme.spacing(3)}; + + padding-top: ${props => props.theme.spacing(props.$density === 'sparse' ? 4 : 3)}; + padding-bottom: ${props => props.theme.spacing(props.$density === 'sparse' ? 4 : 3)}; + + ${props => props.$width && `width: ${props.$width};`} + ${props => props.$hAlign && `text-align: ${props.$hAlign};`}; + ${props => props.$vAlign && `vertical-align: ${props.$vAlign};`}; +`; + +const StyledTh = styled(motion.th)` + border-bottom: 1px solid ${props => props.theme.color.other.tonalStroke}; + text-align: left; + color: ${props => props.theme.color.text.secondary}; + + ${tableHeading} + ${cell} +`; +const Th = ({ + children, + colSpan, + hAlign, + vAlign, + width, + motion, +}: PropsWithChildren< + { + colSpan?: number; + /** A CSS `width` value to use for this cell. */ + width?: string; + /** Controls the CSS `text-align` property for this cell. */ + hAlign?: HAlign; + /** Controls the CSS `vertical-align` property for this cell. */ + vAlign?: VAlign; + } & MotionProp +>) => { + const density = useDensity(); + + return ( + + {children} + + ); +}; +Table.Th = Th; + +const StyledTd = styled(motion.td)` + border-bottom: 1px solid ${props => props.theme.color.other.tonalStroke}; + color: ${props => props.theme.color.text.primary}; + + ${StyledTbody} > ${StyledTr}:last-child > & { + border-bottom: none; + } + + ${tableItem} + ${cell} +`; +const Td = ({ + children, + colSpan, + hAlign, + vAlign, + width, + motion, +}: PropsWithChildren< + { + colSpan?: number; + /** A CSS `width` value to use for this cell. */ + width?: string; + /** Controls the CSS `text-align` property for this cell. */ + hAlign?: HAlign; + /** Controls the CSS `vertical-align` property for this cell. */ + vAlign?: VAlign; + } & MotionProp +>) => { + const density = useDensity(); + + return ( + + {children} + + ); +}; +Table.Td = Td; diff --git a/packages/ui-tailwind/src/Tabs/index.stories.tsx b/packages/ui-deprecated/src/Tabs/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/Tabs/index.stories.tsx rename to packages/ui-deprecated/src/Tabs/index.stories.tsx diff --git a/packages/ui/src/Tabs/index.test.tsx b/packages/ui-deprecated/src/Tabs/index.test.tsx similarity index 100% rename from packages/ui/src/Tabs/index.test.tsx rename to packages/ui-deprecated/src/Tabs/index.test.tsx diff --git a/packages/ui-deprecated/src/Tabs/index.tsx b/packages/ui-deprecated/src/Tabs/index.tsx new file mode 100644 index 0000000000..877574013d --- /dev/null +++ b/packages/ui-deprecated/src/Tabs/index.tsx @@ -0,0 +1,173 @@ +import { styled, css, DefaultTheme } from 'styled-components'; +import { tab, tabSmall } from '../utils/typography'; +import { motion } from 'framer-motion'; +import { useId } from 'react'; +import { buttonBase, overlays } from '../utils/button'; +import * as RadixTabs from '@radix-ui/react-tabs'; +import { ActionType } from '../utils/ActionType'; +import { useDensity } from '../hooks/useDensity'; +import { Density } from '../types/Density.ts'; + +const sparse = css` + ${tab}; + + flex-grow: 1; + flex-shrink: 1; + flex-basis: 0; /** Ensure equal widths */ + + padding: ${props => props.theme.spacing(2)}; +`; + +const compact = css` + ${tabSmall}; + + padding: ${props => props.theme.spacing(1)} ${props => props.theme.spacing(2)}; +`; + +const Root = styled.div<{ + $density: Density; +}>` + display: flex; + align-items: stretch; + box-sizing: border-box; + gap: ${props => props.theme.spacing(4)}; + height: ${props => (props.$density === 'sparse' ? 44 : 28)}px; +`; + +type LimitedActionType = Exclude; + +const outlineColorByActionType: Record = { + default: 'neutralFocusOutline', + accent: 'primaryFocusOutline', + unshield: 'unshieldFocusOutline', +}; + +const gradientColorByActionType: Record = { + default: 'neutral', + accent: 'primary', + unshield: 'unshield', +}; + +const Tab = styled.button<{ + $actionType: LimitedActionType; + $getFocusOutlineColor: (theme: DefaultTheme) => string; + $getBorderRadius: (theme: DefaultTheme) => string; + $density: Density; +}>` + ${buttonBase}; + + height: 100%; + + color: ${props => { + switch (props.$actionType) { + case 'accent': + return props.theme.color.primary.light; + case 'unshield': + return props.theme.color.unshield.light; + default: + return props.theme.color.text.primary; + } + }}; + position: relative; + white-space: nowrap; + + ${overlays} + + ${props => (props.$density === 'sparse' ? sparse : compact)} + + &:focus-within { + outline: none; + } + + &::after { + inset: ${props => props.theme.spacing(0.5)}; + } +`; + +const THIRTY_FIVE_PERCENT_OPACITY_IN_HEX = '59'; +const SelectedIndicator = styled(motion.div)<{ $actionType: LimitedActionType }>` + background: radial-gradient( + at 50% 100%, + ${props => + props.theme.color[gradientColorByActionType[props.$actionType]].light + + THIRTY_FIVE_PERCENT_OPACITY_IN_HEX} + 0%, + transparent 50% + ); + border-bottom: 2px solid + ${props => props.theme.color.action[outlineColorByActionType[props.$actionType]]}; + position: absolute; + inset: 0; + z-index: -1; +`; + +export interface TabsTab { + value: string; + label: string; + disabled?: boolean; +} + +export interface TabsProps { + value: string; + onChange: (value: string) => void; + options: TabsTab[]; + actionType?: LimitedActionType; +} + +/** + * Use tabs for switching between related pages or views. + * + * Built atop Radix UI's `` component, so it's fully accessible and + * supports keyboard navigation. + * + * ```TSX + * + * ``` + */ +export const Tabs = ({ value, onChange, options, actionType = 'default' }: TabsProps) => { + const layoutId = useId(); + const density = useDensity(); + + return ( + + + + {options.map(option => ( + + onChange(option.value)} + disabled={option.disabled} + $density={density} + $actionType={actionType} + $getFocusOutlineColor={theme => + theme.color.action[outlineColorByActionType[actionType]] + } + $getBorderRadius={theme => + `${theme.borderRadius.xs} ${theme.borderRadius.xs} ${theme.borderRadius.none} ${theme.borderRadius.none}` + } + > + {value === option.value && ( + + )} + {option.label} + + + ))} + + + + ); +}; diff --git a/packages/ui-tailwind/src/Text/index.stories.tsx b/packages/ui-deprecated/src/Text/index.stories.tsx similarity index 91% rename from packages/ui-tailwind/src/Text/index.stories.tsx rename to packages/ui-deprecated/src/Text/index.stories.tsx index 5756524324..d9163cf1ac 100644 --- a/packages/ui-tailwind/src/Text/index.stories.tsx +++ b/packages/ui-deprecated/src/Text/index.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Text } from '.'; +import { styled } from 'styled-components'; import { useArgs } from '@storybook/preview-api'; const meta: Meta = { @@ -28,6 +29,13 @@ const meta: Meta = { }; export default meta; +const Wrapper = styled.div<{ $dir: 'column' | 'row' }>` + display: flex; + flex-direction: ${props => props.$dir}; + ${props => (props.$dir === 'row' ? `align-items: center;` : '')} + gap: ${props => props.theme.spacing(2)}; +`; + const OPTIONS = [ 'h1', 'h2', @@ -87,16 +95,16 @@ export const KitchenSink: StoryObj = { ); return ( -
-
+ + Text style: {OPTIONS.map(option => (
+ - + ); }, }; @@ -104,7 +112,7 @@ export const KitchenSink: StoryObj = { export const UsageExample: StoryObj = { render: function Render() { return ( -
+ <> h1. Typography h2. This is a section @@ -145,7 +153,7 @@ export const UsageExample: StoryObj = { academy award day-for-night christopher nolan undercranking. Unreal engine visionary match cut grain vs. noise 35mm anti-hero production design. -
+ ); }, }; diff --git a/packages/ui-deprecated/src/Text/index.tsx b/packages/ui-deprecated/src/Text/index.tsx new file mode 100644 index 0000000000..dd9fc8db40 --- /dev/null +++ b/packages/ui-deprecated/src/Text/index.tsx @@ -0,0 +1,377 @@ +import { styled, css, DefaultTheme, WebTarget } from 'styled-components'; +import { + body, + detail, + h1, + h2, + h3, + h4, + large, + small, + detailTechnical, + strong, + technical, + truncate, + xxl, +} from '../utils/typography'; +import { ReactNode } from 'react'; + +interface StyledProps { + $truncate?: boolean; + $color?: (color: DefaultTheme['color']) => string; + $align?: 'left' | 'center' | 'right'; + $decoration?: 'line-through' | 'underline'; + $transform?: 'uppercase' | 'lowercase' | 'capitalize'; + $break: false | 'word' | undefined; +} + +const textCss = css` + ${props => props.$truncate && truncate} + ${props => props.$align && `text-align: ${props.$align};`} + ${props => props.$decoration && `text-decoration: ${props.$decoration};`} + ${props => props.$transform && `text-transform: ${props.$transform};`} + ${props => props.$break === false && `white-space: nowrap;`} + ${props => props.$break === 'word' && `word-break: break-word;`} +`; + +const H1 = styled.h1` + ${h1} + ${textCss} +`; + +const H2 = styled.h2` + ${h2} + ${textCss} +`; + +const H3 = styled.h3` + ${h3} + ${textCss} +`; + +const H4 = styled.h4` + ${h4} + ${textCss} +`; + +const Xxl = styled.span` + ${xxl} + ${textCss} +`; + +const Large = styled.span` + ${large} + ${textCss} +`; + +const Body = styled.span` + ${body} + ${textCss} +`; + +const Strong = styled.span` + ${strong} + ${textCss} +`; + +const Detail = styled.span` + ${detail} + ${textCss} +`; + +const Small = styled.span` + ${small} + ${textCss} +`; + +const DetailTechnical = styled.span` + ${detailTechnical} + ${textCss} +`; + +const Technical = styled.span` + ${technical} + ${textCss} +`; + +const P = styled.p` + ${body} + ${textCss} + + margin-bottom: ${props => props.theme.lineHeight.textBase}; + + &:last-child { + margin-bottom: 0; + } +`; + +/** + * Utility interface to be used below to ensure that only one text type is used + * at a time. + */ +interface NeverTextTypes { + h1?: never; + h2?: never; + h3?: never; + h4?: never; + xxl?: never; + large?: never; + p?: never; + strong?: never; + detail?: never; + small?: never; + detailTechnical?: never; + technical?: never; + body?: never; +} + +type TextType = + | (Omit & { + /** + * Renders a styled `

`. Pass the `as` prop to use a different HTML + * element with the same styling. + */ + h1: true; + }) + | (Omit & { + /** + * Renders a styled `

`. Pass the `as` prop to use a different HTML + * element with the same styling. + */ + h2: true; + }) + | (Omit & { + /** + * Renders a styled `

`. Pass the `as` prop to use a different HTML + * element with the same styling. + */ + h3: true; + }) + | (Omit & { + /** + * Renders a styled `

`. Pass the `as` prop to use a different HTML + * element with the same styling. + */ + h4: true; + }) + | (Omit & { + /** + * Renders bigger text used for section titles. Renders a `` by + * default; pass the `as` prop to use a different HTML element with the + * same styling. + */ + xxl: true; + }) + | (Omit & { + /** + * Renders big text used for section titles. Renders a `` by + * default; pass the `as` prop to use a different HTML element with the + * same styling. + */ + large: true; + }) + | (Omit & { + /** + * Renders a styled `

` tag with a bottom-margin (unless it's the last + * child). Aside from the margin, `

` is identical to ``. + * + * Note that this is the only component in the entire Penumbra UI library + * that renders an external margin. It's a convenience for developers who + * don't want to wrap each `` in a `

` with the + * appropriate margin, or a flex columnn with a gap. + */ + p: true; + }) + | (Omit & { + /** + * Emphasized body text. + * + * Renders a `` by default; pass the `as` prop to use a different + * HTML element with the same styling. + */ + strong: true; + }) + | (Omit & { + /** + * Detail text used for small bits of tertiary information. + * + * Renders a `` by default; pass the `as` prop to use a different + * HTML element with the same styling. + */ + detail: true; + }) + | (Omit & { + /** + * Small text used for secondary information. + * + * Renders a `` by default; pass the `as` prop to use a different + * HTML element with the same styling. + */ + small: true; + }) + | (Omit & { + /** + * Small monospaced text used for code, values, and other technical + * information. + * + * Renders a `` by default; pass the `as` prop to use a different + * HTML element with the same styling. + */ + detailTechnical: true; + }) + | (Omit & { + /** + * Monospaced text used for code, values, and other technical information. + * + * Renders a `` by default; pass the `as` prop to use a different + * HTML element with the same styling. + */ + technical: true; + }) + | (Omit & { + /** + * Body text used throughout most of our UIs. + * + * Renders a `` by default; pass the `as` prop to use a different + * HTML element with the same styling. + */ + body?: true; + }); + +export type TextProps = TextType & { + children?: ReactNode; + /** + * Which component or HTML element to render this text as. + * + * @example + * ```tsx + * This is a span with H1 styling + * ``` + */ + as?: WebTarget; + /** + * When `true`, will apply styles that 1) prevent text wrapping, 2) hide + * overflow, 3) add an ellpsis when the text overflows. + */ + truncate?: boolean; + /** + * A function that takes the 'color' object of `theme`, and returns a CSS color to render + * the icon with. If left undefined, will default to the `text.primary` color. + */ + color?: (color: DefaultTheme['color']) => string; + /** + * The text alignment + */ + align?: 'left' | 'center' | 'right'; + /** + * The text decoration + */ + decoration?: 'line-through' | 'underline'; + /** + * The text transform + */ + transform?: 'uppercase' | 'lowercase' | 'capitalize'; + /** + * Controls how the text breaks. + */ + break?: false | 'word' | undefined; +}; + +/** + * Runtime equivalent of TypeScript's `Omit` type. Removes extraneous props that + * shouldn't be passed to the DOM. + */ +const omit = >( + object: ObjectType, + key: keyof ObjectType, +) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- we're discarding the unused key + const { [key]: _, ...rest } = object; + return rest; +}; + +/** + * All-purpose text wrapper for quickly styling text per the Penumbra UI + * guidelines. + * + * Use with a _single_ text style name: + * + * ```tsx + * This will be rendered with the `h1` style. + * This will be rendered with the `body` style. + * + * INCORRECT: This will result in a TypeScript error. Only use one text style + * at a time. + * + * ``` + * + * When no text style is passed, it will render using the `body` style. + * + * The heading text styles are rendered as their corresponding heading tags + * (`

`, `

`, etc.), and the `p` style is rendered as a `

` tag. + * All other styles are rendered as ``s. To customize which tag is + * rendered without affecting its appearance, use the `as` prop: + * + * ```tsx + * + * This will render with the h1 style, but inside an inline span tag. + * + * ``` + */ +export const Text = ({ + truncate, + color, + align, + decoration, + transform, + break: breakProp, + ...props +}: TextProps) => { + const styledProps = { + $truncate: truncate, + $color: color, + $align: align, + $decoration: decoration, + $transform: transform, + $break: breakProp, + }; + + if (props.h1) { + return

; + } + if (props.h2) { + return

; + } + if (props.h3) { + return

; + } + if (props.h4) { + return

; + } + if (props.xxl) { + return ; + } + if (props.large) { + return ; + } + if (props.strong) { + return ; + } + if (props.detail) { + return ; + } + if (props.small) { + return ; + } + if (props.detailTechnical) { + return ; + } + if (props.technical) { + return ; + } + if (props.p) { + return

; + } + + return ; +}; diff --git a/packages/ui-tailwind/src/TextInput/index.stories.tsx b/packages/ui-deprecated/src/TextInput/index.stories.tsx similarity index 92% rename from packages/ui-tailwind/src/TextInput/index.stories.tsx rename to packages/ui-deprecated/src/TextInput/index.stories.tsx index c3812d2312..0f01542573 100644 --- a/packages/ui-tailwind/src/TextInput/index.stories.tsx +++ b/packages/ui-deprecated/src/TextInput/index.stories.tsx @@ -15,7 +15,9 @@ const SampleButton = () => ( ); -const addressBookIcon = ; +const addressBookIcon = ( + color.text.primary} /> +); const meta: Meta = { component: TextInput, diff --git a/packages/ui/src/TextInput/index.test.tsx b/packages/ui-deprecated/src/TextInput/index.test.tsx similarity index 100% rename from packages/ui/src/TextInput/index.test.tsx rename to packages/ui-deprecated/src/TextInput/index.test.tsx diff --git a/packages/ui-deprecated/src/TextInput/index.tsx b/packages/ui-deprecated/src/TextInput/index.tsx new file mode 100644 index 0000000000..32b82da61d --- /dev/null +++ b/packages/ui-deprecated/src/TextInput/index.tsx @@ -0,0 +1,149 @@ +import { styled } from 'styled-components'; +import { small } from '../utils/typography'; +import { ActionType, getOutlineColorByActionType } from '../utils/ActionType'; +import { useDisabled } from '../hooks/useDisabled'; +import { forwardRef, ReactNode } from 'react'; + +const Wrapper = styled.div<{ + $hasStartAdornment: boolean; + $hasEndAdornment: boolean; + $actionType: ActionType; +}>` + background-color: ${props => props.theme.color.other.tonalFill5}; + display: flex; + align-items: center; + gap: ${props => props.theme.spacing(2)}; + transition: + outline 0.15s, + background-color 0.15s; + + ${props => props.$hasStartAdornment && `padding-left: ${props.theme.spacing(3)};`} + ${props => props.$hasEndAdornment && `padding-right: ${props.theme.spacing(3)};`} + + &:focus-within { + outline: 2px solid ${props => getOutlineColorByActionType(props.theme, props.$actionType)}; + } + + &:hover { + background-color: ${props => props.theme.color.action.hoverOverlay}; + } +`; + +const StyledInput = styled.input<{ + $actionType: ActionType; + $hasStartAdornment: boolean; + $hasEndAdornment: boolean; +}>` + appearance: none; + border: none; + color: ${props => + props.disabled ? props.theme.color.text.muted : props.theme.color.text.primary}; + background-color: ${props => props.theme.color.base.transparent}; + + padding-left: ${props => (props.$hasStartAdornment ? '0' : props.theme.spacing(3))}; + padding-right: ${props => (props.$hasEndAdornment ? '0' : props.theme.spacing(3))}; + padding-top: ${props => props.theme.spacing(2)}; + padding-bottom: ${props => props.theme.spacing(2)}; + transition: border-color 0.15s; + + box-sizing: border-box; + flex-grow: 1; + + ${small} + + &::placeholder { + color: ${props => props.theme.color.text.secondary}; + } + + &:disabled { + cursor: not-allowed; + } + + &:disabled::placeholder { + color: ${props => props.theme.color.text.muted}; + } + + &:focus { + outline: none; + } + + &::-webkit-outer-spin-button, + &::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + + &[type='number'] { + -moz-appearance: textfield; + } +`; + +export interface TextInputProps { + value?: string; + onChange?: (value: string) => void; + placeholder?: string; + actionType?: ActionType; + disabled?: boolean; + type?: 'email' | 'number' | 'password' | 'tel' | 'text' | 'url'; + /** + * Markup to render inside the text input's visual frame, before the text + * input itself. + */ + startAdornment?: ReactNode; + /** + * Markup to render inside the text input's visual frame, after the text input + * itself. + */ + endAdornment?: ReactNode; + max?: string | number; + min?: string | number; +} + +/** + * A simple text field. + * + * Can be enriched with start and end adornments, which are markup that render + * inside the text input's visual frame. + */ +// eslint-disable-next-line react/display-name -- exotic component +export const TextInput = forwardRef( + ( + { + value, + onChange, + placeholder, + actionType = 'default', + disabled, + type = 'text', + startAdornment = null, + endAdornment = null, + max, + min, + }: TextInputProps, + ref, + ) => ( + + {startAdornment} + + onChange?.(e.target.value)} + placeholder={placeholder} + disabled={useDisabled(disabled)} + type={type} + max={max} + min={min} + ref={ref} + $actionType={actionType} + $hasStartAdornment={!!startAdornment} + $hasEndAdornment={!!endAdornment} + /> + + {endAdornment} + + ), +); diff --git a/packages/ui-tailwind/src/Toast/index.stories.tsx b/packages/ui-deprecated/src/Toast/index.stories.tsx similarity index 53% rename from packages/ui-tailwind/src/Toast/index.stories.tsx rename to packages/ui-deprecated/src/Toast/index.stories.tsx index 8ac45aeb72..a60a7788d0 100644 --- a/packages/ui-tailwind/src/Toast/index.stories.tsx +++ b/packages/ui-deprecated/src/Toast/index.stories.tsx @@ -2,8 +2,9 @@ import type { Meta, StoryObj } from '@storybook/react'; import { openToast, ToastProvider, ToastType } from '.'; import { Button } from '../Button'; -import { Tooltip, TooltipProvider } from '../Tooltip'; +import { Tooltip } from '../Tooltip'; import { Text } from '../Text'; +import { styled } from 'styled-components'; const meta: Meta = { component: ToastProvider, @@ -14,6 +15,12 @@ export default meta; type Story = StoryObj; +const Row = styled.div` + display: flex; + flex-direction: row; + gap: ${props => props.theme.spacing(2)}; +`; + export const Basic: Story = { render: function Render() { const toast = (type: ToastType) => { @@ -59,37 +66,35 @@ export const Basic: Story = { }; return ( - -

- + <> + - All style types of toasts + All style types of toasts -
- - - - - - - -
+ + + + + + + + + - Updating toast + Updating toast -
- - - -
+ + + + + - Action toast + Action toast -
- -
-
- + + + + ); }, }; diff --git a/packages/ui-tailwind/src/Toast/index.tsx b/packages/ui-deprecated/src/Toast/index.tsx similarity index 100% rename from packages/ui-tailwind/src/Toast/index.tsx rename to packages/ui-deprecated/src/Toast/index.tsx diff --git a/packages/ui-tailwind/src/Toast/open.ts b/packages/ui-deprecated/src/Toast/open.ts similarity index 98% rename from packages/ui-tailwind/src/Toast/open.ts rename to packages/ui-deprecated/src/Toast/open.ts index e36adb1806..2de1cd6a27 100644 --- a/packages/ui-tailwind/src/Toast/open.ts +++ b/packages/ui-deprecated/src/Toast/open.ts @@ -16,7 +16,7 @@ const toastFnMap: Record = { export interface ToastProps { type: ToastType; message: string; - description?: string; + description?: ReactNode; persistent?: boolean; dismissible?: boolean; action?: ExternalToast['action']; diff --git a/packages/ui-tailwind/src/Toast/provider.tsx b/packages/ui-deprecated/src/Toast/provider.tsx similarity index 100% rename from packages/ui-tailwind/src/Toast/provider.tsx rename to packages/ui-deprecated/src/Toast/provider.tsx diff --git a/packages/ui/src/Toggle/index.stories.tsx b/packages/ui-deprecated/src/Toggle/index.stories.tsx similarity index 100% rename from packages/ui/src/Toggle/index.stories.tsx rename to packages/ui-deprecated/src/Toggle/index.stories.tsx diff --git a/packages/ui/src/Toggle/index.test.tsx b/packages/ui-deprecated/src/Toggle/index.test.tsx similarity index 100% rename from packages/ui/src/Toggle/index.test.tsx rename to packages/ui-deprecated/src/Toggle/index.test.tsx diff --git a/packages/ui/src/Toggle/index.tsx b/packages/ui-deprecated/src/Toggle/index.tsx similarity index 100% rename from packages/ui/src/Toggle/index.tsx rename to packages/ui-deprecated/src/Toggle/index.tsx diff --git a/packages/ui-tailwind/src/Tooltip/index.stories.tsx b/packages/ui-deprecated/src/Tooltip/index.stories.tsx similarity index 65% rename from packages/ui-tailwind/src/Tooltip/index.stories.tsx rename to packages/ui-deprecated/src/Tooltip/index.stories.tsx index 937b2d1e52..b51ee87658 100644 --- a/packages/ui-tailwind/src/Tooltip/index.stories.tsx +++ b/packages/ui-deprecated/src/Tooltip/index.stories.tsx @@ -1,7 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { Tooltip, TooltipProvider } from './index'; -import { Text } from '../Text'; +import { Tooltip } from '.'; const meta: Meta = { component: Tooltip, @@ -15,15 +14,10 @@ export default meta; type Story = StoryObj; export const Basic: Story = { - render: args => ( - - - - ), args: { title: 'This is a heading', message: 'This is description information. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut et massa mi.', - children: Hover over this text., + children: 'Hover over this text.', }, }; diff --git a/packages/ui-deprecated/src/Tooltip/index.tsx b/packages/ui-deprecated/src/Tooltip/index.tsx new file mode 100644 index 0000000000..b356c1c814 --- /dev/null +++ b/packages/ui-deprecated/src/Tooltip/index.tsx @@ -0,0 +1,93 @@ +import * as RadixTooltip from '@radix-ui/react-tooltip'; +import { ReactNode } from 'react'; +import { styled } from 'styled-components'; +import { Text } from '../Text'; +import { buttonBase } from '../utils/button'; +import { small } from '../utils/typography'; +import { scaleIn } from '../utils/popover.ts'; + +const Content = styled(RadixTooltip.Content).attrs(props => ({ + sideOffset: props.theme.spacing(1, 'number'), +}))` + width: 200px; + padding: ${props => props.theme.spacing(2)}; + + background-color: ${props => props.theme.color.other.dialogBackground}; + border: 1px solid ${props => props.theme.color.other.tonalStroke}; + border-radius: ${props => props.theme.borderRadius.sm}; + backdrop-filter: blur(${props => props.theme.blur.xl}); + + color: ${props => props.theme.color.text.primary}; + + transform-origin: var(--radix-tooltip-content-transform-origin); + animation: ${scaleIn} 0.15s ease-out; +`; + +const Title = styled.div` + ${small} + + margin-bottom: ${props => props.theme.spacing(2)} +`; + +const Trigger = styled(RadixTooltip.Trigger)` + ${buttonBase} +`; + +export interface TooltipProps { + /** An optional title to show in larger text above the message. */ + title?: string; + /** + * A string message to show in the tooltip. Note that only strings are + * allowed; for interactive content, use a `` or a ``. + */ + message: string; + /** + * The trigger for the tooltip. + * + * Note that the trigger will be wrapped in an HTML button element, so only pass content that can be validly nested inside a button (i.e., don't pass another button). + */ + children: ReactNode; +} + +/** + * Use this for small informational text that should appear adjacent to a piece + * of content. + * + * ```tsx + * + * Hover me + * + * ``` + * + * ## Differences between ``, ``, and ``. + * + * These three components provide similar functionality, but are meant to be + * used in distinct ways. + * + * - ``: Use dialogs for interactive or informational content that + * should take the user's attention above everything else on the page. Dialogs + * are typically opened in response to a click from a user, but may also be + * opened and closed programmatically. + * - ``: Use popovers for interactive or informational content that + * should be visually tied to a specific element on the page, such as the + * dropdown menu underneath the menu button. Popovers are typically opened in + * response to a click from a user, but may also be opened and closed + * programmatically. + * - ``: Use tooltips for plain-text informational content that + * should be visually tied to a specific element on the page. Tooltips are + * opened in response to the user hovering over that element. + */ +export const Tooltip = ({ title, message, children }: TooltipProps) => ( + + + {children} + + + + {title && {title}} + + {message} + + + +); diff --git a/packages/ui/src/ValueInput/index.stories.tsx b/packages/ui-deprecated/src/ValueInput/index.stories.tsx similarity index 100% rename from packages/ui/src/ValueInput/index.stories.tsx rename to packages/ui-deprecated/src/ValueInput/index.stories.tsx diff --git a/packages/ui/src/ValueInput/index.tsx b/packages/ui-deprecated/src/ValueInput/index.tsx similarity index 100% rename from packages/ui/src/ValueInput/index.tsx rename to packages/ui-deprecated/src/ValueInput/index.tsx diff --git a/packages/ui-tailwind/src/ValueView/index.stories.tsx b/packages/ui-deprecated/src/ValueViewComponent/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/ValueView/index.stories.tsx rename to packages/ui-deprecated/src/ValueViewComponent/index.stories.tsx diff --git a/packages/ui/src/ValueViewComponent/index.test.tsx b/packages/ui-deprecated/src/ValueViewComponent/index.test.tsx similarity index 100% rename from packages/ui/src/ValueViewComponent/index.test.tsx rename to packages/ui-deprecated/src/ValueViewComponent/index.test.tsx diff --git a/packages/ui/src/ValueViewComponent/index.tsx b/packages/ui-deprecated/src/ValueViewComponent/index.tsx similarity index 100% rename from packages/ui/src/ValueViewComponent/index.tsx rename to packages/ui-deprecated/src/ValueViewComponent/index.tsx diff --git a/packages/ui-tailwind/src/WalletBalance/index.stories.tsx b/packages/ui-deprecated/src/WalletBalance/index.stories.tsx similarity index 100% rename from packages/ui-tailwind/src/WalletBalance/index.stories.tsx rename to packages/ui-deprecated/src/WalletBalance/index.stories.tsx diff --git a/packages/ui/src/WalletBalance/index.test.tsx b/packages/ui-deprecated/src/WalletBalance/index.test.tsx similarity index 100% rename from packages/ui/src/WalletBalance/index.test.tsx rename to packages/ui-deprecated/src/WalletBalance/index.test.tsx diff --git a/packages/ui-deprecated/src/WalletBalance/index.tsx b/packages/ui-deprecated/src/WalletBalance/index.tsx new file mode 100644 index 0000000000..c76cb8c026 --- /dev/null +++ b/packages/ui-deprecated/src/WalletBalance/index.tsx @@ -0,0 +1,127 @@ +import type { MouseEventHandler } from 'react'; +import { styled, type DefaultTheme } from 'styled-components'; +import { Wallet } from 'lucide-react'; +import type { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; +import { getFormattedAmtFromValueView } from '@penumbra-zone/types/value-view'; +import { + getAddressIndex, + getBalanceView, + getMetadataFromBalancesResponse, +} from '@penumbra-zone/getters/balances-response'; +import { Text } from '../Text'; +import { ActionType, getOutlineColorByActionType } from '../utils/ActionType.ts'; +import { asTransientProps } from '../utils/asTransientProps.ts'; + +interface StyledProps { + $actionType: ActionType; + $disabled?: boolean; +} + +const getColorByActionType = ( + theme: DefaultTheme, + actionType: ActionType, + disabled?: boolean, +): string => { + if (disabled) { + return theme.color.text.muted; + } + if (actionType === 'destructive') { + return theme.color.destructive.light; + } + return theme.color.text.secondary; +}; + +const Wrapper = styled.div` + display: flex; + align-items: center; + gap: ${props => props.theme.spacing(1)}; + color: ${props => getColorByActionType(props.theme, props.$actionType, props.$disabled)}; + transition: color 0.15s; +`; + +const AccountWrapper = styled.button` + display: flex; + align-items: center; + gap: ${props => props.theme.spacing(1)}; + padding: ${props => props.theme.spacing(1)} ${props => props.theme.spacing(2)}; + + color: inherit; + border: none; + border-radius: ${props => props.theme.borderRadius.full}; + background-color: ${props => props.theme.color.other.tonalFill5}; + transition: + color 0.15s, + background 0.15s, + outline 0.15s; + + &:hover { + background-color: ${props => props.theme.color.action.hoverOverlay}; + } + + &:focus { + color: ${props => props.theme.color.text.secondary}; + background-color: ${props => props.theme.color.other.tonalFill5}; + outline: 2px solid ${props => getOutlineColorByActionType(props.theme, props.$actionType)}; + } + + &:focus + span { + color: ${props => props.theme.color.text.secondary}; + } +`; + +const ValueText = styled(Text)` + color: inherit; + transition: color 0.15s; +`; + +const WalletIcon = styled(Wallet)` + width: ${props => props.theme.spacing(4)}; + height: ${props => props.theme.spacing(4)}; + transition: color 0.15s; +`; + +export interface WalletBalanceProps { + balance?: BalancesResponse; + actionType?: ActionType; + disabled?: boolean; + onClick?: MouseEventHandler; +} + +/** + * `WalletBalance` renders a `BalancesResponse` — its account index, amount,, and symbol. + * Use this anywhere you would like to render a `BalancesResponse`. + * + * Allows clicking on the wallet icon. + */ +export const WalletBalance = ({ + balance, + actionType = 'default', + disabled, + onClick, +}: WalletBalanceProps) => { + const account = getAddressIndex.optional(balance); + const valueView = getBalanceView.optional(balance); + const metadata = getMetadataFromBalancesResponse.optional(balance); + + if (!valueView || !account || !metadata) { + return null; + } + + return ( + + + + #{account.account} + + + + {getFormattedAmtFromValueView(valueView, true)} {metadata.symbol || 'Unknown'} + + + ); +}; diff --git a/packages/ui/src/hooks/useAnimationDeferredValue/index.test.tsx b/packages/ui-deprecated/src/hooks/useAnimationDeferredValue/index.test.tsx similarity index 100% rename from packages/ui/src/hooks/useAnimationDeferredValue/index.test.tsx rename to packages/ui-deprecated/src/hooks/useAnimationDeferredValue/index.test.tsx diff --git a/packages/ui/src/hooks/useAnimationDeferredValue/index.ts b/packages/ui-deprecated/src/hooks/useAnimationDeferredValue/index.ts similarity index 100% rename from packages/ui/src/hooks/useAnimationDeferredValue/index.ts rename to packages/ui-deprecated/src/hooks/useAnimationDeferredValue/index.ts diff --git a/packages/ui/src/hooks/useDensity/index.ts b/packages/ui-deprecated/src/hooks/useDensity/index.ts similarity index 100% rename from packages/ui/src/hooks/useDensity/index.ts rename to packages/ui-deprecated/src/hooks/useDensity/index.ts diff --git a/packages/ui/src/hooks/useDisabled/index.test.tsx b/packages/ui-deprecated/src/hooks/useDisabled/index.test.tsx similarity index 100% rename from packages/ui/src/hooks/useDisabled/index.test.tsx rename to packages/ui-deprecated/src/hooks/useDisabled/index.test.tsx diff --git a/packages/ui/src/hooks/useDisabled/index.ts b/packages/ui-deprecated/src/hooks/useDisabled/index.ts similarity index 100% rename from packages/ui/src/hooks/useDisabled/index.ts rename to packages/ui-deprecated/src/hooks/useDisabled/index.ts diff --git a/packages/ui/src/hooks/useIsAnimating/index.tsx b/packages/ui-deprecated/src/hooks/useIsAnimating/index.tsx similarity index 100% rename from packages/ui/src/hooks/useIsAnimating/index.tsx rename to packages/ui-deprecated/src/hooks/useIsAnimating/index.tsx diff --git a/packages/ui/src/tailwindConfig.ts b/packages/ui-deprecated/src/tailwindConfig.ts similarity index 100% rename from packages/ui/src/tailwindConfig.ts rename to packages/ui-deprecated/src/tailwindConfig.ts diff --git a/packages/ui/src/types/Density.ts b/packages/ui-deprecated/src/types/Density.ts similarity index 100% rename from packages/ui/src/types/Density.ts rename to packages/ui-deprecated/src/types/Density.ts diff --git a/packages/ui/src/typings.d.ts b/packages/ui-deprecated/src/typings.d.ts similarity index 100% rename from packages/ui/src/typings.d.ts rename to packages/ui-deprecated/src/typings.d.ts diff --git a/packages/ui/src/utils/ActionType.ts b/packages/ui-deprecated/src/utils/ActionType.ts similarity index 100% rename from packages/ui/src/utils/ActionType.ts rename to packages/ui-deprecated/src/utils/ActionType.ts diff --git a/packages/ui/src/utils/DensityContext.ts b/packages/ui-deprecated/src/utils/DensityContext.ts similarity index 100% rename from packages/ui/src/utils/DensityContext.ts rename to packages/ui-deprecated/src/utils/DensityContext.ts diff --git a/packages/ui/src/utils/DisabledContext.ts b/packages/ui-deprecated/src/utils/DisabledContext.ts similarity index 100% rename from packages/ui/src/utils/DisabledContext.ts rename to packages/ui-deprecated/src/utils/DisabledContext.ts diff --git a/packages/ui/src/utils/IsAnimatingContext.ts b/packages/ui-deprecated/src/utils/IsAnimatingContext.ts similarity index 100% rename from packages/ui/src/utils/IsAnimatingContext.ts rename to packages/ui-deprecated/src/utils/IsAnimatingContext.ts diff --git a/packages/ui/src/utils/MotionProp.ts b/packages/ui-deprecated/src/utils/MotionProp.ts similarity index 100% rename from packages/ui/src/utils/MotionProp.ts rename to packages/ui-deprecated/src/utils/MotionProp.ts diff --git a/packages/ui/src/utils/Shrink0.tsx b/packages/ui-deprecated/src/utils/Shrink0.tsx similarity index 100% rename from packages/ui/src/utils/Shrink0.tsx rename to packages/ui-deprecated/src/utils/Shrink0.tsx diff --git a/packages/ui/src/utils/ToStringable.ts b/packages/ui-deprecated/src/utils/ToStringable.ts similarity index 100% rename from packages/ui/src/utils/ToStringable.ts rename to packages/ui-deprecated/src/utils/ToStringable.ts diff --git a/packages/ui/src/utils/asTransientProps.test.ts b/packages/ui-deprecated/src/utils/asTransientProps.test.ts similarity index 100% rename from packages/ui/src/utils/asTransientProps.test.ts rename to packages/ui-deprecated/src/utils/asTransientProps.test.ts diff --git a/packages/ui/src/utils/asTransientProps.ts b/packages/ui-deprecated/src/utils/asTransientProps.ts similarity index 100% rename from packages/ui/src/utils/asTransientProps.ts rename to packages/ui-deprecated/src/utils/asTransientProps.ts diff --git a/packages/ui-tailwind/src/utils/bufs/address-view.ts b/packages/ui-deprecated/src/utils/bufs/address-view.ts similarity index 100% rename from packages/ui-tailwind/src/utils/bufs/address-view.ts rename to packages/ui-deprecated/src/utils/bufs/address-view.ts diff --git a/packages/ui-tailwind/src/utils/bufs/balances-responses.ts b/packages/ui-deprecated/src/utils/bufs/balances-responses.ts similarity index 100% rename from packages/ui-tailwind/src/utils/bufs/balances-responses.ts rename to packages/ui-deprecated/src/utils/bufs/balances-responses.ts diff --git a/packages/ui-tailwind/src/utils/bufs/index.ts b/packages/ui-deprecated/src/utils/bufs/index.ts similarity index 100% rename from packages/ui-tailwind/src/utils/bufs/index.ts rename to packages/ui-deprecated/src/utils/bufs/index.ts diff --git a/packages/ui-tailwind/src/utils/bufs/metadata.ts b/packages/ui-deprecated/src/utils/bufs/metadata.ts similarity index 100% rename from packages/ui-tailwind/src/utils/bufs/metadata.ts rename to packages/ui-deprecated/src/utils/bufs/metadata.ts diff --git a/packages/ui-tailwind/src/utils/bufs/value-view.ts b/packages/ui-deprecated/src/utils/bufs/value-view.ts similarity index 100% rename from packages/ui-tailwind/src/utils/bufs/value-view.ts rename to packages/ui-deprecated/src/utils/bufs/value-view.ts diff --git a/packages/ui-deprecated/src/utils/button.ts b/packages/ui-deprecated/src/utils/button.ts new file mode 100644 index 0000000000..9ba3bbf9d4 --- /dev/null +++ b/packages/ui-deprecated/src/utils/button.ts @@ -0,0 +1,99 @@ +import { css, DefaultTheme } from 'styled-components'; + +export type Priority = 'primary' | 'secondary'; + +/** Shared styles to use for any ` - - ); - }, -); -AssetSelectorTrigger.displayName = 'AssetSelectorTrigger'; diff --git a/packages/ui-tailwind/src/Card/index.tsx b/packages/ui-tailwind/src/Card/index.tsx deleted file mode 100644 index 0683e9381e..0000000000 --- a/packages/ui-tailwind/src/Card/index.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { ReactNode, ElementType } from 'react'; -import cn from 'clsx'; -import { large } from '../utils/typography'; - -export interface CardProps { - children?: ReactNode; - /** - * Which component or HTML element to render this card as. - * - * @example - * ```tsx - * This is a main element with card styling - * ``` - */ - as?: ElementType; - title?: ReactNode; -} - -/** - * ``s are rectangular sections of a page set off from the rest of the - * page by a background and an optional title. They're useful for presenting - * data, or for wrapping a form. - * - * A `` wraps its children in a flex column with a spacing of `4` - * between each top-level HTML element. This results in a standard card layout - * no matter what its contents are. - * - * If you wish to pass children to `` that should not be spaced apart in - * that way, simply pass a single HTML element as the root of the ``'s - * children. That way, the built-in flex column will have no effect: - * - * ```tsx - * - *
- * These two elements... - * ...will not appear in a flex column, but rather inline beside each - * other. - *
- *
- * ``` - * - * You can also use `` and `` to create a stack of - * sections, which are useful for wrapping individual form fields. - * - * ```tsx - * - * - * Section one - * Section two - * - * - * ``` - */ -export const Card = ({ children, as: Wrapper = 'section', title }: CardProps) => { - return ( - - {title &&

{title}

} - -
{children}
-
- ); -}; - -const Stack = ({ children }: { children?: ReactNode }) => { - return
{children}
; -}; -Card.Stack = Stack; - -const Section = ({ children }: { children?: ReactNode }) => ( -
{children}
-); -Card.Section = Section; diff --git a/packages/ui-tailwind/src/Dialog/Content.tsx b/packages/ui-tailwind/src/Dialog/Content.tsx deleted file mode 100644 index 9ffe439910..0000000000 --- a/packages/ui-tailwind/src/Dialog/Content.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { Title as RadixDialogTitle, Close as RadixDialogClose } from '@radix-ui/react-dialog'; -import { ReactNode, useContext } from 'react'; -import { X } from 'lucide-react'; -import { DialogContext } from './Context.tsx'; -import { EmptyContent } from './EmptyContent.tsx'; -import { Display } from '../Display'; -import { Grid } from '../Grid'; -import { Text } from '../Text'; -import { Density } from '../Density'; -import { Button } from '../Button'; - -export interface DialogContentProps { - children?: ReactNode; - /** Renders the element after the dialog title. These elements will be sticky to the top of the dialog */ - headerChildren?: ReactNode; - title: string; - /** Buttons rendered in the footer of a dialog */ - buttons?: ReactNode; - /** @deprecated this prop will be removed in the future */ - zIndex?: number; -} - -export const Content = ({ - children, - headerChildren, - title, - buttons, - zIndex, -}: DialogContentProps) => { - const { showCloseButton } = useContext(DialogContext); - - return ( - - - - - - -
-
-
- - - {title} - - - {headerChildren} -
- -
- {children} - - {buttons &&
{buttons}
} -
- - {/** - * Opening the dialog focuses the first focusable element in the dialog. That's why the Close button - * should be positioned absolutely and rendered as the last element in the dialog content. - */} - {showCloseButton && ( - - -
- -
-
-
- )} -
-
-
- - - -
-
- ); -}; diff --git a/packages/ui-tailwind/src/Dialog/EmptyContent.tsx b/packages/ui-tailwind/src/Dialog/EmptyContent.tsx deleted file mode 100644 index 5f17d510ba..0000000000 --- a/packages/ui-tailwind/src/Dialog/EmptyContent.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { ReactNode } from 'react'; -import { - Overlay as RadixDialogOverlay, - Portal as RadixDialogPortal, - Content as RadixDialogContent, -} from '@radix-ui/react-dialog'; - -export interface DialogEmptyContentProps { - children?: ReactNode; - /** @deprecated this prop will be removed in the future */ - zIndex?: number; -} - -export const EmptyContent = ({ children, zIndex }: DialogEmptyContentProps) => { - return ( - - - - -
- {children} -
-
-
- ); -}; diff --git a/packages/ui-tailwind/src/Dialog/RadioItem.tsx b/packages/ui-tailwind/src/Dialog/RadioItem.tsx deleted file mode 100644 index 8ef98f8c75..0000000000 --- a/packages/ui-tailwind/src/Dialog/RadioItem.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React, { ReactNode, useMemo } from 'react'; -import cn from 'clsx'; -import { RadioGroupItem } from '@radix-ui/react-radio-group'; -import { Text } from '../Text'; -import { - ActionType, - getAriaCheckedOutlineColorByActionType, - getFocusOutlineColorByActionType, -} from '../utils/action-type'; - -export interface DialogRadioItemProps { - /** A required unique string value defining the radio item */ - value: string; - title: ReactNode; - description?: ReactNode; - /** A component rendered on the left side of the item */ - endAdornment?: ReactNode; - /** A component rendered on the right side of the item */ - startAdornment?: ReactNode; - disabled?: boolean; - actionType?: ActionType; - /** A function that closes the dialog on select of the item */ - onClose?: VoidFunction; - /** Fires when the item is clicked or focused using the keyboard */ - onSelect?: VoidFunction; -} - -/** A radio button that selects an asset or a balance from the `AssetSelector` */ -export const RadioItem = ({ - value, - title, - description, - startAdornment, - endAdornment, - disabled, - actionType = 'default', - onClose, - onSelect, -}: DialogRadioItemProps) => { - const handleClick = (event: React.MouseEvent) => { - // Is a click and not an arrow key up/down - if (event.detail > 0) { - onSelect?.(); - onClose?.(); - } - }; - - const handleKeyDown = (event: React.KeyboardEvent) => { - if (event.key === 'Enter' || event.key === ' ') { - event.preventDefault(); - onSelect?.(); - onClose?.(); - } - }; - - const descriptionText = useMemo(() => { - if (!description) { - return null; - } - - if (typeof description === 'string') { - return ( - - {description} - - ); - } - - return description; - }, [description]); - - return ( - - - - ); -}; diff --git a/packages/ui-tailwind/src/MenuItem/index.tsx b/packages/ui-tailwind/src/MenuItem/index.tsx deleted file mode 100644 index 1e661de27d..0000000000 --- a/packages/ui-tailwind/src/MenuItem/index.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import type { LucideIcon } from 'lucide-react'; -import type { FC, MouseEventHandler } from 'react'; -import { getMenuItem, DropdownMenuItemBase } from '../utils/menu-item'; -import { Text } from '../Text'; - -export interface MenuItemProps extends DropdownMenuItemBase { - label: string; - icon?: LucideIcon | FC; - onClick?: MouseEventHandler; -} - -/** - * A button generally used in menus or selectable lists - */ -export const MenuItem = ({ - actionType = 'default', - icon: IconComponent, - label, - onClick, - disabled, -}: MenuItemProps) => { - return ( - - ); -}; diff --git a/packages/ui-tailwind/src/Pill/index.tsx b/packages/ui-tailwind/src/Pill/index.tsx deleted file mode 100644 index 76bd17acb5..0000000000 --- a/packages/ui-tailwind/src/Pill/index.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { ReactNode } from 'react'; -import { body, technical, detail, detailTechnical } from '../utils/typography'; -import { Density, useDensity } from '../utils/density'; -import cn from 'clsx'; - -type Priority = 'primary' | 'secondary'; -type Context = - | 'default' - | 'technical-default' - | 'technical-success' - | 'technical-caution' - | 'technical-destructive'; - -const getFont = (context: Context, density: Density) => { - if (context === 'default') { - return density === 'sparse' ? body : detail; - } - return density === 'sparse' ? technical : detailTechnical; -}; - -const getXPadding = (priority: Priority, density: Density): string => { - if (priority === 'secondary') { - return density === 'sparse' ? 'pr-[10px] pl-[10px]' : 'pr-[6px] pl-[6px]'; - } - return density === 'sparse' ? 'pr-3 pl-3' : 'pr-2 pl-2'; -}; - -const getBackgroundColor = (priority: Priority, context: Context) => { - if (priority === 'secondary') { - return 'bg-transparent'; - } - - const colorMap: Record = { - default: cn('bg-other-tonalFill10'), - 'technical-default': cn('bg-other-tonalFill10'), - 'technical-success': cn('bg-secondary-light'), - 'technical-caution': cn('bg-caution-light'), - 'technical-destructive': cn('bg-destructive-light'), - }; - return colorMap[context]; -}; - -const getColor = (priority: Priority, context: Context): string => { - if (priority === 'primary') { - return context === 'default' || context === 'technical-default' - ? cn('text-text-primary') - : cn('text-secondary-dark'); - } - - const colorMap: Record = { - default: cn('text-text-primary'), - 'technical-default': cn('text-text-primary'), - 'technical-success': cn('text-secondary-light'), - 'technical-caution': cn('text-caution-light'), - 'technical-destructive': cn('text-destructive-light'), - }; - return colorMap[context]; -}; - -export interface PillProps { - children: ReactNode; - priority?: Priority; - context?: Context; -} - -export const Pill = ({ children, priority = 'primary', context = 'default' }: PillProps) => { - const density = useDensity(); - - return ( - - {children} - - ); -}; diff --git a/packages/ui-tailwind/src/Progress/index.tsx b/packages/ui-tailwind/src/Progress/index.tsx deleted file mode 100644 index 871aebb6f4..0000000000 --- a/packages/ui-tailwind/src/Progress/index.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import * as ProgressPrimitive from '@radix-ui/react-progress'; -import cn from 'clsx'; - -export const getIndicatorColor = (value: number, error: boolean): string => { - if (error) { - return cn('bg-destructive-light'); - } - - if (value === 1) { - return cn('bg-secondary-light'); - } - - return cn('bg-caution-light'); -}; - -export interface ProgressProps { - /** Percentage value from 0 to 1 */ - value: number; - /** Displays the skeleton-like moving shade */ - loading?: boolean; - /** Renders red indicator while the progress continues */ - error?: boolean; -} - -/** - * Progress bar with loading and error states - */ -export const Progress = ({ value, loading, error = false }: ProgressProps) => ( - - -
- {loading && ( -
- )} -
- - -); diff --git a/packages/ui-tailwind/src/Table/index.tsx b/packages/ui-tailwind/src/Table/index.tsx deleted file mode 100644 index f4c23a75db..0000000000 --- a/packages/ui-tailwind/src/Table/index.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import { PropsWithChildren, ReactNode } from 'react'; -import cn from 'clsx'; -import { tableHeading, tableItem } from '../utils/typography'; -import { Density, useDensity } from '../utils/density'; -import { ConditionalWrap } from '../ConditionalWrap'; - -export interface TableProps { - /** Content that will appear above the table. */ - title?: ReactNode; - children: ReactNode; - /** Which CSS `table-layout` property to use. */ - tableLayout?: 'fixed' | 'auto'; -} - -/** - * A styled HTML table. - * - * To build a table, you only need to import the `` component. All - * other components are properties on `Table`. - * - * ```tsx - *
- * - * - * Header cell - * Header cell 2 - * - * - * - * - * Body cell - * Body cell 2 - * - * - *
- * ``` - * - * By design, `` elements have limited props. No styling or - * customization is permitted. This ensures that all tables look consistent - * throughout the Penumbra UI. - * - * To render title content above the table, pass a `title` prop: - * - * ```tsx - * - * ... - *
- * - * // or... - * - * Here is some rich table title content}> - * ... - *
- * ``` - */ -export const Table = ({ title, children, tableLayout }: TableProps) => ( - ( -
-
{title}
- {children} -
- )} - > - - {children} -
-
-); - -const Thead = ({ children }: PropsWithChildren) => {children}; -Table.Thead = Thead; - -const Tbody = ({ children }: PropsWithChildren) => {children}; -Table.Tbody = Tbody; - -const Tr = ({ children }: PropsWithChildren) => ( - {children} -); -Table.Tr = Tr; - -type HAlign = 'left' | 'center' | 'right'; -type VAlign = 'top' | 'middle' | 'bottom'; - -const getCell = (density: Density) => - cn('box-border', 'pl-3 pr-3', density === 'sparse' ? 'pt-4 pb-4' : 'pt-3 pb-3'); - -const Th = ({ - children, - colSpan, - hAlign, - vAlign, - width, -}: PropsWithChildren<{ - colSpan?: number; - /** A CSS `width` value to use for this cell. */ - width?: string; - /** Controls the CSS `text-align` property for this cell. */ - hAlign?: HAlign; - /** Controls the CSS `vertical-align` property for this cell. */ - vAlign?: VAlign; -}>) => { - const density = useDensity(); - - return ( - - {children} - - ); -}; -Table.Th = Th; - -const Td = ({ - children, - colSpan, - hAlign, - vAlign, - width, -}: PropsWithChildren<{ - colSpan?: number; - /** A CSS `width` value to use for this cell. */ - width?: string; - /** Controls the CSS `text-align` property for this cell. */ - hAlign?: HAlign; - /** Controls the CSS `vertical-align` property for this cell. */ - vAlign?: VAlign; -}>) => { - const density = useDensity(); - - return ( - - {children} - - ); -}; -Table.Td = Td; diff --git a/packages/ui-tailwind/src/Tabs/index.tsx b/packages/ui-tailwind/src/Tabs/index.tsx deleted file mode 100644 index f58afd9b78..0000000000 --- a/packages/ui-tailwind/src/Tabs/index.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { tab, tabSmall } from '../utils/typography'; -import { buttonBase, getOverlays } from '../utils/button'; -import * as RadixTabs from '@radix-ui/react-tabs'; -import { ActionType } from '../utils/action-type'; -import { useDensity } from '../utils/density'; -import cn from 'clsx'; - -type LimitedActionType = Exclude; - -const getIndicatorColor = (actionType: LimitedActionType): string => { - if (actionType === 'accent') { - return cn('bg-tabAccent'); - } - if (actionType === 'unshield') { - return cn('bg-tabUnshield'); - } - return cn('bg-tabNeutral'); -}; - -const getBorderColor = (actionType: LimitedActionType): string => { - if (actionType === 'accent') { - return cn('border-action-primaryFocusOutline'); - } - if (actionType === 'unshield') { - return cn('border-action-unshieldFocusOutline'); - } - return cn('border-action-neutralFocusOutline'); -}; - -export interface TabsTab { - value: string; - label: string; - disabled?: boolean; -} - -export interface TabsProps { - value: string; - onChange: (value: string) => void; - options: TabsTab[]; - actionType?: LimitedActionType; -} - -/** - * Use tabs for switching between related pages or views. - * - * Built atop Radix UI's `` component, so it's fully accessible and - * supports keyboard navigation. - * - * ```TSX - * - * ``` - */ -export const Tabs = ({ value, onChange, options, actionType = 'default' }: TabsProps) => { - const density = useDensity(); - - return ( - - -
- {options.map(option => ( - - - - ))} -
-
-
- ); -}; diff --git a/packages/ui-tailwind/src/Text/index.tsx b/packages/ui-tailwind/src/Text/index.tsx deleted file mode 100644 index b8b08fdc94..0000000000 --- a/packages/ui-tailwind/src/Text/index.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import cn from 'clsx'; - -import { - body, - detail, - h1, - h2, - h3, - h4, - large, - small, - detailTechnical, - strong, - technical, - xxl, - p, - getTextBase, -} from '../utils/typography'; -import { ElementType, ReactNode } from 'react'; -import { ThemeColor } from '../utils/color'; -import { TextType } from './types'; - -export type TextProps = TextType & { - children?: ReactNode; - /** - * Which component or HTML element to render this text as. - * - * @example - * ```tsx - * This is a span with H1 styling - * ``` - */ - as?: ElementType; - /** - * When `true`, will apply styles that 1) prevent text wrapping, 2) hide - * overflow, 3) add an ellpsis when the text overflows. - */ - truncate?: boolean; - /** A string representing the color key from the Tailwind theme (e.g. 'primary.light') */ - color?: ThemeColor; - /** - * The text alignment - */ - align?: 'left' | 'center' | 'right'; - /** - * The text decoration - */ - decoration?: 'line-through' | 'underline'; - /** - * The text transform - */ - transform?: 'uppercase' | 'lowercase' | 'capitalize'; - /** - * Controls how the text breaks. - */ - break?: 'words' | 'all' | 'keep'; - /** - * Controls how whitespace is handled. - */ - whitespace?: 'nowrap' | 'pre' | 'pre-line' | 'pre-wrap' | 'break-spaces'; -}; - -const ALIGN_MAP: Record['align'], string> = { - center: cn('text-center'), - left: cn('text-left'), - right: cn('text-right'), -}; - -const DECORATION_MAP: Record['decoration'], string> = { - 'line-through': cn('line-through'), - underline: cn('underline'), -}; - -const TRANSFORM_MAP: Record['transform'], string> = { - uppercase: cn('uppercase'), - lowercase: cn('lowercase'), - capitalize: cn('capitalize'), -}; - -const BREAK_MAP: Record['break'], string> = { - all: cn('break-all'), - words: cn('break-words'), - keep: cn('break-keep'), -}; - -const WHITESPACE_MAP: Record['whitespace'], string> = { - nowrap: cn('whitespace-nowrap'), - pre: cn('whitespace-pre'), - 'pre-line': cn('whitespace-pre-line'), - 'pre-wrap': cn('whitespace-pre-wrap'), - 'break-spaces': cn('whitespace-break-spaces'), -}; - -// Composes all props to the Tailwind class list -const getTextOptionClasses = ({ - color, - truncate, - align, - decoration, - transform, - break: breakProp, - whitespace, -}: TextProps): string => { - const truncateClass = truncate ? cn('truncate') : ''; - const alignClass = align && ALIGN_MAP[align]; - const decorationClass = decoration && DECORATION_MAP[decoration]; - const transformClass = transform && TRANSFORM_MAP[transform]; - const breakClass = breakProp && BREAK_MAP[breakProp]; - const whitespaceClass = whitespace && WHITESPACE_MAP[whitespace]; - - return cn( - getTextBase(color), - truncateClass, - alignClass, - decorationClass, - transformClass, - breakClass, - whitespaceClass, - ); -}; - -/** - * All-purpose text wrapper for quickly styling text per the Penumbra UI - * guidelines. - * - * Use with a _single_ text style name: - * - * ```tsx - * This will be rendered with the `h1` style. - * This will be rendered with the `body` style. - * - * INCORRECT: This will result in a TypeScript error. Only use one text style - * at a time. - * - * ``` - * - * When no text style is passed, it will render using the `body` style. - * - * The heading text styles are rendered as their corresponding heading tags - * (`

`, `

`, etc.), and the `p` style is rendered as a `

` tag. - * All other styles are rendered as ``s. To customize which tag is - * rendered without affecting its appearance, use the `as` prop: - * - * ```tsx - * - * This will render with the h1 style, but inside an inline span tag. - * - * ``` - */ -export const Text = (props: TextProps) => { - const classes = getTextOptionClasses(props); - const SpanElement = props.as ?? 'span'; - - if (props.h1) { - const Element = props.as ?? 'h1'; - return {props.children}; - } - if (props.h2) { - const Element = props.as ?? 'h2'; - return {props.children}; - } - if (props.h3) { - const Element = props.as ?? 'h3'; - return {props.children}; - } - if (props.h4) { - const Element = props.as ?? 'h4'; - return {props.children}; - } - - if (props.xxl) { - return {props.children}; - } - if (props.large) { - return {props.children}; - } - if (props.strong) { - return {props.children}; - } - if (props.detail) { - return {props.children}; - } - if (props.small) { - return {props.children}; - } - if (props.detailTechnical) { - return {props.children}; - } - if (props.technical) { - return {props.children}; - } - - if (props.p) { - const Element = props.as ?? 'p'; - return {props.children}; - } - - return {props.children}; -}; diff --git a/packages/ui-tailwind/src/TextInput/index.tsx b/packages/ui-tailwind/src/TextInput/index.tsx deleted file mode 100644 index 10410210e8..0000000000 --- a/packages/ui-tailwind/src/TextInput/index.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { forwardRef, ReactNode } from 'react'; -import { small } from '../utils/typography'; -import { ActionType, getFocusWithinOutlineColorByActionType } from '../utils/action-type'; -import { useDisabled } from '../utils/disabled-context'; -import cn from 'clsx'; - -export interface TextInputProps { - value?: string; - onChange?: (value: string) => void; - placeholder?: string; - actionType?: ActionType; - disabled?: boolean; - type?: 'email' | 'number' | 'password' | 'tel' | 'text' | 'url'; - /** - * Markup to render inside the text input's visual frame, before the text - * input itself. - */ - startAdornment?: ReactNode; - /** - * Markup to render inside the text input's visual frame, after the text input - * itself. - */ - endAdornment?: ReactNode; - max?: string | number; - min?: string | number; -} - -/** - * A simple text field. - * - * Can be enriched with start and end adornments, which are markup that render - * inside the text input's visual frame. - */ -// eslint-disable-next-line react/display-name -- exotic component -export const TextInput = forwardRef( - ( - { - value, - onChange, - placeholder, - actionType = 'default', - disabled, - type = 'text', - startAdornment = null, - endAdornment = null, - max, - min, - }: TextInputProps, - ref, - ) => ( -

- {startAdornment} - - onChange?.(e.target.value)} - placeholder={placeholder} - disabled={useDisabled(disabled)} - type={type} - max={max} - min={min} - ref={ref} - className={cn( - 'box-border grow appearance-none border-none bg-base-transparent py-2', - startAdornment ? 'pl-0' : 'pl-3', - endAdornment ? 'pr-0' : 'pr-3', - disabled ? 'text-text-muted' : 'text-text-primary', - small, - 'placeholder:text-text-secondary', - 'disabled:cursor-not-allowed', - 'disabled:placeholder:text-text-muted', - 'focus:outline-0', - '[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none', - )} - /> - - {endAdornment} -
- ), -); diff --git a/packages/ui-tailwind/src/Tooltip/index.tsx b/packages/ui-tailwind/src/Tooltip/index.tsx deleted file mode 100644 index d22d7dfd1b..0000000000 --- a/packages/ui-tailwind/src/Tooltip/index.tsx +++ /dev/null @@ -1,5 +0,0 @@ -export { TooltipProvider } from '@radix-ui/react-tooltip'; -export type { TooltipProviderProps } from '@radix-ui/react-tooltip'; - -export { Tooltip } from './tooltip'; -export type { TooltipProps } from './tooltip'; diff --git a/packages/ui-tailwind/src/WalletBalance/index.tsx b/packages/ui-tailwind/src/WalletBalance/index.tsx deleted file mode 100644 index 50bb0cc80e..0000000000 --- a/packages/ui-tailwind/src/WalletBalance/index.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import type { MouseEventHandler } from 'react'; -import { Wallet } from 'lucide-react'; -import cn from 'clsx'; -import type { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; -import { getFormattedAmtFromValueView } from '@penumbra-zone/types/value-view'; -import { - getAddressIndex, - getBalanceView, - getMetadataFromBalancesResponse, -} from '@penumbra-zone/getters/balances-response'; -import { ActionType, getOutlineColorByActionType } from '../utils/action-type'; -import { Text } from '../Text'; - -const getColorByActionType = (actionType: ActionType, disabled?: boolean): string => { - if (disabled) { - return cn('text-text-muted'); - } - if (actionType === 'destructive') { - return cn('text-destructive-light'); - } - return cn('text-text-secondary'); -}; - -export interface WalletBalanceProps { - balance?: BalancesResponse; - actionType?: ActionType; - disabled?: boolean; - onClick?: MouseEventHandler; -} - -/** - * `WalletBalance` renders a `BalancesResponse` — its account index, amount,, and symbol. - * Use this anywhere you would like to render a `BalancesResponse`. - * - * Allows clicking on the wallet icon. - */ -export const WalletBalance = ({ - balance, - actionType = 'default', - disabled, - onClick, -}: WalletBalanceProps) => { - const account = getAddressIndex.optional(balance); - const valueView = getBalanceView.optional(balance); - const metadata = getMetadataFromBalancesResponse.optional(balance); - - if (!valueView || !account || !metadata) { - return null; - } - - return ( -
- - - - {getFormattedAmtFromValueView(valueView, true)} {metadata.symbol || 'Unknown'} - -
- ); -}; diff --git a/packages/ui-tailwind/src/utils/button.ts b/packages/ui-tailwind/src/utils/button.ts deleted file mode 100644 index 3ea2ff425d..0000000000 --- a/packages/ui-tailwind/src/utils/button.ts +++ /dev/null @@ -1,76 +0,0 @@ -import cn from 'clsx'; -import type { Density } from './density'; -import { - getAfterOutlineColorByActionType, - getBeforeOutlineColorByActionType, - ActionType, - getBackgroundColorByActionType, -} from './action-type'; - -export type Priority = 'primary' | 'secondary'; - -interface ButtonStyleAttributes { - density: Density; - iconOnly?: boolean | 'adornment'; - actionType: ActionType; -} - -/** Shared styles to use for any `

); diff --git a/packages/ui/src/AssetSelector/SearchFilter.tsx b/packages/ui/src/AssetSelector/SearchFilter.tsx index 3d79e60b43..7b179303a7 100644 --- a/packages/ui/src/AssetSelector/SearchFilter.tsx +++ b/packages/ui/src/AssetSelector/SearchFilter.tsx @@ -12,7 +12,7 @@ export const AssetSelectorSearchFilter = ({ value, onChange }: AssetSelectorSear return ( color.text.primary} />} + startAdornment={} value={value ?? ''} onChange={handleSearch} placeholder='Search...' diff --git a/packages/ui/src/AssetSelector/SelectItem.tsx b/packages/ui/src/AssetSelector/SelectItem.tsx index b7dcba0997..8f17139c83 100644 --- a/packages/ui/src/AssetSelector/SelectItem.tsx +++ b/packages/ui/src/AssetSelector/SelectItem.tsx @@ -1,4 +1,3 @@ -import { styled } from 'styled-components'; import { AssetIcon } from '../AssetIcon'; import { Text } from '../Text'; import { getFormattedAmtFromValueView } from '@penumbra-zone/types/value-view'; @@ -7,32 +6,12 @@ import { getBalanceView, getMetadataFromBalancesResponse, } from '@penumbra-zone/getters/balances-response'; -import { ActionType } from '../utils/ActionType'; +import { ActionType } from '../utils/action-type'; import { AssetSelectorValue } from './shared/types'; -import { media } from '../utils/media'; import { getHash, isBalancesResponse } from './shared/helpers'; import { RadioItem } from '../Dialog/RadioItem'; import { useAssetsSelector } from './shared/Context'; -const AssetTitleText = styled(Text)` - display: inline-block; - max-width: 100px; - - ${media.tablet` - max-width: 300px; - `} - - ${media.lg` - max-width: 400px; - `} -`; - -const Balance = styled.div` - display: flex; - flex-direction: column; - align-items: flex-end; -`; - export interface AssetSelectorItemProps { /** * A `BalancesResponse` or `Metadata` protobuf message type. Renders the asset @@ -77,25 +56,27 @@ export const Item = ({ value, disabled, actionType = 'default' }: AssetSelectorI title={ <> {balance?.valueView && ( - + {getFormattedAmtFromValueView(balance.valueView, true)}{' '} )} - - {metadata?.symbol ?? 'Unknown'} - + + + {metadata?.symbol ?? 'Unknown'} + + } endAdornment={ balance?.addressIndexAccount !== undefined && ( - - color.text.secondary}> +
+ #{balance.addressIndexAccount} - color.text.secondary}> + Account - +
) } /> diff --git a/packages/ui/src/AssetSelector/Trigger.tsx b/packages/ui/src/AssetSelector/Trigger.tsx index c5acc88a4f..396806ce44 100644 --- a/packages/ui/src/AssetSelector/Trigger.tsx +++ b/packages/ui/src/AssetSelector/Trigger.tsx @@ -1,80 +1,15 @@ import { forwardRef, MouseEventHandler } from 'react'; -import { styled, css } from 'styled-components'; import { ChevronsUpDownIcon } from 'lucide-react'; -import { motion } from 'framer-motion'; +import cn from 'clsx'; import { getMetadataFromBalancesResponse } from '@penumbra-zone/getters/balances-response'; -import { ActionType, getOutlineColorByActionType } from '../utils/ActionType.ts'; -import { Density } from '../types/Density.ts'; -import { useDensity } from '../hooks/useDensity'; -import { asTransientProps } from '../utils/asTransientProps.ts'; +import { ActionType, getFocusOutlineColorByActionType } from '../utils/action-type'; +import { useDensity } from '../utils/density'; import { Icon } from '../Icon'; import { Text } from '../Text'; import { AssetIcon } from '../AssetIcon'; import { isMetadata } from './shared/helpers.ts'; -import { Dialog } from '../Dialog/index.tsx'; -import { AssetSelectorValue } from './shared/types.ts'; - -const SparseButton = css` - height: ${props => props.theme.spacing(12)}; - padding: 0 ${props => props.theme.spacing(3)}; -`; - -const CompactButton = css` - height: ${props => props.theme.spacing(8)}; - padding: 0 ${props => props.theme.spacing(2)}; -`; - -const Trigger = styled(motion.button)<{ $density: Density; $actionType: ActionType }>` - display: flex; - justify-content: space-between; - align-items: center; - gap: ${props => props.theme.spacing(1)}; - min-width: ${props => props.theme.spacing(20)}; - border-radius: ${props => props.theme.borderRadius.none}; - background: ${props => props.theme.color.other.tonalFill5}; - transition: - background 0.15s, - outline 0.15s; - - ${props => (props.$density === 'sparse' ? SparseButton : CompactButton)}; - - &:hover { - background-color: ${props => props.theme.color.action.hoverOverlay}; - } - - &:focus { - color: ${props => props.theme.color.text.secondary}; - background: ${props => props.theme.color.other.tonalFill5}; - outline: 2px solid ${props => getOutlineColorByActionType(props.theme, props.$actionType)}; - } - - &:disabled { - background: linear-gradient( - 0deg, - ${props => props.theme.color.action.disabledOverlay} 0%, - ${props => props.theme.color.action.disabledOverlay} 100% - ), - ${props => props.theme.color.other.tonalFill10}; - } -`; - -const Value = styled.div<{ $density: Density; $actionType: ActionType }>` - display: flex; - align-items: center; - gap: ${props => props.theme.spacing(props.$density === 'sparse' ? 2 : 1)}; -`; - -const IconAdornment = styled.i<{ $disabled?: boolean }>` - display: flex; - align-items: center; - justify-content: center; - padding: ${props => props.theme.spacing(1)}; - width: ${props => props.theme.spacing(6)}; - height: ${props => props.theme.spacing(6)}; - border-radius: ${props => props.theme.borderRadius.full}; - background-color: ${props => - props.$disabled ? props.theme.color.action.disabledOverlay : 'transparent'}; -`; +import { Dialog } from '../Dialog'; +import { AssetSelectorValue } from './shared/types'; export interface AssetSelectorTriggerProps { value?: AssetSelectorValue; @@ -85,41 +20,53 @@ export interface AssetSelectorTriggerProps { } export const AssetSelectorTrigger = forwardRef( - ({ value, actionType = 'default', disabled, onClick, layoutId }, ref) => { + ({ value, actionType = 'default', disabled, onClick }, ref) => { const density = useDensity(); const metadata = isMetadata(value) ? value : getMetadataFromBalancesResponse.optional(value); return ( - {!value ? ( - (disabled ? color.text.muted : color.text.primary)}> + Asset ) : ( - +
- (disabled ? color.text.muted : color.text.primary)}> + {metadata?.symbol ?? 'Unknown'} - +
)} - + (disabled ? color.text.muted : color.text.primary)} + color={disabled ? 'text.muted' : 'text.primary'} /> - -
+ +
); }, diff --git a/packages/ui/src/AssetSelector/index.tsx b/packages/ui/src/AssetSelector/index.tsx index 6ee71f2de1..c249155751 100644 --- a/packages/ui/src/AssetSelector/index.tsx +++ b/packages/ui/src/AssetSelector/index.tsx @@ -1,27 +1,14 @@ import { useMemo, useState } from 'react'; -import { styled } from 'styled-components'; import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; -import { isBalancesResponse, isMetadata } from './shared/helpers.ts'; -import { filterMetadataOrBalancesResponseByText } from './shared/filterMetadataOrBalancesResponseByText.ts'; -import { AssetSelectorBaseProps, AssetSelectorValue } from './shared/types.ts'; -import { AssetSelectorCustom, AssetSelectorCustomProps } from './Custom.tsx'; -import { Item, AssetSelectorItemProps } from './SelectItem.tsx'; +import { isBalancesResponse, isMetadata } from './shared/helpers'; +import { filterMetadataOrBalancesResponseByText } from './shared/filterMetadataOrBalancesResponseByText'; +import { AssetSelectorBaseProps, AssetSelectorValue } from './shared/types'; +import { AssetSelectorCustom, AssetSelectorCustomProps } from './Custom'; +import { Item, AssetSelectorItemProps } from './SelectItem'; import { Text } from '../Text'; -import { filterAssets, groupAndSortBalances } from './shared/groupAndSort.ts'; - -const ListItemGroup = styled.div` - display: flex; - flex-direction: column; - gap: ${props => props.theme.spacing(1)}; -`; - -const SelectorList = styled.div` - display: flex; - flex-direction: column; - gap: ${props => props.theme.spacing(4)}; -`; +import { filterAssets, groupAndSortBalances } from './shared/groupAndSort'; export interface AssetSelectorProps extends AssetSelectorBaseProps { /** @@ -123,23 +110,23 @@ export const AssetSelector = ({ onChange={onChange} > {({ getKeyHash }) => ( - +
{!!filteredBalances.length && ( - color.text.secondary}> + Your Tokens )} {filteredBalances.map(([account, balances]) => ( - +
{balances.map(balance => ( ))} - +
))} {!!filteredAssets.length && ( - color.text.secondary}> + All Tokens )} @@ -147,7 +134,7 @@ export const AssetSelector = ({ {filteredAssets.map(asset => ( ))} - +
)} ); diff --git a/packages/ui/src/AssetSelector/shared/types.ts b/packages/ui/src/AssetSelector/shared/types.ts index b214ff7042..cd328b6f64 100644 --- a/packages/ui/src/AssetSelector/shared/types.ts +++ b/packages/ui/src/AssetSelector/shared/types.ts @@ -1,6 +1,6 @@ import { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; -import { ActionType } from '../../utils/ActionType.ts'; +import { ActionType } from '../../utils/action-type'; export type AssetSelectorValue = BalancesResponse | Metadata; diff --git a/packages/ui/src/Button/index.tsx b/packages/ui/src/Button/index.tsx index 70a7626307..1963a51c18 100644 --- a/packages/ui/src/Button/index.tsx +++ b/packages/ui/src/Button/index.tsx @@ -1,99 +1,17 @@ import { FC, forwardRef, MouseEventHandler, ReactNode } from 'react'; -import { styled, css, DefaultTheme } from 'styled-components'; -import { asTransientProps } from '../utils/asTransientProps'; -import { Priority, focusOutline, overlays, buttonBase } from '../utils/button'; -import { getBackgroundColor } from './helpers'; -import { button } from '../utils/typography'; import { LucideIcon } from 'lucide-react'; -import { Density } from '../types/Density'; -import { useDensity } from '../hooks/useDensity'; -import { ActionType } from '../utils/ActionType'; -import { MotionProp } from '../utils/MotionProp'; -import { motion } from 'framer-motion'; - -const iconOnlyAdornment = css` - border-radius: ${props => props.theme.borderRadius.full}; - padding: ${props => props.theme.spacing(1)}; - width: max-content; -`; - -const sparse = css` - border-radius: ${props => props.theme.borderRadius.sm}; - padding-left: ${props => (props.$iconOnly ? 'none' : props.theme.spacing(4))}; - padding-right: ${props => (props.$iconOnly ? 'none' : props.theme.spacing(4))}; - height: 48px; - width: ${props => (props.$iconOnly ? '48px' : '100%')}; - ${props => props.$iconOnly && 'min-width: 48px;'} -`; - -const compact = css` - border-radius: ${props => props.theme.borderRadius.full}; - padding-left: ${props => props.theme.spacing(props.$iconOnly ? 2 : 4)}; - padding-right: ${props => props.theme.spacing(props.$iconOnly ? 2 : 4)}; - height: 32px; - min-width: 32px; - width: max-content; -`; - -const outlineColorByActionType: Record = { - default: 'neutralFocusOutline', - accent: 'primaryFocusOutline', - unshield: 'unshieldFocusOutline', - destructive: 'destructiveFocusOutline', -}; - -const borderColorByActionType: Record< - ActionType, - 'neutral' | 'primary' | 'unshield' | 'destructive' -> = { - default: 'neutral', - accent: 'primary', - unshield: 'unshield', - destructive: 'destructive', -}; - -interface StyledButtonProps { - $iconOnly?: boolean | 'adornment'; - $actionType: ActionType; - $priority: Priority; - $density: Density; - $getFocusOutlineColor: (theme: DefaultTheme) => string; - $getFocusOutlineOffset?: (theme: DefaultTheme) => string | undefined; - $getBorderRadius: (theme: DefaultTheme) => string; -} - -const StyledButton = styled(motion.button)` - ${buttonBase} - ${button} - - background-color: ${props => - getBackgroundColor(props.$actionType, props.$priority, props.theme, props.$iconOnly)}; - outline: ${props => - props.$priority === 'secondary' - ? `1px solid ${props.theme.color[borderColorByActionType[props.$actionType]].main}` - : 'none'}; - outline-offset: -1px; - display: flex; - gap: ${props => props.theme.spacing(2)}; - align-items: center; - justify-content: center; - color: ${props => props.theme.color.neutral.contrast}; - position: relative; +import cn from 'clsx'; +import { getOutlineColorByActionType, ActionType } from '../utils/action-type'; +import { Priority, buttonBase, getBackground, getFocusOutline, getOverlays } from '../utils/button'; +import { button } from '../utils/typography'; +import { useDensity } from '../utils/density'; - ${props => - // eslint-disable-next-line no-nested-ternary -- readable ternary - props.$iconOnly === 'adornment' - ? iconOnlyAdornment - : props.$density === 'sparse' - ? sparse - : compact} - &::after { - outline-offset: -2px; - } +const iconOnlyAdornment = cn('rounded-full p-1 w-max'); +const sparse = (iconOnly?: boolean | 'adornment') => + cn('rounded-sm h-12', iconOnly ? 'w-12 min-w-12 pl-0 pr-0' : 'w-full pl-4 pr-4'); - ${focusOutline} - ${overlays} -`; +const compact = (iconOnly?: boolean | 'adornment') => + cn('rounded-full h-8 min-w-8 w-max', iconOnly ? 'pl-2 pr-2' : 'pl-4 pr-4'); interface BaseButtonProps { type?: HTMLButtonElement['type']; @@ -162,7 +80,7 @@ interface RegularProps { icon?: LucideIcon | FC; } -export type ButtonProps = BaseButtonProps & (IconOnlyProps | RegularProps) & MotionProp; +export type ButtonProps = BaseButtonProps & (IconOnlyProps | RegularProps); /** * A component for all your button needs! @@ -184,40 +102,53 @@ export const Button = forwardRef( actionType = 'default', type = 'button', priority = 'primary', - motion, + ...attrs // needed for the Radix's `asChild` prop to work correctly // https://www.radix-ui.com/primitives/docs/guides/composition#composing-with-your-own-react-components - ...props }, ref, ) => { const density = useDensity(); return ( - theme.color.action[outlineColorByActionType[actionType]]} - $getFocusOutlineOffset={() => (iconOnly === 'adornment' ? '0px' : undefined)} - $getBorderRadius={theme => - density === 'sparse' && iconOnly !== 'adornment' - ? theme.borderRadius.sm - : theme.borderRadius.full - } + {...attrs} + className={cn( + buttonBase, + button, + getBackground(actionType, priority, iconOnly), + getFocusOutline({ density, iconOnly, actionType }), + getOverlays({ actionType, iconOnly, density }), + + '-outline-offset-1', + priority === 'secondary' && 'outline-1', + priority === 'secondary' && getOutlineColorByActionType(actionType), + 'after:-outline-offset-2', + + 'relative', + 'flex gap-2 items-center justify-center', + 'text-neutral-contrast', + + // eslint-disable-next-line no-nested-ternary -- allow + iconOnly === 'adornment' + ? iconOnlyAdornment + : density === 'sparse' + ? sparse(iconOnly) + : compact(iconOnly), + )} > {IconComponent && ( )} {!iconOnly && children} - + ); }, ); diff --git a/packages/ui/src/Card/index.stories.tsx b/packages/ui/src/Card/index.stories.tsx index 3edbfc4bcb..3952743c10 100644 --- a/packages/ui/src/Card/index.stories.tsx +++ b/packages/ui/src/Card/index.stories.tsx @@ -2,39 +2,23 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Card } from '.'; -import storiesBg from './storiesBg.jpg'; -import { styled } from 'styled-components'; import { Text } from '../Text'; -import { FormField } from '../FormField'; -import { TextInput } from '../TextInput'; import { useState } from 'react'; import { Button } from '../Button'; import { Tabs } from '../Tabs'; import { Send } from 'lucide-react'; -const BgWrapper = styled.div` - padding: ${props => props.theme.spacing(20)}; - position: relative; - - &::before { - content: ''; - background: url(${storiesBg}) center / cover; - opacity: 0.6; - filter: blur(4px); - position: absolute; - inset: 0; - z-index: -1; - } -`; - const meta: Meta = { component: Card, tags: ['autodocs', '!dev'], decorators: [ Story => ( - +
- +
), ], argTypes: { @@ -55,7 +39,6 @@ export const Basic: Story = { render: function Render({ as, title }) { const [tab, setTab] = useState('one'); - const [textInput, setTextInput] = useState(''); return ( @@ -90,18 +73,6 @@ export const Basic: Story = { in a <Card.Section />.
- - - - - - +

)} - - + + diff --git a/packages/ui/src/Dialog/EmptyContent.tsx b/packages/ui/src/Dialog/EmptyContent.tsx index 87ac9ab2cc..5f17d510ba 100644 --- a/packages/ui/src/Dialog/EmptyContent.tsx +++ b/packages/ui/src/Dialog/EmptyContent.tsx @@ -4,33 +4,6 @@ import { Portal as RadixDialogPortal, Content as RadixDialogContent, } from '@radix-ui/react-dialog'; -import { styled } from 'styled-components'; - -const Overlay = styled(RadixDialogOverlay)` - backdrop-filter: blur(${props => props.theme.blur.xs}); - background-color: ${props => props.theme.color.other.overlay}; - position: fixed; - inset: 0; - z-index: auto; -`; - -/** - * We make a full-screen wrapper around the dialog's content so that we can - * correctly position it using the same ``/`` as the - * underlying page uses. Note that we use a `styled.div` here, rather than - * `styled(RadixDialog.Content)`, because Radix adds an inline `pointer-events: - * auto` style to that element. We need to make sure there _aren't_ pointer - * events on the dialog content, because of the aforementioned full-screen - * wrapper that appears over the ``. We want to make sure that clicks - * on the full-screen wrapper pass through to the underlying ``, so - * that the dialog closes when the user clicks there. - */ -const DialogContent = styled.div<{ $zIndex?: number }>` - position: fixed; - inset: 0; - pointer-events: none; - ${props => props.$zIndex && `z-index: ${props.$zIndex};`} -`; export interface DialogEmptyContentProps { children?: ReactNode; @@ -41,10 +14,12 @@ export interface DialogEmptyContentProps { export const EmptyContent = ({ children, zIndex }: DialogEmptyContentProps) => { return ( - + - {children} +
+ {children} +
); diff --git a/packages/ui/src/Dialog/RadioItem.tsx b/packages/ui/src/Dialog/RadioItem.tsx index 85cec2658d..8ef98f8c75 100644 --- a/packages/ui/src/Dialog/RadioItem.tsx +++ b/packages/ui/src/Dialog/RadioItem.tsx @@ -1,72 +1,12 @@ import React, { ReactNode, useMemo } from 'react'; +import cn from 'clsx'; import { RadioGroupItem } from '@radix-ui/react-radio-group'; -import { styled } from 'styled-components'; -import { motion } from 'framer-motion'; import { Text } from '../Text'; -import { ActionType, getOutlineColorByActionType } from '../utils/ActionType'; -import { asTransientProps } from '../utils/asTransientProps'; - -const Root = styled(motion.button)<{ - $actionType: ActionType; - $disabled?: boolean; -}>` - border-radius: ${props => props.theme.borderRadius.sm}; - background-color: ${props => props.theme.color.other.tonalFill5}; - padding: ${props => props.theme.spacing(3)}; - - display: flex; - justify-content: space-between; - align-items: center; - text-align: left; - transition: - background 0.15s, - outline 0.15s; - - &:hover { - background: linear-gradient( - 0deg, - ${props => props.theme.color.action.hoverOverlay} 0%, - ${props => props.theme.color.action.hoverOverlay} 100% - ), - ${props => props.theme.color.other.tonalFill5}; - } - - &:focus { - background: linear-gradient( - 0deg, - ${props => props.theme.color.action.hoverOverlay} 0%, - ${props => props.theme.color.action.hoverOverlay} 100% - ), - ${props => props.theme.color.other.tonalFill5}; - outline: 2px solid ${props => getOutlineColorByActionType(props.theme, props.$actionType)}; - } - - &[aria-checked='true'] { - outline: 2px solid ${props => getOutlineColorByActionType(props.theme, props.$actionType)}; - } - - &:disabled { - background: linear-gradient( - 0deg, - ${props => props.theme.color.action.disabledOverlay} 0%, - ${props => props.theme.color.action.disabledOverlay} 100% - ), - ${props => props.theme.color.other.tonalFill5}; - } -`; - -const Info = styled.div` - display: flex; - gap: ${props => props.theme.spacing(2)}; - align-items: center; -`; - -const Title = styled.div` - display: flex; - align-items: center; - white-space: nowrap; - gap: ${props => props.theme.spacing(1)}; -`; +import { + ActionType, + getAriaCheckedOutlineColorByActionType, + getFocusOutlineColorByActionType, +} from '../utils/action-type'; export interface DialogRadioItemProps { /** A required unique string value defining the radio item */ @@ -120,7 +60,7 @@ export const RadioItem = ({ if (typeof description === 'string') { return ( - color.text.secondary} as='div'> + {description} ); @@ -131,21 +71,30 @@ export const RadioItem = ({ return ( - - +
{startAdornment}
- {title} +
{title}
{descriptionText}
- +
{endAdornment} -
+
); }; diff --git a/packages/ui/src/Dialog/index.stories.tsx b/packages/ui/src/Dialog/index.stories.tsx index b67cc659fd..6442007ddc 100644 --- a/packages/ui/src/Dialog/index.stories.tsx +++ b/packages/ui/src/Dialog/index.stories.tsx @@ -5,21 +5,9 @@ import { Button } from '../Button'; import { ComponentType } from 'react'; import { Text } from '../Text'; import { AssetIcon } from '../AssetIcon'; -import { styled } from 'styled-components'; import { Ban, Handshake, ThumbsUp } from 'lucide-react'; import { OSMO_METADATA, PENUMBRA_METADATA, PIZZA_METADATA } from '../utils/bufs'; -const WhiteTextWrapper = styled.div` - color: ${props => props.theme.color.text.primary}; -`; - -const Column = styled.div` - display: flex; - flex-direction: column; - gap: ${props => props.theme.spacing(1)}; - padding-top: ${props => props.theme.spacing(1)}; -`; - const meta: Meta = { component: Dialog, tags: ['autodocs', '!dev'], @@ -48,16 +36,21 @@ export const Basic: Story = { + + + + + } > - +
This is a subheading @@ -73,7 +66,7 @@ export const Basic: Story = { elit. Ut et massa mi. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut et massa mi. - +
); @@ -90,7 +83,7 @@ export const WithRadioItems: Story = { - +
} /> - +
diff --git a/packages/ui/src/Display/index.stories.tsx b/packages/ui/src/Display/index.stories.tsx index 00265605b3..fab620c930 100644 --- a/packages/ui/src/Display/index.stories.tsx +++ b/packages/ui/src/Display/index.stories.tsx @@ -1,7 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Display } from '.'; -import { styled } from 'styled-components'; import { Text } from '../Text'; const meta: Meta = { @@ -12,9 +11,9 @@ const meta: Meta = { }, decorators: [ Story => ( - +
- +
), ], }; @@ -22,20 +21,10 @@ export default meta; type Story = StoryObj; -const OuterWidthIndicator = styled.div` - border: 1px solid ${props => props.theme.color.base.white}; -`; - -const InnerWidthIndicator = styled.div` - background: ${props => props.theme.color.base.white}; - color: ${props => props.theme.color.base.black}; - padding: ${props => props.theme.spacing(2)}; -`; - export const FullWidth: Story = { args: { children: ( - +
The white background that this text sits inside of represents the{' '} inside width of the <Display />{' '} @@ -51,7 +40,7 @@ export const FullWidth: Story = { To test <Display /> at full width, click the "Full Width" item in the left sidebar, and try resizing your browser. - +
), }, }; diff --git a/packages/ui/src/Display/index.tsx b/packages/ui/src/Display/index.tsx index 758831e7bc..f428f9d2f7 100644 --- a/packages/ui/src/Display/index.tsx +++ b/packages/ui/src/Display/index.tsx @@ -1,19 +1,4 @@ import { ReactNode } from 'react'; -import { styled } from 'styled-components'; -import { media } from '../utils/media'; - -const Root = styled.section` - padding: 0 ${props => props.theme.spacing(4)}; - - ${props => media.desktop` - padding: 0 ${props.theme.spacing(8)}; - `} -`; - -const ContentsWrapper = styled.div` - max-width: 1600px; - margin: 0 auto; -`; export interface DisplayProps { children?: ReactNode; @@ -35,8 +20,8 @@ export interface DisplayProps { */ export const Display = ({ children }: DisplayProps) => { return ( - - {children} - +
+
{children}
+
); }; diff --git a/packages/ui/src/DropdownMenu/CheckboxItem.tsx b/packages/ui/src/DropdownMenu/CheckboxItem.tsx index 6dbd6d1bef..8b215708ba 100644 --- a/packages/ui/src/DropdownMenu/CheckboxItem.tsx +++ b/packages/ui/src/DropdownMenu/CheckboxItem.tsx @@ -4,9 +4,8 @@ import { } from '@radix-ui/react-dropdown-menu'; import { ReactNode } from 'react'; import { Check } from 'lucide-react'; -import { asTransientProps } from '../utils/asTransientProps.ts'; import { Text } from '../Text'; -import { DropdownMenuItemBase, MenuItem } from '../utils/menuItem.ts'; +import { DropdownMenuItemBase, getMenuItem } from '../utils/menu-item.ts'; export interface DropdownMenuCheckboxItemProps extends DropdownMenuItemBase { children?: ReactNode; @@ -23,18 +22,18 @@ export const CheckboxItem = ({ }: DropdownMenuCheckboxItemProps) => { return ( - +
{children} - +
); }; diff --git a/packages/ui/src/DropdownMenu/Content.tsx b/packages/ui/src/DropdownMenu/Content.tsx index 8243d165ec..c0b0c3a825 100644 --- a/packages/ui/src/DropdownMenu/Content.tsx +++ b/packages/ui/src/DropdownMenu/Content.tsx @@ -1,11 +1,10 @@ import { ReactNode } from 'react'; -import { useTheme } from 'styled-components'; import { Content as RadixDropdownMenuContent, Portal as RadixDropdownMenuPortal, DropdownMenuContentProps as RadixDropdownMenuContentProps, } from '@radix-ui/react-dropdown-menu'; -import { PopoverContent, PopoverContext } from '../utils/popover.ts'; +import { getPopoverContent, PopoverContext } from '../utils/popover.ts'; export interface DropdownMenuContentProps { children?: ReactNode; @@ -20,17 +19,10 @@ export const Content = ({ align, context = 'default', }: DropdownMenuContentProps) => { - const theme = useTheme(); - return ( - - {children} + +
{children}
); diff --git a/packages/ui/src/DropdownMenu/Item.tsx b/packages/ui/src/DropdownMenu/Item.tsx index 78aeec15a9..bb6f6dbe71 100644 --- a/packages/ui/src/DropdownMenu/Item.tsx +++ b/packages/ui/src/DropdownMenu/Item.tsx @@ -1,8 +1,7 @@ import { ReactNode } from 'react'; import { Item as RadixDropdownMenuItem } from '@radix-ui/react-dropdown-menu'; -import { asTransientProps } from '../utils/asTransientProps.ts'; import { Text } from '../Text'; -import { DropdownMenuItemBase, MenuItem } from '../utils/menuItem.ts'; +import { DropdownMenuItemBase, getMenuItem } from '../utils/menu-item.ts'; export interface DropdownMenuItemProps extends DropdownMenuItemBase { children?: ReactNode; @@ -19,10 +18,10 @@ export const Item = ({ }: DropdownMenuItemProps) => { return ( - +
{icon} {children} - +
); }; diff --git a/packages/ui/src/DropdownMenu/RadioItem.tsx b/packages/ui/src/DropdownMenu/RadioItem.tsx index 63633d4977..47f0187d9c 100644 --- a/packages/ui/src/DropdownMenu/RadioItem.tsx +++ b/packages/ui/src/DropdownMenu/RadioItem.tsx @@ -4,9 +4,8 @@ import { } from '@radix-ui/react-dropdown-menu'; import { ReactNode } from 'react'; import { Check } from 'lucide-react'; -import { asTransientProps } from '../utils/asTransientProps.ts'; import { Text } from '../Text'; -import { DropdownMenuItemBase, MenuItem } from '../utils/menuItem.ts'; +import { DropdownMenuItemBase, getMenuItem } from '../utils/menu-item.ts'; export interface DropdownMenuRadioItemProps extends DropdownMenuItemBase { children?: ReactNode; @@ -21,13 +20,13 @@ export const RadioItem = ({ }: DropdownMenuRadioItemProps) => { return ( - +
{children} - +
); }; diff --git a/packages/ui/src/Grid/index.stories.tsx b/packages/ui/src/Grid/index.stories.tsx index 68ae46aaa0..a69f42c628 100644 --- a/packages/ui/src/Grid/index.stories.tsx +++ b/packages/ui/src/Grid/index.stories.tsx @@ -1,6 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Grid } from '.'; -import { styled } from 'styled-components'; import { Text } from '../Text'; const meta: Meta = { @@ -21,31 +20,23 @@ export default meta; type Story = StoryObj; -const Item = styled.div` - background-color: ${props => props.theme.color.neutral.main}; - display: flex; - align-items: center; - justify-content: center; - padding: ${props => props.theme.spacing(2)}; -`; - export const Demo: Story = { render: function Render() { return ( - +
mobile=12 - +
{Array(2) .fill(null) .map((_, index) => ( - +
mobile=12 tablet=6 - +
))} @@ -53,9 +44,9 @@ export const Demo: Story = { .fill(null) .map((_, index) => ( - +
mobile=6 tablet=6 desktop=3 - +
))} @@ -63,9 +54,9 @@ export const Demo: Story = { .fill(null) .map((_, index) => ( - +
lg=1 - +
))}
diff --git a/packages/ui/src/Grid/index.tsx b/packages/ui/src/Grid/index.tsx index 3444298f91..3a9abb0f20 100644 --- a/packages/ui/src/Grid/index.tsx +++ b/packages/ui/src/Grid/index.tsx @@ -1,7 +1,5 @@ import { PropsWithChildren } from 'react'; -import { styled } from 'styled-components'; -import { AsTransientProps, asTransientProps } from '../utils/asTransientProps'; -import { media } from '../utils/media'; +import cn from 'clsx'; type GridElement = 'div' | 'main' | 'section'; @@ -30,7 +28,7 @@ interface GridItemProps extends BaseGridProps { * The number of columns this grid item should span on mobile. * * The mobile grid layout can only be split in half, so you can only set a - * grid item to 6 or 12 columns on mobile. + * grid item to 6 or 12 columns on mobile. 0 hides the container from mobile screens. */ mobile?: 0 | 6 | 12; /** @@ -47,43 +45,71 @@ interface GridItemProps extends BaseGridProps { xl?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; } -export type GridProps = PropsWithChildren; - -const Container = styled.div` - display: grid; - grid-template-columns: repeat(12, 1fr); - gap: ${props => props.theme.spacing(4)}; -`; +const MOBILE_MAP: Record['mobile'], string> = { + 0: 'hidden', + 6: 'col-span-6', + 12: 'col-span-12', +}; -const Item = styled.div>>` - ${props => media.mobile` - grid-column: span ${props.$mobile ?? 12}; - `} +const TABLET_MAP: Record['tablet'], string> = { + 0: 'tablet:hidden', + 2: 'tablet:col-span-2', + 4: 'tablet:col-span-4', + 6: 'tablet:col-span-6', + 8: 'tablet:col-span-8', + 10: 'tablet:col-span-10', + 12: 'tablet:col-span-12', +}; - ${props => - props.$tablet && - media.tablet` - grid-column: span ${props.$tablet}; - `} +const DESKTOP_MAP: Record['desktop'], string> = { + 0: 'desktop:hidden', + 1: 'desktop:col-span-1', + 2: 'desktop:col-span-2', + 3: 'desktop:col-span-3', + 4: 'desktop:col-span-4', + 5: 'desktop:col-span-5', + 6: 'desktop:col-span-6', + 7: 'desktop:col-span-7', + 8: 'desktop:col-span-8', + 9: 'desktop:col-span-9', + 10: 'desktop:col-span-10', + 11: 'desktop:col-span-11', + 12: 'desktop:col-span-12', +}; - ${props => - props.$desktop && - media.desktop` - grid-column: span ${props.$desktop}; - `} +const LG_MAP: Record['lg'], string> = { + 0: 'lg:hidden', + 1: 'lg:col-span-1', + 2: 'lg:col-span-2', + 3: 'lg:col-span-3', + 4: 'lg:col-span-4', + 5: 'lg:col-span-5', + 6: 'lg:col-span-6', + 7: 'lg:col-span-7', + 8: 'lg:col-span-8', + 9: 'lg:col-span-9', + 10: 'lg:col-span-10', + 11: 'lg:col-span-11', + 12: 'lg:col-span-12', +}; - ${props => - props.$lg && - media.lg` - grid-column: span ${props.$lg}; - `} +const XL_MAP: Record['xl'], string> = { + 0: 'xl:hidden', + 1: 'xl:col-span-1', + 2: 'xl:col-span-2', + 3: 'xl:col-span-3', + 4: 'xl:col-span-4', + 5: 'xl:col-span-5', + 6: 'xl:col-span-6', + 7: 'xl:col-span-7', + 8: 'xl:col-span-8', + 9: 'xl:col-span-9', + 10: 'xl:col-span-10', + 11: 'xl:col-span-11', + 12: 'xl:col-span-12', +}; - ${props => - props.$xl && - media.xl` - grid-column: span ${props.$xl}; - `} -`; +export type GridProps = PropsWithChildren; /** * A responsive grid component that makes 12-column layouts super easy to build. @@ -125,11 +151,19 @@ const Item = styled.div>>` *
* ``` */ -export const Grid = ({ container, children, as = 'div', ...props }: GridProps) => +export const Grid = ({ container, children, as: Container = 'div', ...props }: GridProps) => container ? ( - {children} + {children} ) : ( - + {children} - + ); diff --git a/packages/ui/src/Icon/index.stories.ts b/packages/ui/src/Icon/index.stories.ts index f7dd4137f9..b7f494b781 100644 --- a/packages/ui/src/Icon/index.stories.ts +++ b/packages/ui/src/Icon/index.stories.ts @@ -20,6 +20,6 @@ export const Basic: StoryObj = { args: { IconComponent: ArrowRightLeft, size: 'sm', - color: color => color.text.primary, + color: 'text.primary', }, }; diff --git a/packages/ui/src/Icon/index.tsx b/packages/ui/src/Icon/index.tsx index 0de23de0c2..9746156fab 100644 --- a/packages/ui/src/Icon/index.tsx +++ b/packages/ui/src/Icon/index.tsx @@ -1,6 +1,7 @@ import { LucideIcon } from 'lucide-react'; import { ComponentProps, FC } from 'react'; -import { DefaultTheme, useTheme } from 'styled-components'; +import { ThemeColor, getThemeColorClass } from '../utils/color'; +import cn from 'clsx'; export type IconSize = 'sm' | 'md' | 'lg'; @@ -20,12 +21,8 @@ export interface IconProps { * - `lg`: 32px square */ size: IconSize; - /** - * A function that takes the `color` object of `theme`, and returns a CSS color to render - * the icon with. If left undefined, will default to the parent's text color - * (`currentColor` in SVG terms). - */ - color?: (color: DefaultTheme['color']) => string; + /** A string representing the color key from the Tailwind theme (e.g. 'primary.light') */ + color?: ThemeColor; } const PROPS_BY_SIZE: Record> = { @@ -53,13 +50,17 @@ const PROPS_BY_SIZE: Record> = { * color.primary.main} + * color='text.primary' * /> * ``` */ export const Icon = ({ IconComponent, size = 'sm', color }: IconProps) => { - const theme = useTheme(); - const resolvedColor = color ? color(theme.color) : 'currentColor'; - - return ; + return ( + + ); }; diff --git a/packages/ui/src/Identicon/index.tsx b/packages/ui/src/Identicon/index.tsx index 89671bd9d9..fb518243e2 100644 --- a/packages/ui/src/Identicon/index.tsx +++ b/packages/ui/src/Identicon/index.tsx @@ -1,6 +1,5 @@ import { useMemo } from 'react'; import { generateGradient, generateSolidColor } from './generate'; -import { styled } from 'styled-components'; /** * The view box size is separate from the passed-in `size` prop. @@ -11,22 +10,6 @@ import { styled } from 'styled-components'; */ const VIEW_BOX_SIZE = 24; -const Svg = styled.svg.attrs<{ $size: number }>(props => ({ - width: props.$size, - height: props.$size, - viewBox: `0 0 ${VIEW_BOX_SIZE} ${VIEW_BOX_SIZE}`, - version: '1.1', - xmlns: 'http://www.w3.org/2000/svg', -}))` - display: block; - border-radius: ${props => props.theme.borderRadius.full}; -`; - -const SvgText = styled.text` - text-transform: uppercase; - font-family: ${props => props.theme.font.default}; -`; - export interface IdenticonProps { /** * The ID or other string representation of the object you want an identicon @@ -63,7 +46,14 @@ const IdenticonGradient = ({ uniqueIdentifier, size = 120 }: IdenticonProps) => const gradientId = useMemo(() => `gradient-${uniqueIdentifier}`, [uniqueIdentifier]); return ( - + @@ -79,7 +69,7 @@ const IdenticonGradient = ({ uniqueIdentifier, size = 120 }: IdenticonProps) => height={VIEW_BOX_SIZE} /> - + ); }; @@ -87,11 +77,18 @@ const IdenticonSolid = ({ uniqueIdentifier, size = 120 }: IdenticonProps) => { const color = useMemo(() => generateSolidColor(uniqueIdentifier), [uniqueIdentifier]); return ( - + - + {uniqueIdentifier[0]} - - + + ); }; diff --git a/packages/ui/src/MenuItem/index.tsx b/packages/ui/src/MenuItem/index.tsx index 96341d4ff1..1e661de27d 100644 --- a/packages/ui/src/MenuItem/index.tsx +++ b/packages/ui/src/MenuItem/index.tsx @@ -1,18 +1,7 @@ import type { LucideIcon } from 'lucide-react'; import type { FC, MouseEventHandler } from 'react'; -import { MenuItem as SharedMenuItem, DropdownMenuItemBase } from '../utils/menuItem'; +import { getMenuItem, DropdownMenuItemBase } from '../utils/menu-item'; import { Text } from '../Text'; -import { styled } from 'styled-components'; -import { asTransientProps } from '../utils/asTransientProps.ts'; - -const IconAdornment = styled.i` - display: flex; - align-items: center; - justify-content: center; - padding: ${props => props.theme.spacing(1)}; - width: ${props => props.theme.spacing(6)}; - height: ${props => props.theme.spacing(6)}; -`; export interface MenuItemProps extends DropdownMenuItemBase { label: string; @@ -31,18 +20,13 @@ export const MenuItem = ({ disabled, }: MenuItemProps) => { return ( - + ); }; diff --git a/packages/ui/src/Pill/index.tsx b/packages/ui/src/Pill/index.tsx index 41947b357f..76bd17acb5 100644 --- a/packages/ui/src/Pill/index.tsx +++ b/packages/ui/src/Pill/index.tsx @@ -1,9 +1,7 @@ -import { styled, DefaultTheme } from 'styled-components'; -import { asTransientProps } from '../utils/asTransientProps'; import { ReactNode } from 'react'; import { body, technical, detail, detailTechnical } from '../utils/typography'; -import { Density } from '../types/Density'; -import { useDensity } from '../hooks/useDensity'; +import { Density, useDensity } from '../utils/density'; +import cn from 'clsx'; type Priority = 'primary' | 'secondary'; type Context = @@ -20,67 +18,45 @@ const getFont = (context: Context, density: Density) => { return density === 'sparse' ? technical : detailTechnical; }; -const getXPadding = (priority: Priority, density: Density) => { - let padding = density === 'sparse' ? 3 : 2; +const getXPadding = (priority: Priority, density: Density): string => { if (priority === 'secondary') { - padding = padding - 0.5; + return density === 'sparse' ? 'pr-[10px] pl-[10px]' : 'pr-[6px] pl-[6px]'; } - return padding; + return density === 'sparse' ? 'pr-3 pl-3' : 'pr-2 pl-2'; }; -const getBackgroundColor = (theme: DefaultTheme, priority: Priority, context: Context) => { +const getBackgroundColor = (priority: Priority, context: Context) => { if (priority === 'secondary') { - return 'transparent'; + return 'bg-transparent'; } + const colorMap: Record = { - default: theme.color.other.tonalFill10, - 'technical-default': theme.color.other.tonalFill10, - 'technical-success': theme.color.secondary.light, - 'technical-caution': theme.color.caution.light, - 'technical-destructive': theme.color.destructive.light, + default: cn('bg-other-tonalFill10'), + 'technical-default': cn('bg-other-tonalFill10'), + 'technical-success': cn('bg-secondary-light'), + 'technical-caution': cn('bg-caution-light'), + 'technical-destructive': cn('bg-destructive-light'), }; return colorMap[context]; }; -const getColor = (theme: DefaultTheme, priority: Priority, context: Context) => { +const getColor = (priority: Priority, context: Context): string => { if (priority === 'primary') { return context === 'default' || context === 'technical-default' - ? theme.color.text.primary - : theme.color.secondary.dark; + ? cn('text-text-primary') + : cn('text-secondary-dark'); } const colorMap: Record = { - default: theme.color.text.primary, - 'technical-default': theme.color.text.primary, - 'technical-success': theme.color.secondary.light, - 'technical-caution': theme.color.caution.light, - 'technical-destructive': theme.color.destructive.light, + default: cn('text-text-primary'), + 'technical-default': cn('text-text-primary'), + 'technical-success': cn('text-secondary-light'), + 'technical-caution': cn('text-caution-light'), + 'technical-destructive': cn('text-destructive-light'), }; return colorMap[context]; }; -const Root = styled.span<{ $density: Density; $priority: Priority; $context: Context }>` - box-sizing: border-box; - - border: ${props => - props.$priority === 'secondary' ? `2px dashed ${props.theme.color.other.tonalStroke}` : 'none'}; - border-radius: ${props => props.theme.borderRadius.full}; - - display: inline-block; - max-width: 100%; - width: max-content; - - padding-top: ${props => props.theme.spacing(props.$priority === 'secondary' ? 0.5 : 1)}; - padding-bottom: ${props => props.theme.spacing(props.$priority === 'secondary' ? 0.5 : 1)}; - - padding-left: ${props => props.theme.spacing(getXPadding(props.$priority, props.$density))}; - padding-right: ${props => props.theme.spacing(getXPadding(props.$priority, props.$density))}; - - ${props => getFont(props.$context, props.$density)}; - color: ${props => getColor(props.theme, props.$priority, props.$context)}; - background-color: ${props => getBackgroundColor(props.theme, props.$priority, props.$context)}; -`; - export interface PillProps { children: ReactNode; priority?: Priority; @@ -90,5 +66,21 @@ export interface PillProps { export const Pill = ({ children, priority = 'primary', context = 'default' }: PillProps) => { const density = useDensity(); - return {children}; + return ( + + {children} + + ); }; diff --git a/packages/ui/src/Popover/index.stories.tsx b/packages/ui/src/Popover/index.stories.tsx index 70719d36c5..8bb09f83cf 100644 --- a/packages/ui/src/Popover/index.stories.tsx +++ b/packages/ui/src/Popover/index.stories.tsx @@ -4,17 +4,9 @@ import { Popover } from '.'; import { Button } from '../Button'; import { ComponentType, useState } from 'react'; import { Text } from '../Text'; -import { styled } from 'styled-components'; import { Shield } from 'lucide-react'; import { Density } from '../Density'; -const Wrapper = styled.div` - display: flex; - flex-direction: column; - gap: ${props => props.theme.spacing(4)}; - color: ${props => props.theme.color.text.primary}; -`; - const meta: Meta = { component: Popover, tags: ['autodocs', '!dev'], @@ -44,7 +36,7 @@ export const Basic: Story = { - +
This is a heading @@ -59,7 +51,7 @@ export const Basic: Story = {
-
+
); diff --git a/packages/ui/src/Popover/index.tsx b/packages/ui/src/Popover/index.tsx index db403b93ff..c19f573f2a 100644 --- a/packages/ui/src/Popover/index.tsx +++ b/packages/ui/src/Popover/index.tsx @@ -1,8 +1,7 @@ import { ReactNode } from 'react'; import * as RadixPopover from '@radix-ui/react-popover'; import type { PopoverContentProps as RadixPopoverContentProps } from '@radix-ui/react-popover'; -import { useTheme } from 'styled-components'; -import { PopoverContent, PopoverContext } from '../utils/popover.ts'; +import { getPopoverContent, PopoverContext } from '../utils/popover.ts'; interface ControlledPopoverProps { /** @@ -115,17 +114,10 @@ export interface PopoverContentProps { * `side` and `align` props. */ const Content = ({ children, side, align, context = 'default' }: PopoverContentProps) => { - const theme = useTheme(); - return ( - - {children} + +
{children}
); diff --git a/packages/ui/src/Progress/index.tsx b/packages/ui/src/Progress/index.tsx index 3c13381b6d..871aebb6f4 100644 --- a/packages/ui/src/Progress/index.tsx +++ b/packages/ui/src/Progress/index.tsx @@ -1,63 +1,18 @@ import * as ProgressPrimitive from '@radix-ui/react-progress'; -import { styled, type DefaultTheme, keyframes } from 'styled-components'; +import cn from 'clsx'; -export const infiniteLoading = keyframes` - from { - left: -20%; - } - to { - left: 100%; - } -`; - -const Root = styled(ProgressPrimitive.Root)<{ $error: boolean }>` - position: relative; - width: 100%; - height: ${props => props.theme.spacing(1)}; - background-color: ${props => - props.$error ? props.theme.color.destructive.light : props.theme.color.other.tonalFill5}; - transition: background-color 0.15s; - overflow: hidden; -`; - -export const getIndicatorColor = (theme: DefaultTheme, value: number, error: boolean): string => { +export const getIndicatorColor = (value: number, error: boolean): string => { if (error) { - return theme.color.destructive.light; + return cn('bg-destructive-light'); } if (value === 1) { - return theme.color.secondary.light; + return cn('bg-secondary-light'); } - return theme.color.caution.light; + return cn('bg-caution-light'); }; -const Indicator = styled.div<{ $value: number; $error: boolean }>` - height: 100%; - width: 100%; - background-color: ${props => getIndicatorColor(props.theme, props.$value, props.$error)}; - transition: - transform 0.5s cubic-bezier(0.65, 0, 0.35, 1), - background-color 0.15s; - overflow: hidden; -`; - -const Loading = styled.div` - position: absolute; - top: 0; - left: -20%; - width: 20%; - height: 100%; - filter: blur(2px); - background: linear-gradient( - 90deg, - rgba(255, 255, 255, 0) 0%, - #fff 50%, - rgba(255, 255, 255, 0) 100% - ); - animation: ${infiniteLoading} 1s linear infinite; -`; - export interface ProgressProps { /** Percentage value from 0 to 1 */ value: number; @@ -71,15 +26,32 @@ export interface ProgressProps { * Progress bar with loading and error states */ export const Progress = ({ value, loading, error = false }: ProgressProps) => ( - + - - {loading && } - + {loading && ( +
+ )} +
-
+ ); diff --git a/packages/ui/src/Table/index.tsx b/packages/ui/src/Table/index.tsx index b3ce822426..f4c23a75db 100644 --- a/packages/ui/src/Table/index.tsx +++ b/packages/ui/src/Table/index.tsx @@ -1,34 +1,10 @@ import { PropsWithChildren, ReactNode } from 'react'; -import { styled, css } from 'styled-components'; +import cn from 'clsx'; import { tableHeading, tableItem } from '../utils/typography'; -import { Density } from '../types/Density'; -import { useDensity } from '../hooks/useDensity'; +import { Density, useDensity } from '../utils/density'; import { ConditionalWrap } from '../ConditionalWrap'; -import { motion } from 'framer-motion'; -import { MotionProp } from '../utils/MotionProp'; -const FIVE_PERCENT_OPACITY_IN_HEX = '0d'; - -// So named to avoid naming conflicts with `` -const StyledTable = styled(motion.table)<{ $tableLayout?: 'fixed' | 'auto' }>` - width: 100%; - background-color: ${props => props.theme.color.neutral.contrast + FIVE_PERCENT_OPACITY_IN_HEX}; - padding-left: ${props => props.theme.spacing(3)}; - padding-right: ${props => props.theme.spacing(3)}; - border-radius: ${props => props.theme.borderRadius.sm}; - table-layout: ${props => props.$tableLayout ?? 'auto'}; -`; - -const TitleAndTableWrapper = styled.div` - display: flex; - flex-direction: column; -`; - -const TitleWrapper = styled.div` - padding: ${props => props.theme.spacing(3)}; -`; - -export interface TableProps extends MotionProp { +export interface TableProps { /** Content that will appear above the table. */ title?: ReactNode; children: ReactNode; @@ -81,139 +57,105 @@ export const Table = ({ title, children, tableLayout }: TableProps) => ( ( - - {title} +
+
{title}
{children} - +
)} > - +
{children} - +
); const Thead = ({ children }: PropsWithChildren) => {children}; Table.Thead = Thead; -const StyledTbody = styled.tbody``; // Needs to be a styled component for `StyledTd` below -const Tbody = ({ children }: PropsWithChildren) => {children}; +const Tbody = ({ children }: PropsWithChildren) => {children}; Table.Tbody = Tbody; -const StyledTr = styled(motion.tr)``; // Needs to be a styled component for `StyledTd` below -const Tr = ({ children, motion }: PropsWithChildren) => ( - {children} +const Tr = ({ children }: PropsWithChildren) => ( + {children} ); Table.Tr = Tr; type HAlign = 'left' | 'center' | 'right'; type VAlign = 'top' | 'middle' | 'bottom'; -interface CellStyledProps { - $density: Density; - $width?: string; - $hAlign?: HAlign; - $vAlign?: VAlign; -} -const cell = css` - box-sizing: border-box; +const getCell = (density: Density) => + cn('box-border', 'pl-3 pr-3', density === 'sparse' ? 'pt-4 pb-4' : 'pt-3 pb-3'); - padding-left: ${props => props.theme.spacing(3)}; - padding-right: ${props => props.theme.spacing(3)}; - - padding-top: ${props => props.theme.spacing(props.$density === 'sparse' ? 4 : 3)}; - padding-bottom: ${props => props.theme.spacing(props.$density === 'sparse' ? 4 : 3)}; - - ${props => props.$width && `width: ${props.$width};`} - ${props => props.$hAlign && `text-align: ${props.$hAlign};`}; - ${props => props.$vAlign && `vertical-align: ${props.$vAlign};`}; -`; - -const StyledTh = styled(motion.th)` - border-bottom: 1px solid ${props => props.theme.color.other.tonalStroke}; - text-align: left; - color: ${props => props.theme.color.text.secondary}; - - ${tableHeading} - ${cell} -`; const Th = ({ children, colSpan, hAlign, vAlign, width, - motion, -}: PropsWithChildren< - { - colSpan?: number; - /** A CSS `width` value to use for this cell. */ - width?: string; - /** Controls the CSS `text-align` property for this cell. */ - hAlign?: HAlign; - /** Controls the CSS `vertical-align` property for this cell. */ - vAlign?: VAlign; - } & MotionProp ->) => { +}: PropsWithChildren<{ + colSpan?: number; + /** A CSS `width` value to use for this cell. */ + width?: string; + /** Controls the CSS `text-align` property for this cell. */ + hAlign?: HAlign; + /** Controls the CSS `vertical-align` property for this cell. */ + vAlign?: VAlign; +}>) => { const density = useDensity(); return ( - {children} - + ); }; Table.Th = Th; -const StyledTd = styled(motion.td)` - border-bottom: 1px solid ${props => props.theme.color.other.tonalStroke}; - color: ${props => props.theme.color.text.primary}; - - ${StyledTbody} > ${StyledTr}:last-child > & { - border-bottom: none; - } - - ${tableItem} - ${cell} -`; const Td = ({ children, colSpan, hAlign, vAlign, width, - motion, -}: PropsWithChildren< - { - colSpan?: number; - /** A CSS `width` value to use for this cell. */ - width?: string; - /** Controls the CSS `text-align` property for this cell. */ - hAlign?: HAlign; - /** Controls the CSS `vertical-align` property for this cell. */ - vAlign?: VAlign; - } & MotionProp ->) => { +}: PropsWithChildren<{ + colSpan?: number; + /** A CSS `width` value to use for this cell. */ + width?: string; + /** Controls the CSS `text-align` property for this cell. */ + hAlign?: HAlign; + /** Controls the CSS `vertical-align` property for this cell. */ + vAlign?: VAlign; +}>) => { const density = useDensity(); return ( - {children} - + ); }; Table.Td = Td; diff --git a/packages/ui/src/Tabs/index.tsx b/packages/ui/src/Tabs/index.tsx index 877574013d..f58afd9b78 100644 --- a/packages/ui/src/Tabs/index.tsx +++ b/packages/ui/src/Tabs/index.tsx @@ -1,105 +1,31 @@ -import { styled, css, DefaultTheme } from 'styled-components'; import { tab, tabSmall } from '../utils/typography'; -import { motion } from 'framer-motion'; -import { useId } from 'react'; -import { buttonBase, overlays } from '../utils/button'; +import { buttonBase, getOverlays } from '../utils/button'; import * as RadixTabs from '@radix-ui/react-tabs'; -import { ActionType } from '../utils/ActionType'; -import { useDensity } from '../hooks/useDensity'; -import { Density } from '../types/Density.ts'; - -const sparse = css` - ${tab}; - - flex-grow: 1; - flex-shrink: 1; - flex-basis: 0; /** Ensure equal widths */ - - padding: ${props => props.theme.spacing(2)}; -`; - -const compact = css` - ${tabSmall}; - - padding: ${props => props.theme.spacing(1)} ${props => props.theme.spacing(2)}; -`; - -const Root = styled.div<{ - $density: Density; -}>` - display: flex; - align-items: stretch; - box-sizing: border-box; - gap: ${props => props.theme.spacing(4)}; - height: ${props => (props.$density === 'sparse' ? 44 : 28)}px; -`; +import { ActionType } from '../utils/action-type'; +import { useDensity } from '../utils/density'; +import cn from 'clsx'; type LimitedActionType = Exclude; -const outlineColorByActionType: Record = { - default: 'neutralFocusOutline', - accent: 'primaryFocusOutline', - unshield: 'unshieldFocusOutline', -}; - -const gradientColorByActionType: Record = { - default: 'neutral', - accent: 'primary', - unshield: 'unshield', +const getIndicatorColor = (actionType: LimitedActionType): string => { + if (actionType === 'accent') { + return cn('bg-tabAccent'); + } + if (actionType === 'unshield') { + return cn('bg-tabUnshield'); + } + return cn('bg-tabNeutral'); }; -const Tab = styled.button<{ - $actionType: LimitedActionType; - $getFocusOutlineColor: (theme: DefaultTheme) => string; - $getBorderRadius: (theme: DefaultTheme) => string; - $density: Density; -}>` - ${buttonBase}; - - height: 100%; - - color: ${props => { - switch (props.$actionType) { - case 'accent': - return props.theme.color.primary.light; - case 'unshield': - return props.theme.color.unshield.light; - default: - return props.theme.color.text.primary; - } - }}; - position: relative; - white-space: nowrap; - - ${overlays} - - ${props => (props.$density === 'sparse' ? sparse : compact)} - - &:focus-within { - outline: none; +const getBorderColor = (actionType: LimitedActionType): string => { + if (actionType === 'accent') { + return cn('border-action-primaryFocusOutline'); } - - &::after { - inset: ${props => props.theme.spacing(0.5)}; + if (actionType === 'unshield') { + return cn('border-action-unshieldFocusOutline'); } -`; - -const THIRTY_FIVE_PERCENT_OPACITY_IN_HEX = '59'; -const SelectedIndicator = styled(motion.div)<{ $actionType: LimitedActionType }>` - background: radial-gradient( - at 50% 100%, - ${props => - props.theme.color[gradientColorByActionType[props.$actionType]].light + - THIRTY_FIVE_PERCENT_OPACITY_IN_HEX} - 0%, - transparent 50% - ); - border-bottom: 2px solid - ${props => props.theme.color.action[outlineColorByActionType[props.$actionType]]}; - position: absolute; - inset: 0; - z-index: -1; -`; + return cn('border-action-neutralFocusOutline'); +}; export interface TabsTab { value: string; @@ -133,13 +59,17 @@ export interface TabsProps { * ``` */ export const Tabs = ({ value, onChange, options, actionType = 'default' }: TabsProps) => { - const layoutId = useId(); const density = useDensity(); return ( - +
{options.map(option => ( - onChange(option.value)} disabled={option.disabled} - $density={density} - $actionType={actionType} - $getFocusOutlineColor={theme => - theme.color.action[outlineColorByActionType[actionType]] - } - $getBorderRadius={theme => - `${theme.borderRadius.xs} ${theme.borderRadius.xs} ${theme.borderRadius.none} ${theme.borderRadius.none}` - } + className={cn( + buttonBase, + getOverlays({ actionType, density }), + 'h-full relative whitespace-nowrap text-text-primary', + density === 'sparse' + ? cn(tab, 'grow shrink basis-0 p-2') + : cn(tabSmall, 'py-1 px-2'), + 'before:rounded-tl-xs before:rounded-tr-xs before:rounded-bl-none before:rounded-br-none', + 'focus-within:outline-none', + 'after:inset-[2px]', + )} > {value === option.value && ( - +
)} {option.label} - + ))} - +
); diff --git a/packages/ui/src/Text/index.stories.tsx b/packages/ui/src/Text/index.stories.tsx index d9163cf1ac..5756524324 100644 --- a/packages/ui/src/Text/index.stories.tsx +++ b/packages/ui/src/Text/index.stories.tsx @@ -1,7 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Text } from '.'; -import { styled } from 'styled-components'; import { useArgs } from '@storybook/preview-api'; const meta: Meta = { @@ -29,13 +28,6 @@ const meta: Meta = { }; export default meta; -const Wrapper = styled.div<{ $dir: 'column' | 'row' }>` - display: flex; - flex-direction: ${props => props.$dir}; - ${props => (props.$dir === 'row' ? `align-items: center;` : '')} - gap: ${props => props.theme.spacing(2)}; -`; - const OPTIONS = [ 'h1', 'h2', @@ -95,16 +87,16 @@ export const KitchenSink: StoryObj = { ); return ( - - +
+
Text style: {OPTIONS.map(option => (
- + ); }, }; @@ -112,7 +104,7 @@ export const KitchenSink: StoryObj = { export const UsageExample: StoryObj = { render: function Render() { return ( - <> +
h1. Typography h2. This is a section @@ -153,7 +145,7 @@ export const UsageExample: StoryObj = { academy award day-for-night christopher nolan undercranking. Unreal engine visionary match cut grain vs. noise 35mm anti-hero production design. - +
); }, }; diff --git a/packages/ui/src/Text/index.tsx b/packages/ui/src/Text/index.tsx index dd9fc8db40..b8b08fdc94 100644 --- a/packages/ui/src/Text/index.tsx +++ b/packages/ui/src/Text/index.tsx @@ -1,4 +1,5 @@ -import { styled, css, DefaultTheme, WebTarget } from 'styled-components'; +import cn from 'clsx'; + import { body, detail, @@ -11,232 +12,13 @@ import { detailTechnical, strong, technical, - truncate, xxl, + p, + getTextBase, } from '../utils/typography'; -import { ReactNode } from 'react'; - -interface StyledProps { - $truncate?: boolean; - $color?: (color: DefaultTheme['color']) => string; - $align?: 'left' | 'center' | 'right'; - $decoration?: 'line-through' | 'underline'; - $transform?: 'uppercase' | 'lowercase' | 'capitalize'; - $break: false | 'word' | undefined; -} - -const textCss = css` - ${props => props.$truncate && truncate} - ${props => props.$align && `text-align: ${props.$align};`} - ${props => props.$decoration && `text-decoration: ${props.$decoration};`} - ${props => props.$transform && `text-transform: ${props.$transform};`} - ${props => props.$break === false && `white-space: nowrap;`} - ${props => props.$break === 'word' && `word-break: break-word;`} -`; - -const H1 = styled.h1` - ${h1} - ${textCss} -`; - -const H2 = styled.h2` - ${h2} - ${textCss} -`; - -const H3 = styled.h3` - ${h3} - ${textCss} -`; - -const H4 = styled.h4` - ${h4} - ${textCss} -`; - -const Xxl = styled.span` - ${xxl} - ${textCss} -`; - -const Large = styled.span` - ${large} - ${textCss} -`; - -const Body = styled.span` - ${body} - ${textCss} -`; - -const Strong = styled.span` - ${strong} - ${textCss} -`; - -const Detail = styled.span` - ${detail} - ${textCss} -`; - -const Small = styled.span` - ${small} - ${textCss} -`; - -const DetailTechnical = styled.span` - ${detailTechnical} - ${textCss} -`; - -const Technical = styled.span` - ${technical} - ${textCss} -`; - -const P = styled.p` - ${body} - ${textCss} - - margin-bottom: ${props => props.theme.lineHeight.textBase}; - - &:last-child { - margin-bottom: 0; - } -`; - -/** - * Utility interface to be used below to ensure that only one text type is used - * at a time. - */ -interface NeverTextTypes { - h1?: never; - h2?: never; - h3?: never; - h4?: never; - xxl?: never; - large?: never; - p?: never; - strong?: never; - detail?: never; - small?: never; - detailTechnical?: never; - technical?: never; - body?: never; -} - -type TextType = - | (Omit & { - /** - * Renders a styled `

`. Pass the `as` prop to use a different HTML - * element with the same styling. - */ - h1: true; - }) - | (Omit & { - /** - * Renders a styled `

`. Pass the `as` prop to use a different HTML - * element with the same styling. - */ - h2: true; - }) - | (Omit & { - /** - * Renders a styled `

`. Pass the `as` prop to use a different HTML - * element with the same styling. - */ - h3: true; - }) - | (Omit & { - /** - * Renders a styled `

`. Pass the `as` prop to use a different HTML - * element with the same styling. - */ - h4: true; - }) - | (Omit & { - /** - * Renders bigger text used for section titles. Renders a `` by - * default; pass the `as` prop to use a different HTML element with the - * same styling. - */ - xxl: true; - }) - | (Omit & { - /** - * Renders big text used for section titles. Renders a `` by - * default; pass the `as` prop to use a different HTML element with the - * same styling. - */ - large: true; - }) - | (Omit & { - /** - * Renders a styled `

` tag with a bottom-margin (unless it's the last - * child). Aside from the margin, `

` is identical to ``. - * - * Note that this is the only component in the entire Penumbra UI library - * that renders an external margin. It's a convenience for developers who - * don't want to wrap each `` in a `

` with the - * appropriate margin, or a flex columnn with a gap. - */ - p: true; - }) - | (Omit & { - /** - * Emphasized body text. - * - * Renders a `` by default; pass the `as` prop to use a different - * HTML element with the same styling. - */ - strong: true; - }) - | (Omit & { - /** - * Detail text used for small bits of tertiary information. - * - * Renders a `` by default; pass the `as` prop to use a different - * HTML element with the same styling. - */ - detail: true; - }) - | (Omit & { - /** - * Small text used for secondary information. - * - * Renders a `` by default; pass the `as` prop to use a different - * HTML element with the same styling. - */ - small: true; - }) - | (Omit & { - /** - * Small monospaced text used for code, values, and other technical - * information. - * - * Renders a `` by default; pass the `as` prop to use a different - * HTML element with the same styling. - */ - detailTechnical: true; - }) - | (Omit & { - /** - * Monospaced text used for code, values, and other technical information. - * - * Renders a `` by default; pass the `as` prop to use a different - * HTML element with the same styling. - */ - technical: true; - }) - | (Omit & { - /** - * Body text used throughout most of our UIs. - * - * Renders a `` by default; pass the `as` prop to use a different - * HTML element with the same styling. - */ - body?: true; - }); +import { ElementType, ReactNode } from 'react'; +import { ThemeColor } from '../utils/color'; +import { TextType } from './types'; export type TextProps = TextType & { children?: ReactNode; @@ -248,17 +30,14 @@ export type TextProps = TextType & { * This is a span with H1 styling * ``` */ - as?: WebTarget; + as?: ElementType; /** * When `true`, will apply styles that 1) prevent text wrapping, 2) hide * overflow, 3) add an ellpsis when the text overflows. */ truncate?: boolean; - /** - * A function that takes the 'color' object of `theme`, and returns a CSS color to render - * the icon with. If left undefined, will default to the `text.primary` color. - */ - color?: (color: DefaultTheme['color']) => string; + /** A string representing the color key from the Tailwind theme (e.g. 'primary.light') */ + color?: ThemeColor; /** * The text alignment */ @@ -274,20 +53,70 @@ export type TextProps = TextType & { /** * Controls how the text breaks. */ - break?: false | 'word' | undefined; + break?: 'words' | 'all' | 'keep'; + /** + * Controls how whitespace is handled. + */ + whitespace?: 'nowrap' | 'pre' | 'pre-line' | 'pre-wrap' | 'break-spaces'; }; -/** - * Runtime equivalent of TypeScript's `Omit` type. Removes extraneous props that - * shouldn't be passed to the DOM. - */ -const omit = >( - object: ObjectType, - key: keyof ObjectType, -) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars -- we're discarding the unused key - const { [key]: _, ...rest } = object; - return rest; +const ALIGN_MAP: Record['align'], string> = { + center: cn('text-center'), + left: cn('text-left'), + right: cn('text-right'), +}; + +const DECORATION_MAP: Record['decoration'], string> = { + 'line-through': cn('line-through'), + underline: cn('underline'), +}; + +const TRANSFORM_MAP: Record['transform'], string> = { + uppercase: cn('uppercase'), + lowercase: cn('lowercase'), + capitalize: cn('capitalize'), +}; + +const BREAK_MAP: Record['break'], string> = { + all: cn('break-all'), + words: cn('break-words'), + keep: cn('break-keep'), +}; + +const WHITESPACE_MAP: Record['whitespace'], string> = { + nowrap: cn('whitespace-nowrap'), + pre: cn('whitespace-pre'), + 'pre-line': cn('whitespace-pre-line'), + 'pre-wrap': cn('whitespace-pre-wrap'), + 'break-spaces': cn('whitespace-break-spaces'), +}; + +// Composes all props to the Tailwind class list +const getTextOptionClasses = ({ + color, + truncate, + align, + decoration, + transform, + break: breakProp, + whitespace, +}: TextProps): string => { + const truncateClass = truncate ? cn('truncate') : ''; + const alignClass = align && ALIGN_MAP[align]; + const decorationClass = decoration && DECORATION_MAP[decoration]; + const transformClass = transform && TRANSFORM_MAP[transform]; + const breakClass = breakProp && BREAK_MAP[breakProp]; + const whitespaceClass = whitespace && WHITESPACE_MAP[whitespace]; + + return cn( + getTextBase(color), + truncateClass, + alignClass, + decorationClass, + transformClass, + breakClass, + whitespaceClass, + ); }; /** @@ -318,60 +147,53 @@ const omit = >( * * ``` */ -export const Text = ({ - truncate, - color, - align, - decoration, - transform, - break: breakProp, - ...props -}: TextProps) => { - const styledProps = { - $truncate: truncate, - $color: color, - $align: align, - $decoration: decoration, - $transform: transform, - $break: breakProp, - }; +export const Text = (props: TextProps) => { + const classes = getTextOptionClasses(props); + const SpanElement = props.as ?? 'span'; if (props.h1) { - return

; + const Element = props.as ?? 'h1'; + return {props.children}; } if (props.h2) { - return

; + const Element = props.as ?? 'h2'; + return {props.children}; } if (props.h3) { - return

; + const Element = props.as ?? 'h3'; + return {props.children}; } if (props.h4) { - return

; + const Element = props.as ?? 'h4'; + return {props.children}; } + if (props.xxl) { - return ; + return {props.children}; } if (props.large) { - return ; + return {props.children}; } if (props.strong) { - return ; + return {props.children}; } if (props.detail) { - return ; + return {props.children}; } if (props.small) { - return ; + return {props.children}; } if (props.detailTechnical) { - return ; + return {props.children}; } if (props.technical) { - return ; + return {props.children}; } + if (props.p) { - return

; + const Element = props.as ?? 'p'; + return {props.children}; } - return ; + return {props.children}; }; diff --git a/packages/ui-tailwind/src/Text/types.ts b/packages/ui/src/Text/types.ts similarity index 100% rename from packages/ui-tailwind/src/Text/types.ts rename to packages/ui/src/Text/types.ts diff --git a/packages/ui/src/TextInput/index.stories.tsx b/packages/ui/src/TextInput/index.stories.tsx index 0f01542573..c3812d2312 100644 --- a/packages/ui/src/TextInput/index.stories.tsx +++ b/packages/ui/src/TextInput/index.stories.tsx @@ -15,9 +15,7 @@ const SampleButton = () => ( ); -const addressBookIcon = ( - color.text.primary} /> -); +const addressBookIcon = ; const meta: Meta = { component: TextInput, diff --git a/packages/ui/src/TextInput/index.tsx b/packages/ui/src/TextInput/index.tsx index 32b82da61d..10410210e8 100644 --- a/packages/ui/src/TextInput/index.tsx +++ b/packages/ui/src/TextInput/index.tsx @@ -1,82 +1,8 @@ -import { styled } from 'styled-components'; -import { small } from '../utils/typography'; -import { ActionType, getOutlineColorByActionType } from '../utils/ActionType'; -import { useDisabled } from '../hooks/useDisabled'; import { forwardRef, ReactNode } from 'react'; - -const Wrapper = styled.div<{ - $hasStartAdornment: boolean; - $hasEndAdornment: boolean; - $actionType: ActionType; -}>` - background-color: ${props => props.theme.color.other.tonalFill5}; - display: flex; - align-items: center; - gap: ${props => props.theme.spacing(2)}; - transition: - outline 0.15s, - background-color 0.15s; - - ${props => props.$hasStartAdornment && `padding-left: ${props.theme.spacing(3)};`} - ${props => props.$hasEndAdornment && `padding-right: ${props.theme.spacing(3)};`} - - &:focus-within { - outline: 2px solid ${props => getOutlineColorByActionType(props.theme, props.$actionType)}; - } - - &:hover { - background-color: ${props => props.theme.color.action.hoverOverlay}; - } -`; - -const StyledInput = styled.input<{ - $actionType: ActionType; - $hasStartAdornment: boolean; - $hasEndAdornment: boolean; -}>` - appearance: none; - border: none; - color: ${props => - props.disabled ? props.theme.color.text.muted : props.theme.color.text.primary}; - background-color: ${props => props.theme.color.base.transparent}; - - padding-left: ${props => (props.$hasStartAdornment ? '0' : props.theme.spacing(3))}; - padding-right: ${props => (props.$hasEndAdornment ? '0' : props.theme.spacing(3))}; - padding-top: ${props => props.theme.spacing(2)}; - padding-bottom: ${props => props.theme.spacing(2)}; - transition: border-color 0.15s; - - box-sizing: border-box; - flex-grow: 1; - - ${small} - - &::placeholder { - color: ${props => props.theme.color.text.secondary}; - } - - &:disabled { - cursor: not-allowed; - } - - &:disabled::placeholder { - color: ${props => props.theme.color.text.muted}; - } - - &:focus { - outline: none; - } - - &::-webkit-outer-spin-button, - &::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; - } - - &[type='number'] { - -moz-appearance: textfield; - } -`; +import { small } from '../utils/typography'; +import { ActionType, getFocusWithinOutlineColorByActionType } from '../utils/action-type'; +import { useDisabled } from '../utils/disabled-context'; +import cn from 'clsx'; export interface TextInputProps { value?: string; @@ -122,14 +48,20 @@ export const TextInput = forwardRef( }: TextInputProps, ref, ) => ( - {startAdornment} - onChange?.(e.target.value)} placeholder={placeholder} @@ -138,12 +70,21 @@ export const TextInput = forwardRef( max={max} min={min} ref={ref} - $actionType={actionType} - $hasStartAdornment={!!startAdornment} - $hasEndAdornment={!!endAdornment} + className={cn( + 'box-border grow appearance-none border-none bg-base-transparent py-2', + startAdornment ? 'pl-0' : 'pl-3', + endAdornment ? 'pr-0' : 'pr-3', + disabled ? 'text-text-muted' : 'text-text-primary', + small, + 'placeholder:text-text-secondary', + 'disabled:cursor-not-allowed', + 'disabled:placeholder:text-text-muted', + 'focus:outline-0', + '[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none', + )} /> {endAdornment} - +

), ); diff --git a/packages/ui/src/Toast/index.stories.tsx b/packages/ui/src/Toast/index.stories.tsx index a60a7788d0..8ac45aeb72 100644 --- a/packages/ui/src/Toast/index.stories.tsx +++ b/packages/ui/src/Toast/index.stories.tsx @@ -2,9 +2,8 @@ import type { Meta, StoryObj } from '@storybook/react'; import { openToast, ToastProvider, ToastType } from '.'; import { Button } from '../Button'; -import { Tooltip } from '../Tooltip'; +import { Tooltip, TooltipProvider } from '../Tooltip'; import { Text } from '../Text'; -import { styled } from 'styled-components'; const meta: Meta = { component: ToastProvider, @@ -15,12 +14,6 @@ export default meta; type Story = StoryObj; -const Row = styled.div` - display: flex; - flex-direction: row; - gap: ${props => props.theme.spacing(2)}; -`; - export const Basic: Story = { render: function Render() { const toast = (type: ToastType) => { @@ -66,35 +59,37 @@ export const Basic: Story = { }; return ( - <> - + +
+ - All style types of toasts + All style types of toasts - - - - - - - - - +
+ + + + + + + +
- Updating toast + Updating toast - - - - - +
+ + + +
- Action toast + Action toast - - - - +
+ +
+
+
); }, }; diff --git a/packages/ui/src/Toast/open.ts b/packages/ui/src/Toast/open.ts index 2de1cd6a27..e36adb1806 100644 --- a/packages/ui/src/Toast/open.ts +++ b/packages/ui/src/Toast/open.ts @@ -16,7 +16,7 @@ const toastFnMap: Record = { export interface ToastProps { type: ToastType; message: string; - description?: ReactNode; + description?: string; persistent?: boolean; dismissible?: boolean; action?: ExternalToast['action']; diff --git a/packages/ui/src/Tooltip/index.stories.tsx b/packages/ui/src/Tooltip/index.stories.tsx index b51ee87658..937b2d1e52 100644 --- a/packages/ui/src/Tooltip/index.stories.tsx +++ b/packages/ui/src/Tooltip/index.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { Tooltip } from '.'; +import { Tooltip, TooltipProvider } from './index'; +import { Text } from '../Text'; const meta: Meta = { component: Tooltip, @@ -14,10 +15,15 @@ export default meta; type Story = StoryObj; export const Basic: Story = { + render: args => ( + + + + ), args: { title: 'This is a heading', message: 'This is description information. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut et massa mi.', - children: 'Hover over this text.', + children: Hover over this text., }, }; diff --git a/packages/ui/src/Tooltip/index.tsx b/packages/ui/src/Tooltip/index.tsx index b356c1c814..d22d7dfd1b 100644 --- a/packages/ui/src/Tooltip/index.tsx +++ b/packages/ui/src/Tooltip/index.tsx @@ -1,93 +1,5 @@ -import * as RadixTooltip from '@radix-ui/react-tooltip'; -import { ReactNode } from 'react'; -import { styled } from 'styled-components'; -import { Text } from '../Text'; -import { buttonBase } from '../utils/button'; -import { small } from '../utils/typography'; -import { scaleIn } from '../utils/popover.ts'; +export { TooltipProvider } from '@radix-ui/react-tooltip'; +export type { TooltipProviderProps } from '@radix-ui/react-tooltip'; -const Content = styled(RadixTooltip.Content).attrs(props => ({ - sideOffset: props.theme.spacing(1, 'number'), -}))` - width: 200px; - padding: ${props => props.theme.spacing(2)}; - - background-color: ${props => props.theme.color.other.dialogBackground}; - border: 1px solid ${props => props.theme.color.other.tonalStroke}; - border-radius: ${props => props.theme.borderRadius.sm}; - backdrop-filter: blur(${props => props.theme.blur.xl}); - - color: ${props => props.theme.color.text.primary}; - - transform-origin: var(--radix-tooltip-content-transform-origin); - animation: ${scaleIn} 0.15s ease-out; -`; - -const Title = styled.div` - ${small} - - margin-bottom: ${props => props.theme.spacing(2)} -`; - -const Trigger = styled(RadixTooltip.Trigger)` - ${buttonBase} -`; - -export interface TooltipProps { - /** An optional title to show in larger text above the message. */ - title?: string; - /** - * A string message to show in the tooltip. Note that only strings are - * allowed; for interactive content, use a `` or a ``. - */ - message: string; - /** - * The trigger for the tooltip. - * - * Note that the trigger will be wrapped in an HTML button element, so only pass content that can be validly nested inside a button (i.e., don't pass another button). - */ - children: ReactNode; -} - -/** - * Use this for small informational text that should appear adjacent to a piece - * of content. - * - * ```tsx - * - * Hover me - * - * ``` - * - * ## Differences between ``, ``, and ``. - * - * These three components provide similar functionality, but are meant to be - * used in distinct ways. - * - * - ``: Use dialogs for interactive or informational content that - * should take the user's attention above everything else on the page. Dialogs - * are typically opened in response to a click from a user, but may also be - * opened and closed programmatically. - * - ``: Use popovers for interactive or informational content that - * should be visually tied to a specific element on the page, such as the - * dropdown menu underneath the menu button. Popovers are typically opened in - * response to a click from a user, but may also be opened and closed - * programmatically. - * - ``: Use tooltips for plain-text informational content that - * should be visually tied to a specific element on the page. Tooltips are - * opened in response to the user hovering over that element. - */ -export const Tooltip = ({ title, message, children }: TooltipProps) => ( - - - {children} - - - - {title && {title}} - - {message} - - - -); +export { Tooltip } from './tooltip'; +export type { TooltipProps } from './tooltip'; diff --git a/packages/ui-tailwind/src/Tooltip/tooltip.tsx b/packages/ui/src/Tooltip/tooltip.tsx similarity index 100% rename from packages/ui-tailwind/src/Tooltip/tooltip.tsx rename to packages/ui/src/Tooltip/tooltip.tsx diff --git a/packages/ui/src/ValueViewComponent/index.stories.tsx b/packages/ui/src/ValueView/index.stories.tsx similarity index 100% rename from packages/ui/src/ValueViewComponent/index.stories.tsx rename to packages/ui/src/ValueView/index.stories.tsx diff --git a/packages/ui-tailwind/src/ValueView/index.tsx b/packages/ui/src/ValueView/index.tsx similarity index 100% rename from packages/ui-tailwind/src/ValueView/index.tsx rename to packages/ui/src/ValueView/index.tsx diff --git a/packages/ui/src/WalletBalance/index.tsx b/packages/ui/src/WalletBalance/index.tsx index c76cb8c026..50bb0cc80e 100644 --- a/packages/ui/src/WalletBalance/index.tsx +++ b/packages/ui/src/WalletBalance/index.tsx @@ -1,6 +1,6 @@ import type { MouseEventHandler } from 'react'; -import { styled, type DefaultTheme } from 'styled-components'; import { Wallet } from 'lucide-react'; +import cn from 'clsx'; import type { BalancesResponse } from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb'; import { getFormattedAmtFromValueView } from '@penumbra-zone/types/value-view'; import { @@ -8,78 +8,19 @@ import { getBalanceView, getMetadataFromBalancesResponse, } from '@penumbra-zone/getters/balances-response'; +import { ActionType, getOutlineColorByActionType } from '../utils/action-type'; import { Text } from '../Text'; -import { ActionType, getOutlineColorByActionType } from '../utils/ActionType.ts'; -import { asTransientProps } from '../utils/asTransientProps.ts'; -interface StyledProps { - $actionType: ActionType; - $disabled?: boolean; -} - -const getColorByActionType = ( - theme: DefaultTheme, - actionType: ActionType, - disabled?: boolean, -): string => { +const getColorByActionType = (actionType: ActionType, disabled?: boolean): string => { if (disabled) { - return theme.color.text.muted; + return cn('text-text-muted'); } if (actionType === 'destructive') { - return theme.color.destructive.light; + return cn('text-destructive-light'); } - return theme.color.text.secondary; + return cn('text-text-secondary'); }; -const Wrapper = styled.div` - display: flex; - align-items: center; - gap: ${props => props.theme.spacing(1)}; - color: ${props => getColorByActionType(props.theme, props.$actionType, props.$disabled)}; - transition: color 0.15s; -`; - -const AccountWrapper = styled.button` - display: flex; - align-items: center; - gap: ${props => props.theme.spacing(1)}; - padding: ${props => props.theme.spacing(1)} ${props => props.theme.spacing(2)}; - - color: inherit; - border: none; - border-radius: ${props => props.theme.borderRadius.full}; - background-color: ${props => props.theme.color.other.tonalFill5}; - transition: - color 0.15s, - background 0.15s, - outline 0.15s; - - &:hover { - background-color: ${props => props.theme.color.action.hoverOverlay}; - } - - &:focus { - color: ${props => props.theme.color.text.secondary}; - background-color: ${props => props.theme.color.other.tonalFill5}; - outline: 2px solid ${props => getOutlineColorByActionType(props.theme, props.$actionType)}; - } - - &:focus + span { - color: ${props => props.theme.color.text.secondary}; - } -`; - -const ValueText = styled(Text)` - color: inherit; - transition: color 0.15s; -`; - -const WalletIcon = styled(Wallet)` - width: ${props => props.theme.spacing(4)}; - height: ${props => props.theme.spacing(4)}; - transition: color 0.15s; -`; - export interface WalletBalanceProps { balance?: BalancesResponse; actionType?: ActionType; @@ -108,20 +49,35 @@ export const WalletBalance = ({ } return ( - - + - + {getFormattedAmtFromValueView(valueView, true)} {metadata.symbol || 'Unknown'} - - + +

); }; diff --git a/packages/ui-tailwind/src/theme/fonts.css b/packages/ui/src/theme/fonts.css similarity index 100% rename from packages/ui-tailwind/src/theme/fonts.css rename to packages/ui/src/theme/fonts.css diff --git a/packages/ui/src/PenumbraUIProvider/fonts/IosevkaTerm-Regular.woff2 b/packages/ui/src/theme/fonts/IosevkaTerm-Regular.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/IosevkaTerm-Regular.woff2 rename to packages/ui/src/theme/fonts/IosevkaTerm-Regular.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/Poppins-Italic-LatinExt.woff2 b/packages/ui/src/theme/fonts/Poppins-Italic-LatinExt.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/Poppins-Italic-LatinExt.woff2 rename to packages/ui/src/theme/fonts/Poppins-Italic-LatinExt.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/Poppins-Italic.woff2 b/packages/ui/src/theme/fonts/Poppins-Italic.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/Poppins-Italic.woff2 rename to packages/ui/src/theme/fonts/Poppins-Italic.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/Poppins-Medium-LatinExt.woff2 b/packages/ui/src/theme/fonts/Poppins-Medium-LatinExt.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/Poppins-Medium-LatinExt.woff2 rename to packages/ui/src/theme/fonts/Poppins-Medium-LatinExt.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/Poppins-Medium.woff2 b/packages/ui/src/theme/fonts/Poppins-Medium.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/Poppins-Medium.woff2 rename to packages/ui/src/theme/fonts/Poppins-Medium.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/Poppins-MediumItalic-LatinExt.woff2 b/packages/ui/src/theme/fonts/Poppins-MediumItalic-LatinExt.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/Poppins-MediumItalic-LatinExt.woff2 rename to packages/ui/src/theme/fonts/Poppins-MediumItalic-LatinExt.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/Poppins-MediumItalic.woff2 b/packages/ui/src/theme/fonts/Poppins-MediumItalic.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/Poppins-MediumItalic.woff2 rename to packages/ui/src/theme/fonts/Poppins-MediumItalic.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/Poppins-Regular-LatinExt.woff2 b/packages/ui/src/theme/fonts/Poppins-Regular-LatinExt.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/Poppins-Regular-LatinExt.woff2 rename to packages/ui/src/theme/fonts/Poppins-Regular-LatinExt.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/Poppins-Regular.woff2 b/packages/ui/src/theme/fonts/Poppins-Regular.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/Poppins-Regular.woff2 rename to packages/ui/src/theme/fonts/Poppins-Regular.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/WorkSans-Medium-LatinExt.woff2 b/packages/ui/src/theme/fonts/WorkSans-Medium-LatinExt.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/WorkSans-Medium-LatinExt.woff2 rename to packages/ui/src/theme/fonts/WorkSans-Medium-LatinExt.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/WorkSans-Medium-Vietnamese.woff2 b/packages/ui/src/theme/fonts/WorkSans-Medium-Vietnamese.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/WorkSans-Medium-Vietnamese.woff2 rename to packages/ui/src/theme/fonts/WorkSans-Medium-Vietnamese.woff2 diff --git a/packages/ui/src/PenumbraUIProvider/fonts/WorkSans-Medium.woff2 b/packages/ui/src/theme/fonts/WorkSans-Medium.woff2 similarity index 100% rename from packages/ui/src/PenumbraUIProvider/fonts/WorkSans-Medium.woff2 rename to packages/ui/src/theme/fonts/WorkSans-Medium.woff2 diff --git a/packages/ui-tailwind/src/theme/globals.css b/packages/ui/src/theme/globals.css similarity index 100% rename from packages/ui-tailwind/src/theme/globals.css rename to packages/ui/src/theme/globals.css diff --git a/packages/ui-tailwind/src/theme/index.tsx b/packages/ui/src/theme/index.tsx similarity index 100% rename from packages/ui-tailwind/src/theme/index.tsx rename to packages/ui/src/theme/index.tsx diff --git a/packages/ui-tailwind/src/theme/tailwind-config.ts b/packages/ui/src/theme/tailwind-config.ts similarity index 90% rename from packages/ui-tailwind/src/theme/tailwind-config.ts rename to packages/ui/src/theme/tailwind-config.ts index 6028b96233..bf2e3f727c 100644 --- a/packages/ui-tailwind/src/theme/tailwind-config.ts +++ b/packages/ui/src/theme/tailwind-config.ts @@ -6,10 +6,7 @@ import { theme } from './theme'; * the Penumbra UI theme values. */ export const tailwindConfig = { - content: [ - './node_modules/@penumbra-zone/ui-tailwind/**/*.{js,ts,jsx,tsx,mdx,css}', - './node_modules/@penumbra-zone/ui/**/*.{js,ts,jsx,tsx,mdx,css}', - ], + content: ['./node_modules/@penumbra-zone/ui/**/*.{js,ts,jsx,tsx,mdx,css}'], theme: { extend: { borderRadius: theme.borderRadius, diff --git a/packages/ui-tailwind/src/theme/theme.ts b/packages/ui/src/theme/theme.ts similarity index 100% rename from packages/ui-tailwind/src/theme/theme.ts rename to packages/ui/src/theme/theme.ts diff --git a/packages/ui-tailwind/src/utils/action-type.ts b/packages/ui/src/utils/action-type.ts similarity index 100% rename from packages/ui-tailwind/src/utils/action-type.ts rename to packages/ui/src/utils/action-type.ts diff --git a/packages/ui/src/utils/button.ts b/packages/ui/src/utils/button.ts index 9ba3bbf9d4..3ea2ff425d 100644 --- a/packages/ui/src/utils/button.ts +++ b/packages/ui/src/utils/button.ts @@ -1,99 +1,76 @@ -import { css, DefaultTheme } from 'styled-components'; +import cn from 'clsx'; +import type { Density } from './density'; +import { + getAfterOutlineColorByActionType, + getBeforeOutlineColorByActionType, + ActionType, + getBackgroundColorByActionType, +} from './action-type'; export type Priority = 'primary' | 'secondary'; -/** Shared styles to use for any `