From 848205f5cb87637f43bc109d41109904b026756b Mon Sep 17 00:00:00 2001 From: Brandon McConnell Date: Tue, 9 Sep 2025 15:44:07 -0400 Subject: [PATCH] Upgrade to Tailwind CSS v4 (#1173) --- .eslintrc.json | 23 - app/(auth)/login/page.tsx | 10 +- app/(auth)/register/page.tsx | 10 +- app/globals.css | 364 ++++++++------ artifacts/text/client.tsx | 4 +- biome.jsonc | 7 +- components.json | 2 +- components/app-sidebar.tsx | 12 +- components/artifact-actions.tsx | 2 +- components/artifact-messages.tsx | 4 +- components/artifact.tsx | 26 +- components/auth-form.tsx | 4 +- components/chat-header.tsx | 6 +- components/chat.tsx | 4 +- components/code-editor.tsx | 2 +- components/console.tsx | 18 +- components/document-preview.tsx | 28 +- components/document-skeleton.tsx | 36 +- components/document.tsx | 12 +- components/elements/actions.tsx | 4 +- components/elements/conversation.tsx | 4 +- components/elements/prompt-input.tsx | 12 +- components/elements/reasoning.tsx | 6 +- components/elements/response.tsx | 2 +- components/elements/source.tsx | 2 +- components/elements/task.tsx | 2 +- components/elements/tool.tsx | 17 +- components/elements/web-preview.tsx | 2 +- components/greeting.tsx | 6 +- components/image-editor.tsx | 6 +- components/message-actions.tsx | 4 +- components/message-editor.tsx | 10 +- components/message-reasoning.tsx | 10 +- components/message.tsx | 28 +- components/messages.tsx | 12 +- components/model-selector.tsx | 10 +- components/multimodal-input.tsx | 28 +- components/preview-attachment.tsx | 6 +- components/sidebar-history-item.tsx | 6 +- components/sidebar-history.tsx | 24 +- components/sidebar-toggle.tsx | 6 +- components/sidebar-user-nav.tsx | 14 +- components/sign-out-form.tsx | 2 +- components/submit-button.tsx | 2 +- components/suggested-actions.tsx | 51 +- components/suggestion.tsx | 16 +- components/text-editor.tsx | 2 +- components/toast.tsx | 6 +- components/toolbar.tsx | 16 +- components/ui/alert-dialog.tsx | 8 +- components/ui/avatar.tsx | 32 +- components/ui/badge.tsx | 26 +- components/ui/button.tsx | 2 +- components/ui/card.tsx | 6 +- components/ui/carousel.tsx | 200 ++++---- components/ui/collapsible.tsx | 12 +- components/ui/dropdown-menu.tsx | 14 +- components/ui/hover-card.tsx | 24 +- components/ui/input.tsx | 2 +- components/ui/scroll-area.tsx | 34 +- components/ui/select.tsx | 12 +- components/ui/separator.tsx | 2 +- components/ui/sheet.tsx | 8 +- components/ui/sidebar.tsx | 54 +-- components/ui/textarea.tsx | 2 +- components/ui/tooltip.tsx | 2 +- components/version-footer.tsx | 2 +- components/visibility-selector.tsx | 10 +- components/weather.tsx | 12 +- hooks/use-scroll-to-bottom.tsx | 4 +- lib/ai/models.mock.ts | 2 +- lib/ai/models.ts | 3 +- package.json | 7 +- pnpm-lock.yaml | 694 ++++++++++++++------------- postcss.config.mjs | 3 +- tailwind.config.ts | 81 ---- 76 files changed, 1098 insertions(+), 1050 deletions(-) delete mode 100644 .eslintrc.json delete mode 100644 tailwind.config.ts diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index a44aff8..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "extends": [ - "next/core-web-vitals", - "plugin:import/recommended", - "plugin:import/typescript", - "prettier", - "plugin:tailwindcss/recommended" - ], - "plugins": ["tailwindcss"], - "rules": { - "tailwindcss/no-custom-classname": "off", - "tailwindcss/classnames-order": "off" - }, - "settings": { - "import/resolver": { - "typescript": { - "alwaysTryTypes": true, - "project": "./tsconfig.json" - } - } - }, - "ignorePatterns": ["**/components/ui/**"] -} diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index e5be52a..2c9759b 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -50,17 +50,17 @@ export default function Page() { }; return ( -
-
+
+
-

Sign In

-

+

Sign In

+

Use your email and password to sign in

Sign in -

+

{"Don't have an account? "} -

+
+
-

Sign Up

-

+

Sign Up

+

Create an account with your email and password

Sign Up -

+

{'Already have an account? '} .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .ͼo.cm-selectionBackground, .ͼo.cm-content::selection { - @apply bg-zinc-200 dark:bg-zinc-900 !important; + @apply bg-zinc-200! dark:bg-zinc-900!; } .cm-activeLine, .cm-activeLineGutter { - @apply bg-transparent !important; + @apply bg-transparent!; } .cm-activeLine { - @apply rounded-r-sm !important; + @apply rounded-r-sm!; } .cm-lineNumbers { - @apply min-w-7; + @apply min-w-7; } .cm-foldGutter { - @apply min-w-3; + @apply min-w-3; } .cm-lineNumbers .cm-activeLineGutter { - @apply rounded-l-sm !important; + @apply rounded-l-sm!; } .suggestion-highlight { - @apply bg-blue-200 hover:bg-blue-300 dark:hover:bg-blue-400/50 dark:text-blue-50 dark:bg-blue-500/40; + @apply bg-blue-200 hover:bg-blue-300 dark:hover:bg-blue-400/50 dark:text-blue-50 dark:bg-blue-500/40; } /* minimal scrollbar styling */ ::-webkit-scrollbar { - width: 6px; - height: 6px; + width: 6px; + height: 6px; } ::-webkit-scrollbar-track { - background: transparent; + background: transparent; } ::-webkit-scrollbar-thumb { - background: hsl(var(--border)); - border-radius: 3px; - transition: background 0.2s ease; + background: var(--border); + border-radius: 3px; + transition: background 0.2s ease; } ::-webkit-scrollbar-thumb:hover { - background: hsl(var(--muted-foreground) / 0.5); + background: --alpha(var(--muted-foreground) / 0.5); } ::-webkit-scrollbar-corner { - background: transparent; + background: transparent; } /* firefox scrollbar styling */ * { - scrollbar-width: thin; - scrollbar-color: hsl(var(--border)) transparent; + scrollbar-width: thin; + scrollbar-color: var(--border) transparent; } diff --git a/artifacts/text/client.tsx b/artifacts/text/client.tsx index f2371ac..813c400 100644 --- a/artifacts/text/client.tsx +++ b/artifacts/text/client.tsx @@ -77,7 +77,7 @@ export const textArtifact = new Artifact<'text', TextArtifactMetadata>({ return ( <> -

+
({ /> {metadata?.suggestions && metadata.suggestions.length > 0 ? ( -
+
) : null}
diff --git a/biome.jsonc b/biome.jsonc index d227936..65729f6 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -62,7 +62,7 @@ "useArrayLiterals": "warn", // Not in recommended ruleset, turning on manually "noNewSymbol": "warn", // Not in recommended ruleset, turning on manually "useJsxKeyInIterable": "off", // Rule is buggy, revisit later - "useExhaustiveDependencies": "off", // Community feedback on this rule has been poor, we will continue with ESLint + "useExhaustiveDependencies": "warn", // Errors by default, switching to warn instead "noUnnecessaryContinue": "off" // Turned off due to developer preferences }, "security": { @@ -80,11 +80,12 @@ "noExplicitAny": "off" // We trust Vercelians to use any only when necessary }, "nursery": { - "noStaticElementInteractions": "warn", - "noHeadImportInDocument": "warn", "noDocumentImportInPage": "warn", "noDuplicateElseIf": "warn", + "noHeadImportInDocument": "warn", "noIrregularWhitespace": "warn", + "noStaticElementInteractions": "warn", + "useSortedClasses": "error", "useValidAutocomplete": "warn" } } diff --git a/components.json b/components.json index 5b6d2bc..388ec17 100644 --- a/components.json +++ b/components.json @@ -4,7 +4,7 @@ "rsc": true, "tsx": true, "tailwind": { - "config": "tailwind.config.ts", + "config": "", "css": "app/globals.css", "baseColor": "zinc", "cssVariables": true, diff --git a/components/app-sidebar.tsx b/components/app-sidebar.tsx index e6d2213..f90029f 100644 --- a/components/app-sidebar.tsx +++ b/components/app-sidebar.tsx @@ -26,15 +26,15 @@ export function AppSidebar({ user }: { user: User | undefined }) { -
+
{ setOpenMobile(false); }} - className="flex flex-row gap-3 items-center" + className="flex flex-row items-center gap-3" > - + Chatbot @@ -43,7 +43,7 @@ export function AppSidebar({ user }: { user: User | undefined }) { - New Chat + + New Chat +
diff --git a/components/artifact-actions.tsx b/components/artifact-actions.tsx index a5689d3..e5f2551 100644 --- a/components/artifact-actions.tsx +++ b/components/artifact-actions.tsx @@ -54,7 +54,7 @@ function PureArtifactActions({ variant="outline" className={cn('h-fit dark:hover:bg-zinc-700', { 'p-2': !action.label, - 'py-1.5 px-2': action.label, + 'px-2 py-1.5': action.label, })} onClick={async () => { setIsLoading(true); diff --git a/components/artifact-messages.tsx b/components/artifact-messages.tsx index 5cb6f93..dbc37f6 100644 --- a/components/artifact-messages.tsx +++ b/components/artifact-messages.tsx @@ -42,7 +42,7 @@ function PureArtifactMessages({ return (
{messages.map((message, index) => ( diff --git a/components/artifact.tsx b/components/artifact.tsx index 9f5d6d7..d6e2904 100644 --- a/components/artifact.tsx +++ b/components/artifact.tsx @@ -259,14 +259,14 @@ function PureArtifact({ {artifact.isVisible && ( {!isMobile && ( {!isCurrentVersion && ( -
+
-
+
-
-
+
+
{artifact.title}
{isContentDirty ? ( -
+
Saving changes...
) : document ? ( -
+
{`Updated ${formatDistance( new Date(document.createdAt), new Date(), @@ -434,7 +434,7 @@ function PureArtifact({ )}`}
) : ( -
+
)}
@@ -450,7 +450,7 @@ function PureArtifact({ />
-
+
@@ -40,7 +40,7 @@ export function AuthForm({
diff --git a/components/chat-header.tsx b/components/chat-header.tsx index e8b4816..5ecae19 100644 --- a/components/chat-header.tsx +++ b/components/chat-header.tsx @@ -29,13 +29,13 @@ function PureChatHeader({ const { width: windowWidth } = useWindowSize(); return ( -
+
{(!open || windowWidth < 768) && ( ); } diff --git a/components/elements/actions.tsx b/components/elements/actions.tsx index 2cd0306..d2d8eb8 100644 --- a/components/elements/actions.tsx +++ b/components/elements/actions.tsx @@ -13,7 +13,7 @@ import type { ComponentProps } from 'react'; export type ActionsProps = ComponentProps<'div'>; export const Actions = ({ className, children, ...props }: ActionsProps) => ( -
+
{children}
); @@ -35,7 +35,7 @@ export const Action = ({ const button = (