diff --git a/bun.lock b/bun.lock
index 92b608335..ecd7a16e0 100644
--- a/bun.lock
+++ b/bun.lock
@@ -21,16 +21,16 @@
"@opentelemetry/semantic-conventions": "^1.36.0",
"@radix-ui/react-avatar": "^1.1.4",
"@radix-ui/react-checkbox": "^1.3.3",
- "@radix-ui/react-dialog": "^1.1.7",
+ "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.7",
"@radix-ui/react-label": "^2.1.3",
- "@radix-ui/react-popover": "^1.1.7",
+ "@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-radio-group": "^1.3.8",
"@radix-ui/react-scroll-area": "^1.2.4",
"@radix-ui/react-select": "^2.1.7",
"@radix-ui/react-separator": "^1.1.3",
"@radix-ui/react-slider": "^1.2.4",
- "@radix-ui/react-slot": "^1.2.3",
+ "@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.12",
"@radix-ui/react-toast": "^1.2.7",
"@radix-ui/react-tooltip": "^1.2.0",
@@ -76,9 +76,8 @@
"file-type": "^21.3.0",
"geist": "^1.3.1",
"immer": "^10.1.1",
- "lucide-react": "^0.525.0",
"micromatch": "^4.0.8",
- "motion": "^12.18.1",
+ "motion": "^12.23.25",
"nanoid": "^5.0.9",
"next": "16.1.5",
"next-safe-action": "^8.0.11",
@@ -153,6 +152,8 @@
},
},
"overrides": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "@nodelib/fs.stat": "2.0.5",
"@shikijs/core": "2.3.2",
"@shikijs/themes": "2.3.2",
"shiki": "2.3.2",
@@ -1621,7 +1622,7 @@
"fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="],
- "framer-motion": ["framer-motion@12.23.24", "", { "dependencies": { "motion-dom": "^12.23.23", "motion-utils": "^12.23.6", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w=="],
+ "framer-motion": ["framer-motion@12.23.25", "", { "dependencies": { "motion-dom": "^12.23.23", "motion-utils": "^12.23.6", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-gUHGl2e4VG66jOcH0JHhuJQr6ZNwrET9g31ZG0xdXzT0CznP7fHX4P8Bcvuc4MiUB90ysNnWX2ukHRIggkl6hQ=="],
"fs-extra": ["fs-extra@4.0.3", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg=="],
@@ -1871,8 +1872,6 @@
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
- "lucide-react": ["lucide-react@0.525.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Tm1txJ2OkymCGkvwoHt33Y2JpN5xucVq1slHcgE6Lk0WjDfjgKWor5CdVER8U6DvcfMwh4M8XxmpTiyzfmfDYQ=="],
-
"lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="],
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
@@ -1973,7 +1972,7 @@
"module-details-from-path": ["module-details-from-path@1.0.4", "", {}, "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w=="],
- "motion": ["motion@12.23.24", "", { "dependencies": { "framer-motion": "^12.23.24", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-Rc5E7oe2YZ72N//S3QXGzbnXgqNrTESv8KKxABR20q2FLch9gHLo0JLyYo2hZ238bZ9Gx6cWhj9VO0IgwbMjCw=="],
+ "motion": ["motion@12.23.25", "", { "dependencies": { "framer-motion": "^12.23.25", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-Fk5Y1kcgxYiTYOUjmwfXQAP7tP+iGqw/on1UID9WEL/6KpzxPr9jY2169OsjgZvXJdpraKXy0orkjaCVIl5fgQ=="],
"motion-dom": ["motion-dom@12.23.23", "", { "dependencies": { "motion-utils": "^12.23.6" } }, "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA=="],
diff --git a/package.json b/package.json
index e24fa2a43..1694cd31e 100644
--- a/package.json
+++ b/package.json
@@ -62,16 +62,16 @@
"@opentelemetry/semantic-conventions": "^1.36.0",
"@radix-ui/react-avatar": "^1.1.4",
"@radix-ui/react-checkbox": "^1.3.3",
- "@radix-ui/react-dialog": "^1.1.7",
+ "@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.7",
"@radix-ui/react-label": "^2.1.3",
- "@radix-ui/react-popover": "^1.1.7",
+ "@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-radio-group": "^1.3.8",
"@radix-ui/react-scroll-area": "^1.2.4",
"@radix-ui/react-select": "^2.1.7",
"@radix-ui/react-separator": "^1.1.3",
"@radix-ui/react-slider": "^1.2.4",
- "@radix-ui/react-slot": "^1.2.3",
+ "@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.12",
"@radix-ui/react-toast": "^1.2.7",
"@radix-ui/react-tooltip": "^1.2.0",
@@ -117,9 +117,8 @@
"file-type": "^21.3.0",
"geist": "^1.3.1",
"immer": "^10.1.1",
- "lucide-react": "^0.525.0",
"micromatch": "^4.0.8",
- "motion": "^12.18.1",
+ "motion": "^12.23.25",
"nanoid": "^5.0.9",
"next": "16.1.5",
"next-safe-action": "^8.0.11",
diff --git a/src/app/(auth)/auth/cli/page.tsx b/src/app/(auth)/auth/cli/page.tsx
index 221daca26..b6ad3aafd 100644
--- a/src/app/(auth)/auth/cli/page.tsx
+++ b/src/app/(auth)/auth/cli/page.tsx
@@ -1,4 +1,3 @@
-import { CloudIcon, LaptopIcon, Link2Icon } from 'lucide-react'
import { redirect } from 'next/navigation'
import { Suspense } from 'react'
import { AUTH_URLS, PROTECTED_URLS } from '@/configs/urls'
@@ -8,6 +7,7 @@ import { createClient } from '@/core/shared/clients/supabase/server'
import { encodedRedirect } from '@/lib/utils/auth'
import { generateE2BUserAccessToken } from '@/lib/utils/server'
import { Alert, AlertDescription, AlertTitle } from '@/ui/primitives/alert'
+import { CloudIcon, LinkIcon, SystemIcon } from '@/ui/primitives/icons'
// Types
type CLISearchParams = Promise<{
@@ -59,13 +59,13 @@ function CLIIcons() {
return (
-
+
-
+
-
+
)
diff --git a/src/app/(auth)/confirm/page.tsx b/src/app/(auth)/confirm/page.tsx
index 07cd39f90..6bdb0c085 100644
--- a/src/app/(auth)/confirm/page.tsx
+++ b/src/app/(auth)/confirm/page.tsx
@@ -115,7 +115,9 @@ export default function ConfirmPage() {
diff --git a/src/app/(auth)/forgot-password/page.tsx b/src/app/(auth)/forgot-password/page.tsx
index 3aa518ee9..8c8e1d4ac 100644
--- a/src/app/(auth)/forgot-password/page.tsx
+++ b/src/app/(auth)/forgot-password/page.tsx
@@ -103,7 +103,7 @@ export default function ForgotPassword() {
placeholder="you@example.com"
required
/>
-
+
Reset Password
diff --git a/src/app/(auth)/sign-in/page.tsx b/src/app/(auth)/sign-in/page.tsx
index 7bc10651f..7faa4bf36 100644
--- a/src/app/(auth)/sign-in/page.tsx
+++ b/src/app/(auth)/sign-in/page.tsx
@@ -149,7 +149,10 @@ export default function Login() {
-
+
Sign in
diff --git a/src/app/(auth)/sign-up/page.tsx b/src/app/(auth)/sign-up/page.tsx
index e1022c484..3604c688a 100644
--- a/src/app/(auth)/sign-up/page.tsx
+++ b/src/app/(auth)/sign-up/page.tsx
@@ -181,7 +181,7 @@ export default function SignUp() {
Sign up
diff --git a/src/app/dashboard/[teamSlug]/keys/page.tsx b/src/app/dashboard/[teamSlug]/keys/page.tsx
index 7acc106ef..b1409f0b7 100644
--- a/src/app/dashboard/[teamSlug]/keys/page.tsx
+++ b/src/app/dashboard/[teamSlug]/keys/page.tsx
@@ -1,4 +1,3 @@
-import { Plus } from 'lucide-react'
import CreateApiKeyDialog from '@/features/dashboard/settings/keys/create-api-key-dialog'
import ApiKeysTable from '@/features/dashboard/settings/keys/table'
import Frame from '@/ui/frame'
@@ -10,6 +9,7 @@ import {
CardHeader,
CardTitle,
} from '@/ui/primitives/card'
+import { AddIcon } from '@/ui/primitives/icons'
interface KeysPageClientProps {
params: Promise<{
@@ -38,7 +38,7 @@ export default async function KeysPage({ params }: KeysPageClientProps) {
- CREATE KEY
+ CREATE KEY
diff --git a/src/app/dashboard/[teamSlug]/webhooks/page.tsx b/src/app/dashboard/[teamSlug]/webhooks/page.tsx
index 11146c781..19bca5b4d 100644
--- a/src/app/dashboard/[teamSlug]/webhooks/page.tsx
+++ b/src/app/dashboard/[teamSlug]/webhooks/page.tsx
@@ -1,4 +1,3 @@
-import { Plus } from 'lucide-react'
import { notFound } from 'next/navigation'
import { INCLUDE_ARGUS } from '@/configs/flags'
import WebhookAddEditDialog from '@/features/dashboard/settings/webhooks/add-edit-dialog'
@@ -11,6 +10,7 @@ import {
CardDescription,
CardHeader,
} from '@/ui/primitives/card'
+import { AddIcon } from '@/ui/primitives/icons'
interface WebhooksPageClientProps {
params: Promise<{
@@ -43,7 +43,7 @@ export default async function WebhooksPage({
- Add Webhook
+ Add Webhook
diff --git a/src/app/dashboard/unauthorized.tsx b/src/app/dashboard/unauthorized.tsx
index 6a6a8fb8f..24d4c45a5 100644
--- a/src/app/dashboard/unauthorized.tsx
+++ b/src/app/dashboard/unauthorized.tsx
@@ -1,6 +1,5 @@
'use client'
-import { ArrowLeft, HomeIcon, ShieldX, UsersIcon } from 'lucide-react'
import Link from 'next/link'
import { PROTECTED_URLS } from '@/configs/urls'
import { AsciiBackgroundPattern } from '@/ui/patterns'
@@ -12,6 +11,12 @@ import {
CardFooter,
CardHeader,
} from '@/ui/primitives/card'
+import {
+ ArrowLeftIcon,
+ HomeIcon,
+ PersonsIcon,
+ ShieldXIcon,
+} from '@/ui/primitives/icons'
export default function Unauthorized() {
return (
@@ -20,7 +25,7 @@ export default function Unauthorized() {
-
+
403
Access denied.
@@ -31,27 +36,27 @@ export default function Unauthorized() {
team owner or administrator to request access.
-
-
-
-
-
+
+
+
+
+
Home
-
-
-
+
+
+
My Teams
window.history.back()}
- className="w-full gap-2"
+ className="w-full"
>
-
+
Go Back
diff --git a/src/configs/sidebar.ts b/src/configs/sidebar.ts
index 64f6102d6..7ca6f3ed0 100644
--- a/src/configs/sidebar.ts
+++ b/src/configs/sidebar.ts
@@ -1,16 +1,16 @@
+import { JSX } from 'react'
import {
- Activity,
- Box,
- Container,
- CreditCard,
- Key,
- type LucideProps,
- Settings,
- UserRoundCog,
- Users,
-} from 'lucide-react'
-import type { ForwardRefExoticComponent, JSX, RefAttributes } from 'react'
-import { GaugeIcon, WebhookIcon } from '@/ui/primitives/icons'
+ AccountSettingsIcon,
+ CardIcon,
+ GaugeIcon,
+ KeyIcon,
+ PersonsIcon,
+ SandboxIcon,
+ SettingsIcon,
+ TemplateIcon,
+ UsageIcon,
+ WebhookIcon,
+} from '@/ui/primitives/icons'
import { INCLUDE_ARGUS, INCLUDE_BILLING } from './flags'
import { PROTECTED_URLS } from './urls'
@@ -21,11 +21,8 @@ type SidebarNavArgs = {
export type SidebarNavItem = {
label: string
href: (args: SidebarNavArgs) => string
- icon:
- | ForwardRefExoticComponent<
- Omit & RefAttributes
- >
- | ((...args: any[]) => JSX.Element)
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ icon: (...args: any[]) => JSX.Element
group?: string
activeMatch?: string
}
@@ -35,13 +32,13 @@ export const SIDEBAR_MAIN_LINKS: SidebarNavItem[] = [
{
label: 'Sandboxes',
href: (args) => PROTECTED_URLS.SANDBOXES(args.teamSlug!),
- icon: Box,
+ icon: SandboxIcon,
activeMatch: `/dashboard/*/sandboxes/**`,
},
{
label: 'Templates',
href: (args) => PROTECTED_URLS.TEMPLATES(args.teamSlug!),
- icon: Container,
+ icon: TemplateIcon,
activeMatch: `/dashboard/*/templates/**`,
},
@@ -63,21 +60,21 @@ export const SIDEBAR_MAIN_LINKS: SidebarNavItem[] = [
{
label: 'General',
href: (args) => PROTECTED_URLS.GENERAL(args.teamSlug!),
- icon: Settings,
+ icon: SettingsIcon,
group: 'team',
activeMatch: `/dashboard/*/general`,
},
{
label: 'API Keys',
href: (args) => PROTECTED_URLS.KEYS(args.teamSlug!),
- icon: Key,
+ icon: KeyIcon,
group: 'team',
activeMatch: `/dashboard/*/keys`,
},
{
label: 'Members',
href: (args) => PROTECTED_URLS.MEMBERS(args.teamSlug!),
- icon: Users,
+ icon: PersonsIcon,
group: 'team',
activeMatch: `/dashboard/*/members`,
},
@@ -88,7 +85,7 @@ export const SIDEBAR_MAIN_LINKS: SidebarNavItem[] = [
{
label: 'Usage',
href: (args: SidebarNavArgs) => PROTECTED_URLS.USAGE(args.teamSlug!),
- icon: Activity,
+ icon: UsageIcon,
group: 'billing',
activeMatch: `/dashboard/*/usage/**`,
},
@@ -103,7 +100,7 @@ export const SIDEBAR_MAIN_LINKS: SidebarNavItem[] = [
label: 'Billing',
href: (args: SidebarNavArgs) =>
PROTECTED_URLS.BILLING(args.teamSlug!),
- icon: CreditCard,
+ icon: CardIcon,
group: 'billing',
activeMatch: `/dashboard/*/billing/**`,
},
@@ -115,7 +112,7 @@ export const SIDEBAR_EXTRA_LINKS: SidebarNavItem[] = [
{
label: 'Account Settings',
href: () => PROTECTED_URLS.ACCOUNT_SETTINGS,
- icon: UserRoundCog,
+ icon: AccountSettingsIcon,
},
]
diff --git a/src/features/auth/form-message.tsx b/src/features/auth/form-message.tsx
index 9d823936e..f79a6b4ac 100644
--- a/src/features/auth/form-message.tsx
+++ b/src/features/auth/form-message.tsx
@@ -1,9 +1,9 @@
'use client'
-import { AlertCircle, CheckCircle2, Info } from 'lucide-react'
import { motion } from 'motion/react'
import { cn } from '@/lib/utils'
import { Alert, AlertDescription } from '@/ui/primitives/alert'
+import { AlertIcon, InfoIcon, SuccessIcon } from '@/ui/primitives/icons'
// TODO: this type is used in more places than just authentication
// -> should probably be renamed / moved to a more appropriate location
@@ -29,7 +29,7 @@ export function AuthFormMessage({
>
{'success' in message && (
-
+
{decodeURIComponent(message.success!)}
@@ -37,7 +37,7 @@ export function AuthFormMessage({
)}
{'error' in message && (
-
+
{decodeURIComponent(message.error!)}
@@ -45,7 +45,7 @@ export function AuthFormMessage({
)}
{'message' in message && (
-
+
{decodeURIComponent(message.message!)}
diff --git a/src/features/auth/oauth-provider-buttons.tsx b/src/features/auth/oauth-provider-buttons.tsx
index a7fd7855d..4f6dc6f38 100644
--- a/src/features/auth/oauth-provider-buttons.tsx
+++ b/src/features/auth/oauth-provider-buttons.tsx
@@ -14,7 +14,7 @@ export function OAuthProviders() {
return (
execute({ provider: 'google', returnTo: returnTo || undefined })
}
@@ -43,7 +43,7 @@ export function OAuthProviders() {
execute({ provider: 'github', returnTo: returnTo || undefined })
}
diff --git a/src/features/dashboard/account/email-settings.tsx b/src/features/dashboard/account/email-settings.tsx
index af10e9441..95a31269c 100644
--- a/src/features/dashboard/account/email-settings.tsx
+++ b/src/features/dashboard/account/email-settings.tsx
@@ -159,7 +159,7 @@ export function EmailSettings({ className }: EmailSettingsProps) {
Has to be a valid e-mail address.
diff --git a/src/features/dashboard/account/name-settings.tsx b/src/features/dashboard/account/name-settings.tsx
index 95307e129..d2276e1c0 100644
--- a/src/features/dashboard/account/name-settings.tsx
+++ b/src/features/dashboard/account/name-settings.tsx
@@ -113,7 +113,7 @@ export function NameSettings({ className }: NameSettingsProps) {
Max 100 characters.
diff --git a/src/features/dashboard/account/password-settings.tsx b/src/features/dashboard/account/password-settings.tsx
index 8884ab479..563770d85 100644
--- a/src/features/dashboard/account/password-settings.tsx
+++ b/src/features/dashboard/account/password-settings.tsx
@@ -200,7 +200,7 @@ export function PasswordSettings({
diff --git a/src/features/dashboard/account/reauth-dialog.tsx b/src/features/dashboard/account/reauth-dialog.tsx
index 37c0a0f4e..c5d322709 100644
--- a/src/features/dashboard/account/reauth-dialog.tsx
+++ b/src/features/dashboard/account/reauth-dialog.tsx
@@ -27,7 +27,7 @@ export function ReauthDialog({ open, onOpenChange }: ReauthDialogProps) {
}
confirm="Sign in again"
confirmProps={{
- variant: 'default',
+ variant: 'primary',
}}
onConfirm={handleReauth}
/>
diff --git a/src/features/dashboard/account/user-access-token.tsx b/src/features/dashboard/account/user-access-token.tsx
index e95070e22..2bc1a1560 100644
--- a/src/features/dashboard/account/user-access-token.tsx
+++ b/src/features/dashboard/account/user-access-token.tsx
@@ -1,12 +1,12 @@
'use client'
-import { Eye, EyeOff } from 'lucide-react'
import { useAction } from 'next-safe-action/hooks'
import { useState } from 'react'
import { getUserAccessTokenAction } from '@/core/server/actions/user-actions'
import { defaultErrorToast, useToast } from '@/lib/hooks/use-toast'
import CopyButton from '@/ui/copy-button'
-import { Button } from '@/ui/primitives/button'
+import { IconButton } from '@/ui/primitives/icon-button'
+import { EyeIcon, EyeOffIcon } from '@/ui/primitives/icons'
import { Input } from '@/ui/primitives/input'
import { Loader } from '@/ui/primitives/loader_d'
@@ -36,17 +36,16 @@ export default function UserAccessToken({ className }: UserAccessTokenProps) {
return (
-
)
diff --git a/src/features/dashboard/billing/addons.tsx b/src/features/dashboard/billing/addons.tsx
index eb12e5f6c..70e2e123c 100644
--- a/src/features/dashboard/billing/addons.tsx
+++ b/src/features/dashboard/billing/addons.tsx
@@ -117,13 +117,8 @@ function AvailableAddons({
) : (
-
- Buy Add-on
+
+ Buy
)}
>
@@ -173,7 +168,7 @@ function AddonsUpgradePlaceholder() {
Upgrade to Pro to purchase add-ons for higher concurrency limits.
-
+
Upgrade to Pro
diff --git a/src/features/dashboard/billing/concurrent-sandboxes-addon-dialog.tsx b/src/features/dashboard/billing/concurrent-sandboxes-addon-dialog.tsx
index 06eaed682..a2f2a16be 100644
--- a/src/features/dashboard/billing/concurrent-sandboxes-addon-dialog.tsx
+++ b/src/features/dashboard/billing/concurrent-sandboxes-addon-dialog.tsx
@@ -7,12 +7,6 @@ import {
useStripe,
} from '@stripe/react-stripe-js'
import { useMutation, useQueryClient } from '@tanstack/react-query'
-import {
- AlertCircle,
- ArrowRight,
- CircleDollarSign,
- CreditCard,
-} from 'lucide-react'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
import { DASHBOARD_TEAMS_LIST_QUERY_OPTIONS } from '@/core/application/teams/queries'
@@ -28,7 +22,13 @@ import {
DialogHeader,
DialogTitle,
} from '@/ui/primitives/dialog'
-import { SandboxIcon } from '@/ui/primitives/icons'
+import {
+ AlertIcon,
+ ArrowRightIcon,
+ CardIcon,
+ CreditsIcon,
+ SandboxIcon,
+} from '@/ui/primitives/icons'
import { Loader } from '@/ui/primitives/loader'
import { useDashboard } from '../context'
import {
@@ -190,15 +190,13 @@ function DialogContent_Inner({
{!showPaymentForm && !isProcessing ? (
Increase Concurrency Limit
-
+
) : !showPaymentForm ? (
@@ -228,7 +226,7 @@ function PaymentAuthFailedAlert() {
variant="warning"
className="animate-in fade-in slide-in-from-top-2 duration-300"
>
-
+
Payment authentication failed in the last attempt. Please select a new
payment method or enter the same card details again to retry.
@@ -265,14 +263,14 @@ function AddonFeaturesList({
-
+
Raises current subscription by ${monthlyPriceCents / 100} /month
-
+
Pay ${(amountDueCents / 100).toFixed(2)} now for the remaining
time of the month
@@ -378,14 +376,12 @@ function PaymentElementForm({
{!isProcessing ? (
Increase Concurrency Limit
-
+
) : (
diff --git a/src/features/dashboard/billing/invoices.tsx b/src/features/dashboard/billing/invoices.tsx
index f561445ce..3971d032c 100644
--- a/src/features/dashboard/billing/invoices.tsx
+++ b/src/features/dashboard/billing/invoices.tsx
@@ -153,10 +153,10 @@ export default function BillingInvoicesTable() {
{formatCurrency(invoice.cost)}
-
+
View
-
+
diff --git a/src/features/dashboard/billing/select-plan.tsx b/src/features/dashboard/billing/select-plan.tsx
index 0b243cde9..5fd02aafa 100644
--- a/src/features/dashboard/billing/select-plan.tsx
+++ b/src/features/dashboard/billing/select-plan.tsx
@@ -178,7 +178,7 @@ function PlanCard({
const teamDisplayName = getTeamDisplayName(team)
- const buttonVariant = isBaseTier ? 'outline' : 'default'
+ const buttonVariant = isBaseTier ? 'secondary' : 'primary'
const buttonText = isBaseTier ? 'Downgrade' : 'Upgrade'
return (
@@ -198,9 +198,7 @@ function PlanCard({
{isCurrentPlan ? (
-
- Your current plan
-
+ Your current plan
) : (
@@ -210,7 +208,7 @@ function PlanCard({
{!isBaseTier && }
diff --git a/src/features/dashboard/billing/selected-plan.tsx b/src/features/dashboard/billing/selected-plan.tsx
index 33bb57bd5..fad5fc171 100644
--- a/src/features/dashboard/billing/selected-plan.tsx
+++ b/src/features/dashboard/billing/selected-plan.tsx
@@ -118,9 +118,9 @@ function PlanDetails({
-
+
{isOnPlanPage ? (
-
+
Change Plan
@@ -130,23 +130,23 @@ function PlanDetails({
) : (
<>
{isBaseTier ? (
-
+
Upgrade for higher concurrency
) : (
-
+
Manage plan & add-ons
)}
Manage payment
diff --git a/src/features/dashboard/build/header-cells.tsx b/src/features/dashboard/build/header-cells.tsx
index ede75eb91..423013c16 100644
--- a/src/features/dashboard/build/header-cells.tsx
+++ b/src/features/dashboard/build/header-cells.tsx
@@ -1,4 +1,3 @@
-import { ArrowUpRight } from 'lucide-react'
import { useRouter } from 'next/navigation'
import { useEffect, useState } from 'react'
import { PROTECTED_URLS } from '@/configs/urls'
@@ -28,10 +27,8 @@ export function Template({
return (
{
e.stopPropagation()
e.preventDefault()
@@ -88,9 +85,7 @@ export function RanFor({
className="whitespace-nowrap text-fg-secondary group/time"
>
In {formatDurationCompact(duration)}{' '}
-
- · {formattedTimestamp}
-
+ · {formattedTimestamp}
)
}
@@ -106,9 +101,7 @@ export function StartedAt({ timestamp }: { timestamp: number }) {
className="whitespace-nowrap text-fg-secondary group/time"
>
{formatTimeAgoCompact(elapsed)}{' '}
-
- · {formattedTimestamp}
-
+ · {formattedTimestamp}
)
}
diff --git a/src/features/dashboard/build/header.tsx b/src/features/dashboard/build/header.tsx
index 48bba80f2..dafdf9fb7 100644
--- a/src/features/dashboard/build/header.tsx
+++ b/src/features/dashboard/build/header.tsx
@@ -30,7 +30,7 @@ export default function BuildHeader({
{buildId}
@@ -125,8 +125,6 @@ function StatusBanner({ status, statusMessage }: StatusBannerProps) {
>
)}
diff --git a/src/features/dashboard/common/log-level-filter.tsx b/src/features/dashboard/common/log-level-filter.tsx
index b2818e2dc..7da260853 100644
--- a/src/features/dashboard/common/log-level-filter.tsx
+++ b/src/features/dashboard/common/log-level-filter.tsx
@@ -39,10 +39,7 @@ export function LogLevelFilter({
-
+
Min Level · {selectedLabel}
diff --git a/src/features/dashboard/layouts/header.tsx b/src/features/dashboard/layouts/header.tsx
index ad20e0a95..25ac0834e 100644
--- a/src/features/dashboard/layouts/header.tsx
+++ b/src/features/dashboard/layouts/header.tsx
@@ -38,7 +38,7 @@ export default function DashboardLayoutHeader({
className
)}
>
-
+
@@ -48,15 +48,13 @@ export default function DashboardLayoutHeader({
{copyableValue && (
)}
-
+
diff --git a/src/features/dashboard/limits/limit-form.tsx b/src/features/dashboard/limits/limit-form.tsx
index 2d99dfa1a..4e5bd7d35 100644
--- a/src/features/dashboard/limits/limit-form.tsx
+++ b/src/features/dashboard/limits/limit-form.tsx
@@ -137,7 +137,7 @@ export default function LimitForm({
className={cn('space-y-3', className)}
onSubmit={form.handleSubmit(handleSave)}
>
-
+
Set
@@ -191,10 +190,8 @@ export default function LimitForm({
Clear
@@ -207,7 +204,7 @@ export default function LimitForm({
}
return (
-
+
{'$ '}
@@ -216,8 +213,7 @@ export default function LimitForm({
setIsEditing(true)}
>
Edit
@@ -225,10 +221,9 @@ export default function LimitForm({
Clear
diff --git a/src/features/dashboard/members/add-member-dialog.tsx b/src/features/dashboard/members/add-member-dialog.tsx
index 61494b43a..cfb47eee1 100644
--- a/src/features/dashboard/members/add-member-dialog.tsx
+++ b/src/features/dashboard/members/add-member-dialog.tsx
@@ -1,6 +1,5 @@
'use client'
-import { Plus } from 'lucide-react'
import { useState } from 'react'
import { AddMemberForm } from '@/features/dashboard/members/add-member-form'
import { Button } from '@/ui/primitives/button'
@@ -11,6 +10,7 @@ import {
DialogTitle,
DialogTrigger,
} from '@/ui/primitives/dialog'
+import { AddIcon } from '@/ui/primitives/icons'
export const AddMemberDialog = () => {
const [open, setOpen] = useState(false)
@@ -18,13 +18,8 @@ export const AddMemberDialog = () => {
return (
-
-
+
+
Add new member
diff --git a/src/features/dashboard/members/add-member-form.tsx b/src/features/dashboard/members/add-member-form.tsx
index 80d656cf2..fa64da3fd 100644
--- a/src/features/dashboard/members/add-member-form.tsx
+++ b/src/features/dashboard/members/add-member-form.tsx
@@ -20,7 +20,6 @@ import {
FormLabel,
FormMessage,
} from '@/ui/primitives/form'
-import { AddIcon } from '@/ui/primitives/icons'
import { Input } from '@/ui/primitives/input'
import { useDashboard } from '../context'
@@ -73,37 +72,31 @@ export const AddMemberForm = ({ className, onSuccess }: AddMemberFormProps) => {
)
diff --git a/src/features/dashboard/members/member-table-row.tsx b/src/features/dashboard/members/member-table-row.tsx
index 341d68708..947160011 100644
--- a/src/features/dashboard/members/member-table-row.tsx
+++ b/src/features/dashboard/members/member-table-row.tsx
@@ -19,7 +19,7 @@ import { formatDate } from '@/lib/utils/formatting'
import { E2BLogo } from '@/ui/brand'
import { Avatar, AvatarFallback, AvatarImage } from '@/ui/primitives/avatar'
import { Badge } from '@/ui/primitives/badge'
-import { Button } from '@/ui/primitives/button'
+import { IconButton } from '@/ui/primitives/icon-button'
import { TrashIcon } from '@/ui/primitives/icons'
import { TableCell, TableRow } from '@/ui/primitives/table'
import { useDashboard } from '../context'
@@ -157,12 +157,7 @@ const NameCell = ({
{name ?? email}
{isCurrentUser ? (
-
+
You
) : null}
@@ -270,15 +265,9 @@ const AddedCell = ({
setOpen={setRemoveDialogOpen}
teamName={teamName}
trigger={
-
-
-
+
+
+
}
/>
) : null}
diff --git a/src/features/dashboard/members/members-page-content.tsx b/src/features/dashboard/members/members-page-content.tsx
index b43e7e772..66e343c4f 100644
--- a/src/features/dashboard/members/members-page-content.tsx
+++ b/src/features/dashboard/members/members-page-content.tsx
@@ -1,10 +1,10 @@
'use client'
-import { Search } from 'lucide-react'
import { useMemo, useState } from 'react'
import type { TeamMember } from '@/core/modules/teams/models'
import { cn } from '@/lib/utils'
import { pluralize } from '@/lib/utils/formatting'
+import { SearchIcon } from '@/ui/primitives/icons'
import { Input } from '@/ui/primitives/input'
import { AddMemberDialog } from './add-member-dialog'
import MemberTable from './member-table'
@@ -37,7 +37,7 @@ const MembersPageContent = ({
-
diff --git a/src/features/dashboard/members/remove-member-dialog.tsx b/src/features/dashboard/members/remove-member-dialog.tsx
index db40343c6..b8676d1d3 100644
--- a/src/features/dashboard/members/remove-member-dialog.tsx
+++ b/src/features/dashboard/members/remove-member-dialog.tsx
@@ -54,18 +54,16 @@ export const RemoveMemberDialog = ({
Cancel
diff --git a/src/features/dashboard/navbar/file-drop-zone.tsx b/src/features/dashboard/navbar/file-drop-zone.tsx
index 8436706dc..8d65ff7d9 100644
--- a/src/features/dashboard/navbar/file-drop-zone.tsx
+++ b/src/features/dashboard/navbar/file-drop-zone.tsx
@@ -1,8 +1,8 @@
'use client'
-import { Upload } from 'lucide-react'
import { useCallback, useRef, useState } from 'react'
import { cn } from '@/lib/utils'
+import { UploadIcon } from '@/ui/primitives/icons'
interface FileDropZoneProps {
onFilesSelected: (files: File[]) => void
@@ -101,7 +101,7 @@ export default function FileDropZone({
isDisabled && 'cursor-not-allowed opacity-50 border-stroke'
)}
>
-
+
{isUploading
? 'Uploading...'
diff --git a/src/features/dashboard/navbar/report-issue-dialog.tsx b/src/features/dashboard/navbar/report-issue-dialog.tsx
index 5ff222a02..b65db71cd 100644
--- a/src/features/dashboard/navbar/report-issue-dialog.tsx
+++ b/src/features/dashboard/navbar/report-issue-dialog.tsx
@@ -2,7 +2,6 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { useMutation } from '@tanstack/react-query'
-import { Paperclip, X } from 'lucide-react'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { usePostHog } from 'posthog-js/react'
import { useCallback, useEffect, useState } from 'react'
@@ -29,6 +28,7 @@ import {
FormLabel,
FormMessage,
} from '@/ui/primitives/form'
+import { CloseIcon, FileIcon } from '@/ui/primitives/icons'
import { Textarea } from '@/ui/primitives/textarea'
import FileDropZone from './file-drop-zone'
@@ -240,7 +240,7 @@ export default function ContactSupportDialog({
key={`${file.name}-${i}`}
className="flex items-center gap-2 text-sm text-fg-secondary"
>
-
+
{file.name}
{(file.size / 1024).toFixed(0)}KB
@@ -251,7 +251,7 @@ export default function ContactSupportDialog({
disabled={isSubmitting}
className="shrink-0 text-fg-tertiary hover:text-fg transition-colors"
>
-
+
))}
@@ -260,7 +260,7 @@ export default function ContactSupportDialog({
handleOpenChange(false)}
disabled={isSubmitting}
>
@@ -269,7 +269,7 @@ export default function ContactSupportDialog({
Send
diff --git a/src/features/dashboard/sandbox/header/ended-at.tsx b/src/features/dashboard/sandbox/header/ended-at.tsx
index acb89ce57..a807172fe 100644
--- a/src/features/dashboard/sandbox/header/ended-at.tsx
+++ b/src/features/dashboard/sandbox/header/ended-at.tsx
@@ -46,12 +46,7 @@ export default function EndedAt() {
{prefix}, {timeStr}
-
+
)
}
diff --git a/src/features/dashboard/sandbox/header/kill-button.tsx b/src/features/dashboard/sandbox/header/kill-button.tsx
index e8c66bcaf..f177191bf 100644
--- a/src/features/dashboard/sandbox/header/kill-button.tsx
+++ b/src/features/dashboard/sandbox/header/kill-button.tsx
@@ -4,7 +4,6 @@ import { useAction } from 'next-safe-action/hooks'
import { useState } from 'react'
import { toast } from 'sonner'
import { killSandboxAction } from '@/core/server/actions/sandbox-actions'
-import { cn } from '@/lib/utils/ui'
import { AlertPopover } from '@/ui/alert-popover'
import { Button } from '@/ui/primitives/button'
import { TrashIcon } from '@/ui/primitives/icons'
@@ -53,19 +52,14 @@ export default function KillButton({ className }: KillButtonProps) {
description="Are you sure you want to kill this sandbox? The sandbox state will be lost and cannot be recovered."
confirm="Kill Sandbox"
trigger={
-
-
+
+
Kill
}
confirmProps={{
disabled: isExecuting,
- loading: isExecuting,
+ loading: isExecuting ? 'Killing...' : undefined,
}}
onConfirm={handleKill}
onCancel={() => setOpen(false)}
diff --git a/src/features/dashboard/sandbox/header/metadata.tsx b/src/features/dashboard/sandbox/header/metadata.tsx
index e9fa7cec6..708e14420 100644
--- a/src/features/dashboard/sandbox/header/metadata.tsx
+++ b/src/features/dashboard/sandbox/header/metadata.tsx
@@ -1,8 +1,8 @@
'use client'
-import { Braces, CircleSlash } from 'lucide-react'
import { JsonPopover } from '@/ui/json-popover'
import { Badge } from '@/ui/primitives/badge'
+import { BlockIcon, MetadataIcon } from '@/ui/primitives/icons'
import { useSandboxContext } from '../context'
export default function Metadata() {
@@ -11,21 +11,14 @@ export default function Metadata() {
if (!sandboxInfo || sandboxInfo.state === 'killed' || !sandboxInfo.metadata) {
return (
- N/A
+ N/A
)
}
return (
-
-
+
+
Metadata
)
diff --git a/src/features/dashboard/sandbox/header/remaining-time.tsx b/src/features/dashboard/sandbox/header/remaining-time.tsx
index d7163322d..56d61b383 100644
--- a/src/features/dashboard/sandbox/header/remaining-time.tsx
+++ b/src/features/dashboard/sandbox/header/remaining-time.tsx
@@ -1,11 +1,12 @@
'use client'
-import { RefreshCw, Square } from 'lucide-react'
import { motion } from 'motion/react'
import { useCallback, useEffect, useState } from 'react'
import { cn } from '@/lib/utils'
import { Badge } from '@/ui/primitives/badge'
import { Button } from '@/ui/primitives/button'
+import { IconButton } from '@/ui/primitives/icon-button'
+import { DotIcon, RefreshIcon } from '@/ui/primitives/icons'
import { useSandboxContext } from '../context'
export default function RemainingTime() {
@@ -45,7 +46,7 @@ export default function RemainingTime() {
if (!isRunning) {
return (
- Stopped
+ Stopped
)
}
@@ -54,24 +55,22 @@ export default function RemainingTime() {
)
diff --git a/src/features/dashboard/sandbox/header/started-at.tsx b/src/features/dashboard/sandbox/header/started-at.tsx
index f38ef5e0a..2e6614ba1 100644
--- a/src/features/dashboard/sandbox/header/started-at.tsx
+++ b/src/features/dashboard/sandbox/header/started-at.tsx
@@ -31,16 +31,11 @@ export default function StartedAt() {
})
return (
-
+
)
}
diff --git a/src/features/dashboard/sandbox/header/status.tsx b/src/features/dashboard/sandbox/header/status.tsx
index a8fe0e976..da92dd441 100644
--- a/src/features/dashboard/sandbox/header/status.tsx
+++ b/src/features/dashboard/sandbox/header/status.tsx
@@ -1,7 +1,7 @@
'use client'
-import { Circle, Square } from 'lucide-react'
import { Badge } from '@/ui/primitives/badge'
+import { DotIcon, PausedIcon } from '@/ui/primitives/icons'
import { useSandboxContext } from '../context'
export default function Status() {
@@ -11,7 +11,7 @@ export default function Status() {
if (state === 'paused') {
return (
-
+
Paused
)
@@ -19,11 +19,13 @@ export default function Status() {
return (
- {isRunning ? (
-
- ) : (
-
- )}
+
{isRunning ? 'Running' : 'Stopped'}
)
diff --git a/src/features/dashboard/sandbox/header/template-id.tsx b/src/features/dashboard/sandbox/header/template-id.tsx
index fa254285c..0444b77f0 100644
--- a/src/features/dashboard/sandbox/header/template-id.tsx
+++ b/src/features/dashboard/sandbox/header/template-id.tsx
@@ -13,14 +13,9 @@ export default function TemplateId() {
}, [sandboxInfo])
return (
-
+
{value}
-
+
)
}
diff --git a/src/features/dashboard/sandbox/inspect/dir.tsx b/src/features/dashboard/sandbox/inspect/dir.tsx
index 6cf5ac1ac..beda65082 100644
--- a/src/features/dashboard/sandbox/inspect/dir.tsx
+++ b/src/features/dashboard/sandbox/inspect/dir.tsx
@@ -1,9 +1,9 @@
'use client'
-import { AlertCircle, FolderClosed, FolderOpen } from 'lucide-react'
import { AnimatePresence, motion } from 'motion/react'
import { cn } from '@/lib/utils'
import { DataTableRow } from '@/ui/data-table'
+import { AlertIcon, FolderIcon, FolderOpenIcon } from '@/ui/primitives/icons'
import SandboxInspectEmptyNode from './empty-node'
import type { FilesystemNode } from './filesystem/types'
import { useDirectory } from './hooks/use-directory'
@@ -51,9 +51,9 @@ export default function SandboxInspectDir({ dir }: SandboxInspectDirProps) {
)}
>
{isExpanded && isLoaded ? (
-
+
) : (
-
+
)}
{hasError && (
-
+
{error}
)}
diff --git a/src/features/dashboard/sandbox/inspect/file.tsx b/src/features/dashboard/sandbox/inspect/file.tsx
index f420c0506..ba8db5215 100644
--- a/src/features/dashboard/sandbox/inspect/file.tsx
+++ b/src/features/dashboard/sandbox/inspect/file.tsx
@@ -1,8 +1,8 @@
'use client'
-import { AlertCircle, FileIcon } from 'lucide-react'
import { cn } from '@/lib/utils'
import { DataTableRow } from '@/ui/data-table'
+import { AlertIcon, FileIcon } from '@/ui/primitives/icons'
import type { FilesystemNode } from './filesystem/types'
import { useFile } from './hooks/use-file'
import NodeLabel from './node-label'
@@ -42,7 +42,7 @@ export default function SandboxInspectFile({ file }: SandboxInspectFileProps) {
{hasError && (
-
+
{error}
)}
diff --git a/src/features/dashboard/sandbox/inspect/filesystem.tsx b/src/features/dashboard/sandbox/inspect/filesystem.tsx
index 1fb84def5..9ec6fee7b 100644
--- a/src/features/dashboard/sandbox/inspect/filesystem.tsx
+++ b/src/features/dashboard/sandbox/inspect/filesystem.tsx
@@ -26,7 +26,7 @@ export default function SandboxInspectFilesystem({
isRunning && children.length === 0 && (!isLoaded || isLoading)
return (
-
+
-
+
Incompatible template
@@ -76,10 +80,7 @@ export default function SandboxInspectIncompatible({
The folder should contain an{' '}
-
- e2b.toml
- {' '}
- file.
+ e2b.toml file.
@@ -87,9 +88,7 @@ export default function SandboxInspectIncompatible({
Rebuild the template
Use{' '}
-
- e2b template build
- {' '}
+ e2b template build {' '}
along with custom{' '}
{' '}
and any other arguments to rebuild. For example:
-
- -c "start.sh"
-
+ -c "start.sh"
@@ -120,25 +117,23 @@ export default function SandboxInspectIncompatible({
-
+
Back to sandboxes
Documentation{' '}
-
+
diff --git a/src/features/dashboard/sandbox/inspect/not-found.tsx b/src/features/dashboard/sandbox/inspect/not-found.tsx
index 884175ba2..05648b47d 100644
--- a/src/features/dashboard/sandbox/inspect/not-found.tsx
+++ b/src/features/dashboard/sandbox/inspect/not-found.tsx
@@ -1,6 +1,5 @@
'use client'
-import { ArrowLeft, ArrowUp, Home, RefreshCw } from 'lucide-react'
import { useParams, useRouter } from 'next/navigation'
import { useCallback, useEffect, useState, useTransition } from 'react'
import { PROTECTED_URLS } from '@/configs/urls'
@@ -8,6 +7,12 @@ import { l, serializeErrorForLog } from '@/core/shared/clients/logger/logger'
import { useSandboxInspectAnalytics } from '@/lib/hooks/use-analytics'
import { cn } from '@/lib/utils'
import { Button } from '@/ui/primitives/button'
+import {
+ ArrowLeftIcon,
+ ArrowUpIcon,
+ HomeIcon,
+ RefreshIcon,
+} from '@/ui/primitives/icons'
import { useSandboxContext } from '../context'
import SandboxInspectEmptyFrame from './empty'
@@ -64,26 +69,26 @@ export default function SandboxInspectNotFound() {
<>
setRootPath('')}
disabled={isPending && pendingPath === ''}
>
-
+
Reset
setRootPath('/')}
disabled={isPending && pendingPath === '/'}
>
-
+
To Root
resetTransition(async () => {
router.refresh()
@@ -92,7 +97,7 @@ export default function SandboxInspectNotFound() {
className="w-full gap-2"
disabled={isResetPending}
>
-
) : (
router.push(PROTECTED_URLS.SANDBOXES(teamSlug as string))}
className="w-full gap-2"
>
-
+
Back to Sandboxes
)
diff --git a/src/features/dashboard/sandbox/inspect/parent-dir-item.tsx b/src/features/dashboard/sandbox/inspect/parent-dir-item.tsx
index e2f6fb17c..b7087c763 100644
--- a/src/features/dashboard/sandbox/inspect/parent-dir-item.tsx
+++ b/src/features/dashboard/sandbox/inspect/parent-dir-item.tsx
@@ -1,11 +1,11 @@
'use client'
-import { FolderUp } from 'lucide-react'
import { useRouter } from 'next/navigation'
import path from 'path'
import { useTransition } from 'react'
import { cn } from '@/lib/utils'
import { DataTableRow } from '@/ui/data-table'
+import { FolderUpIcon } from '@/ui/primitives/icons'
interface SandboxInspectParentDirItemProps {
rootPath: string
@@ -55,7 +55,7 @@ export default function SandboxInspectParentDirItem({
}
}}
>
-
+
..
)
diff --git a/src/features/dashboard/sandbox/inspect/root-path-input.tsx b/src/features/dashboard/sandbox/inspect/root-path-input.tsx
index 3ee555ec3..d32d6c9aa 100644
--- a/src/features/dashboard/sandbox/inspect/root-path-input.tsx
+++ b/src/features/dashboard/sandbox/inspect/root-path-input.tsx
@@ -1,12 +1,12 @@
'use client'
-import { ArrowRight } from 'lucide-react'
import { useRouter } from 'next/navigation'
import { useEffect, useState, useTransition } from 'react'
import { l, serializeErrorForLog } from '@/core/shared/clients/logger/logger'
import { useSandboxInspectAnalytics } from '@/lib/hooks/use-analytics'
import { cn } from '@/lib/utils'
import { Button } from '@/ui/primitives/button'
+import { ArrowRightIcon } from '@/ui/primitives/icons'
import { Input } from '@/ui/primitives/input'
import { Loader } from '@/ui/primitives/loader_d'
@@ -76,12 +76,12 @@ export default function RootPathInput({
/>
- Go {isPending ? : }
+ Go {isPending ? : }
)
diff --git a/src/features/dashboard/sandbox/inspect/stopped-banner.tsx b/src/features/dashboard/sandbox/inspect/stopped-banner.tsx
index f45fe6811..f299b5db3 100644
--- a/src/features/dashboard/sandbox/inspect/stopped-banner.tsx
+++ b/src/features/dashboard/sandbox/inspect/stopped-banner.tsx
@@ -1,6 +1,5 @@
'use client'
-import { AlertTriangle } from 'lucide-react'
import { AnimatePresence, motion } from 'motion/react'
import { useMemo } from 'react'
import { cn } from '@/lib/utils'
@@ -10,6 +9,7 @@ import {
CardTitle,
cardVariants,
} from '@/ui/primitives/card'
+import { WarningIcon } from '@/ui/primitives/icons'
import { useSandboxContext } from '../context'
import { useLastUpdated, useWatcherError } from './hooks/use-watcher'
@@ -42,9 +42,9 @@ export function StoppedBanner({ rootNodeCount }: StoppedBannerProps) {
'overflow-hidden border'
)}
>
-
+
-
+
{showWatcherError
? 'Live filesystem updates disabled'
diff --git a/src/features/dashboard/sandbox/inspect/viewer-header.tsx b/src/features/dashboard/sandbox/inspect/viewer-header.tsx
index 34e5e1aab..32e37fdc3 100644
--- a/src/features/dashboard/sandbox/inspect/viewer-header.tsx
+++ b/src/features/dashboard/sandbox/inspect/viewer-header.tsx
@@ -1,7 +1,13 @@
-import { Download, FileIcon, RefreshCcw, X } from 'lucide-react'
import { motion } from 'motion/react'
import CopyButton from '@/ui/copy-button'
import { Button } from '@/ui/primitives/button'
+import { IconButton } from '@/ui/primitives/icon-button'
+import {
+ CloseIcon,
+ DownloadIcon,
+ FileIcon,
+ RefreshIcon,
+} from '@/ui/primitives/icons'
import type { FileContentState } from './filesystem/store'
interface SandboxInspectViewerHeaderProps {
@@ -27,23 +33,14 @@ export default function SandboxInspectViewerHeader({
{name}
{fileContentState?.type === 'text' && (
-
+
)}
-
-
-
+
+
+
-
+
-
+
-
+
-
-
-
+
+
+
)
}
diff --git a/src/features/dashboard/sandbox/inspect/viewer.tsx b/src/features/dashboard/sandbox/inspect/viewer.tsx
index bed8b5606..8d12123dc 100644
--- a/src/features/dashboard/sandbox/inspect/viewer.tsx
+++ b/src/features/dashboard/sandbox/inspect/viewer.tsx
@@ -1,7 +1,6 @@
'use client'
import { AnimatePresence } from 'framer-motion'
-import { Download } from 'lucide-react'
import { useEffect, useState } from 'react'
import ShikiHighlighter, { type Language } from 'react-shiki'
import { useShikiTheme } from '@/configs/shiki'
@@ -9,6 +8,7 @@ import { useIsMobile } from '@/lib/hooks/use-mobile'
import { cn } from '@/lib/utils'
import { Button } from '@/ui/primitives/button'
import { Drawer, DrawerContent } from '@/ui/primitives/drawer'
+import { DownloadIcon } from '@/ui/primitives/icons'
import { ScrollArea, ScrollBar } from '@/ui/primitives/scroll-area'
import {
@@ -155,9 +155,9 @@ function TextContent({
return (
This file is empty.
-
+
Download
-
+
)
@@ -215,9 +215,9 @@ function UnreadableContent({ state, onDownload }: UnreadableContentProps) {
File is too large to preview ({sizeMB} MB). Limit is {maxSizeMB} MB.
-
+
Download
-
+
)
@@ -226,9 +226,9 @@ function UnreadableContent({ state, onDownload }: UnreadableContentProps) {
return (
This file is not readable.
-
+
Download
-
+
)
diff --git a/src/features/dashboard/sandbox/monitoring/components/chart-overlays.tsx b/src/features/dashboard/sandbox/monitoring/components/chart-overlays.tsx
index 2c3424adc..51bc27a39 100644
--- a/src/features/dashboard/sandbox/monitoring/components/chart-overlays.tsx
+++ b/src/features/dashboard/sandbox/monitoring/components/chart-overlays.tsx
@@ -1,6 +1,10 @@
-import { PowerIcon, SquareIcon } from 'lucide-react'
import { cn } from '@/lib/utils'
-import { type AddIcon, PausedIcon, RunningIcon } from '@/ui/primitives/icons'
+import {
+ AddIcon,
+ BlockIcon,
+ PausedIcon,
+ RunningIcon,
+} from '@/ui/primitives/icons'
import { withOpacity } from '../utils/chart-colors'
import type {
CrosshairMarker,
@@ -20,14 +24,11 @@ const MARKER_BORDER_OPACITY = 0.12
import { formatHoverTimestamp } from '../utils/formatters'
-const SANDBOX_LIFECYCLE_EVENT_ICON_MAP: Record<
- string,
- typeof AddIcon | typeof PowerIcon
-> = {
- [SANDBOX_LIFECYCLE_EVENT_CREATED]: PowerIcon,
+const SANDBOX_LIFECYCLE_EVENT_ICON_MAP: Record = {
+ [SANDBOX_LIFECYCLE_EVENT_CREATED]: AddIcon,
[SANDBOX_LIFECYCLE_EVENT_PAUSED]: PausedIcon,
[SANDBOX_LIFECYCLE_EVENT_RESUMED]: RunningIcon,
- [SANDBOX_LIFECYCLE_EVENT_KILLED]: SquareIcon,
+ [SANDBOX_LIFECYCLE_EVENT_KILLED]: BlockIcon,
}
function LifecycleEventOverlayGroup({
diff --git a/src/features/dashboard/sandbox/monitoring/components/monitoring-time-range-controls.tsx b/src/features/dashboard/sandbox/monitoring/components/monitoring-time-range-controls.tsx
index 757019df3..fedbb7e3d 100644
--- a/src/features/dashboard/sandbox/monitoring/components/monitoring-time-range-controls.tsx
+++ b/src/features/dashboard/sandbox/monitoring/components/monitoring-time-range-controls.tsx
@@ -1,11 +1,11 @@
'use client'
-import { RotateCcw } from 'lucide-react'
import { useCallback, useMemo, useState } from 'react'
import { cn } from '@/lib/utils'
import { LiveDot } from '@/ui/live'
import { Button } from '@/ui/primitives/button'
-import { TimeIcon } from '@/ui/primitives/icons'
+import { IconButton } from '@/ui/primitives/icon-button'
+import { RefreshIcon, TimeIcon } from '@/ui/primitives/icons'
import {
Popover,
PopoverContent,
@@ -189,8 +189,7 @@ export default function SandboxMonitoringTimeRangeControls({
{isPolling ? (
@@ -234,15 +233,13 @@ export default function SandboxMonitoringTimeRangeControls({
{canResetZoom ? (
-
-
-
+
+
) : null}
diff --git a/src/features/dashboard/sandboxes/list/open-sandbox-dialog.tsx b/src/features/dashboard/sandboxes/list/open-sandbox-dialog.tsx
index 9d9efb71b..4c5bff11e 100644
--- a/src/features/dashboard/sandboxes/list/open-sandbox-dialog.tsx
+++ b/src/features/dashboard/sandboxes/list/open-sandbox-dialog.tsx
@@ -90,7 +90,7 @@ export function OpenSandboxDialog() {
return (
- Inspect a Sandbox
+ Inspect a Sandbox
@@ -146,8 +146,8 @@ export function OpenSandboxDialog() {
Open Details
diff --git a/src/features/dashboard/sandboxes/list/table-body.tsx b/src/features/dashboard/sandboxes/list/table-body.tsx
index 62dd511c3..ec6b92073 100644
--- a/src/features/dashboard/sandboxes/list/table-body.tsx
+++ b/src/features/dashboard/sandboxes/list/table-body.tsx
@@ -1,8 +1,8 @@
-import { ExternalLink, X } from 'lucide-react'
import type { RefObject } from 'react'
import { useVirtualRows } from '@/lib/hooks/use-virtual-rows'
import { DataTableBody } from '@/ui/data-table'
import { Button } from '@/ui/primitives/button'
+import { AddIcon, CloseIcon } from '@/ui/primitives/icons'
import SandboxesListEmpty from './empty'
import { useSandboxesMetrics } from './hooks/use-sandboxes-metrics'
import { useSandboxListTableStore } from './stores/table-store'
@@ -71,8 +71,8 @@ export const SandboxesTableBody = ({
title="No Results Found"
description="No sandboxes match your current filters."
actions={
-
- Reset Filters
+
+ Reset Filters
}
className="h-full max-md:sticky max-md:left-0 max-md:w-[calc(100svw-1.5rem)]"
@@ -82,10 +82,10 @@ export const SandboxesTableBody = ({
title="No Sandboxes Yet"
description="Running sandboxes can be observed here."
actions={
-
+
+
Create a Sandbox
-
}
diff --git a/src/features/dashboard/sandboxes/list/table-cells.tsx b/src/features/dashboard/sandboxes/list/table-cells.tsx
index 0144e961e..8e6163f71 100644
--- a/src/features/dashboard/sandboxes/list/table-cells.tsx
+++ b/src/features/dashboard/sandboxes/list/table-cells.tsx
@@ -1,7 +1,6 @@
'use client'
import type { CellContext } from '@tanstack/react-table'
-import { ArrowUpRight } from 'lucide-react'
import { useRouter } from 'next/navigation'
import { useMemo } from 'react'
import { PROTECTED_URLS } from '@/configs/urls'
@@ -10,6 +9,7 @@ import { useTemplateTableStore } from '@/features/dashboard/templates/list/store
import { formatLocalLogStyleTimestamp } from '@/lib/utils/formatting'
import { JsonPopover } from '@/ui/json-popover'
import { Button } from '@/ui/primitives/button'
+import { ExternalLinkIcon } from '@/ui/primitives/icons'
import { useDashboard } from '../../context'
import { useSandboxMetricsStore } from './stores/metrics-store'
import type { SandboxListRow } from './table-config'
@@ -120,11 +120,11 @@ export function TemplateCell({
return (
{
- event.stopPropagation()
- event.preventDefault()
+ variant="link-table"
+ size="none"
+ onClick={(e) => {
+ e.stopPropagation()
+ e.preventDefault()
if (!templateId) {
return
@@ -135,7 +135,7 @@ export function TemplateCell({
}}
>
{templateIdentifier}
-
+
)
}
diff --git a/src/features/dashboard/sandboxes/list/table-filters.tsx b/src/features/dashboard/sandboxes/list/table-filters.tsx
index 4d06a2e19..b127d3a99 100644
--- a/src/features/dashboard/sandboxes/list/table-filters.tsx
+++ b/src/features/dashboard/sandboxes/list/table-filters.tsx
@@ -1,4 +1,3 @@
-import { ListFilter, Plus } from 'lucide-react'
import * as React from 'react'
import { memo, useCallback } from 'react'
import { useDebounceValue } from 'usehooks-ts'
@@ -20,6 +19,7 @@ import {
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from '@/ui/primitives/dropdown-menu'
+import { AddIcon, FilterIcon } from '@/ui/primitives/icons'
import { Input } from '@/ui/primitives/input'
import { Label } from '@/ui/primitives/label'
import { Separator } from '@/ui/primitives/separator'
@@ -127,11 +127,11 @@ const TemplateFilter = memo(function TemplateFilter() {
className="w-full"
/>
-
+
@@ -221,8 +221,7 @@ const ResourcesFilter = memo(function ResourcesFilter() {
/>
{localValues.cpu > 0 && (
@@ -250,8 +249,7 @@ const ResourcesFilter = memo(function ResourcesFilter() {
/>
{localValues.memory > 0 && (
@@ -304,8 +302,8 @@ const SandboxesTableFilters = memo(function SandboxesTableFilters({
>
-
- Filter{' '}
+
+ Filters{' '}
diff --git a/src/features/dashboard/sandboxes/monitoring/charts/concurrent-chart/components/range-label.tsx b/src/features/dashboard/sandboxes/monitoring/charts/concurrent-chart/components/range-label.tsx
index e15bb0aaa..8bee8a034 100644
--- a/src/features/dashboard/sandboxes/monitoring/charts/concurrent-chart/components/range-label.tsx
+++ b/src/features/dashboard/sandboxes/monitoring/charts/concurrent-chart/components/range-label.tsx
@@ -10,13 +10,11 @@ export function RangeLabel({ label, copyValue }: RangeLabelProps) {
@@ -24,9 +22,7 @@ export function RangeLabel({ label, copyValue }: RangeLabelProps) {
diff --git a/src/features/dashboard/sandboxes/monitoring/charts/concurrent-chart/components/time-range-selector.tsx b/src/features/dashboard/sandboxes/monitoring/charts/concurrent-chart/components/time-range-selector.tsx
index 9adb5eb50..8e7905458 100644
--- a/src/features/dashboard/sandboxes/monitoring/charts/concurrent-chart/components/time-range-selector.tsx
+++ b/src/features/dashboard/sandboxes/monitoring/charts/concurrent-chart/components/time-range-selector.tsx
@@ -70,10 +70,10 @@ export function TimeRangeSelector({
onValueChange={handleTimePickerChange}
>
key !== 'custom').map((key) => (
-
+
Failed
diff --git a/src/features/dashboard/sandboxes/monitoring/time-picker/index.tsx b/src/features/dashboard/sandboxes/monitoring/time-picker/index.tsx
index b575a260c..947d04109 100644
--- a/src/features/dashboard/sandboxes/monitoring/time-picker/index.tsx
+++ b/src/features/dashboard/sandboxes/monitoring/time-picker/index.tsx
@@ -1,9 +1,7 @@
'use client'
import { AnimatePresence, motion } from 'framer-motion'
-import { ChevronRight } from 'lucide-react'
import { memo, type ReactNode, useCallback, useEffect, useRef } from 'react'
-
import { cn } from '@/lib/utils'
import { tryParseDatetime } from '@/lib/utils/formatting'
import type { TimeframeState } from '@/lib/utils/timeframe'
@@ -15,6 +13,7 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/ui/primitives/dropdown-menu'
+import { ChevronRightIcon } from '@/ui/primitives/icons'
import { RadioGroup, RadioGroupItem } from '@/ui/primitives/radio-group'
import { MAX_DAYS_AGO, TIME_OPTIONS } from './constants'
@@ -253,7 +252,7 @@ export const TimePicker = memo(function TimePicker({
Custom
-
+
diff --git a/src/features/dashboard/sandboxes/monitoring/time-picker/time-panel.tsx b/src/features/dashboard/sandboxes/monitoring/time-picker/time-panel.tsx
index f647e7d3b..8add8c0d7 100644
--- a/src/features/dashboard/sandboxes/monitoring/time-picker/time-panel.tsx
+++ b/src/features/dashboard/sandboxes/monitoring/time-picker/time-panel.tsx
@@ -257,7 +257,7 @@ export const TimePanel = forwardRef
(
type="submit"
disabled={!form.formState.isDirty}
className="w-fit self-end mt-auto"
- variant="outline"
+ variant="secondary"
>
Apply
diff --git a/src/features/dashboard/settings/general/info-card.tsx b/src/features/dashboard/settings/general/info-card.tsx
index aaab3dd2a..19f52428b 100644
--- a/src/features/dashboard/settings/general/info-card.tsx
+++ b/src/features/dashboard/settings/general/info-card.tsx
@@ -31,17 +31,17 @@ export function InfoCard({ className }: InfoCardProps) {
E-Mail
{team.email}
-
+
Team ID
{team.id}
-
+
Team Slug
{team.slug}
-
+
diff --git a/src/features/dashboard/settings/general/name-card.tsx b/src/features/dashboard/settings/general/name-card.tsx
index b9d629b78..3a39fa5cb 100644
--- a/src/features/dashboard/settings/general/name-card.tsx
+++ b/src/features/dashboard/settings/general/name-card.tsx
@@ -4,6 +4,7 @@ import { zodResolver } from '@hookform/resolvers/zod'
import { useHookFormOptimisticAction } from '@next-safe-action/adapter-react-hook-form/hooks'
import { useQueryClient } from '@tanstack/react-query'
import { AnimatePresence, motion } from 'motion/react'
+import { useMemo } from 'react'
import { USER_MESSAGES } from '@/configs/user-messages'
import { getTransformedDefaultTeamName } from '@/core/modules/teams/utils'
import { updateTeamNameAction } from '@/core/server/actions/team-actions'
@@ -15,8 +16,9 @@ import {
useToast,
} from '@/lib/hooks/use-toast'
import { exponentialSmoothing } from '@/lib/utils'
+import { cn } from '@/lib/utils/ui'
import { useTRPC } from '@/trpc/client'
-import { Button } from '@/ui/primitives/button'
+import { Button, buttonVariants } from '@/ui/primitives/button'
import {
Card,
CardContent,
@@ -32,6 +34,7 @@ import {
FormMessage,
} from '@/ui/primitives/form'
import { Input } from '@/ui/primitives/input'
+import { Loader } from '@/ui/primitives/loader'
interface NameCardProps {
className?: string
@@ -98,6 +101,9 @@ export function NameCard({ className }: NameCardProps) {
optimisticState?.team ?? team
)
+ const name = watch('name')
+ const isNameDirty = useMemo(() => name !== team.name, [name, team.name])
+
return (
@@ -110,7 +116,7 @@ export function NameCard({ className }: NameCardProps) {
diff --git a/src/features/dashboard/settings/general/profile-picture-card.tsx b/src/features/dashboard/settings/general/profile-picture-card.tsx
index e6193d522..c41c952dc 100644
--- a/src/features/dashboard/settings/general/profile-picture-card.tsx
+++ b/src/features/dashboard/settings/general/profile-picture-card.tsx
@@ -2,7 +2,6 @@
import { useQueryClient } from '@tanstack/react-query'
import { AnimatePresence, motion } from 'framer-motion'
-import { ChevronsUp, ImagePlusIcon, Loader2, Pencil } from 'lucide-react'
import { useAction } from 'next-safe-action/hooks'
import { useRef, useState } from 'react'
import { USER_MESSAGES } from '@/configs/user-messages'
@@ -18,6 +17,12 @@ import { useTRPC } from '@/trpc/client'
import { Avatar, AvatarFallback, AvatarImage } from '@/ui/primitives/avatar'
import { Badge } from '@/ui/primitives/badge'
import { cardVariants } from '@/ui/primitives/card'
+import {
+ EditIcon,
+ PhotoIcon,
+ SpinnerIcon,
+ UploadIcon,
+} from '@/ui/primitives/icons'
interface ProfilePictureCardProps {
className?: string
@@ -113,10 +118,10 @@ export function ProfilePictureCard({ className }: ProfilePictureCardProps) {
alt={`${team.name}'s profile picture`}
/>
-
+
Upload{' '}
-
+
@@ -143,7 +148,7 @@ export function ProfilePictureCard({ className }: ProfilePictureCardProps) {
exit="initial"
transition={{ duration: 0.2, ease: exponentialSmoothing(5) }}
>
-
+
) : isUploading ? (
-
+
) : null}
diff --git a/src/features/dashboard/settings/keys/create-api-key-dialog.tsx b/src/features/dashboard/settings/keys/create-api-key-dialog.tsx
index d8f465449..d4e8deeec 100644
--- a/src/features/dashboard/settings/keys/create-api-key-dialog.tsx
+++ b/src/features/dashboard/settings/keys/create-api-key-dialog.tsx
@@ -124,7 +124,10 @@ const CreateApiKeyDialog: FC = ({ children }) => {
/>
-
+
Create Key
@@ -154,7 +157,7 @@ const CreateApiKeyDialog: FC = ({ children }) => {
- Close
+ Close
>
diff --git a/src/features/dashboard/settings/keys/table-row.tsx b/src/features/dashboard/settings/keys/table-row.tsx
index 86f2467c4..01508dc1e 100644
--- a/src/features/dashboard/settings/keys/table-row.tsx
+++ b/src/features/dashboard/settings/keys/table-row.tsx
@@ -1,6 +1,5 @@
'use client'
-import { MoreHorizontal } from 'lucide-react'
import { motion } from 'motion/react'
import { useAction } from 'next-safe-action/hooks'
import { useState } from 'react'
@@ -15,7 +14,6 @@ import {
} from '@/lib/hooks/use-toast'
import { exponentialSmoothing } from '@/lib/utils'
import { AlertDialog } from '@/ui/alert-dialog'
-import { Button } from '@/ui/primitives/button'
import {
DropdownMenu,
DropdownMenuContent,
@@ -24,6 +22,8 @@ import {
DropdownMenuLabel,
DropdownMenuTrigger,
} from '@/ui/primitives/dropdown-menu'
+import { IconButton } from '@/ui/primitives/icon-button'
+import { IndicatorDotsIcon } from '@/ui/primitives/icons'
import { TableCell, TableRow } from '@/ui/primitives/table'
interface TableRowProps {
@@ -93,7 +93,7 @@ export default function ApiKeyTableRow({
onConfirm={deleteKey}
confirmProps={{
disabled: isDeleting,
- loading: isDeleting,
+ loading: isDeleting ? 'Deleting...' : undefined,
}}
/>
@@ -123,7 +123,7 @@ export default function ApiKeyTableRow({
-
+
-
+
-
+
@@ -148,7 +148,7 @@ export default function ApiKeyTableRow({
onClick={() => setIsDeleteDialogOpen(true)}
disabled={isDeleting}
>
- X Delete
+ Delete
diff --git a/src/features/dashboard/settings/webhooks/add-edit-dialog.tsx b/src/features/dashboard/settings/webhooks/add-edit-dialog.tsx
index baf9fa112..23787a632 100644
--- a/src/features/dashboard/settings/webhooks/add-edit-dialog.tsx
+++ b/src/features/dashboard/settings/webhooks/add-edit-dialog.tsx
@@ -2,7 +2,6 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { useHookFormAction } from '@next-safe-action/adapter-react-hook-form/hooks'
-import { PlusIcon } from 'lucide-react'
import { useState } from 'react'
import { upsertWebhookAction } from '@/core/server/actions/webhooks-actions'
import { UpsertWebhookSchema } from '@/core/server/functions/webhooks/schema'
@@ -21,7 +20,7 @@ import {
DialogTrigger,
} from '@/ui/primitives/dialog'
import { Form } from '@/ui/primitives/form'
-import { CheckIcon } from '@/ui/primitives/icons'
+import { AddIcon, CheckIcon } from '@/ui/primitives/icons'
import { Loader } from '@/ui/primitives/loader'
import { useDashboard } from '../../context'
import { WebhookAddEditDialogSteps } from './add-edit-dialog-steps'
@@ -239,7 +238,7 @@ export default function WebhookAddEditDialog({
{currentStep === 1 ? (
@@ -261,7 +260,7 @@ export default function WebhookAddEditDialog({
className="w-full"
disabled={!isStep2Valid}
>
-
+
Add
>
diff --git a/src/features/dashboard/settings/webhooks/edit-secret-dialog.tsx b/src/features/dashboard/settings/webhooks/edit-secret-dialog.tsx
index cb52a6a1e..6e86312cc 100644
--- a/src/features/dashboard/settings/webhooks/edit-secret-dialog.tsx
+++ b/src/features/dashboard/settings/webhooks/edit-secret-dialog.tsx
@@ -175,7 +175,7 @@ export default function WebhookEditSecretDialog({
type="submit"
disabled={!isSecretValid}
className="w-full"
- variant="outline"
+ variant="secondary"
>
Confirm
diff --git a/src/features/dashboard/settings/webhooks/table-row.tsx b/src/features/dashboard/settings/webhooks/table-row.tsx
index 780d5b347..839599747 100644
--- a/src/features/dashboard/settings/webhooks/table-row.tsx
+++ b/src/features/dashboard/settings/webhooks/table-row.tsx
@@ -1,14 +1,7 @@
'use client'
-import {
- Lock,
- MoreHorizontal,
- Pencil,
- Webhook as WebhookIcon,
-} from 'lucide-react'
import { useState } from 'react'
import { Badge } from '@/ui/primitives/badge'
-import { Button } from '@/ui/primitives/button'
import {
DropdownMenu,
DropdownMenuContent,
@@ -16,7 +9,14 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/ui/primitives/dropdown-menu'
-import { TrashIcon } from '@/ui/primitives/icons'
+import { IconButton } from '@/ui/primitives/icon-button'
+import {
+ EditIcon,
+ IndicatorDotsIcon,
+ PrivateIcon,
+ TrashIcon,
+ WebhookIcon,
+} from '@/ui/primitives/icons'
import { TableCell, TableRow } from '@/ui/primitives/table'
import WebhookAddEditDialog from './add-edit-dialog'
import WebhookDeleteDialog from './delete-dialog'
@@ -100,20 +100,21 @@ export default function WebhookTableRow({
-
-
-
+
+
+
e.preventDefault()}>
- Edit
+ Edit
e.preventDefault()}>
- Rotate Secret
+ Rotate
+ Secret
diff --git a/src/features/dashboard/sidebar/blocked-banner.tsx b/src/features/dashboard/sidebar/blocked-banner.tsx
index eab172897..63d9f1ff6 100644
--- a/src/features/dashboard/sidebar/blocked-banner.tsx
+++ b/src/features/dashboard/sidebar/blocked-banner.tsx
@@ -1,11 +1,11 @@
'use client'
-import { AlertOctagonIcon } from 'lucide-react'
import { AnimatePresence, motion } from 'motion/react'
import { useRouter } from 'next/navigation'
import { useMemo } from 'react'
import { PROTECTED_URLS } from '@/configs/urls'
import { cn, exponentialSmoothing } from '@/lib/utils'
+import { WarningIcon } from '@/ui/primitives/icons'
import { SidebarMenuButton, SidebarMenuItem } from '@/ui/primitives/sidebar'
import { useDashboard } from '../context'
@@ -45,7 +45,9 @@ export default function TeamBlockageAlert({
'bg-accent-error-bg text-accent-error-highlight border-accent-error-bg',
}}
onClick={handleClick}
- className="h-12 bg-accent-error-bg"
+ className={cn('h-9 bg-accent-error-bg', {
+ 'cursor-default': !handleClick,
+ })}
asChild
>
-
+
-
+
Team is Blocked
{team.blockedReason && (
diff --git a/src/features/dashboard/sidebar/command.tsx b/src/features/dashboard/sidebar/command.tsx
index 7c4968853..1ee3635d2 100644
--- a/src/features/dashboard/sidebar/command.tsx
+++ b/src/features/dashboard/sidebar/command.tsx
@@ -1,6 +1,5 @@
'use client'
-import { ChevronRight } from 'lucide-react'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
import { SIDEBAR_ALL_LINKS } from '@/configs/sidebar'
@@ -53,14 +52,15 @@ export default function DashboardSidebarCommand({
tooltip="Go to..."
variant={isSidebarOpen ? 'outline' : 'default'}
className={cn(
- 'text-fg-tertiary h-10 relative transition-all',
+ 'text-fg-tertiary relative transition-all pl-3 !font-normal',
'group-data-[collapsible=icon]:border-x-0 group-data-[collapsible=icon]:border-y group-data-[collapsible=icon]:!w-full group-data-[collapsible=icon]:!p-0',
className
)}
onClick={() => setOpen(true)}
>
-
- Go to
+
+ > Go to
+
@@ -86,7 +86,7 @@ export default function DashboardSidebarContent() {
>
- handleDialogChange(false)}
- disabled={isExecuting}
- >
- Cancel
-
-
- Create Team
-
+ {isExecuting ? (
+
+
+ Creating Team...
+
+ ) : (
+ <>
+ handleDialogChange(false)}
+ disabled={isExecuting}
+ >
+ Cancel
+
+
+ Create Team
+
+ >
+ )}
diff --git a/src/features/dashboard/sidebar/footer.tsx b/src/features/dashboard/sidebar/footer.tsx
index 348251221..c5146aab1 100644
--- a/src/features/dashboard/sidebar/footer.tsx
+++ b/src/features/dashboard/sidebar/footer.tsx
@@ -1,6 +1,5 @@
'use client'
-import { Book, Github, LifeBuoy, MessageSquarePlus } from 'lucide-react'
import Link from 'next/link'
import {
INCLUDE_DASHBOARD_FEEDBACK_SURVEY,
@@ -8,7 +7,13 @@ import {
} from '@/configs/flags'
import { GITHUB_URL } from '@/configs/urls'
import { cn } from '@/lib/utils'
-import ExternalIcon from '@/ui/external-icon'
+import {
+ BugIcon,
+ DocsIcon,
+ ExternalLinkIcon,
+ FeedbackIcon,
+ GithubIcon,
+} from '@/ui/primitives/icons'
import {
SIDEBAR_TRANSITION_CLASSNAMES,
SidebarFooter,
@@ -35,28 +40,18 @@ export default function DashboardSidebarFooter() {
target="_blank"
rel="noopener noreferrer"
>
-
+
GitHub
-
+
-
+
Documentation
-
+
@@ -84,13 +79,12 @@ export default function DashboardSidebarFooter() {
trigger={
-
+
Feedback
}
@@ -109,13 +103,12 @@ export default function DashboardSidebarFooter() {
trigger={
-
+
Support
}
diff --git a/src/features/dashboard/sidebar/menu-teams.tsx b/src/features/dashboard/sidebar/menu-teams.tsx
index 1a41b6159..18ed1ae54 100644
--- a/src/features/dashboard/sidebar/menu-teams.tsx
+++ b/src/features/dashboard/sidebar/menu-teams.tsx
@@ -61,19 +61,24 @@ export default function DashboardSidebarMenuTeams() {
return (
{user?.email && (
- {user.email}
+
+ {user.email}
+
)}
{teams.length > 0 ? (
teams.map((team) => (
-
-
+
+
-
+
{team.name?.charAt(0).toUpperCase() || '?'}
-
+
{getTeamDisplayName(team)}
diff --git a/src/features/dashboard/sidebar/menu.tsx b/src/features/dashboard/sidebar/menu.tsx
index 8beb64593..3d7499bda 100644
--- a/src/features/dashboard/sidebar/menu.tsx
+++ b/src/features/dashboard/sidebar/menu.tsx
@@ -1,6 +1,5 @@
'use client'
-import { ChevronsUpDown, LogOut, Plus, UserRoundCog } from 'lucide-react'
import Link from 'next/link'
import { useState } from 'react'
import { PROTECTED_URLS } from '@/configs/urls'
@@ -16,18 +15,18 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/ui/primitives/dropdown-menu'
+import {
+ AccountSettingsIcon,
+ AddIcon,
+ LogoutIcon,
+ UnpackIcon,
+} from '@/ui/primitives/icons'
import { SidebarMenuButton, SidebarMenuItem } from '@/ui/primitives/sidebar'
import { useDashboard } from '../context'
import { CreateTeamDialog } from './create-team-dialog'
import DashboardSidebarMenuTeams from './menu-teams'
-interface DashboardSidebarMenuProps {
- className?: string
-}
-
-export default function DashboardSidebarMenu({
- className,
-}: DashboardSidebarMenuProps) {
+export default function DashboardSidebarMenu() {
const { team } = useDashboard()
const [createTeamOpen, setCreateTeamOpen] = useState(false)
@@ -37,22 +36,14 @@ export default function DashboardSidebarMenu({
return (
<>
-
+
-
+
-
+
TEAM
{getTeamDisplayName(team)}
-
+
setCreateTeamOpen(true)}
>
- Create New Team
+ Create new team
-
+
-
+
- Account Settings
+ Account settings
- Log Out
+ Log out
diff --git a/src/features/dashboard/sidebar/sidebar-mobile.tsx b/src/features/dashboard/sidebar/sidebar-mobile.tsx
index de4201c1e..69f049458 100644
--- a/src/features/dashboard/sidebar/sidebar-mobile.tsx
+++ b/src/features/dashboard/sidebar/sidebar-mobile.tsx
@@ -1,6 +1,6 @@
-import { Sidebar as SidebarIcon } from 'lucide-react'
import { cn } from '@/lib/utils'
import { Drawer, DrawerContent, DrawerTrigger } from '@/ui/primitives/drawer'
+import { MenuIcon } from '@/ui/primitives/icons'
import Sidebar from './sidebar'
interface SidebarMobileProps {
@@ -11,7 +11,7 @@ export default function SidebarMobile({ className }: SidebarMobileProps) {
return (
-
+
diff --git a/src/features/dashboard/sidebar/toggle.tsx b/src/features/dashboard/sidebar/toggle.tsx
index 75b8cb1d6..eb60de04b 100644
--- a/src/features/dashboard/sidebar/toggle.tsx
+++ b/src/features/dashboard/sidebar/toggle.tsx
@@ -1,12 +1,12 @@
'use client'
-import { ArrowLeftToLine, ArrowRightFromLine } from 'lucide-react'
import { AnimatePresence, motion } from 'motion/react'
import useKeydown from '@/lib/hooks/use-keydown'
import { cn } from '@/lib/utils'
import { E2BLogo } from '@/ui/brand'
import ClientOnly from '@/ui/client-only'
-import { Button } from '@/ui/primitives/button'
+import { IconButton } from '@/ui/primitives/icon-button'
+import { CollapseLeftIcon, ExpandRightIcon } from '@/ui/primitives/icons'
import { useSidebar } from '@/ui/primitives/sidebar'
import ShortcutTooltip from '@/ui/shortcut-tooltip'
@@ -26,7 +26,7 @@ export default function DashboardSidebarToggle() {
{/* When the sidebar is closing, we want the logo to fade out AND be removed from the DOM. */}
@@ -49,18 +49,9 @@ export default function DashboardSidebarToggle() {
)}
-
- {isOpen ? (
-
- ) : (
-
- )}
-
+
+ {isOpen ? : }
+
)
diff --git a/src/features/dashboard/templates/builds/header.tsx b/src/features/dashboard/templates/builds/header.tsx
index a0d74c57e..2c783b8d8 100644
--- a/src/features/dashboard/templates/builds/header.tsx
+++ b/src/features/dashboard/templates/builds/header.tsx
@@ -115,11 +115,7 @@ export default function BuildsHeader() {
-
+
Status •{' '}
{localStatuses.length}/{STATUS_OPTIONS.length}
diff --git a/src/features/dashboard/templates/builds/table-cells.tsx b/src/features/dashboard/templates/builds/table-cells.tsx
index c57e63a61..2222fe610 100644
--- a/src/features/dashboard/templates/builds/table-cells.tsx
+++ b/src/features/dashboard/templates/builds/table-cells.tsx
@@ -1,6 +1,5 @@
'use client'
-import { ArrowUpRight } from 'lucide-react'
import { useRouter } from 'next/navigation'
import { useEffect, useState } from 'react'
import { PROTECTED_URLS } from '@/configs/urls'
@@ -46,11 +45,9 @@ export function Template({
return (
{
e.stopPropagation()
e.preventDefault()
@@ -60,7 +57,6 @@ export function Template({
}}
>
{template}
-
)
}
diff --git a/src/features/dashboard/templates/list/table-body.tsx b/src/features/dashboard/templates/list/table-body.tsx
index 56c06eff3..4d9f74b80 100644
--- a/src/features/dashboard/templates/list/table-body.tsx
+++ b/src/features/dashboard/templates/list/table-body.tsx
@@ -1,11 +1,11 @@
import { flexRender, type Table } from '@tanstack/react-table'
-import { ExternalLink, X } from 'lucide-react'
import type { RefObject } from 'react'
import type { Template } from '@/core/modules/templates/models'
import { useVirtualRows } from '@/lib/hooks/use-virtual-rows'
import { DataTableBody, DataTableCell, DataTableRow } from '@/ui/data-table'
import Empty from '@/ui/empty'
import { Button } from '@/ui/primitives/button'
+import { CloseIcon, ExternalLinkIcon } from '@/ui/primitives/icons'
import { useTemplateTableStore } from './stores/table-store'
const ROW_HEIGHT_PX = 32
@@ -58,8 +58,8 @@ export function TemplatesTableBody({
title="No Results Found"
description="No templates match your current filters"
message={
-
- Reset Filters
+
+ Reset Filters
}
className="h-[70%] max-md:sticky max-md:left-0 max-md:w-[calc(100svw-1.5rem)]"
@@ -72,10 +72,10 @@ export function TemplatesTableBody({
title="No Templates Yet"
description="Your Templates can be managed here"
message={
-
+
Create a Template
-
+
}
diff --git a/src/features/dashboard/templates/list/table-cells.tsx b/src/features/dashboard/templates/list/table-cells.tsx
index 996117eea..7892bc7f2 100644
--- a/src/features/dashboard/templates/list/table-cells.tsx
+++ b/src/features/dashboard/templates/list/table-cells.tsx
@@ -2,7 +2,6 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import type { CellContext } from '@tanstack/react-table'
-import { Check, Copy, Lock, LockOpen, MoreVertical } from 'lucide-react'
import { useMemo, useState } from 'react'
import type { DefaultTemplate, Template } from '@/core/modules/templates/models'
import { useClipboard } from '@/lib/hooks/use-clipboard'
@@ -30,6 +29,14 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/ui/primitives/dropdown-menu'
+import { IconButton } from '@/ui/primitives/icon-button'
+import {
+ CheckIcon,
+ CopyIcon,
+ IndicatorDotsIcon,
+ PrivateIcon,
+ UnlockIcon,
+} from '@/ui/primitives/icons'
import { Loader } from '@/ui/primitives/loader_d'
import ResourceUsage from '../../common/resource-usage'
import { useDashboard } from '../../context'
@@ -217,24 +224,18 @@ export function ActionsCell({
onConfirm={() => deleteTemplate()}
confirmProps={{
disabled: isDeleting,
- loading: isDeleting,
+ loading: isDeleting ? 'Deleting...' : undefined,
}}
/>
-
- {isUpdating ? (
-
- ) : (
-
- )}
-
+ {isUpdating ? : }
+
@@ -245,12 +246,12 @@ export function ActionsCell({
>
{template.public ? (
<>
-
+
Set Internal
>
) : (
<>
-
+
Set Public
>
)}
@@ -350,9 +351,9 @@ export function TemplateNameCell({
aria-hidden="true"
>
{wasCopied ? (
-
+
) : (
-
+
)}
)}
@@ -450,7 +451,7 @@ export function VisibilityCell({
size="sm"
className={cn('uppercase bg-fill', !isPublic && 'pl-[3]')}
>
- {!isPublic && }
+ {!isPublic && }
{isPublic ? 'Public' : 'Internal'}
)
diff --git a/src/features/dashboard/templates/list/table-filters.tsx b/src/features/dashboard/templates/list/table-filters.tsx
index 97c10932e..7efadf9bd 100644
--- a/src/features/dashboard/templates/list/table-filters.tsx
+++ b/src/features/dashboard/templates/list/table-filters.tsx
@@ -1,6 +1,5 @@
'use client'
-import { ListFilter } from 'lucide-react'
import * as React from 'react'
import { useDebounceValue } from 'usehooks-ts'
import { cn } from '@/lib/utils'
@@ -18,6 +17,7 @@ import {
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from '@/ui/primitives/dropdown-menu'
+import { FilterIcon } from '@/ui/primitives/icons'
import { Label } from '@/ui/primitives/label'
import { Separator } from '@/ui/primitives/separator'
import { TableFilterButton } from '@/ui/table-filter-button'
@@ -84,8 +84,7 @@ const ResourcesFilter = () => {
/>
{localValues.cpu > 0 && (
@@ -112,12 +111,7 @@ const ResourcesFilter = () => {
className="w-full"
/>
{localValues.memory > 0 && (
-
+
Clear
)}
@@ -160,8 +154,8 @@ const TemplatesTableFilters = React.forwardRef<
>
-
- Filter{' '}
+
+ Filters{' '}
diff --git a/src/features/dashboard/usage/usage-metric-chart.tsx b/src/features/dashboard/usage/usage-metric-chart.tsx
index 761333fa6..b8eb922cf 100644
--- a/src/features/dashboard/usage/usage-metric-chart.tsx
+++ b/src/features/dashboard/usage/usage-metric-chart.tsx
@@ -1,11 +1,9 @@
'use client'
import { DialogTitle } from '@radix-ui/react-dialog'
-import { Maximize2 } from 'lucide-react'
import { useState } from 'react'
import { AnimatedMetricDisplay } from '@/features/dashboard/sandboxes/monitoring/charts/animated-metric-display'
import { cn } from '@/lib/utils'
-import { Button } from '@/ui/primitives/button'
import {
Card,
CardContent,
@@ -13,6 +11,8 @@ import {
cardVariants,
} from '@/ui/primitives/card'
import { Dialog, DialogContent } from '@/ui/primitives/dialog'
+import { IconButton } from '@/ui/primitives/icon-button'
+import { UnpackIcon } from '@/ui/primitives/icons'
import ComputeUsageChart from './compute-usage-chart'
import { useUsageCharts } from './usage-charts-context'
import { UsageTimeRangeControls } from './usage-time-range-controls'
@@ -95,18 +95,17 @@ function UsageMetricChartContent({
onBrushEnd={onBrushEnd}
/>
{isChartHovered && !isFullscreen && (
- setFullscreenMetric(metric)}
- variant="ghost"
- size="iconSm"
+ variant="secondary"
className={cn(
cardVariants({ variant: 'layer' }),
'hidden lg:flex absolute top-4 right-4 opacity-70 hover:opacity-100 animate-fade-slide-in'
)}
aria-label="Expand chart to fullscreen"
>
-
-
+
+
)}
@@ -143,10 +142,7 @@ export function UsageMetricChart({
open={isFullscreen}
onOpenChange={(open) => !open && setFullscreenMetric(null)}
>
-
+
{/* title just here to avoid accessibility dev error from radix */}
{METRIC_CONFIGS[metric].title}
diff --git a/src/features/dashboard/usage/usage-time-range-controls.tsx b/src/features/dashboard/usage/usage-time-range-controls.tsx
index 84bcaddd8..a1e11be61 100644
--- a/src/features/dashboard/usage/usage-time-range-controls.tsx
+++ b/src/features/dashboard/usage/usage-time-range-controls.tsx
@@ -1,12 +1,12 @@
'use client'
-import { ChevronLeft, ChevronRight } from 'lucide-react'
import { useCallback, useMemo, useState } from 'react'
import { cn } from '@/lib/utils'
import { findMatchingPreset } from '@/lib/utils/time-range'
import { formatTimeframeAsISO8601Interval } from '@/lib/utils/timeframe'
import CopyButton from '@/ui/copy-button'
import { Button } from '@/ui/primitives/button'
+import { ChevronLeftIcon, ChevronRightIcon } from '@/ui/primitives/icons'
import {
Popover,
PopoverContent,
@@ -134,26 +134,23 @@ export function UsageTimeRangeControls({
return (
-
+
{rangeLabel}
@@ -187,13 +184,12 @@ export function UsageTimeRangeControls({
-
+
)
diff --git a/src/lib/hooks/use-clipboard.ts b/src/lib/hooks/use-clipboard.ts
index bb9768d21..834922960 100644
--- a/src/lib/hooks/use-clipboard.ts
+++ b/src/lib/hooks/use-clipboard.ts
@@ -1,3 +1,5 @@
+'use client'
+
import { useCallback, useState } from 'react'
/**
diff --git a/src/styles/theme.css b/src/styles/theme.css
index 2058328ae..2d05dd6cc 100644
--- a/src/styles/theme.css
+++ b/src/styles/theme.css
@@ -88,6 +88,7 @@
--accent-error-highlight: #ff4400;
--accent-error-bg: rgba(255, 68, 0, 0.16);
--accent-error-bg-large: rgba(255, 68, 0, 0.08);
+ --accent-error-bg-large-solid: #faebe6;
--accent-secondary-error-highlight: #ff8763;
--accent-secondary-error-bg: rgb(255, 135, 99, 0.16);
@@ -187,6 +188,7 @@
--accent-error-highlight: #f54545;
--accent-error-bg: rgba(245, 69, 69, 0.16);
--accent-error-bg-large: rgba(245, 69, 69, 0.08);
+ --accent-error-bg-large-solid: #1d0f0f;
--accent-secondary-error-highlight: #ff8763;
--accent-secondary-error-bg: rgba(255, 135, 99, 0.16);
@@ -297,6 +299,7 @@
--color-accent-error-highlight: var(--accent-error-highlight);
--color-accent-error-bg: var(--accent-error-bg);
--color-accent-error-bg-large: var(--accent-error-bg-large);
+ --color-accent-error-bg-large-solid: var(--accent-error-bg-large-solid);
--color-accent-secondary-error-highlight: var(
--accent-secondary-error-highlight
diff --git a/src/ui/alert-dialog.tsx b/src/ui/alert-dialog.tsx
index 41f71ecb2..b3ac378ba 100644
--- a/src/ui/alert-dialog.tsx
+++ b/src/ui/alert-dialog.tsx
@@ -51,7 +51,7 @@ export const AlertDialog: FC = ({
{children && {children}
}
- {cancel}
+ {cancel}
= ({
{children && {children}
}
-
+
{cancel}
-
+
{confirm}
diff --git a/src/ui/brand.tsx b/src/ui/brand.tsx
index 5cfeeca36..5ed480f24 100644
--- a/src/ui/brand.tsx
+++ b/src/ui/brand.tsx
@@ -1,4 +1,4 @@
-import { cn } from '@/lib/utils'
+import { cn } from '@/lib/utils/ui'
import { Badge, type BadgeProps } from '@/ui/primitives/badge'
export const E2BLogo = ({
diff --git a/src/ui/code-block.tsx b/src/ui/code-block.tsx
index 82631ad52..b55399bd9 100644
--- a/src/ui/code-block.tsx
+++ b/src/ui/code-block.tsx
@@ -128,9 +128,7 @@ export const CodeBlock = forwardRef(
) : (
allowCopy && (
)
diff --git a/src/ui/copy-button-inline.tsx b/src/ui/copy-button-inline.tsx
index 303a06f45..12e1154a6 100644
--- a/src/ui/copy-button-inline.tsx
+++ b/src/ui/copy-button-inline.tsx
@@ -1,6 +1,7 @@
import { useRef, useState } from 'react'
import { useClipboard } from '@/lib/hooks/use-clipboard'
import { cn } from '@/lib/utils/ui'
+import { CheckIcon, CopyIcon } from '@/ui/primitives/icons'
export default function CopyButtonInline({
value,
@@ -11,33 +12,35 @@ export default function CopyButtonInline({
children: React.ReactNode
className?: string
}) {
- const [wasCopied, copy] = useClipboard()
- const buttonRef = useRef(null)
- const [capturedWidth, setCapturedWidth] = useState(null)
+ const [wasCopied, copy] = useClipboard(2000)
const handleClick = (e: React.MouseEvent) => {
e.stopPropagation()
- if (buttonRef.current && !wasCopied) {
- setCapturedWidth(buttonRef.current.offsetWidth)
- }
copy(value)
}
return (
- {wasCopied ? 'Copied!' : children}
+ {children}
+
+ {wasCopied ? (
+
+ ) : (
+
+ )}
+
)
}
diff --git a/src/ui/copy-button.tsx b/src/ui/copy-button.tsx
index af27dad71..825b7e346 100644
--- a/src/ui/copy-button.tsx
+++ b/src/ui/copy-button.tsx
@@ -1,40 +1,52 @@
'use client'
-import { CheckIcon } from 'lucide-react'
-import type { FC } from 'react'
+import { AnimatePresence, motion } from 'motion/react'
+import { FC } from 'react'
import { useClipboard } from '@/lib/hooks/use-clipboard'
-import { Button, type ButtonProps } from '@/ui/primitives/button'
-import { CopyIcon } from './primitives/icons'
+import { EASE_APPEAR } from '@/lib/utils/ui'
+import { IconButton, IconButtonProps } from '@/ui/primitives/icon-button'
+import { CheckIcon, CopyIcon } from '@/ui/primitives/icons'
-interface CopyButtonProps extends ButtonProps {
+interface CopyButtonProps extends IconButtonProps {
value: string
onCopy?: () => void
}
-const CopyButton: FC = ({
- value,
- onCopy,
- onClick,
- ...props
-}) => {
- const [wasCopied, copy] = useClipboard()
-
- const handleClick = (e: React.MouseEvent) => {
- e.stopPropagation()
- e.preventDefault()
- copy(value)
- onCopy?.()
- onClick?.(e)
- }
+const CopyButton: FC = ({ value, onCopy, ...props }) => {
+ const [wasCopied, copy] = useClipboard(1000)
return (
-
- {wasCopied ? (
-
- ) : (
-
- )}
-
+ {
+ copy(value)
+ onCopy?.()
+ }}
+ {...props}
+ >
+
+ {wasCopied ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
)
}
diff --git a/src/ui/data-table.tsx b/src/ui/data-table.tsx
index 7059a12bd..d317e4943 100644
--- a/src/ui/data-table.tsx
+++ b/src/ui/data-table.tsx
@@ -1,12 +1,8 @@
import type { Cell, Header } from '@tanstack/react-table'
-import {
- ArrowDownWideNarrow,
- ArrowUpDown,
- ArrowUpNarrowWide,
-} from 'lucide-react'
import * as React from 'react'
import { cn } from '@/lib/utils'
import { Button } from '@/ui/primitives/button'
+import { SortAscIcon, SortDescIcon } from '@/ui/primitives/icons'
import {
Select,
SelectContent,
@@ -73,14 +69,14 @@ function DataTableHead({
{sorting === undefined ? (
// Show the arrow for the next state based on sortDescFirst
header.column.columnDef.sortDescFirst ? (
-
+
) : (
-
+
)
) : sorting ? (
-
+
) : (
-
+
)}
)}
@@ -179,7 +175,6 @@ const DataTable = React.forwardRef(
className={cn(
// Base table styles from table.tsx
'w-full caption-bottom',
- 'font-mono',
// Div table styles
'w-fit',
className
@@ -265,32 +260,32 @@ function DataTablePagination({
onPageChange(0)}
disabled={pageIndex === 0}
>
««
onPageChange(pageIndex - 1)}
disabled={pageIndex === 0}
>
«
onPageChange(pageIndex + 1)}
disabled={pageIndex === pageCount - 1}
>
»
onPageChange(pageCount - 1)}
disabled={pageIndex === pageCount - 1}
>
diff --git a/src/ui/docs-code-block.tsx b/src/ui/docs-code-block.tsx
index b4f0f9d6d..9cb029a1a 100644
--- a/src/ui/docs-code-block.tsx
+++ b/src/ui/docs-code-block.tsx
@@ -1,6 +1,5 @@
'use client'
import type { ScrollAreaViewportProps } from '@radix-ui/react-scroll-area'
-import { Check, Copy } from 'lucide-react'
import {
type ButtonHTMLAttributes,
forwardRef,
@@ -12,6 +11,7 @@ import {
import { useClipboard } from '@/lib/hooks/use-clipboard'
import { cn } from '@/lib/utils'
import { buttonVariants } from './primitives/button'
+import { CheckIcon, CopyIcon } from './primitives/icons'
import { ScrollArea, ScrollBar, ScrollViewport } from './primitives/scroll-area'
export type CodeBlockProps = HTMLAttributes & {
@@ -160,7 +160,8 @@ function CopyButton({
type="button"
className={cn(
buttonVariants({
- variant: 'ghost',
+ variant: 'tertiary',
+ size: 'none',
}),
'transition-opacity group-hover:opacity-100 [&_svg]:size-3.5',
!isCopied && '[@media(hover:hover)]:opacity-0',
@@ -170,8 +171,10 @@ function CopyButton({
onClick={onCopy}
{...props}
>
-
-
+
diff --git a/src/ui/error-indicator.tsx b/src/ui/error-indicator.tsx
index 22542bd59..cf40fc404 100644
--- a/src/ui/error-indicator.tsx
+++ b/src/ui/error-indicator.tsx
@@ -1,6 +1,5 @@
'use client'
-import { RefreshCcw } from 'lucide-react'
import { useRouter } from 'next/navigation'
import { useTransition } from 'react'
import { cn } from '@/lib/utils'
@@ -13,6 +12,7 @@ import {
CardHeader,
CardTitle,
} from './primitives/card'
+import { RefreshIcon } from './primitives/icons'
interface ErrorIndicatorProps {
title?: string
@@ -50,12 +50,12 @@ export function ErrorIndicator({
)}
startTransition(() => router.refresh())}
- className="w-full max-w-md gap-2"
+ className="w-full max-w-md gap-1"
>
-
Refresh
diff --git a/src/ui/error-tooltip.tsx b/src/ui/error-tooltip.tsx
index 42e6eea6e..30f7fb166 100644
--- a/src/ui/error-tooltip.tsx
+++ b/src/ui/error-tooltip.tsx
@@ -1,4 +1,4 @@
-import { AlertTriangle } from 'lucide-react'
+import { WarningIcon } from './primitives/icons'
import {
Tooltip,
TooltipContent,
@@ -17,11 +17,11 @@ export default function ErrorTooltip({ children, trigger }: ErrorTooltipProps) {
{trigger || (
-
+
)}
-
-
+
+
{children}
diff --git a/src/ui/external-icon.tsx b/src/ui/external-icon.tsx
index 840268e2f..3f846ef15 100644
--- a/src/ui/external-icon.tsx
+++ b/src/ui/external-icon.tsx
@@ -1,5 +1,5 @@
-import { ChevronRight } from 'lucide-react'
import { cn } from '@/lib/utils'
+import { ChevronRightIcon } from './primitives/icons'
interface ExternalIconProps {
className?: string
@@ -7,7 +7,7 @@ interface ExternalIconProps {
export default function ExternalIcon({ className }: ExternalIconProps) {
return (
- & {
- icon?: LucideIcon
+ icon?: Icon
}): React.ReactElement {
return (
{Icon ? (
) : (
-
+
)}
)
diff --git a/src/ui/json-popover.tsx b/src/ui/json-popover.tsx
index 24192ab5b..dc96d9330 100644
--- a/src/ui/json-popover.tsx
+++ b/src/ui/json-popover.tsx
@@ -33,10 +33,10 @@ export function JsonPopover({
{
diff --git a/src/ui/live.tsx b/src/ui/live.tsx
index 29af56f85..e30ffd859 100644
--- a/src/ui/live.tsx
+++ b/src/ui/live.tsx
@@ -51,7 +51,6 @@ export function LiveBadge({
return (
-
-
-
-
-
+
+
+
+
+
Home
-
-
-
+
+
+
Dashboard
window.history.back()}
- className="w-full gap-2"
+ className="w-full"
>
-
+
Go Back
diff --git a/src/ui/number-input.tsx b/src/ui/number-input.tsx
index 73c72fa34..881678e43 100644
--- a/src/ui/number-input.tsx
+++ b/src/ui/number-input.tsx
@@ -1,9 +1,9 @@
'use client'
-import { ChevronDown, ChevronUp } from 'lucide-react'
import * as React from 'react'
import { cn } from '@/lib/utils'
-import { Button } from './primitives/button'
+import { IconButton } from './primitives/icon-button'
+import { ChevronDownIcon, ChevronUpIcon } from './primitives/icons'
import { Input } from './primitives/input'
export interface NumberInputProps
@@ -97,34 +97,26 @@ export function NumberInput({
return (
- = max}
>
-
+
Increase
-
-
+
-
+
Decrease
-
+
-
+
-
-
+
-
+
Auto-refresh
{interval === 0 ? 'Off' : formatSeconds(remainingSeconds)}
diff --git a/src/ui/primitives/badge.tsx b/src/ui/primitives/badge.tsx
index e65cc848b..bd970e6f4 100644
--- a/src/ui/primitives/badge.tsx
+++ b/src/ui/primitives/badge.tsx
@@ -1,41 +1,45 @@
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import type * as React from 'react'
-import { cn } from '@/lib/utils/index'
+import { cn } from '@/lib/utils/ui'
const badgeVariants = cva(
- 'inline-flex items-center cursor-default justify-center focus-visible:ring-1 w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 [&>svg]:pointer-events-none ![&>svg]:pl-0.75 aria-invalid:ring-accent-error-highlight/20 aria-invalid:border-accent-error-highlight transition-[color,box-shadow] overflow-hidden',
+ [
+ // Base layout and sizing
+ 'inline-flex items-center justify-center w-fit',
+ // Text and cursor
+ 'prose-label uppercase cursor-default whitespace-nowrap shrink-0 overflow-hidden',
+ // Icon styles
+ ' [&>svg]:pointer-events-none ![&>svg]:pl-0.75 [&>svg]:size-3',
+ // Interactive states
+ 'focus-visible:ring-1',
+ // Error state
+ 'aria-invalid:ring-accent-error-highlight/20 aria-invalid:border-accent-error-highlight',
+ ].join(' '),
{
variants: {
variant: {
- default: 'bg-bg-highlight text-fg-secondary',
+ default: 'bg-fill text-fg-secondary',
positive: 'bg-accent-positive-bg text-accent-positive-highlight',
warning: 'bg-accent-warning-bg text-accent-warning-highlight',
info: 'bg-accent-info-bg text-accent-info-highlight',
- main: 'bg-accent-main-bg text-accent-main-highlight',
error: 'bg-accent-error-bg text-accent-error-highlight',
code: 'bg-bg-1 ring-1 ring-stroke text-fg-secondary font-mono',
},
- size: {
- default: 'h-5 px-1 gap-1',
- sm: 'h-4.5 px-[5] text-xs gap-0.5',
- lg: 'h-7 px-2 gap-1.5',
- xl: 'h-9 px-3 gap-1.5',
- },
can: {
none: '',
hover: 'hover:ring-1 ring-[currentColor]',
},
- typography: {
- highlight: 'prose-label-highlight',
- regular: 'prose-label',
+ size: {
+ sm: 'h-4.5 px-1 gap-0.5',
+ md: 'h-5.5 px-2 gap-1',
+ lg: 'h-6.5 px-2 gap-1.5',
},
},
defaultVariants: {
variant: 'default',
- size: 'default',
+ size: 'sm',
can: 'none',
- typography: 'regular',
},
}
)
diff --git a/src/ui/primitives/button.tsx b/src/ui/primitives/button.tsx
index 4b6a0d05e..25219ab5d 100644
--- a/src/ui/primitives/button.tsx
+++ b/src/ui/primitives/button.tsx
@@ -1,75 +1,82 @@
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import * as React from 'react'
-import { cn } from '@/lib/utils/index'
-import { Loader } from './loader_d'
+import { cn } from '@/lib/utils/ui'
+import { Loader } from './loader'
+
+const linkStyles = [
+ 'text-fg-secondary underline underline-offset-2',
+ 'hover:opacity-80', // hover
+ 'data-[display-state=hover]:opacity-80', // duplicated hover, for display purposes
+ 'disabled:opacity-50', // disabled
+]
const buttonVariants = cva(
[
- 'inline-flex items-center cursor-pointer justify-center whitespace-nowrap',
- 'font-mono uppercase',
- 'transition-colors duration-150',
- 'focus-visible:outline-none ',
- 'disabled:pointer-events-none disabled:opacity-50',
+ 'inline-flex items-center cursor-pointer justify-center whitespace-nowrap',
+ 'transition-colors [&_svg]:transition-colors disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0',
+ '[&_svg]:text-icon-tertiary',
].join(' '),
{
variants: {
variant: {
- default: [
+ primary: [
+ 'prose-body-highlight',
+ '[&_svg]:text-icon-inverted',
'bg-bg-inverted text-fg-inverted',
- 'hover:bg-bg-inverted-hover focus:bg-bg-inverted-hover',
- 'active:translate-y-[1px] active:shadow-none',
+ 'hover:bg-bg-inverted-hover', // hover
+ 'data-[display-state=hover]:bg-bg-inverted-hover', // duplicated hover, for display purposes
+ 'disabled:text-fg-tertiary disabled:bg-fill disabled:[&_svg]:text-icon-tertiary', // disabled
+ 'data-[state=open]:bg-bg-inverted-hover',
].join(' '),
- accent: [
- 'bg-accent-main-bg text-accent-main-highlight ',
- 'hover:bg-accent-main-bg/80 focus:bg-accent-main-bg/80',
- 'active:translate-y-[1px] active:shadow-none',
+ secondary: [
+ 'prose-body-highlight',
+ 'border',
+ 'hover:border-stroke-active', // hover
+ 'data-[display-state=hover]:border-stroke-active', // duplicated hover, for display purposes
+ 'active:bg-bg-1 active:[&_svg]:text-icon', // active
+ 'data-[display-state=active]:bg-bg-1 data-[display-state=active]:[&_svg]:text-icon', // duplicated active, for display purposes
+ 'disabled:opacity-65', // disabled
+ 'data-[state=open]:bg-bg-1',
].join(' '),
- ghost: [
- 'bg-transparent',
- 'hover:bg-transparent focus:bg-transparent',
- 'active:translate-y-[1px] active:shadow-none',
+ tertiary: [
+ 'prose-body-highlight',
+ 'text-fg',
+ 'hover:text-fg hover:underline', // hover
+ 'data-[display-state=hover]:text-fg data-[display-state=hover]:underline', // duplicated hover, for display purposes
+ 'active:text-fg active:[&_svg]:text-icon', // active
+ 'data-[display-state=active]:text-fg data-[display-state=active]:[&_svg]:text-icon', // duplicated active, for display purposes
+ 'disabled:opacity-65 disabled:text-fg-tertiary', // disabled
].join(' '),
- muted: [
- 'border bg-bg-hover text-fg-secondary hover:text-fg',
- 'hover:bg-bg-hover/90 focus:bg-bg-hover/90',
- 'active:translate-y-[1px] active:shadow-none',
+ quaternary: [
+ 'prose-body-highlight',
+ 'text-fg-tertiary',
+ 'hover:text-fg', // hover
+ 'data-[display-state=hover]:text-fg', // duplicated hover, for display purposes
+ 'active:text-fg active:[&_svg]:text-icon', // active
+ 'data-[display-state=active]:text-fg data-[display-state=active]:[&_svg]:text-icon', // duplicated active, for display purposes
+ 'disabled:opacity-65', // disabled
].join(' '),
error: [
- 'bg-accent-error-bg text-accent-error-highlight',
- 'hover:bg-accent-error-bg focus:bg-accent-error-bg',
- 'active:translate-y-[1px] active:shadow-none',
- ].join(' '),
- warning: [
- 'bg-accent-warning-bg text-accent-warning-highlight',
- 'hover:bg-accent-warning-bg focus:bg-accent-warning-bg',
- 'active:translate-y-[1px] active:shadow-none',
- ].join(' '),
- outline: [
- 'border border-stroke bg-transparent',
- 'hover:bg-bg-1 focus:bg-bg-1',
- 'active:translate-y-[1px] active:shadow-none',
- ].join(' '),
- link: [
- 'text-accent-main-highlight underline-offset-4',
- 'hover:underline hover:bg-transparent',
- 'focus:ring-0 focus:underline focus:bg-transparent',
- 'shadow-none',
+ 'prose-body-highlight',
+ '[&_svg]:text-icon-inverted',
+ 'bg-accent-error-highlight text-fg-inverted',
+ 'hover:bg-accent-error-highlight/90', // hover
+ 'data-[display-state=hover]:bg-accent-error-highlight/90', // duplicated hover, for display purposes
+ 'disabled:text-fg-tertiary disabled:bg-fill disabled:[&_svg]:text-icon-tertiary', // disabled
+ 'data-[state=open]:bg-accent-error-highlight/90',
].join(' '),
+ link: ['prose-body', ...linkStyles].join(' '),
+ 'link-table': ['prose-table', ...linkStyles].join(' '),
},
size: {
- default: 'h-8 px-3 gap-2',
- sm: 'h-7 px-2 gap-1 text-xs',
- md: 'h-9 px-3 gap-2',
- lg: 'h-10 px-4 gap-2',
- icon: 'h-8 w-8 gap-2',
- iconSm: 'h-7 w-7 gap-1',
- iconLg: 'h-10 w-10 text-xl gap-2',
- slate: 'h-auto px-0 py-0 gap-1',
+ default:
+ '[&_svg]:size-4 h-9 py-1.5 gap-1 [&:has(svg)]:pr-3 [&:has(svg)]:pl-2.5 px-4',
+ none: 'gap-1 [&_svg]:size-4',
},
},
defaultVariants: {
- variant: 'default',
+ variant: 'primary',
size: 'default',
},
}
@@ -79,31 +86,31 @@ export interface ButtonProps
extends React.ButtonHTMLAttributes,
VariantProps {
asChild?: boolean
- loading?: boolean
+ loading?: string
}
const Button = React.forwardRef(
- (
- { className, variant, size, asChild = false, loading = false, ...props },
- ref
- ) => {
+ ({ className, variant, size, asChild = false, loading, ...props }, ref) => {
+ if (loading) {
+ return (
+
+ {loading}
+
+ )
+ }
+
const Comp = asChild ? Slot : 'button'
return (
- {loading ? (
-
- {props.children}
-
-
- ) : (
- props.children
- )}
-
+ />
)
}
)
diff --git a/src/ui/primitives/calendar.tsx b/src/ui/primitives/calendar.tsx
index 1db9e5630..b2c430fc1 100644
--- a/src/ui/primitives/calendar.tsx
+++ b/src/ui/primitives/calendar.tsx
@@ -1,19 +1,14 @@
'use client'
-import {
- ChevronDownIcon,
- ChevronLeftIcon,
- ChevronRightIcon,
-} from 'lucide-react'
import * as React from 'react'
import {
type DayButton,
DayPicker,
getDefaultClassNames,
} from 'react-day-picker'
-
import { cn } from '@/lib/utils/index'
import { Button, buttonVariants } from '@/ui/primitives/button'
+import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from './icons'
// we need to properly type the Calendar props to work with react-day-picker's union types
// the DayPicker component has different prop requirements based on the mode
@@ -81,7 +76,7 @@ function Calendar({
classNames,
showOutsideDays = true,
captionLayout = 'label',
- buttonVariant = 'ghost',
+ buttonVariant = 'tertiary',
formatters,
components,
minDate,
@@ -258,8 +253,8 @@ function CalendarDayButton({
return (
,
@@ -41,7 +40,7 @@ const CommandInput = React.forwardRef<
React.ComponentPropsWithoutRef
>(({ className, ...props }, ref) => (
-
+
{
hideClose?: boolean
- closeButtonClassName?: string
}
function DialogContent({
className,
children,
hideClose,
- closeButtonClassName,
...props
}: DialogContentProps) {
return (
@@ -65,8 +68,17 @@ function DialogContent({
-
+
Close
)}
@@ -118,7 +135,7 @@ function DialogTitle({
return (
)
@@ -131,7 +148,7 @@ function DialogDescription({
return (
)
diff --git a/src/ui/primitives/dropdown-menu.tsx b/src/ui/primitives/dropdown-menu.tsx
index 054d04032..f3bfd3ad7 100644
--- a/src/ui/primitives/dropdown-menu.tsx
+++ b/src/ui/primitives/dropdown-menu.tsx
@@ -2,11 +2,10 @@
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
import type { VariantProps } from 'class-variance-authority'
-import { ChevronRight } from 'lucide-react'
import * as React from 'react'
import { cn } from '@/lib/utils'
import { Checkbox } from './checkbox'
-import { CheckIcon } from './icons'
+import { CheckIcon, ChevronRightIcon } from './icons'
import {
menuContentStyles,
menuGroupStyles,
@@ -51,7 +50,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
{...props}
>
{children}
-
+
))
DropdownMenuSubTrigger.displayName =
diff --git a/src/ui/primitives/icon-button.tsx b/src/ui/primitives/icon-button.tsx
new file mode 100644
index 000000000..25adc157b
--- /dev/null
+++ b/src/ui/primitives/icon-button.tsx
@@ -0,0 +1,69 @@
+import { Slot } from '@radix-ui/react-slot'
+import { cva, type VariantProps } from 'class-variance-authority'
+import * as React from 'react'
+import { cn } from '@/lib/utils/ui'
+
+const iconButtonVariants = cva(
+ [
+ 'inline-flex items-center cursor-pointer justify-center shrink-0',
+ 'transition-colors [&_svg]:transition-colors disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0',
+ '[&_svg]:text-icon-tertiary',
+ ].join(' '),
+ {
+ variants: {
+ variant: {
+ secondary: [
+ 'h-9 w-9 [&_svg]:size-4',
+ 'border',
+ 'hover:border-stroke-active', // hover
+ 'data-[display-state=hover]:border-stroke-active', // display hover
+ 'active:bg-bg-1', // active
+ 'data-[display-state=active]:bg-bg-1', // display active
+ 'disabled:opacity-50', // disabled
+ 'data-[state=open]:bg-bg-1', // open (e.g. popover trigger)
+ 'data-[selected=true]:bg-bg-1 data-[selected=true]:border-stroke-active data-[selected=true]:[&_svg]:text-fg', // selected
+ ].join(' '),
+ tertiary: [
+ 'size-4 [&_svg]:size-4',
+ // auto-shrink to 12×12 when nested inside a Badge (data-slot="badge")
+ 'in-data-[slot=badge]:size-3 in-data-[slot=badge]:[&_svg]:size-3',
+ 'hover:[&_svg]:text-icon', // hover
+ 'data-[display-state=hover]:[&_svg]:text-icon', // display hover
+ 'active:[&_svg]:text-icon', // active
+ 'data-[display-state=active]:[&_svg]:text-icon', // display active
+ 'disabled:opacity-50', // disabled
+ ].join(' '),
+ },
+ size: {
+ default: '',
+ xl: 'size-14 [&_svg]:size-7',
+ },
+ },
+ defaultVariants: {
+ variant: 'tertiary',
+ size: 'default',
+ },
+ }
+)
+
+export interface IconButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean
+}
+
+const IconButton = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : 'button'
+ return (
+
+ )
+ }
+)
+IconButton.displayName = 'IconButton'
+
+export { IconButton, iconButtonVariants }
diff --git a/src/ui/primitives/icons.tsx b/src/ui/primitives/icons.tsx
index 9fb556d21..126e7797a 100644
--- a/src/ui/primitives/icons.tsx
+++ b/src/ui/primitives/icons.tsx
@@ -1,14 +1,16 @@
import type React from 'react'
import { cn } from '@/lib/utils/index'
-const DEFAULT_CLASS_NAMES = 'size-6'
+const DEFAULT_CLASS_NAMES = 'size-4'
-interface IconProps extends React.SVGProps {
+export interface IconProps extends React.SVGProps {
className?: string
height?: number
width?: number
}
+export type Icon = React.ComponentType
+
export const SandboxIcon = ({ className, ...props }: IconProps) => (
(
)
+export const BugIcon = ({ className, ...props }: IconProps) => (
+
+
+
+)
+
+export const FeedbackIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
export const CodeChevronIcon = ({ className, ...props }: IconProps) => (
(
)
+export const UnlockIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+
+)
+
export const EnterpriseIcon = ({ className, ...props }: IconProps) => (
(
)
+export const ArrowRightIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const ArrowLeftIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const ArrowUpIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const HomeIcon = ({ className, ...props }: IconProps) => (
+
+
+
+)
+
+export const MoonIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const SunIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const SystemIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const CalendarIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+
+
+)
+
+export const CloudIcon = ({ className, ...props }: IconProps) => (
+
+
+
+)
+
+export const LinkIcon = ({ className, ...props }: IconProps) => (
+
+
+
+)
+
+export const SelectIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const SuccessIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const EyeIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const EyeOffIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+
+
+
+)
+
+export const DownloadIcon = ({ className, ...props }: IconProps) => (
+
+
+
+)
+
+export const FolderIcon = ({ className, ...props }: IconProps) => (
+
+
+
+)
+
+export const FolderOpenIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const FolderUpIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+
+)
+
+export const FileIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const SpinnerIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const TerminalCustomIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+)
+
+export const SortIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+
+
+)
+
+export const SortAscIcon = ({ className, ...props }: IconProps) => (
+
+
+
+)
+
+export const SortDescIcon = ({ className, ...props }: IconProps) => (
+
+
+
+)
+
export const InvoiceIcon = ({ className, ...props }: IconProps) => (
(
)
+export const DashboardIcon = ({ className, ...props }: IconProps) => (
+
+
+
+
+
+)
+
+export const ShieldXIcon = ({ className, ...props }: IconProps) => (
+
+
+
+)
+
+export const UploadIcon = ({ className, ...props }: IconProps) => (
+
+
+
+)
+
export const WebhookIcon = ({ className, ...props }: IconProps) => (
(
- {index > 0 && '+'}
+ {index > 0 && ' '}
{formattedKey}
)
diff --git a/src/ui/primitives/loader.tsx b/src/ui/primitives/loader.tsx
index 0fbb58cb5..f2e0f5c21 100644
--- a/src/ui/primitives/loader.tsx
+++ b/src/ui/primitives/loader.tsx
@@ -1,3 +1,5 @@
+'use client'
+
import * as React from 'react'
import styled, { css } from 'styled-components'
@@ -62,7 +64,7 @@ const StyledLoader = styled.div`
`
const Loader = React.forwardRef(
- ({ className, variant = 'square', size = 'md', ...props }, ref) => {
+ ({ className, variant = 'slash', size = 'md', ...props }, ref) => {
return (
<>