Skip to content

Styled components to tailwind demo migration #6317

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .continue/rules/migrate-styled-components-to-tailwind.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
alwaysApply: false
---

Convert all of the styled components in this file into tailwind CSS. If a variable is used that is not already in @theme.ts and @tailwind.config.cjs, then you should figure out where it comes from and try adding that so it can be used. Wherever a function is called to interpolate a value, you can just use inline `styles={{ ... }}`. For ternaries, you could use @cn.ts.
107 changes: 76 additions & 31 deletions gui/src/components/AssistantAndOrgListbox/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@ import {
} from "@heroicons/react/24/outline";
import { useState } from "react";
import styled from "styled-components";
import {
defaultBorderRadius,
lightGray,
vscCommandCenterInactiveBorder,
} from "..";
import { lightGray } from "..";
import { cn } from "../../util/cn";
import { ToolTip } from "../gui/Tooltip";

export const OptionDiv = styled.div<{
Expand Down Expand Up @@ -47,11 +44,6 @@ export const OptionDiv = styled.div<{

export const MAX_HEIGHT_PX = 300;

export const Divider = styled.div`
height: 0.5px;
background-color: ${vscCommandCenterInactiveBorder};
`;

interface ModelOptionProps {
children: React.ReactNode;
idx: number;
Expand All @@ -64,28 +56,81 @@ interface ModelOptionProps {
onClickError?: (e: any) => void;
}

const IconBase = styled.div<{ $hovered: boolean }>`
width: 1.2em;
height: 1.2em;
cursor: pointer;
padding: 4px;
border-radius: ${defaultBorderRadius};
opacity: ${(props) => (props.$hovered ? 0.75 : 0)};
visibility: ${(props) => (props.$hovered ? "visible" : "hidden")};

&:hover {
opacity: 1;
background-color: ${lightGray}33;
}
`;
interface IconBaseProps {
$hovered: boolean;
onClick?: (e: any) => void;
className?: string;
children?: React.ReactNode;
[key: string]: any;
}

function IconBase({
$hovered,
onClick,
className,
children,
...props
}: IconBaseProps) {
return (
<div
className={cn(
"rounded-default h-[1.2em] w-[1.2em] cursor-pointer p-1",
$hovered ? "visible opacity-75" : "invisible opacity-0",
"hover:bg-lightgray/20 hover:opacity-100",
className,
)}
onClick={onClick}
{...props}
>
{children}
</div>
);
}

const StyledCog6ToothIcon = styled(IconBase).attrs({ as: Cog6ToothIcon })``;
const StyledArrowTopRightOnSquareIcon = styled(IconBase).attrs({
as: ArrowTopRightOnSquareIcon,
})``;
const StyledExclamationTriangleIcon = styled(IconBase).attrs({
as: ExclamationTriangleIcon,
})``;
const StyledCog6ToothIcon = ({
$hovered,
onClick,
}: {
$hovered: boolean;
onClick?: (e: any) => void;
}) => (
<IconBase $hovered={$hovered} onClick={onClick}>
<Cog6ToothIcon />
</IconBase>
);

const StyledArrowTopRightOnSquareIcon = ({
$hovered,
onClick,
}: {
$hovered: boolean;
onClick?: (e: any) => void;
}) => (
<IconBase $hovered={$hovered} onClick={onClick}>
<ArrowTopRightOnSquareIcon />
</IconBase>
);

const StyledExclamationTriangleIcon = ({
$hovered,
onClick,
className,
...props
}: {
$hovered: boolean;
onClick?: (e: any) => void;
className?: string;
[key: string]: any;
}) => (
<IconBase
$hovered={$hovered}
onClick={onClick}
className={className}
{...props}
>
<ExclamationTriangleIcon />
</IconBase>
);

export function Option({
children,
Expand Down
21 changes: 0 additions & 21 deletions gui/src/components/Footer.tsx

This file was deleted.

2 changes: 0 additions & 2 deletions gui/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { incrementFreeTrialCount } from "../util/freeTrial";
import { ROUTES } from "../util/navigation";
import { FatalErrorIndicator } from "./config/FatalErrorNotice";
import TextDialog from "./dialogs";
import Footer from "./Footer";
import { LumpProvider } from "./mainInput/Lump/LumpContext";
import { useMainEditor } from "./mainInput/TipTapEditor";
import {
Expand Down Expand Up @@ -252,7 +251,6 @@ const Layout = () => {
<PostHogPageView />
<Outlet />
<FatalErrorIndicator />
<Footer />
</GridDiv>
</div>
<div style={{ fontSize: fontSize(-4) }} id="tooltip-portal-div" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,7 @@
import { ReactNode, useMemo } from "react";
import { Tooltip } from "react-tooltip";
import styled from "styled-components";
import { lightGray, vscForeground } from "../..";
import { getFontSize } from "../../../util";

export const ToolbarButton = styled.button`
display: flex;
align-items: center;
border: none;
outline: none;
background: transparent;

color: ${vscForeground};
font-size: ${getFontSize() - 2}px;

&:hover {
cursor: pointer;
filter: brightness(1.25);
}
`;

interface ToolbarButtonWithTooltipProps {
onClick: () => void;
children: ReactNode;
Expand All @@ -40,15 +22,17 @@ export function ToolbarButtonWithTooltip({

return (
<>
<ToolbarButton
<button
onClick={onClick}
style={{ color: lightGray }}
style={{
fontSize: `${getFontSize() - 2}px`,
}}
data-tooltip-id={tooltipId}
data-testid={testId}
className="px-0.5"
className="text-foreground flex items-center border-none bg-transparent px-0.5 outline-none hover:cursor-pointer hover:brightness-125"
>
{children}
</ToolbarButton>
</button>
<Tooltip id={tooltipId} place="top">
{tooltipContent}
</Tooltip>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { ChevronDownIcon } from "@heroicons/react/24/outline";
import { inferResolvedUriFromRelativePath } from "core/util/ideUtils";
import { useContext, useEffect, useMemo, useState } from "react";
import styled from "styled-components";
import {
defaultBorderRadius,
vscCommandCenterInactiveBorder,
vscEditorBackground,
} from "../..";
import { IdeMessengerContext } from "../../../context/IdeMessenger";
import { useIdeMessengerRequest } from "../../../hooks/useIdeMessengerRequest";
import { useWebviewListener } from "../../../hooks/useWebviewListener";
Expand All @@ -25,29 +19,6 @@ import { FileInfo } from "./FileInfo";
import { InsertButton } from "./InsertButton";
import { RunInTerminalButton } from "./RunInTerminalButton";

const TopDiv = styled.div`
display: flex;
flex-direction: column;
outline: 1px solid ${vscCommandCenterInactiveBorder};
outline-offset: -0.5px;
border-radius: ${defaultBorderRadius};
margin-bottom: 8px !important;
margin-top: 8px !important;
background-color: ${vscEditorBackground};
min-width: 0;
`;

const ToolbarDiv = styled.div<{ isExpanded: boolean }>`
display: flex;
justify-content: space-between;
align-items: center;
font-size: ${getFontSize() - 2}px;
padding: 4px 6px;
margin: 0;
border-bottom: ${({ isExpanded }) =>
isExpanded ? `1px solid ${vscCommandCenterInactiveBorder}` : "inherit"};
`;

export interface StepContainerPreToolbarProps {
codeBlockContent: string;
language: string | null;
Expand Down Expand Up @@ -290,9 +261,12 @@ export function StepContainerPreToolbar({
}

return (
<TopDiv>
<ToolbarDiv isExpanded={isExpanded} className="find-widget-skip gap-3">
<div className="max-w-[50% flex flex-row items-center">
<div className="outline-command-border -outline-offset-0.5 rounded-default bg-editor mb-2 mt-2 flex min-w-0 flex-col outline outline-1">
<div
className={`find-widget-skip m-0 flex items-center justify-between gap-3 px-1.5 py-1 ${isExpanded ? "border-command-border border-b" : ""}`}
style={{ fontSize: `${getFontSize() - 2}px` }}
>
<div className="flex max-w-[50%] flex-row items-center">
<ChevronDownIcon
data-testid="toggle-codeblock"
onClick={() => setIsExpanded(!isExpanded)}
Expand Down Expand Up @@ -323,11 +297,11 @@ export function StepContainerPreToolbar({

{renderActionButtons()}
</div>
</ToolbarDiv>
</div>

{isExpanded && (
<div className="overflow-hidden overflow-y-auto">{children}</div>
)}
</TopDiv>
</div>
);
}
14 changes: 14 additions & 0 deletions gui/src/util/cn.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

/**
* Combines multiple class values and merges Tailwind CSS classes.
*
* This utility function combines the functionality of clsx (for conditional class names)
* and tailwind-merge (for intelligently merging Tailwind CSS classes, removing duplicates
* and conflicts).
*
* @param inputs - Class values that can be strings, objects, arrays, or conditional expressions
* @returns A merged string of class names with Tailwind conflicts resolved
*
* @example
* cn('px-2 py-1', 'px-4') // Returns 'py-1 px-4' (px-2 is overridden by px-4)
* cn('text-red-500', { 'text-blue-500': isActive }) // Conditionally applies classes
*/
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
3 changes: 3 additions & 0 deletions gui/tailwind.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ module.exports = {
borderRadius: {
default: "5px",
},
outlineOffset: {
0.5: "0.5px",
},
colors: {
background: varWithFallback("background"),
foreground: varWithFallback("foreground"),
Expand Down
Loading