### What problem does this PR solve? feat: Add banner #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.14.0
| @@ -13,6 +13,7 @@ | |||
| "@hookform/resolvers": "^3.9.1", | |||
| "@js-preview/excel": "^1.7.8", | |||
| "@monaco-editor/react": "^4.6.0", | |||
| "@radix-ui/react-aspect-ratio": "^1.1.0", | |||
| "@radix-ui/react-avatar": "^1.1.1", | |||
| "@radix-ui/react-checkbox": "^1.1.2", | |||
| "@radix-ui/react-dropdown-menu": "^2.1.2", | |||
| @@ -4085,6 +4086,28 @@ | |||
| } | |||
| } | |||
| }, | |||
| "node_modules/@radix-ui/react-aspect-ratio": { | |||
| "version": "1.1.0", | |||
| "resolved": "https://registry.npmmirror.com/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.0.tgz", | |||
| "integrity": "sha512-dP87DM/Y7jFlPgUZTlhx6FF5CEzOiaxp2rBCKlaXlpH5Ip/9Fg5zZ9lDOQ5o/MOfUlf36eak14zoWYpgcgGoOg==", | |||
| "dependencies": { | |||
| "@radix-ui/react-primitive": "2.0.0" | |||
| }, | |||
| "peerDependencies": { | |||
| "@types/react": "*", | |||
| "@types/react-dom": "*", | |||
| "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", | |||
| "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" | |||
| }, | |||
| "peerDependenciesMeta": { | |||
| "@types/react": { | |||
| "optional": true | |||
| }, | |||
| "@types/react-dom": { | |||
| "optional": true | |||
| } | |||
| } | |||
| }, | |||
| "node_modules/@radix-ui/react-avatar": { | |||
| "version": "1.1.1", | |||
| "resolved": "https://registry.npmmirror.com/@radix-ui/react-avatar/-/react-avatar-1.1.1.tgz", | |||
| @@ -24,6 +24,7 @@ | |||
| "@hookform/resolvers": "^3.9.1", | |||
| "@js-preview/excel": "^1.7.8", | |||
| "@monaco-editor/react": "^4.6.0", | |||
| "@radix-ui/react-aspect-ratio": "^1.1.0", | |||
| "@radix-ui/react-avatar": "^1.1.1", | |||
| "@radix-ui/react-checkbox": "^1.1.2", | |||
| "@radix-ui/react-dropdown-menu": "^2.1.2", | |||
| @@ -0,0 +1,7 @@ | |||
| 'use client'; | |||
| import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio'; | |||
| const AspectRatio = AspectRatioPrimitive.Root; | |||
| export { AspectRatio }; | |||
| @@ -0,0 +1,36 @@ | |||
| import { cva, type VariantProps } from 'class-variance-authority'; | |||
| import * as React from 'react'; | |||
| import { cn } from '@/lib/utils'; | |||
| const badgeVariants = cva( | |||
| 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', | |||
| { | |||
| variants: { | |||
| variant: { | |||
| default: | |||
| 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80', | |||
| secondary: | |||
| 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80', | |||
| destructive: | |||
| 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80', | |||
| outline: 'text-foreground', | |||
| }, | |||
| }, | |||
| defaultVariants: { | |||
| variant: 'default', | |||
| }, | |||
| }, | |||
| ); | |||
| export interface BadgeProps | |||
| extends React.HTMLAttributes<HTMLDivElement>, | |||
| VariantProps<typeof badgeVariants> {} | |||
| function Badge({ className, variant, ...props }: BadgeProps) { | |||
| return ( | |||
| <div className={cn(badgeVariants({ variant }), className)} {...props} /> | |||
| ); | |||
| } | |||
| export { Badge, badgeVariants }; | |||
| @@ -0,0 +1,51 @@ | |||
| import { Card, CardContent } from '@/components/ui/card'; | |||
| import { ArrowRight } from 'lucide-react'; | |||
| function BannerCard() { | |||
| return ( | |||
| <Card className="w-auto border-none h-3/4"> | |||
| <CardContent className="p-4"> | |||
| <span className="inline-block bg-backgroundCoreWeak rounded-sm px-1 text-xs"> | |||
| System | |||
| </span> | |||
| <div className="flex mt-1 gap-4"> | |||
| <span className="text-lg truncate">Setting up your LLM</span> | |||
| <ArrowRight /> | |||
| </div> | |||
| </CardContent> | |||
| </Card> | |||
| ); | |||
| } | |||
| function MyCard() { | |||
| return ( | |||
| <div className="w-[265px] h-[87px] pl-[17px] pr-[13px] py-[15px] bg-[#b8b5cb]/20 rounded-xl border border-[#e6e3f6]/10 backdrop-blur-md justify-between items-end inline-flex"> | |||
| <div className="grow shrink basis-0 flex-col justify-start items-start gap-[9px] inline-flex"> | |||
| <div className="px-1 py-0.5 bg-[#644bf7] rounded justify-center items-center gap-2 inline-flex"> | |||
| <div className="text-white text-xs font-medium font-['IBM Plex Mono'] leading-none"> | |||
| System | |||
| </div> | |||
| </div> | |||
| <div className="self-stretch text-white text-lg font-normal font-['Inter'] leading-7"> | |||
| Setting up your LLM | |||
| </div> | |||
| </div> | |||
| <div className="w-6 h-6 relative" /> | |||
| </div> | |||
| ); | |||
| } | |||
| export function Banner() { | |||
| return ( | |||
| <section className="bg-[url('@/assets/banner.png')] bg-cover h-28 rounded-2xl mx-14 my-8 flex gap-8 justify-between"> | |||
| <div className="h-full text-3xl font-bold items-center inline-flex ml-6"> | |||
| Welcome to RAGFlow | |||
| </div> | |||
| <div className="flex justify-between items-center gap-10 mr-5"> | |||
| <BannerCard></BannerCard> | |||
| <BannerCard></BannerCard> | |||
| <MyCard></MyCard> | |||
| </div> | |||
| </section> | |||
| ); | |||
| } | |||
| @@ -1,12 +1,14 @@ | |||
| import { CardWithForm } from './card'; | |||
| import { Banner } from './banner'; | |||
| import { HomeHeader } from './header'; | |||
| import NextBanner from './next-banner'; | |||
| const Home = () => { | |||
| return ( | |||
| <div> | |||
| <HomeHeader></HomeHeader> | |||
| <section> | |||
| <CardWithForm></CardWithForm> | |||
| <Banner></Banner> | |||
| <NextBanner></NextBanner> | |||
| </section> | |||
| </div> | |||
| ); | |||
| @@ -0,0 +1,64 @@ | |||
| import { Badge } from '@/components/ui/badge'; | |||
| import { Card, CardContent } from '@/components/ui/card'; | |||
| import { ArrowRight, X } from 'lucide-react'; | |||
| const guideCards = [ | |||
| { | |||
| badge: 'System', | |||
| title: 'Setting up your LLM', | |||
| }, | |||
| { | |||
| badge: 'Chat app', | |||
| title: 'Configuration guides', | |||
| }, | |||
| { | |||
| badge: 'Search app', | |||
| title: 'Prompt setting guides', | |||
| }, | |||
| ]; | |||
| export default function WelcomeGuide(): JSX.Element { | |||
| return ( | |||
| <div className="flex w-full max-w-[1800px] items-center gap-4 px-[60px] py-6 relative bg-[#223d8e0d] rounded-3xl overflow-hidden"> | |||
| <div | |||
| className="absolute inset-0 bg-gradient-to-r from-pink-300 via-purple-400 to-blue-500 opacity-75" | |||
| style={{ | |||
| backgroundSize: 'cover', | |||
| backgroundPosition: 'center', | |||
| }} | |||
| /> | |||
| <h1 className="relative flex-1 text-4xl font-bold text-white"> | |||
| Welcome to RAGFlow | |||
| </h1> | |||
| <div className="inline-flex items-center gap-[22px] relative"> | |||
| {guideCards.map((card, index) => ( | |||
| <Card | |||
| key={index} | |||
| className="w-[265px] backdrop-blur-md border-colors-outline-neutral-standard" | |||
| > | |||
| <CardContent className="flex items-end justify-between p-[15px]"> | |||
| <div className="flex flex-col items-start gap-[9px] flex-1"> | |||
| <Badge | |||
| variant="secondary" | |||
| className="bg-colors-background-core-weak text-colors-text-neutral-strong" | |||
| > | |||
| {card.badge} | |||
| </Badge> | |||
| <p className="text-lg text-colors-text-neutral-strong"> | |||
| {card.title} | |||
| </p> | |||
| </div> | |||
| <ArrowRight className="w-6 h-6" /> | |||
| </CardContent> | |||
| </Card> | |||
| ))} | |||
| </div> | |||
| <button className="relative p-1 hover:bg-white/10 rounded-full transition-colors"> | |||
| <X className="w-6 h-6 text-white" /> | |||
| </button> | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -65,6 +65,10 @@ module.exports = { | |||
| DEFAULT: 'var(--background-core-standard)', | |||
| foreground: 'var(--background-core-standard-foreground)', | |||
| }, | |||
| backgroundCoreWeak: { | |||
| DEFAULT: 'var(--background-core-weak)', | |||
| foreground: 'var(--background-core-weak-foreground)', | |||
| }, | |||
| }, | |||
| borderRadius: { | |||
| lg: `var(--radius)`, | |||
| @@ -84,6 +84,9 @@ | |||
| --background-inverse-strong: rgba(255, 255, 255, 0.15); | |||
| --background-inverse-strong-foreground: rgba(255, 255, 255, 1); | |||
| --background-core-weak: rgb(101, 75, 248); | |||
| --background-core-weak-foreground: rgba(255, 255, 255, 1); | |||
| } | |||
| } | |||