web: Homepage changes (#9675)
Co-authored-by: roomote[bot] <219738659+roomote[bot]@users.noreply.github.com> Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
BIN
apps/web-roo-code/public/illustrations/form-factor-cloud.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
apps/web-roo-code/public/illustrations/form-factor-extension.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/1.jpg
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/10.jpg
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/11.jpg
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/12.jpg
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/13.jpg
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/14.jpg
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/15.jpg
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/16.jpg
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/17.jpg
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/18.jpg
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/19.jpg
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/2.jpg
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/20.jpg
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/21.jpg
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/22.jpg
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/23.jpg
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/24.jpg
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/3.jpg
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/4.jpg
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/5.jpg
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/6.jpg
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/7.jpg
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/8.jpg
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
apps/web-roo-code/public/illustrations/user-faces/9.jpg
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
1
apps/web-roo-code/public/logos/bedrock.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Bedrock</title><path d="M13.05 15.513h3.08c.214 0 .389.177.389.394v1.82a1.704 1.704 0 011.296 1.661c0 .943-.755 1.708-1.685 1.708-.931 0-1.686-.765-1.686-1.708 0-.807.554-1.484 1.297-1.662v-1.425h-2.69v4.663a.395.395 0 01-.188.338l-2.69 1.641a.385.385 0 01-.405-.002l-4.926-3.086a.395.395 0 01-.185-.336V16.3L2.196 14.87A.395.395 0 012 14.555L2 14.528V9.406c0-.14.073-.27.192-.34l2.465-1.462V4.448c0-.129.062-.249.165-.322l.021-.014L9.77 1.058a.385.385 0 01.407 0l2.69 1.675a.395.395 0 01.185.336V7.6h3.856V5.683a1.704 1.704 0 01-1.296-1.662c0-.943.755-1.708 1.685-1.708.931 0 1.685.765 1.685 1.708 0 .807-.553 1.484-1.296 1.662v2.311a.391.391 0 01-.389.394h-4.245v1.806h6.624a1.69 1.69 0 011.64-1.313c.93 0 1.685.764 1.685 1.707 0 .943-.754 1.708-1.685 1.708a1.69 1.69 0 01-1.64-1.314H13.05v1.937h4.953l.915 1.18a1.66 1.66 0 01.84-.227c.931 0 1.685.764 1.685 1.707 0 .943-.754 1.708-1.685 1.708-.93 0-1.685-.765-1.685-1.708 0-.346.102-.668.276-.937l-.724-.935H13.05v1.806zM9.973 1.856L7.93 3.122V6.09h-.778V3.604L5.435 4.669v2.945l2.11 1.36L9.712 7.61V5.334h.778V7.83c0 .136-.07.263-.184.335L7.963 9.638v2.081l1.422 1.009-.446.646-1.406-.998-1.53 1.005-.423-.66 1.605-1.055v-1.99L5.038 8.29l-2.26 1.34v1.676l1.972-1.189.398.677-2.37 1.429V14.3l2.166 1.258 2.27-1.368.397.677-2.176 1.311V19.3l1.876 1.175 2.365-1.426.398.678-2.017 1.216 1.918 1.201 2.298-1.403v-5.78l-4.758 2.893-.4-.675 5.158-3.136V3.289L9.972 1.856zM16.13 18.47a.913.913 0 00-.908.92c0 .507.406.918.908.918a.913.913 0 00.907-.919.913.913 0 00-.907-.92zm3.63-3.81a.913.913 0 00-.908.92c0 .508.406.92.907.92a.913.913 0 00.908-.92.913.913 0 00-.908-.92zm1.555-4.99a.913.913 0 00-.908.92c0 .507.407.918.908.918a.913.913 0 00.907-.919.913.913 0 00-.907-.92zM17.296 3.1a.913.913 0 00-.907.92c0 .508.406.92.907.92a.913.913 0 00.908-.92.913.913 0 00-.908-.92z"></path></svg>
|
||||
|
After Width: | Height: | Size: 2 KiB |
1
apps/web-roo-code/public/logos/moonshot.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>MoonshotAI</title><path d="M1.052 16.916l9.539 2.552a21.007 21.007 0 00.06 2.033l5.956 1.593a11.997 11.997 0 01-5.586.865l-.18-.016-.044-.004-.084-.009-.094-.01a11.605 11.605 0 01-.157-.02l-.107-.014-.11-.016a11.962 11.962 0 01-.32-.051l-.042-.008-.075-.013-.107-.02-.07-.015-.093-.019-.075-.016-.095-.02-.097-.023-.094-.022-.068-.017-.088-.022-.09-.024-.095-.025-.082-.023-.109-.03-.062-.02-.084-.025-.093-.028-.105-.034-.058-.019-.08-.026-.09-.031-.066-.024a6.293 6.293 0 01-.044-.015l-.068-.025-.101-.037-.057-.022-.08-.03-.087-.035-.088-.035-.079-.032-.095-.04-.063-.028-.063-.027a5.655 5.655 0 01-.041-.018l-.066-.03-.103-.047-.052-.024-.096-.046-.062-.03-.084-.04-.086-.044-.093-.047-.052-.027-.103-.055-.057-.03-.058-.032a6.49 6.49 0 01-.046-.026l-.094-.053-.06-.034-.051-.03-.072-.041-.082-.05-.093-.056-.052-.032-.084-.053-.061-.039-.079-.05-.07-.047-.053-.035a7.785 7.785 0 01-.054-.036l-.044-.03-.044-.03a6.066 6.066 0 01-.04-.028l-.057-.04-.076-.054-.069-.05-.074-.054-.056-.042-.076-.057-.076-.059-.086-.067-.045-.035-.064-.052-.074-.06-.089-.073-.046-.039-.046-.039a7.516 7.516 0 01-.043-.037l-.045-.04-.061-.053-.07-.062-.068-.06-.062-.058-.067-.062-.053-.05-.088-.084a13.28 13.28 0 01-.099-.097l-.029-.028-.041-.042-.069-.07-.05-.051-.05-.053a6.457 6.457 0 01-.168-.179l-.08-.088-.062-.07-.071-.08-.042-.049-.053-.062-.058-.068-.046-.056a7.175 7.175 0 01-.027-.033l-.045-.055-.066-.082-.041-.052-.05-.064-.02-.025a11.99 11.99 0 01-1.44-2.402zm-1.02-5.794l11.353 3.037a20.468 20.468 0 00-.469 2.011l10.817 2.894a12.076 12.076 0 01-1.845 2.005L.657 15.923l-.016-.046-.035-.104a11.965 11.965 0 01-.05-.153l-.007-.023a11.896 11.896 0 01-.207-.741l-.03-.126-.018-.08-.021-.097-.018-.081-.018-.09-.017-.084-.018-.094c-.026-.141-.05-.283-.071-.426l-.017-.118-.011-.083-.013-.102a12.01 12.01 0 01-.019-.161l-.005-.047a12.12 12.12 0 01-.034-2.145zm1.593-5.15l11.948 3.196c-.368.605-.705 1.231-1.01 1.875l11.295 3.022c-.142.82-.368 1.612-.668 2.365l-11.55-3.09L.124 10.26l.015-.1.008-.049.01-.067.015-.087.018-.098c.026-.148.056-.295.088-.442l.028-.124.02-.085.024-.097c.022-.09.045-.18.07-.268l.028-.102.023-.083.03-.1.025-.082.03-.096.026-.082.031-.095a11.896 11.896 0 011.01-2.232zm4.442-4.4L17.352 4.59a20.77 20.77 0 00-1.688 1.721l7.823 2.093c.267.852.442 1.744.513 2.665L2.106 5.213l.045-.065.027-.04.04-.055.046-.065.055-.076.054-.072.064-.086.05-.065.057-.073.055-.07.06-.074.055-.069.065-.077.054-.066.066-.077.053-.06.072-.082.053-.06.067-.074.054-.058.073-.078.058-.06.063-.067.168-.17.1-.098.059-.056.076-.071a12.084 12.084 0 012.272-1.677zM12.017 0h.097l.082.001.069.001.054.002.068.002.046.001.076.003.047.002.06.003.054.002.087.005.105.007.144.011.088.007.044.004.077.008.082.008.047.005.102.012.05.006.108.014.081.01.042.006.065.01.207.032.07.012.065.011.14.026.092.018.11.022.046.01.075.016.041.01L14.7.3l.042.01.065.015.049.012.071.017.096.024.112.03.113.03.113.032.05.015.07.02.078.024.073.023.05.016.05.016.076.025.099.033.102.036.048.017.064.023.093.034.11.041.116.045.1.04.047.02.06.024.041.018.063.026.04.018.057.025.11.048.1.046.074.035.075.036.06.028.092.046.091.045.102.052.053.028.049.026.046.024.06.033.041.022.052.029.088.05.106.06.087.051.057.034.053.032.096.059.088.055.098.062.036.024.064.041.084.056.04.027.062.042.062.043.023.017c.054.037.108.075.161.114l.083.06.065.048.056.043.086.065.082.064.04.03.05.041.086.069.079.065.085.071c.712.6 1.353 1.283 1.909 2.031L7.222.994l.062-.027.065-.028.081-.034.086-.035c.113-.045.227-.09.341-.131l.096-.035.093-.033.084-.03.096-.031c.087-.03.176-.058.264-.085l.091-.027.086-.025.102-.03.085-.023.1-.026L9.04.37l.09-.023.091-.022.095-.022.09-.02.098-.021.091-.02.095-.018.092-.018.1-.018.091-.016.098-.017.092-.014.097-.015.092-.013.102-.013.091-.012.105-.012.09-.01.105-.01c.093-.01.186-.018.28-.024l.106-.008.09-.005.11-.006.093-.004.1-.004.097-.002.099-.002.197-.002z"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
1
apps/web-roo-code/public/logos/openrouter.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>OpenRouter</title><path d="M16.804 1.957l7.22 4.105v.087L16.73 10.21l.017-2.117-.821-.03c-1.059-.028-1.611.002-2.268.11-1.064.175-2.038.577-3.147 1.352L8.345 11.03c-.284.195-.495.336-.68.455l-.515.322-.397.234.385.23.53.338c.476.314 1.17.796 2.701 1.866 1.11.775 2.083 1.177 3.147 1.352l.3.045c.694.091 1.375.094 2.825.033l.022-2.159 7.22 4.105v.087L16.589 22l.014-1.862-.635.022c-1.386.042-2.137.002-3.138-.162-1.694-.28-3.26-.926-4.881-2.059l-2.158-1.5a21.997 21.997 0 00-.755-.498l-.467-.28a55.927 55.927 0 00-.76-.43C2.908 14.73.563 14.116 0 14.116V9.888l.14.004c.564-.007 2.91-.622 3.809-1.124l1.016-.58.438-.274c.428-.28 1.072-.726 2.686-1.853 1.621-1.133 3.186-1.78 4.881-2.059 1.152-.19 1.974-.213 3.814-.138l.02-1.907z"></path></svg>
|
||||
|
After Width: | Height: | Size: 906 B |
|
|
@ -14,7 +14,7 @@ import "./globals.css"
|
|||
const inter = Inter({ subsets: ["latin"] })
|
||||
|
||||
const OG_TITLE = "Meet Roo Code"
|
||||
const OG_DESCRIPTION = "The AI dev team that gets things done."
|
||||
const OG_DESCRIPTION = "Your AI Software Engineering Team in the IDE and the Cloud."
|
||||
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL(SEO.url),
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
/* eslint-disable react/jsx-no-target-blank */
|
||||
|
||||
import { getVSCodeDownloads } from "@/lib/stats"
|
||||
|
||||
import { Button } from "@/components/ui"
|
||||
import {
|
||||
AnimatedBackground,
|
||||
CodeExample,
|
||||
CompanyLogos,
|
||||
FAQSection,
|
||||
Features,
|
||||
InstallSection,
|
||||
Testimonials,
|
||||
CTASection,
|
||||
OptionOverviewSection,
|
||||
PillarsSection,
|
||||
UseExamplesSection,
|
||||
} from "@/components/homepage"
|
||||
import { EXTERNAL_LINKS } from "@/lib/constants"
|
||||
import { ArrowRight } from "lucide-react"
|
||||
|
|
@ -20,70 +16,67 @@ import { StructuredData } from "@/components/structured-data"
|
|||
export const revalidate = 3600
|
||||
|
||||
export default async function Home() {
|
||||
const downloads = await getVSCodeDownloads()
|
||||
|
||||
return (
|
||||
<>
|
||||
<StructuredData />
|
||||
<section className="relative flex h-[calc(125vh-theme(spacing.12))] items-center overflow-hidden md:h-[calc(80svh-theme(spacing.12))]">
|
||||
<AnimatedBackground />
|
||||
<div className="container relative flex items-center h-full z-10 mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid h-full relative gap-8 md:gap-12 lg:grid-cols-2 lg:gap-16">
|
||||
<div className="flex flex-col px-4 justify-center space-y-6 sm:space-y-8">
|
||||
<div>
|
||||
<h1 className="text-4xl font-bold tracking-tight mt-8 text-center md:text-left md:text-4xl lg:text-5xl lg:mt-0">
|
||||
The AI dev team that gets things done.
|
||||
</h1>
|
||||
<p className="mt-4 max-w-md text-lg text-muted-foreground text-center md:text-left sm:mt-6">
|
||||
Roo's specialized modes stay on task and ship great code. Open source and works
|
||||
with any model.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col space-y-3 sm:flex-row sm:space-x-4 sm:space-y-0">
|
||||
<Button
|
||||
size="lg"
|
||||
className="w-full hover:bg-gray-200 dark:bg-white dark:text-black sm:w-auto">
|
||||
<a
|
||||
href="https://marketplace.visualstudio.com/items?itemName=RooVeterinaryInc.roo-cline"
|
||||
target="_blank"
|
||||
className="flex w-full items-center justify-center">
|
||||
Install VS Code Extension
|
||||
<ArrowRight className="ml-2" />
|
||||
</a>
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
className="w-full sm:w-auto bg-white/20 dark:bg-white/10 backdrop-blur-sm border border-black/40 dark:border-white/30 hover:border-blue-400 hover:bg-white/30 dark:hover:bg-white/20 hover:shadow-[0_0_20px_rgba(59,130,246,0.5)] transition-all duration-300">
|
||||
<a
|
||||
href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP}
|
||||
target="_blank"
|
||||
className="flex w-full items-center justify-center">
|
||||
Try Cloud
|
||||
<ArrowRight className="ml-2" />
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
<CompanyLogos />
|
||||
<section className="relative flex flex-col items-center overflow-hidden pt-20 pb-12 md:pt-32 md:pb-16">
|
||||
<div className="absolute inset-y-0 left-1/2 h-full w-full max-w-[1200px] -translate-x-1/2 z-1">
|
||||
<div className="absolute left-1/2 top-1/2 h-[400px] w-full -translate-x-1/2 -translate-y-1/2 rounded-full bg-violet-500/10 dark:bg-violet-700/20 blur-[140px]" />
|
||||
</div>
|
||||
<div className="container relative z-10 mx-auto px-4 sm:px-6 lg:px-8 flex flex-col items-center text-center">
|
||||
<h1 className="text-3xl md:text-4xl font-bold tracking-tight text-foreground max-w-4xl mb-6">
|
||||
Your AI Software Engineering Team is here.
|
||||
<br />
|
||||
<span className="text-muted-foreground">Interactive in the IDE, autonomous in the cloud.</span>
|
||||
</h1>
|
||||
<div className="mt-2 max-w-3xl text-lg text-muted-foreground mb-10 space-y-3">
|
||||
<p>
|
||||
Use the <strong className="text-nowrap">Roo Code Extension</strong> on your computer for
|
||||
full control, or delegate work to your{" "}
|
||||
<strong className="text-nowrap">Roo Code Cloud Agents</strong> from the web, Slack, Github
|
||||
or wherever your team is.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row gap-4 mb-16">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<Button size="xl" className="w-full">
|
||||
<a
|
||||
href={EXTERNAL_LINKS.MARKETPLACE}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="flex items-center justify-center">
|
||||
Install VS Code Extension
|
||||
<ArrowRight className="ml-2 size-5" />
|
||||
</a>
|
||||
</Button>
|
||||
<span className="text-xs text-muted-foreground">Free and Open Source</span>
|
||||
</div>
|
||||
<div className="relative flex items-center mx-auto h-full mt-8 lg:mt-0">
|
||||
<div className="flex items-center justify-center">
|
||||
<CodeExample />
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<Button size="xl" className="w-full">
|
||||
<a
|
||||
href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP_HOME}
|
||||
className="flex items-center justify-center">
|
||||
Try Cloud for Free
|
||||
<ArrowRight className="ml-2 size-5" />
|
||||
</a>
|
||||
</Button>
|
||||
<span className="text-xs text-muted-foreground">No credit card needed</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-12 px-4">
|
||||
<CompanyLogos />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div id="product">
|
||||
<Features />
|
||||
</div>
|
||||
<div id="testimonials">
|
||||
<Testimonials />
|
||||
</div>
|
||||
<div id="faq">
|
||||
<FAQSection />
|
||||
</div>
|
||||
<InstallSection downloads={downloads} />
|
||||
|
||||
<PillarsSection />
|
||||
<OptionOverviewSection />
|
||||
<UseExamplesSection />
|
||||
<Testimonials />
|
||||
<FAQSection />
|
||||
<CTASection />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { EXTERNAL_LINKS } from "@/lib/constants"
|
|||
import { useLogoSrc } from "@/lib/hooks/use-logo-src"
|
||||
import { ScrollButton } from "@/components/ui"
|
||||
import ThemeToggle from "@/components/chromes/theme-toggle"
|
||||
import { ChevronDown, Cloud, X } from "lucide-react"
|
||||
import { ChevronDown, X } from "lucide-react"
|
||||
|
||||
interface NavBarProps {
|
||||
stars: string | null
|
||||
|
|
@ -104,6 +104,20 @@ export function NavBar({ stars, downloads }: NavBarProps) {
|
|||
{stars !== null && <span>{stars}</span>}
|
||||
</Link>
|
||||
</div>
|
||||
<a
|
||||
href={EXTERNAL_LINKS.CLOUD_APP_LOGIN}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hidden items-center gap-1.5 rounded-md py-2 text-sm border border-primary-background px-4 font-medium text-primary-background transition-all duration-200 hover:shadow-lg hover:scale-105 lg:flex">
|
||||
Log in
|
||||
</a>
|
||||
<a
|
||||
href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP_HOME}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hidden items-center gap-1.5 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-all duration-200 hover:shadow-lg hover:scale-105 md:flex">
|
||||
Sign Up
|
||||
</a>
|
||||
<Link
|
||||
href={EXTERNAL_LINKS.MARKETPLACE}
|
||||
target="_blank"
|
||||
|
|
@ -114,14 +128,6 @@ export function NavBar({ stars, downloads }: NavBarProps) {
|
|||
</span>
|
||||
{downloads !== null && <span>{downloads}</span>}
|
||||
</Link>
|
||||
<a
|
||||
href={EXTERNAL_LINKS.CLOUD_APP_LOGIN}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hidden items-center gap-1.5 rounded-md py-2 text-sm border border-primary-background px-4 font-medium text-primary-background transition-all duration-200 hover:shadow-lg hover:scale-105 md:flex whitespace-nowrap">
|
||||
<Cloud className="inline h-4 w-4" />
|
||||
Log in
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
|
|
@ -226,15 +232,24 @@ export function NavBar({ stars, downloads }: NavBarProps) {
|
|||
{downloads !== null && <span>{downloads}</span>}
|
||||
</Link>
|
||||
</div>
|
||||
<a
|
||||
href={EXTERNAL_LINKS.CLOUD_APP_LOGIN}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-2 rounded-lg border border-primary bg-background p-4 mx-4 mb-4 text-base font-semibold text-primary"
|
||||
onClick={() => setIsMenuOpen(false)}>
|
||||
<Cloud className="h-5 w-5" />
|
||||
Log in
|
||||
</a>
|
||||
<div className="flex gap-2 px-4 pb-4">
|
||||
<a
|
||||
href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP_HOME}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-2 rounded-full border border-primary bg-foreground p-4 w-full text-base font-semibold text-background"
|
||||
onClick={() => setIsMenuOpen(false)}>
|
||||
Sign up
|
||||
</a>
|
||||
<a
|
||||
href={EXTERNAL_LINKS.CLOUD_APP_LOGIN}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-2 rounded-full border border-primary bg-background p-4 w-full text-base font-semibold text-primary"
|
||||
onClick={() => setIsMenuOpen(false)}>
|
||||
Log in
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
|
|||
109
apps/web-roo-code/src/components/homepage/cloud-section.tsx
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import { Bot, Settings2, ShieldCheck } from "lucide-react"
|
||||
|
||||
export function CloudSection() {
|
||||
return (
|
||||
<section className="py-24 bg-muted/30">
|
||||
<div className="container px-4 mx-auto sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">Asynchronous Engineering.</h2>
|
||||
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
|
||||
Stop watching the cursor. Deploy specialized agents to work while you sleep.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Pipeline Diagram Visual */}
|
||||
<div className="flex flex-wrap items-center justify-center gap-4 mb-20 text-sm font-medium">
|
||||
<div className="px-4 py-2 bg-background border border-border rounded-lg">Ticket</div>
|
||||
<div className="w-8 h-[1px] bg-border" />
|
||||
<div className="px-4 py-2 bg-purple-500/10 border border-purple-500/20 text-purple-500 rounded-lg">
|
||||
Planner Agent
|
||||
</div>
|
||||
<div className="w-8 h-[1px] bg-border" />
|
||||
<div className="px-4 py-2 bg-blue-500/10 border border-blue-500/20 text-blue-500 rounded-lg">
|
||||
Coder Agent
|
||||
</div>
|
||||
<div className="w-8 h-[1px] bg-border" />
|
||||
<div className="px-4 py-2 bg-green-500/10 border border-green-500/20 text-green-500 rounded-lg">
|
||||
GitHub PR
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-12">
|
||||
<div className="bg-background p-8 rounded-2xl border border-border shadow-sm">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="p-2 bg-blue-500/10 rounded-lg">
|
||||
<ShieldCheck className="h-6 w-6 text-blue-500" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">Purpose-Built Agents (Safety)</h3>
|
||||
</div>
|
||||
<h4 className="text-lg font-semibold mb-2">Zero Drift via Role Constraints</h4>
|
||||
<p className="text-muted-foreground mb-6">
|
||||
Fear of agents going haywire is solved by architecture, not prompt engineering. Cloud Agents
|
||||
enforce the strict Modes you use locally.
|
||||
</p>
|
||||
<ul className="space-y-4">
|
||||
<li className="flex gap-3 items-start">
|
||||
<Bot className="h-5 w-5 text-purple-500 mt-0.5" />
|
||||
<div>
|
||||
<span className="font-bold">The Planner:</span>
|
||||
<span className="text-muted-foreground ml-2">
|
||||
Maps dependencies. Read-Only access.
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex gap-3 items-start">
|
||||
<Bot className="h-5 w-5 text-blue-500 mt-0.5" />
|
||||
<div>
|
||||
<span className="font-bold">The Builder:</span>
|
||||
<span className="text-muted-foreground ml-2">
|
||||
Writes code based on the plan. Scoped file access.
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex gap-3 items-start">
|
||||
<Bot className="h-5 w-5 text-green-500 mt-0.5" />
|
||||
<div>
|
||||
<span className="font-bold">The Reviewer:</span>
|
||||
<span className="text-muted-foreground ml-2">
|
||||
Analyzes diffs. Cannot push to main.
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="bg-background p-8 rounded-2xl border border-border shadow-sm">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="p-2 bg-purple-500/10 rounded-lg">
|
||||
<Settings2 className="h-6 w-6 text-purple-500" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">Orchestrated Configuration</h3>
|
||||
</div>
|
||||
<h4 className="text-lg font-semibold mb-2">Optimize Your AI Workforce</h4>
|
||||
<p className="text-muted-foreground mb-6">
|
||||
Just as you choose models locally, you configure them for the cloud to balance performance
|
||||
vs. cost.
|
||||
</p>
|
||||
<div className="p-4 bg-muted/50 rounded-lg border border-border">
|
||||
<div className="text-sm font-mono text-muted-foreground mb-2">Config Example:</div>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between items-center p-2 bg-background rounded border border-border">
|
||||
<span className="font-medium">Planner Agent</span>
|
||||
<span className="text-xs bg-purple-500/10 text-purple-500 px-2 py-1 rounded">
|
||||
o1-preview (Reasoning)
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center p-2 bg-background rounded border border-border">
|
||||
<span className="font-medium">Unit Test Agent</span>
|
||||
<span className="text-xs bg-blue-500/10 text-blue-500 px-2 py-1 rounded">
|
||||
Haiku (Speed/Cost)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
|
@ -7,13 +7,13 @@ const logos = ["Apple", "Netflix", "Microsoft", "Amazon", "ByteDance", "Rakuten"
|
|||
|
||||
export function CompanyLogos() {
|
||||
return (
|
||||
<div className="mt-14">
|
||||
<div>
|
||||
<motion.p
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5, ease: "easeOut" }}
|
||||
className="text-xs text-muted-foreground text-center mb-2 sm:text-left">
|
||||
Making devs more productive at
|
||||
className="text-xs text-muted-foreground text-center mb-2 ">
|
||||
Helping teams ship more at
|
||||
</motion.p>
|
||||
<div className="mt-4 flex flex-wrap items-center gap-6 justify-center sm:justify-start">
|
||||
{logos.map((logo, index) => (
|
||||
|
|
@ -25,7 +25,7 @@ export function CompanyLogos() {
|
|||
<Image
|
||||
width={0}
|
||||
height={0}
|
||||
className="h-[18px] w-auto overflow-clip opacity-70 dark:invert"
|
||||
className="h-[22px] w-auto overflow-clip opacity-70 dark:invert"
|
||||
src={`/logos/${logo.toLowerCase().replace(/\s+/g, "-")}.svg`}
|
||||
alt={`${logo} Logo`}
|
||||
/>
|
||||
|
|
|
|||
37
apps/web-roo-code/src/components/homepage/cta-section.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { Button } from "@/components/ui"
|
||||
import { ArrowRight, Download } from "lucide-react"
|
||||
import { EXTERNAL_LINKS } from "@/lib/constants"
|
||||
|
||||
export function CTASection() {
|
||||
return (
|
||||
<section className="py-24 bg-muted/30 border-t border-border">
|
||||
<div className="container px-4 mx-auto sm:px-6 lg:px-8 text-center">
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-5xl mb-8">Build faster. Solo or Together.</h2>
|
||||
|
||||
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
|
||||
<Button size="lg" className="w-full sm:w-auto h-12 px-8 text-base">
|
||||
<a
|
||||
href={EXTERNAL_LINKS.MARKETPLACE}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-2">
|
||||
<Download className="h-4 w-4" />
|
||||
Install on VS Code
|
||||
</a>
|
||||
</Button>
|
||||
|
||||
<Button variant="outline" size="lg" className="w-full sm:w-auto h-12 px-8 text-base">
|
||||
<a
|
||||
href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-2">
|
||||
Try Cloud for Free
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
import { GitMerge, Terminal, MessageSquare } from "lucide-react"
|
||||
|
||||
export function EcosystemSection() {
|
||||
return (
|
||||
<section className="py-24 bg-background">
|
||||
<div className="container px-4 mx-auto sm:px-6 lg:px-8 text-center">
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-16">Integrated into your SDLC.</h2>
|
||||
|
||||
<div className="relative max-w-4xl mx-auto">
|
||||
{/* Triangle Connection Lines - Absolute positioned */}
|
||||
<div className="absolute inset-0 hidden md:block pointer-events-none">
|
||||
<svg
|
||||
className="w-full h-full"
|
||||
viewBox="0 0 800 400"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M400 50 L150 350"
|
||||
stroke="currentColor"
|
||||
strokeOpacity="0.1"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="8 8"
|
||||
/>
|
||||
<path
|
||||
d="M400 50 L650 350"
|
||||
stroke="currentColor"
|
||||
strokeOpacity="0.1"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="8 8"
|
||||
/>
|
||||
<path
|
||||
d="M150 350 L650 350"
|
||||
stroke="currentColor"
|
||||
strokeOpacity="0.1"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="8 8"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-8 relative z-10">
|
||||
{/* Step 1: Dispatch */}
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="w-16 h-16 rounded-2xl bg-blue-500/10 flex items-center justify-center mb-6 border border-blue-500/20">
|
||||
<MessageSquare className="h-8 w-8 text-blue-500" />
|
||||
</div>
|
||||
<div className="text-sm font-bold text-blue-500 mb-2">01. DISPATCH</div>
|
||||
<h3 className="text-xl font-bold mb-3">Trigger Task</h3>
|
||||
<p className="text-muted-foreground text-sm max-w-[250px]">
|
||||
Trigger a task via @Roo in Slack or the VS Code terminal.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 2: Execute */}
|
||||
<div className="flex flex-col items-center md:-mt-12">
|
||||
<div className="w-16 h-16 rounded-2xl bg-purple-500/10 flex items-center justify-center mb-6 border border-purple-500/20">
|
||||
<Terminal className="h-8 w-8 text-purple-500" />
|
||||
</div>
|
||||
<div className="text-sm font-bold text-purple-500 mb-2">02. EXECUTE</div>
|
||||
<h3 className="text-xl font-bold mb-3">Run Agents</h3>
|
||||
<p className="text-muted-foreground text-sm max-w-[250px]">
|
||||
Agents run in isolated, ephemeral docker containers.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Step 3: Merge */}
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="w-16 h-16 rounded-2xl bg-green-500/10 flex items-center justify-center mb-6 border border-green-500/20">
|
||||
<GitMerge className="h-8 w-8 text-green-500" />
|
||||
</div>
|
||||
<div className="text-sm font-bold text-green-500 mb-2">03. MERGE</div>
|
||||
<h3 className="text-xl font-bold mb-3">Review PR</h3>
|
||||
<p className="text-muted-foreground text-sm max-w-[250px]">
|
||||
The output is always a standard GitHub Pull Request. You review code, not chat logs.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
|
@ -6,3 +6,9 @@ export * from "./features"
|
|||
export * from "./install-section"
|
||||
export * from "./testimonials"
|
||||
export * from "./whats-new-button"
|
||||
export * from "./option-overview-section"
|
||||
export * from "./pillars-section"
|
||||
export * from "./cloud-section"
|
||||
export * from "./ecosystem-section"
|
||||
export * from "./cta-section"
|
||||
export * from "./use-examples-section"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
import { Laptop, Cloud, ArrowRight } from "lucide-react"
|
||||
import { Button } from "../ui"
|
||||
import { EXTERNAL_LINKS } from "@/lib/constants"
|
||||
|
||||
export function OptionOverviewSection() {
|
||||
return (
|
||||
<section className="py-24 bg-background">
|
||||
<div className="container px-4 mx-auto sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
|
||||
Different form factors for different ways of working.
|
||||
</h2>
|
||||
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
|
||||
Roo's always there to help you get stuff done.
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 max-w-5xl mx-auto relative z-1">
|
||||
<div className="absolute left-1/2 top-[140px] -translate-x-1/2 z-1">
|
||||
<div className="rounded-full size-[300px] border-[10px] border-dashed animate-[spin_10s_linear_infinite] blur-[5px]" />
|
||||
</div>
|
||||
|
||||
<div className="rounded-3xl bg-card outline outline-border/50 hover:outline-8 shadow-xl p-8 h-full group transition-all hover:shadow-2xl hover:shadow-blue-800/30 relative">
|
||||
<div className="size-15 p-3 rounded-full flex items-center justify-center shadow-lg absolute -top-4 -right-2 transition-all outline outline-foreground/5 bg-card group group-hover:outline-3 group-hover:scale-105">
|
||||
<Laptop className="size-8 text-blue-500" strokeWidth={1.5} />
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold tracking-tight mb-2">Roo Code VS Code Extension</h3>
|
||||
<p className="font-semibold text-blue-500 mb-4">For Individual Work</p>
|
||||
|
||||
<div className="text-muted-foreground mb-4">
|
||||
<p>
|
||||
Run Roo directly in VS Code (or any fork – even Cursor!), stay close to the code and
|
||||
control everything:
|
||||
</p>
|
||||
<ul className="list-inside my-4 space-y-1">
|
||||
<li className="list-disc">Approve every action (or set it to auto-approve)</li>
|
||||
<li className="list-disc">Manage the context window</li>
|
||||
<li className="list-disc">Configure every detail</li>
|
||||
<li className="list-disc">Preview changes live</li>
|
||||
<li className="list-disc">Stick to your customized editor</li>
|
||||
<li className="list-disc">Write code by hand (gasp!)</li>
|
||||
</ul>
|
||||
<p>
|
||||
Ideal for real-time debugging or quick iteration where you need full, immediate control.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Button size="lg" variant="default" className="bg-blue-600 hover:bg-blue-600/80">
|
||||
<a
|
||||
href={EXTERNAL_LINKS.MARKETPLACE}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="flex items-center justify-center">
|
||||
Install now
|
||||
<ArrowRight className="ml-2" />
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="rounded-3xl bg-card outline outline-border/50 hover:outline-8 shadow-xl p-8 h-full group transition-all hover:shadow-2xl hover:shadow-blue-800/30 relative">
|
||||
<div className="size-15 p-3 rounded-full flex items-center justify-center shadow-lg absolute -top-4 -right-2 transition-all outline outline-foreground/5 bg-card group group-hover:outline-3 group-hover:scale-105">
|
||||
<Cloud className="size-8 text-violet-500" strokeWidth={1.5} />
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold tracking-tight mb-2">Roo Code Cloud</h3>
|
||||
<div className="font-semibold text-violet-500 mb-4">For Team Work with Agents</div>
|
||||
|
||||
<div className="text-muted-foreground mb-4">
|
||||
<p>
|
||||
Create your agent team in the Cloud, give them access to Github and start giving them
|
||||
tasks:
|
||||
</p>
|
||||
<ul className="list-inside my-4 space-y-1">
|
||||
<li className="list-disc">
|
||||
Use agents like the Planner, Coder, Explainer, Reviewer and Fixer
|
||||
</li>
|
||||
<li className="list-disc">Choose your provider and model</li>
|
||||
<li className="list-disc">
|
||||
Create tasks from the Web and Slack (more integrations soon)
|
||||
</li>
|
||||
<li className="list-disc">Get PR Reviews (and fixes) directly on Github</li>
|
||||
<li className="list-disc">Collaborate with co-workers</li>
|
||||
</ul>
|
||||
<p>
|
||||
Ideal for kicking projects off, parallelizing execution and looping in the rest of your
|
||||
team.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Button size="lg" variant="default" className="bg-violet-600 hover:bg-violet-600/80">
|
||||
<a href={EXTERNAL_LINKS.CLOUD_APP_SIGNUP_HOME} className="flex items-center justify-center">
|
||||
Try now for free
|
||||
<ArrowRight className="ml-2" />
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
202
apps/web-roo-code/src/components/homepage/pillars-section.tsx
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
import { Brain, Keyboard, Shield, Users2, Map, Code, MessageCircleQuestion, Bug, TestTube } from "lucide-react"
|
||||
import Image from "next/image"
|
||||
import { Link } from "../ui"
|
||||
|
||||
const MODEL_LOGOS = [
|
||||
"OpenRouter",
|
||||
"Anthropic",
|
||||
"OpenAI",
|
||||
"Gemini",
|
||||
"Grok",
|
||||
"Bedrock",
|
||||
"Moonshot",
|
||||
"Qwen",
|
||||
"Kimi",
|
||||
"Mistral",
|
||||
"Ollama",
|
||||
]
|
||||
const MODE_EXAMPLES = [
|
||||
{
|
||||
name: "Architect",
|
||||
description: "Plans complex changes without making changes.",
|
||||
icon: Map,
|
||||
},
|
||||
{
|
||||
name: "Code",
|
||||
description: "Implements, refactors and optimizes code.",
|
||||
icon: Code,
|
||||
},
|
||||
{
|
||||
name: "Ask",
|
||||
description: "Explains functionality and program behavior.",
|
||||
icon: MessageCircleQuestion,
|
||||
},
|
||||
{
|
||||
name: "Debug",
|
||||
description: "Diagnoses issues, traces failures, and proposes targeted, reliable fixes.",
|
||||
icon: Bug,
|
||||
},
|
||||
{
|
||||
name: "Test",
|
||||
description: "Creates and improves performant tests without changing the actual functionality.",
|
||||
icon: TestTube,
|
||||
},
|
||||
]
|
||||
|
||||
export function PillarsSection() {
|
||||
return (
|
||||
<section className="py-24 bg-muted/30 relative">
|
||||
<div className="absolute inset-y-0 left-1/2 h-full w-full max-w-[1200px] -translate-x-1/2">
|
||||
<div className="absolute left-1/2 top-1/2 h-[800px] w-full -translate-x-1/2 -translate-y-1/2 rounded-full bg-blue-500/10 dark:bg-blue-700/20 blur-[140px]" />
|
||||
</div>
|
||||
<div className="container px-4 mx-auto sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl mb-4">
|
||||
To trust an agent, you have to do it on your own terms.
|
||||
</h2>
|
||||
<p className="text-xl text-muted-foreground max-w-xl mx-auto">
|
||||
Roo is designed from the ground up to give you the confidence to do ever more with AI.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:grid md:grid-cols-8 gap-8">
|
||||
<div className="relative md:col-span-3 h-full">
|
||||
<div className="rounded-2xl bg-card outline outline-border/50 hover:outline-8 shadow-lg p-8 h-full group transition-all hover:shadow-2xl">
|
||||
<div className="absolute -right-3 -top-5 bg-card border shadow-md rounded-full p-3 transition-all group-hover:-top-4 group-hover:-right-2 group-hover:scale-110 group-hover:shadow-xl">
|
||||
<Brain className="size-8 text-violet-600 shrink-0 mt-1" strokeWidth={1.5} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold mb-1">Model-agnostic by design</h3>
|
||||
<h4 className="font-semibold text-lg">Flexible and future-proof.</h4>
|
||||
<div className="text-muted-foreground my-4 space-y-1">
|
||||
<p>
|
||||
"The best model in the world" changes every other week. Providers
|
||||
throttle models with no warning. 1st-party coding agents only work with their own
|
||||
models.
|
||||
</p>
|
||||
<p>Roo doesn't care.</p>
|
||||
<p>
|
||||
It works great with 10s of models, from frontier to open weight. Choose from{" "}
|
||||
<Link href="/provider/pricing">the curated selection we offer at-cost</Link> or
|
||||
bring your own key.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Compatible with dozens of providers
|
||||
</span>
|
||||
<div className="mt-4 flex flex-wrap items-center gap-4">
|
||||
{MODEL_LOGOS.map((logo, index) => (
|
||||
<Image
|
||||
key={logo}
|
||||
width={20}
|
||||
height={20}
|
||||
className="size-6 overflow-clip dark:invert"
|
||||
style={{ opacity: 1.1 - index / MODEL_LOGOS.length }}
|
||||
src={`/logos/${logo.toLowerCase()}.svg`}
|
||||
alt={`${logo} Logo`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative col-span-5 h-full">
|
||||
<div className="rounded-2xl bg-card outline outline-border/50 hover:outline-8 shadow-lg p-8 h-full group transition-all hover:shadow-2xl">
|
||||
<div className="absolute -right-3 -top-5 bg-card border shadow-lg rounded-full p-3 transition-all group-hover:-top-4 group-hover:-right-2 group-hover:scale-110 group-hover:shadow-xl">
|
||||
<Users2 className="size-8 text-violet-600 shrink-0 mt-1" strokeWidth={1.5} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold mb-1">Role-specific Modes</h3>
|
||||
<h4 className="font-semibold text-lg">On-task and under control.</h4>
|
||||
<div className="text-muted-foreground my-4 space-y-1">
|
||||
<p>
|
||||
As capable as they are, when let loose, LLMs hallucinate, cheat and can cause
|
||||
real damage.
|
||||
</p>
|
||||
<p>
|
||||
Roo's Modes keep models focused on a given task and limit their access to
|
||||
tools which are relevant to their role, keeping the context window clearer and
|
||||
avoiding surprises.
|
||||
</p>
|
||||
<p>
|
||||
Modes are even smart enough to ask to switch to another when stepping outside
|
||||
their responsibilities.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<span className="text-muted-foreground text-sm">Some examples</span>
|
||||
<ul className="flex gap-2 flex-wrap mt-2">
|
||||
{MODE_EXAMPLES.map((mode) => {
|
||||
const Icon = mode.icon
|
||||
return (
|
||||
<li
|
||||
key={mode.name}
|
||||
className="rounded-lg border bg-border/40 w-full md:w-[30%] min-w-[200px] text-sm px-3 py-2 flex gap-1">
|
||||
<Icon className="text-muted-foreground size-4 shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<p className="font-semibold">{mode.name}</p>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
{mode.description}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative col-span-4 h-full">
|
||||
<div className="rounded-2xl bg-card outline outline-border/50 hover:outline-8 shadow-lg p-8 h-full group transition-all hover:shadow-2xl">
|
||||
<div className="absolute -right-3 -top-5 bg-card border shadow-lg rounded-full p-3 transition-all group-hover:-top-4 group-hover:-right-2 group-hover:scale-110 group-hover:shadow-xl">
|
||||
<Keyboard className="size-8 text-violet-600 shrink-0 mt-1" strokeWidth={1.5} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold mb-1">Highly configurable</h3>
|
||||
<h4 className="font-semibold text-lg">Make it fit your workflow.</h4>
|
||||
<div className="text-muted-foreground my-4 space-y-1">
|
||||
<p>
|
||||
Developer tools need to fit like gloves. Highly tweakable,
|
||||
keyboard-shortcut-heavy gloves.
|
||||
</p>
|
||||
<p>We made Roo thoughtfully configurable to fit your workflow as best it can.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative col-span-4 h-full">
|
||||
<div className="rounded-2xl bg-card outline outline-border/50 hover:outline-8 shadow-lg p-8 h-full group transition-all hover:shadow-2xl">
|
||||
<div className="absolute -right-3 -top-5 bg-card border shadow-lg rounded-full p-3 transition-all group-hover:-top-4 group-hover:-right-2 group-hover:scale-110 group-hover:shadow-xl">
|
||||
<Shield className="size-8 text-violet-600 shrink-0 mt-1" strokeWidth={1.5} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold mb-1">Secure and transparent</h3>
|
||||
<h4 className="font-semibold text-lg">Open source from the get go.</h4>
|
||||
<div className="text-muted-foreground my-4 space-y-1">
|
||||
<p>
|
||||
The Roo Code Extension is{" "}
|
||||
<Link target="_blank" href="https://github.com/Roo-Code-Inc/Roo-Code">
|
||||
open source
|
||||
</Link>{" "}
|
||||
so you can see for yourself exactly what it's doing and we don't use
|
||||
your data for training.
|
||||
</p>
|
||||
<p>
|
||||
Plus we're fully SOC2 Type 2 compliant and follow industry-standard
|
||||
security practices.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
|
@ -193,11 +193,9 @@ export function Testimonials() {
|
|||
<div className="container relative z-10 mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="mx-auto mb-8 md:max-w-2xl text-center">
|
||||
<h2 className="text-4xl font-bold tracking-tight sm:text-5xl">
|
||||
Developers <em>really</em> shipping with AI are using Roo Code
|
||||
More than 1 million people are shipping with Roo.
|
||||
</h2>
|
||||
<p className="mt-6 text-lg text-muted-foreground">
|
||||
Join more than 1M people revolutionizing their workflow worldwide
|
||||
</p>
|
||||
<p className="mt-6 text-lg text-muted-foreground">And they have some great things to say.</p>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
|
|
@ -247,7 +245,11 @@ export function Testimonials() {
|
|||
{testimonial.name}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground transition-colors duration-300 dark:text-muted-foreground/80">
|
||||
{testimonial.role} at {testimonial.origin}
|
||||
{testimonial.role !== "Reviewer" && (
|
||||
<>
|
||||
{testimonial.role} at {testimonial.origin}
|
||||
</>
|
||||
)}
|
||||
{testimonial.stars && (
|
||||
<span className="flex items-center mt-1">
|
||||
{" "}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,430 @@
|
|||
"use client"
|
||||
|
||||
import { useMemo, useState } from "react"
|
||||
import { motion, AnimatePresence } from "framer-motion"
|
||||
import {
|
||||
LucideIcon,
|
||||
Pointer,
|
||||
Slack,
|
||||
Github,
|
||||
Code,
|
||||
GitPullRequest,
|
||||
Wrench,
|
||||
Map,
|
||||
MessageCircleQuestionMark,
|
||||
CornerDownRight,
|
||||
ChevronDown,
|
||||
} from "lucide-react"
|
||||
import Image from "next/image"
|
||||
import { Button } from "../ui"
|
||||
|
||||
interface UseCase {
|
||||
role: string
|
||||
use: string
|
||||
agent: UseCaseAgent
|
||||
context: UseCaseSource
|
||||
}
|
||||
|
||||
interface UseCaseSource {
|
||||
name: string
|
||||
icon: LucideIcon
|
||||
}
|
||||
|
||||
interface UseCaseAgent {
|
||||
name: string
|
||||
icon: LucideIcon
|
||||
}
|
||||
|
||||
interface PositionedUseCase extends UseCase {
|
||||
layer: 1 | 2 | 3 | 4
|
||||
position: { x: number; y: number }
|
||||
scale: number
|
||||
zIndex: number
|
||||
avatar: string
|
||||
}
|
||||
|
||||
const SOURCES = {
|
||||
slack: {
|
||||
name: "Slack",
|
||||
icon: Slack,
|
||||
},
|
||||
web: {
|
||||
name: "Web",
|
||||
icon: Pointer,
|
||||
},
|
||||
github: {
|
||||
name: "Github",
|
||||
icon: Github,
|
||||
},
|
||||
extension: {
|
||||
name: "Extension",
|
||||
icon: Code,
|
||||
},
|
||||
}
|
||||
|
||||
const AGENTS = {
|
||||
explainer: {
|
||||
name: "Explainer",
|
||||
icon: MessageCircleQuestionMark,
|
||||
},
|
||||
planner: {
|
||||
name: "Planner",
|
||||
icon: Map,
|
||||
},
|
||||
coder: {
|
||||
name: "Coder",
|
||||
icon: Code,
|
||||
},
|
||||
reviewer: {
|
||||
name: "Reviewer",
|
||||
icon: GitPullRequest,
|
||||
},
|
||||
fixer: {
|
||||
name: "Fixer",
|
||||
icon: Wrench,
|
||||
},
|
||||
}
|
||||
|
||||
const USE_CASES: UseCase[] = [
|
||||
{
|
||||
role: "Frontend Developer",
|
||||
use: "Take Lisa's feedback above and incorporate it into the landing page.",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.slack,
|
||||
},
|
||||
{
|
||||
role: "Customer Success",
|
||||
use: "What could be causing this bug as described by the customer?",
|
||||
agent: AGENTS.explainer,
|
||||
context: SOURCES.web,
|
||||
},
|
||||
{
|
||||
role: "Backend Engineer",
|
||||
use: "Create a migration denormalizing total_cost calculation and backfill the remainder.",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.extension,
|
||||
},
|
||||
{
|
||||
role: "Security Engineer",
|
||||
use: "Do we use any of the libraries mentioned in the thread?",
|
||||
agent: AGENTS.explainer,
|
||||
context: SOURCES.slack,
|
||||
},
|
||||
{
|
||||
role: "Designer",
|
||||
use: "Refactor the button component to use CSS variables",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.slack,
|
||||
},
|
||||
{
|
||||
role: "Product Manager",
|
||||
use: "How big of a change would it be to turn this from a yes/no to have 4 options?",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.web,
|
||||
},
|
||||
{
|
||||
role: "QA Engineer",
|
||||
use: "Write a Playwright test for the login flow failure case, extract existing mocks into shared.",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.github,
|
||||
},
|
||||
{
|
||||
role: "DevOps Engineer",
|
||||
use: "Update the Dockerfile to use Node 20 Alpine.",
|
||||
agent: AGENTS.fixer,
|
||||
context: SOURCES.slack,
|
||||
},
|
||||
{
|
||||
role: "Mobile Developer",
|
||||
use: "Copy what we did in PR #4253 and apply to this component.",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.slack,
|
||||
},
|
||||
{
|
||||
role: "Technical Writer",
|
||||
use: "Generate JSDoc comments for the auth utility functions.",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.github,
|
||||
},
|
||||
{
|
||||
role: "Junior Developer",
|
||||
use: "Review this pull request for potential performance improvements.",
|
||||
agent: AGENTS.reviewer,
|
||||
context: SOURCES.github,
|
||||
},
|
||||
{
|
||||
role: "Engineering Manager",
|
||||
use: "Break down this user profile feature into technical tasks, grouped by skill.",
|
||||
agent: AGENTS.planner,
|
||||
context: SOURCES.web,
|
||||
},
|
||||
{
|
||||
role: "Support Engineer",
|
||||
use: "What's causing this stack trace? The customer is on MacOS 26.1.",
|
||||
agent: AGENTS.explainer,
|
||||
context: SOURCES.web,
|
||||
},
|
||||
{
|
||||
role: "Frontend Developer",
|
||||
use: "Make the navigation menu responsive on mobile devices.",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.web,
|
||||
},
|
||||
{
|
||||
role: "Backend Engineer",
|
||||
use: "Give me two architecture options for the notification system in this PRD.",
|
||||
agent: AGENTS.planner,
|
||||
context: SOURCES.web,
|
||||
},
|
||||
{
|
||||
role: "Designer",
|
||||
use: "Implement the loading spinner animation in CSS.",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.web,
|
||||
},
|
||||
{
|
||||
role: "Customer Success",
|
||||
use: "Write a script to find patterns in these CPU load logs.",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.slack,
|
||||
},
|
||||
{
|
||||
role: "Full Stack Dev",
|
||||
use: "Refactor user_preferences to use named columns instead of a single JSON blob",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.extension,
|
||||
},
|
||||
{
|
||||
role: "QA Engineer",
|
||||
use: "Automate the regression suite for the checkout process.",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.extension,
|
||||
},
|
||||
{
|
||||
role: "DevOps Engineer",
|
||||
use: "Understand why this build error only happens in prod and fix it.",
|
||||
agent: AGENTS.coder,
|
||||
context: SOURCES.extension,
|
||||
},
|
||||
{
|
||||
role: "Product Marketer",
|
||||
use: "What were the 5 most significant PRs merged in the past week?",
|
||||
agent: AGENTS.explainer,
|
||||
context: SOURCES.slack,
|
||||
},
|
||||
{
|
||||
role: "Junior Developer",
|
||||
use: "Explain how useEffect dependency arrays work here.",
|
||||
agent: AGENTS.explainer,
|
||||
context: SOURCES.extension,
|
||||
},
|
||||
{
|
||||
role: "Senior Engineer",
|
||||
use: "Check if this implementation follows the Single Responsibility Principle.",
|
||||
agent: AGENTS.reviewer,
|
||||
context: SOURCES.github,
|
||||
},
|
||||
]
|
||||
|
||||
// Seeded random number generator for consistent layout
|
||||
function seededRandom(seed: number) {
|
||||
let value = seed
|
||||
return () => {
|
||||
value = (value * 9301 + 49297) % 233280
|
||||
return value / 233280
|
||||
}
|
||||
}
|
||||
|
||||
const LAYER_SCALES = {
|
||||
1: 0.7,
|
||||
2: 0.85,
|
||||
3: 1.0,
|
||||
4: 1.15,
|
||||
}
|
||||
|
||||
function distributeItems(items: UseCase[]): PositionedUseCase[] {
|
||||
const rng = seededRandom(Math.random() * 12345)
|
||||
const zones = { rows: 7, cols: 4 }
|
||||
const zoneWidth = 100 / zones.cols
|
||||
const zoneHeight = 100 / zones.rows
|
||||
|
||||
// Create array of zone indices [0...19] and shuffle them
|
||||
const zoneIndices = Array.from({ length: items.length }, (_, i) => i)
|
||||
for (let i = zoneIndices.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(rng() * (i + 1))
|
||||
const temp = zoneIndices[i]!
|
||||
zoneIndices[i] = zoneIndices[j]!
|
||||
zoneIndices[j] = temp
|
||||
}
|
||||
|
||||
return items.map((item, index) => {
|
||||
// Assign to a random unique zone
|
||||
const zoneIndex = zoneIndices[index]!
|
||||
const row = Math.floor(zoneIndex / zones.cols)
|
||||
const col = zoneIndex % zones.cols
|
||||
|
||||
// Distribute layers evenly
|
||||
const layer = ((index % 4) + 1) as 1 | 2 | 3 | 4
|
||||
|
||||
// Calculate base position (center of zone)
|
||||
const baseX = col * zoneWidth + zoneWidth / 2
|
||||
const baseY = row * zoneHeight + zoneHeight / 2
|
||||
|
||||
// Add jitter (±35% of zone size to keep somewhat contained but messy)
|
||||
const jitterX = (rng() - 0.5) * zoneWidth * 0.7
|
||||
const jitterY = (rng() - 0.5) * zoneHeight * 0.7
|
||||
|
||||
return {
|
||||
...item,
|
||||
avatar: `/illustrations/user-faces/${index + 1}.jpg`,
|
||||
layer,
|
||||
position: {
|
||||
x: baseX + jitterX,
|
||||
y: baseY + jitterY,
|
||||
},
|
||||
scale: LAYER_SCALES[layer],
|
||||
zIndex: layer,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function UseCaseCardContent({
|
||||
item,
|
||||
opacity = 1,
|
||||
className = "",
|
||||
}: {
|
||||
item: UseCase & { avatar: string }
|
||||
opacity?: number
|
||||
className?: string
|
||||
}) {
|
||||
const ContextIcon: LucideIcon = item.context.icon
|
||||
return (
|
||||
<div
|
||||
className={`rounded-xl outline outline-border/50 bg-card/80 backdrop-blur-sm p-3 md:p-4 shadow-xl transition-all hover:shadow-xl hover:outline-8 ${className}`}>
|
||||
<div
|
||||
className="text-sm flex items-center gap-2 font-medium text-violet-600 mb-1"
|
||||
style={{ opacity: opacity }}>
|
||||
<Image
|
||||
src={item.avatar}
|
||||
className="size-6 rounded-full outline-1 outline-border"
|
||||
alt=""
|
||||
width={18}
|
||||
height={18}
|
||||
unoptimized
|
||||
/>
|
||||
<span className="text-nowrap">{item.role}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="text-[0.7em] flex flex-wrap items-center gap-1 text-muted-foreground mb-1"
|
||||
style={{ opacity: opacity }}>
|
||||
<CornerDownRight className="size-4 shrink-0 ml-3 -mt-1" />
|
||||
<span className="text-nowrap font-mono">To {item.agent.name} Agent</span>
|
||||
</div>
|
||||
|
||||
<div className="text-base font-light leading-tight my-1 ml-8" style={{ opacity: opacity }}>
|
||||
{item.use}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="text-[0.7em] font-light text-muted-foreground leading-tight mt-2 ml-8"
|
||||
style={{ opacity: opacity }}>
|
||||
via <ContextIcon strokeWidth={1.5} className="size-3.5 inline ml-1" /> {item.context.name}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function DesktopUseCaseCard({ item }: { item: PositionedUseCase }) {
|
||||
const opacity = Math.min(1, 0.5 + item.layer / 3)
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className="absolute w-[200px] cursor-default group"
|
||||
style={{
|
||||
left: `${item.position.x}%`,
|
||||
top: `${item.position.y}%`,
|
||||
zIndex: item.zIndex,
|
||||
width: Math.round(300 + Math.random() * 100),
|
||||
}}
|
||||
initial={{ opacity: 0, scale: 0 }}
|
||||
whileInView={{
|
||||
opacity: 1,
|
||||
scale: item.scale,
|
||||
transition: {
|
||||
duration: 0.1,
|
||||
delay: 0, // Stagger by layer
|
||||
},
|
||||
}}
|
||||
whileHover={{
|
||||
scale: 1.3,
|
||||
zIndex: 30,
|
||||
}}
|
||||
viewport={{ once: true }}
|
||||
// Use standard CSS transform for the positioning to avoid conflicts with Framer Motion's scale
|
||||
transformTemplate={({ scale }) => `translate(-50%, -50%) scale(${scale})`}>
|
||||
<UseCaseCardContent
|
||||
item={item}
|
||||
opacity={opacity}
|
||||
className={item.layer === 4 ? "shadow-lg border-border" : ""}
|
||||
/>
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
|
||||
export function UseExamplesSection() {
|
||||
const positionedItems = useMemo(() => distributeItems(USE_CASES), [])
|
||||
const [showAllMobile, setShowAllMobile] = useState(false)
|
||||
|
||||
return (
|
||||
<section className="pt-24 bg-background overflow-hidden relative">
|
||||
<div className="absolute inset-y-0 left-1/2 h-full w-full max-w-[1200px] -translate-x-1/2">
|
||||
<div className="absolute left-1/2 top-1/2 h-[700px] w-full -translate-x-1/2 -translate-y-1/2 rounded-full bg-foreground/10 blur-[140px]" />
|
||||
</div>
|
||||
<div className="container px-4 mx-auto sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-4xl font-bold tracking-tight mb-4">
|
||||
The AI team to help your <em>entire</em> human team
|
||||
</h2>
|
||||
<p className="text-xl font-light text-muted-foreground max-w-2xl mx-auto">
|
||||
Developers, PMs, Designers, Customer Success: everyone moves faster and more independently with
|
||||
Roo.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Mobile: Vertical Staggered List */}
|
||||
<div className="md:hidden flex flex-col gap-2 px-2 pb-12 max-w-md mx-auto">
|
||||
<AnimatePresence mode="popLayout">
|
||||
{positionedItems.slice(0, showAllMobile ? undefined : 8).map((item, index) => (
|
||||
<motion.div
|
||||
key={item.use} // Use a unique key for proper animation tracking
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: (index % 8) * 0.1, duration: 0.4 }}
|
||||
viewport={{ once: true, margin: "-50px" }}
|
||||
className={`w-[90%] ${index % 2 === 0 ? "self-start" : "self-end"}`}>
|
||||
<UseCaseCardContent item={item} />
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
|
||||
{!showAllMobile && (
|
||||
<div className="text-center mt-8 z-10">
|
||||
<Button variant="outline" onClick={() => setShowAllMobile(true)}>
|
||||
More
|
||||
<ChevronDown />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Desktop: Positioned Items Container */}
|
||||
<div className="hidden md:block relative h-[800px] md:min-h-[800px] w-full max-w-6xl mx-auto">
|
||||
{positionedItems.map((item, index) => (
|
||||
<DesktopUseCaseCard key={index} item={item} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
|
@ -5,12 +5,12 @@ import { cva, type VariantProps } from "class-variance-authority"
|
|||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
||||
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
||||
default: "bg-primary text-primary-foreground shadow hover:bg-primary/80",
|
||||
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/80",
|
||||
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
||||
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
|
|
@ -18,8 +18,9 @@ const buttonVariants = cva(
|
|||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2",
|
||||
sm: "h-8 rounded-md px-3 text-xs",
|
||||
lg: "h-10 rounded-md px-8",
|
||||
sm: "h-8 px-3 text-xs",
|
||||
lg: "h-10 px-8",
|
||||
xl: "h-14 px-8 text-lg",
|
||||
icon: "h-9 w-9",
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@ export * from "./chart"
|
|||
export * from "./modal"
|
||||
export * from "./scroll-button"
|
||||
export * from "./table"
|
||||
export * from "./link"
|
||||
|
|
|
|||
38
apps/web-roo-code/src/components/ui/link.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import * as React from "react"
|
||||
import NextLink from "next/link"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
type BaseLinkProps = React.ComponentPropsWithoutRef<typeof NextLink>
|
||||
|
||||
type LinkProps = BaseLinkProps & {
|
||||
newWindow?: boolean
|
||||
}
|
||||
|
||||
const Link = React.forwardRef<React.ElementRef<typeof NextLink>, LinkProps>(
|
||||
({ className, newWindow = false, target, rel, ...props }, ref) => {
|
||||
const computedTarget = newWindow ? "_blank" : target
|
||||
const computedRel = newWindow
|
||||
? rel
|
||||
? rel.includes("noreferrer")
|
||||
? rel
|
||||
: `${rel} noreferrer`
|
||||
: "noreferrer"
|
||||
: rel
|
||||
|
||||
return (
|
||||
<NextLink
|
||||
ref={ref}
|
||||
className={cn("underline hover:no-underline", className)}
|
||||
target={computedTarget}
|
||||
rel={computedRel}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
Link.displayName = "Link"
|
||||
|
||||
export { Link }
|
||||
export type { LinkProps }
|
||||
|
|
@ -26,6 +26,7 @@ export const EXTERNAL_LINKS = {
|
|||
TESTIMONIALS: "https://roocode.com/#testimonials",
|
||||
CLOUD_APP_LOGIN: "https://app.roocode.com/sign-in",
|
||||
CLOUD_APP_SIGNUP: "https://app.roocode.com/sign-up",
|
||||
CLOUD_APP_SIGNUP_HOME: "https://app.roocode.com/sign-up?redirect_url=/cloud-agents/setup",
|
||||
CLOUD_APP_SIGNUP_PRO: "https://app.roocode.com/sign-up?redirect_url=/cloud-agents/setup",
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ function formatNumber(num: number): string {
|
|||
// if number is 1 million or more, format as millions
|
||||
if (num >= 1000000) {
|
||||
const truncated = Math.floor((num / 1000000) * 10) / 10
|
||||
return truncated.toFixed(1) + "M"
|
||||
return truncated.toFixed(2) + "M"
|
||||
}
|
||||
|
||||
// otherwise, format as thousands
|
||||
|
|
|
|||
|
|
@ -1429,7 +1429,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
|
|||
icon={<Cloud className="size-5 shrink-0" />}
|
||||
onClick={() => openUpsell()}
|
||||
dismissOnClick={false}
|
||||
className="bg-none mt-6 border-border rounded-xl p-0 py-3 !text-base">
|
||||
className="bg-none mt-6 border-border rounded-xl p-0 py-3 !text-base">
|
||||
<Trans
|
||||
i18nKey="cloud:upsell.taskList"
|
||||
components={{
|
||||
|
|
|
|||