From a53dffd8d3d7ef91b6dc4d98f512cf9240a87b1d Mon Sep 17 00:00:00 2001 From: Andrew Jiang Date: Fri, 8 Nov 2024 14:48:42 -0500 Subject: [PATCH] update styles --- .../ui/fern-docs-search-ui/.depcheckrc.json | 4 + packages/ui/fern-docs-search-ui/package.json | 11 +- .../src/app/api/anthropic/route.ts | 4 +- .../src/app/client-component.tsx | 16 +- .../fern-docs-search-ui/src/app/component.tsx | 14 +- .../fern-docs-search-ui/src/app/globals.css | 88 ++++++++-- .../ui/fern-docs-search-ui/src/app/page.tsx | 2 +- .../src/components/chat.tsx | 27 +++ .../src/components/desktop/DesktopCommand.tsx | 43 +++-- .../desktop/DesktopInstantSearch.tsx | 4 +- .../icons/ArrowTurnDownLeftIcon.tsx | 23 --- .../components/icons/RegularCalendarIcon.tsx | 23 --- .../components/icons/RegularFileLinesIcon.tsx | 23 --- .../src/components/icons/RemoteIcon.tsx | 43 +++-- .../src/components/shared/HitContent.tsx | 8 +- .../src/components/ui/button.tsx | 46 ++++++ .../src/components/ui/cn.ts | 6 + .../src/components/ui/dialog.tsx | 96 +++++++++++ .../src/components/ui/input.tsx | 21 +++ .../ui/fern-docs-search-ui/tailwind.config.ts | 50 +++++- pnpm-lock.yaml | 156 +++++++++++------- 21 files changed, 529 insertions(+), 179 deletions(-) create mode 100644 packages/ui/fern-docs-search-ui/.depcheckrc.json create mode 100644 packages/ui/fern-docs-search-ui/src/components/chat.tsx delete mode 100644 packages/ui/fern-docs-search-ui/src/components/icons/ArrowTurnDownLeftIcon.tsx delete mode 100644 packages/ui/fern-docs-search-ui/src/components/icons/RegularCalendarIcon.tsx delete mode 100644 packages/ui/fern-docs-search-ui/src/components/icons/RegularFileLinesIcon.tsx create mode 100644 packages/ui/fern-docs-search-ui/src/components/ui/button.tsx create mode 100644 packages/ui/fern-docs-search-ui/src/components/ui/cn.ts create mode 100644 packages/ui/fern-docs-search-ui/src/components/ui/dialog.tsx create mode 100644 packages/ui/fern-docs-search-ui/src/components/ui/input.tsx diff --git a/packages/ui/fern-docs-search-ui/.depcheckrc.json b/packages/ui/fern-docs-search-ui/.depcheckrc.json new file mode 100644 index 0000000000..b104cbe8e6 --- /dev/null +++ b/packages/ui/fern-docs-search-ui/.depcheckrc.json @@ -0,0 +1,4 @@ +{ + "ignores": ["autoprefixer", "postcss"], + "ignore-patterns": ["dist"] +} diff --git a/packages/ui/fern-docs-search-ui/package.json b/packages/ui/fern-docs-search-ui/package.json index 2f9f58ea8c..a6b5444e92 100644 --- a/packages/ui/fern-docs-search-ui/package.json +++ b/packages/ui/fern-docs-search-ui/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "dev": "next dev --turbo", + "dev": "next dev", "dev:build": "next build", "dev:start": "next start", "dev:lint": "next lint" @@ -17,7 +17,9 @@ "devDependencies": { "@types/react": "^18.0.20", "@types/react-dom": "^18.2.18", + "autoprefixer": "^10.4.16", "next": "^14", + "postcss": "^8.4.33", "react": "^18.2.0", "react-dom": "^18.2.0", "swr": "^2.2.5", @@ -27,18 +29,25 @@ "dependencies": { "@ai-sdk/anthropic": "^0.0.56", "@date-fns/tz": "^1.1.2", + "@fern-ui/chatbot": "workspace:*", "@fern-ui/fern-docs-search-server": "workspace:*", "@fern-ui/fern-http-method-tag": "workspace:*", + "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-slot": "^1.1.0", "ai": "^3.4.33", "algoliasearch": "^5.10.2", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", "cmdk": "^1.0.4", "date-fns": "^2.30.0", "es-toolkit": "^1.24.0", "instantsearch.css": "8.5.1", "instantsearch.js": "4.75.3", + "lucide-react": "^0.378.0", "react-instantsearch": "7.13.3", "react-instantsearch-nextjs": "0.3.16", "server-only": "^0.0.1", + "tailwind-merge": "^2.3.0", "ts-essentials": "^10.0.1", "zod": "^3.23.8" } diff --git a/packages/ui/fern-docs-search-ui/src/app/api/anthropic/route.ts b/packages/ui/fern-docs-search-ui/src/app/api/anthropic/route.ts index 2d77ab6746..c136a4d7c2 100644 --- a/packages/ui/fern-docs-search-ui/src/app/api/anthropic/route.ts +++ b/packages/ui/fern-docs-search-ui/src/app/api/anthropic/route.ts @@ -98,8 +98,9 @@ export async function POST(request: Request): Promise { const records: string[] = []; for (const { objectID, ...hit } of allHits.values()) { - records.push(`* ObjectID=\`${objectID}\`, Record=\`${JSON.stringify(toContent(hit))}\``); + records.push(`${objectID}, ${JSON.stringify(toContent(hit))}`); } + const { object } = await generateObject({ model: smallModel, system: "You are a reference extractor.", @@ -114,6 +115,7 @@ export async function POST(request: Request): Promise { ${text} ## Records +ObjectID, Record ${records.join("\n")}`, }); diff --git a/packages/ui/fern-docs-search-ui/src/app/client-component.tsx b/packages/ui/fern-docs-search-ui/src/app/client-component.tsx index fb9954f111..5af425b51e 100644 --- a/packages/ui/fern-docs-search-ui/src/app/client-component.tsx +++ b/packages/ui/fern-docs-search-ui/src/app/client-component.tsx @@ -1,11 +1,15 @@ "use client"; import { DesktopInstantSearch } from "@/components/desktop/DesktopInstantSearch"; +import { Dialog, DialogContent } from "@/components/ui/dialog"; import { useInitialResults } from "@/hooks/useInitialResults"; -import { ReactElement } from "react"; +import { ChatbotModal } from "@fern-ui/chatbot"; +import { ReactElement, useState } from "react"; import useSWR from "swr"; export function DesktopInstantSearchClient({ appId, domain }: { appId: string; domain: string }): ReactElement | false { + const [isChatOpen, setIsChatOpen] = useState(false); + const handleSubmit = (path: string) => { window.open(`https://${domain}${path}`, "_blank", "noopener,noreferrer"); }; @@ -20,6 +24,10 @@ export function DesktopInstantSearchClient({ appId, domain }: { appId: string; d const { initialResults } = useInitialResults(domain); + const chatStream = async (_message: string, _conversationId: string) => { + return [undefined, new AbortController()] as const; + }; + if (!apiKey) { return false; } @@ -39,9 +47,15 @@ export function DesktopInstantSearchClient({ appId, domain }: { appId: string; d appId={appId} apiKey={apiKey} onSubmit={handleSubmit} + onAskAI={() => setIsChatOpen(true)} // disabled={isLoading || initialResultsLoading || !apiKey} initialResults={initialResults} /> + + + + + ); } diff --git a/packages/ui/fern-docs-search-ui/src/app/component.tsx b/packages/ui/fern-docs-search-ui/src/app/component.tsx index 0fa194becc..260924f6ac 100644 --- a/packages/ui/fern-docs-search-ui/src/app/component.tsx +++ b/packages/ui/fern-docs-search-ui/src/app/component.tsx @@ -1,5 +1,7 @@ "use client"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; import { useRouter, useSearchParams } from "next/navigation"; import { useState, type ReactElement } from "react"; import { useFormStatus } from "react-dom"; @@ -31,15 +33,15 @@ export function DesktopInstantSearchWrapper({ appId }: { appId: string }): React } }} > - - +
handleReindex(selectedDomain)}> @@ -56,8 +58,8 @@ export function DesktopInstantSearchWrapper({ appId }: { appId: string }): React function SubmitButton() { const { pending } = useFormStatus(); return ( - + ); } diff --git a/packages/ui/fern-docs-search-ui/src/app/globals.css b/packages/ui/fern-docs-search-ui/src/app/globals.css index 9573c8aea9..953f5a2e5a 100644 --- a/packages/ui/fern-docs-search-ui/src/app/globals.css +++ b/packages/ui/fern-docs-search-ui/src/app/globals.css @@ -1,23 +1,85 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss/base"; +@import "tailwindcss/components"; +@import "tailwindcss/utilities"; +@import "@fern-ui/chatbot/src/index.scss"; -:root { - --background: #ffffff; - --foreground: #171717; +body { + font-family: + -apple-system, + blinkmacsystemfont, + segoe ui, + roboto, + oxygen, + ubuntu, + cantarell, + open sans, + helvetica neue, + sans-serif; } -@media (prefers-color-scheme: dark) { +@layer base { :root { - --background: #0a0a0a; - --foreground: #ededed; + --background: 108 100% 99%; + --foreground: 120 33% 5%; + --card: 108 100% 99%; + --card-foreground: 120 33% 5%; + --popover: 108 100% 99%; + --popover-foreground: 120 33% 5%; + --primary: 127 72% 37%; + --primary-foreground: 0 0% 98%; + --secondary: 108 20% 95%; + --secondary-foreground: 0 0% 9%; + --muted: 108 20% 95%; + --muted-foreground: 0 0% 45.1%; + --accent: 108 20% 95%; + --accent-foreground: 0 0% 9%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + --ring: 127 72% 37%; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + --radius: 0.5rem; + } + .dark { + --background: 120 33% 5%; + --foreground: 0 0% 98%; + --card: 120 33% 5%; + --card-foreground: 0 0% 98%; + --popover: 120 33% 5%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + --secondary: 120 34% 12%; + --secondary-foreground: 0 0% 98%; + --muted: 120 34% 12%; + --muted-foreground: 0 0% 63.9%; + --accent: 120 34% 12%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 120 34% 12%; + --input: 120 34% 12%; + --ring: 0 0% 83.1%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; } } -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } } @layer components { diff --git a/packages/ui/fern-docs-search-ui/src/app/page.tsx b/packages/ui/fern-docs-search-ui/src/app/page.tsx index fd4701ab0c..6c927246e6 100644 --- a/packages/ui/fern-docs-search-ui/src/app/page.tsx +++ b/packages/ui/fern-docs-search-ui/src/app/page.tsx @@ -6,7 +6,7 @@ import { DesktopInstantSearchWrapper } from "./component"; export default async function Home(): Promise { return ( -
+
Loading...
}> diff --git a/packages/ui/fern-docs-search-ui/src/components/chat.tsx b/packages/ui/fern-docs-search-ui/src/components/chat.tsx new file mode 100644 index 0000000000..cb157569ac --- /dev/null +++ b/packages/ui/fern-docs-search-ui/src/components/chat.tsx @@ -0,0 +1,27 @@ +"use client"; + +import { useChat } from "ai/react"; +import { ReactElement } from "react"; + +export default function Chat(): ReactElement { + const { messages, input, handleInputChange, handleSubmit } = useChat(); + return ( +
+ {messages.map((m) => ( +
+ {m.role === "user" ? "User: " : "AI: "} + {m.content} +
+ ))} + + + + +
+ ); +} diff --git a/packages/ui/fern-docs-search-ui/src/components/desktop/DesktopCommand.tsx b/packages/ui/fern-docs-search-ui/src/components/desktop/DesktopCommand.tsx index 10beaf3373..089db4d3ab 100644 --- a/packages/ui/fern-docs-search-ui/src/components/desktop/DesktopCommand.tsx +++ b/packages/ui/fern-docs-search-ui/src/components/desktop/DesktopCommand.tsx @@ -1,11 +1,10 @@ import { InitialResultsResponse } from "@/server/browse-results"; import { AlgoliaRecord } from "@fern-ui/fern-docs-search-server/types"; import { Command } from "cmdk"; +import { FileText, History, MessageCircle } from "lucide-react"; import { ReactElement, useDeferredValue } from "react"; import { useHits, useSearchBox } from "react-instantsearch"; import { MarkRequired } from "ts-essentials"; -import { RegularCalendarIcon } from "../icons/RegularCalendarIcon"; -import { RegularFileLinesIcon } from "../icons/RegularFileLinesIcon"; import { RemoteIcon } from "../icons/RemoteIcon"; import { HitContent } from "../shared/HitContent"; import { generateHits } from "../shared/hits"; @@ -17,10 +16,12 @@ export function DesktopCommand({ initialResults, placeholder, onSubmit, + onAskAI, }: { initialResults: InitialResultsResponse; placeholder?: string; onSubmit: (path: string) => void; + onAskAI?: () => void; }): ReactElement { const { query, refine } = useSearchBox(); const { items: rawHits } = useHits(); @@ -43,8 +44,24 @@ export function DesktopCommand({ No results found + + onAskAI?.()}> + + + Ask AI + {query.trimStart().length > 0 && ( + <> + + {query} + + + )} + + + + {groups.map((group, index) => ( - + {group.hits.map((hit) => ( onSubmit(hit.path)} className="flex gap-2 cursor-default" > - {hit.icon != null ? ( - - ) : hit.record?.type === "changelog" ? ( - - ) : ( - - )} + {hit.record != null && ( } /> )} @@ -71,3 +82,15 @@ export function DesktopCommand({ ); } + +function Icon({ icon, type }: { icon: string | undefined; type: string | undefined }): ReactElement { + if (icon) { + return ; + } + + if (type === "changelog") { + return ; + } + + return ; +} diff --git a/packages/ui/fern-docs-search-ui/src/components/desktop/DesktopInstantSearch.tsx b/packages/ui/fern-docs-search-ui/src/components/desktop/DesktopInstantSearch.tsx index 612ba2c811..fb3ea2c074 100644 --- a/packages/ui/fern-docs-search-ui/src/components/desktop/DesktopInstantSearch.tsx +++ b/packages/ui/fern-docs-search-ui/src/components/desktop/DesktopInstantSearch.tsx @@ -11,6 +11,7 @@ interface DesktopInstantSearchProps { apiKey: string; initialResults: InitialResultsResponse; onSubmit: (path: string) => void; + onAskAI?: () => void; } export function DesktopInstantSearch({ @@ -18,6 +19,7 @@ export function DesktopInstantSearch({ apiKey, initialResults, onSubmit, + onAskAI, }: DesktopInstantSearchProps): ReactElement { const ref = useRef(algoliasearch(appId, apiKey)); @@ -38,7 +40,7 @@ export function DesktopInstantSearch({ attributesToSnippet={["description:24", "content:24"]} ignorePlurals /> - + ); } diff --git a/packages/ui/fern-docs-search-ui/src/components/icons/ArrowTurnDownLeftIcon.tsx b/packages/ui/fern-docs-search-ui/src/components/icons/ArrowTurnDownLeftIcon.tsx deleted file mode 100644 index 3352004c78..0000000000 --- a/packages/ui/fern-docs-search-ui/src/components/icons/ArrowTurnDownLeftIcon.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { SVGProps, forwardRef } from "react"; - -export const ArrowTurnDownLeftIcon = forwardRef>((props, ref) => ( - -)); - -ArrowTurnDownLeftIcon.displayName = "ArrowTurnDownLeftIcon"; diff --git a/packages/ui/fern-docs-search-ui/src/components/icons/RegularCalendarIcon.tsx b/packages/ui/fern-docs-search-ui/src/components/icons/RegularCalendarIcon.tsx deleted file mode 100644 index c4ba39dbc4..0000000000 --- a/packages/ui/fern-docs-search-ui/src/components/icons/RegularCalendarIcon.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { SVGProps, forwardRef } from "react"; - -export const RegularCalendarIcon = forwardRef>((props, ref) => ( - -)); - -RegularCalendarIcon.displayName = "RegularCalendarIcon"; diff --git a/packages/ui/fern-docs-search-ui/src/components/icons/RegularFileLinesIcon.tsx b/packages/ui/fern-docs-search-ui/src/components/icons/RegularFileLinesIcon.tsx deleted file mode 100644 index 5dd58d385b..0000000000 --- a/packages/ui/fern-docs-search-ui/src/components/icons/RegularFileLinesIcon.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { SVGProps, forwardRef } from "react"; - -export const RegularFileLinesIcon = forwardRef>((props, ref) => ( - -)); - -RegularFileLinesIcon.displayName = "RegularFileLinesIcon"; diff --git a/packages/ui/fern-docs-search-ui/src/components/icons/RemoteIcon.tsx b/packages/ui/fern-docs-search-ui/src/components/icons/RemoteIcon.tsx index 03decb45d2..191ccea1bf 100644 --- a/packages/ui/fern-docs-search-ui/src/components/icons/RemoteIcon.tsx +++ b/packages/ui/fern-docs-search-ui/src/components/icons/RemoteIcon.tsx @@ -1,22 +1,37 @@ -import { ReactElement, SVGProps } from "react"; +import { FileText } from "lucide-react"; +import { SVGProps, forwardRef } from "react"; import useSWRImmutable from "swr/immutable"; -import { RegularFileLinesIcon } from "./RegularFileLinesIcon"; -export function RemoteIcon({ icon, ...props }: { icon: string } & SVGProps): ReactElement { - const { data } = useSWRImmutable(icon, () => fetch(getIconUrl(icon)).then((res) => res.text())); +export const RemoteIcon = forwardRef>( + ({ icon, ...props }, ref) => { + const { data } = useSWRImmutable(icon, () => fetch(getIconUrl(icon)).then((res) => res.text())); - if (data == null) { - return ; - } + if (data == null) { + return ; + } - // parse the svg - const { props: svgProps, body } = parseSvg(data); - delete svgProps.class; - delete svgProps.className; - delete svgProps.hidden; + // parse the svg + const { props: svgProps, body } = parseSvg(data); + delete svgProps.class; + delete svgProps.className; + delete svgProps.hidden; - return ; -} + return ( + + ); + }, +); + +RemoteIcon.displayName = "RemoteIcon"; // parse the svg function parseSvg(svg: string): { diff --git a/packages/ui/fern-docs-search-ui/src/components/shared/HitContent.tsx b/packages/ui/fern-docs-search-ui/src/components/shared/HitContent.tsx index 4a0c5dfb52..d856a0b8cb 100644 --- a/packages/ui/fern-docs-search-ui/src/components/shared/HitContent.tsx +++ b/packages/ui/fern-docs-search-ui/src/components/shared/HitContent.tsx @@ -3,7 +3,7 @@ import { ParameterRecord } from "@fern-ui/fern-docs-search-server/types"; import { HttpMethodTag } from "@fern-ui/fern-http-method-tag"; import { Hit } from "algoliasearch/lite"; import { format } from "date-fns"; -import { ReactElement } from "react"; +import { Fragment, ReactElement } from "react"; import { Highlight, Snippet } from "react-instantsearch"; import { MarkRequired, UnreachableCaseError } from "ts-essentials"; import { AlgoliaRecordHit, ApiReferenceRecordHit, ChangelogRecordHit, MarkdownRecordHit } from "../types"; @@ -35,10 +35,10 @@ function HierarchyBreadcrumb({ return (
{breadcrumb.map((title, idx) => ( - <> - {title} + + {title} {idx < breadcrumb.length - 1 && {" / "}} - + ))}
); diff --git a/packages/ui/fern-docs-search-ui/src/components/ui/button.tsx b/packages/ui/fern-docs-search-ui/src/components/ui/button.tsx new file mode 100644 index 0000000000..68bf639fa2 --- /dev/null +++ b/packages/ui/fern-docs-search-ui/src/components/ui/button.tsx @@ -0,0 +1,46 @@ +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; +import * as React from "react"; +import { cn } from "./cn"; + +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", + { + 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", + 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", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "size-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ; + }, +); +Button.displayName = "Button"; + +export { Button, buttonVariants }; diff --git a/packages/ui/fern-docs-search-ui/src/components/ui/cn.ts b/packages/ui/fern-docs-search-ui/src/components/ui/cn.ts new file mode 100644 index 0000000000..98e692155a --- /dev/null +++ b/packages/ui/fern-docs-search-ui/src/components/ui/cn.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]): string { + return twMerge(clsx(inputs)); +} diff --git a/packages/ui/fern-docs-search-ui/src/components/ui/dialog.tsx b/packages/ui/fern-docs-search-ui/src/components/ui/dialog.tsx new file mode 100644 index 0000000000..8c95ef72b0 --- /dev/null +++ b/packages/ui/fern-docs-search-ui/src/components/ui/dialog.tsx @@ -0,0 +1,96 @@ +"use client"; + +import * as DialogPrimitive from "@radix-ui/react-dialog"; +import { X } from "lucide-react"; +import * as React from "react"; +import { cn } from "./cn"; + +const Dialog = DialogPrimitive.Root; + +const DialogTrigger = DialogPrimitive.Trigger; + +const DialogPortal = DialogPrimitive.Portal; + +const DialogClose = DialogPrimitive.Close; + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ className, ...props }: React.HTMLAttributes): React.ReactElement => ( +
+); +DialogHeader.displayName = "DialogHeader"; + +const DialogFooter = ({ className, ...props }: React.HTMLAttributes): React.ReactElement => ( +
+); +DialogFooter.displayName = "DialogFooter"; + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; + +export { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogOverlay, + DialogPortal, + DialogTitle, + DialogTrigger, +}; diff --git a/packages/ui/fern-docs-search-ui/src/components/ui/input.tsx b/packages/ui/fern-docs-search-ui/src/components/ui/input.tsx new file mode 100644 index 0000000000..a9530964b5 --- /dev/null +++ b/packages/ui/fern-docs-search-ui/src/components/ui/input.tsx @@ -0,0 +1,21 @@ +import * as React from "react"; +import { cn } from "./cn"; + +const Input = React.forwardRef>( + ({ className, type, ...props }, ref) => { + return ( + + ); + }, +); +Input.displayName = "Input"; + +export { Input }; diff --git a/packages/ui/fern-docs-search-ui/tailwind.config.ts b/packages/ui/fern-docs-search-ui/tailwind.config.ts index 35cbde3c39..2428e227aa 100644 --- a/packages/ui/fern-docs-search-ui/tailwind.config.ts +++ b/packages/ui/fern-docs-search-ui/tailwind.config.ts @@ -1,17 +1,63 @@ +import path from "path"; import type { Config } from "tailwindcss"; import plugin from "tailwindcss/plugin"; const config: Config = { + darkMode: "class", content: [ "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", "./src/components/**/*.{js,ts,jsx,tsx,mdx}", "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + path.join(path.dirname(require.resolve("@fern-ui/chatbot")), "**/*.{ts,tsx}"), ], theme: { extend: { colors: { - background: "var(--background)", - foreground: "var(--foreground)", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + chart: { + "1": "hsl(var(--chart-1))", + "2": "hsl(var(--chart-2))", + "3": "hsl(var(--chart-3))", + "4": "hsl(var(--chart-4))", + "5": "hsl(var(--chart-5))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", }, }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a8605a7b22..945fa3f2a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1369,7 +1369,7 @@ importers: version: 4.2.1(vite@5.4.10(@types/node@18.19.33)(less@4.2.0)(sass@1.77.0)(stylus@0.62.0)(terser@5.31.0)) autoprefixer: specifier: ^10.4.16 - version: 10.4.19(postcss@8.4.31) + version: 10.4.19(postcss@8.4.47) chromatic: specifier: ^11.3.0 version: 11.3.2 @@ -1399,7 +1399,7 @@ importers: version: 0.10.0 postcss-import: specifier: ^16.0.1 - version: 16.1.0(postcss@8.4.31) + version: 16.1.0(postcss@8.4.47) prettier: specifier: ^3.3.2 version: 3.3.2 @@ -1653,7 +1653,7 @@ importers: version: 4.2.1(vite@5.4.10(@types/node@18.19.33)(less@4.2.0)(sass@1.77.0)(stylus@0.62.0)(terser@5.31.0)) autoprefixer: specifier: ^10.4.16 - version: 10.4.19(postcss@8.4.31) + version: 10.4.19(postcss@8.4.47) chromatic: specifier: ^11.3.0 version: 11.3.2 @@ -1674,7 +1674,7 @@ importers: version: 0.10.0 postcss-import: specifier: ^16.0.1 - version: 16.1.0(postcss@8.4.31) + version: 16.1.0(postcss@8.4.47) prettier: specifier: ^3.3.2 version: 3.3.2 @@ -2369,18 +2369,33 @@ importers: '@date-fns/tz': specifier: ^1.1.2 version: 1.1.2 + '@fern-ui/chatbot': + specifier: workspace:* + version: link:../chatbot '@fern-ui/fern-docs-search-server': specifier: workspace:* version: link:../fern-docs-search-server '@fern-ui/fern-http-method-tag': specifier: workspace:* version: link:../fern-http-method-tag + '@radix-ui/react-dialog': + specifier: ^1.1.1 + version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': + specifier: ^1.1.0 + version: 1.1.0(@types/react@18.3.3)(react@18.3.1) ai: specifier: ^3.4.33 version: 3.4.33(react@18.3.1)(sswr@2.1.0(svelte@5.1.12))(svelte@5.1.12)(vue@3.5.12(typescript@5.4.3))(zod@3.23.8) algoliasearch: specifier: ^5.10.2 version: 5.10.2 + class-variance-authority: + specifier: ^0.7.0 + version: 0.7.0 + clsx: + specifier: ^2.1.1 + version: 2.1.1 cmdk: specifier: ^1.0.4 version: 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -2396,6 +2411,9 @@ importers: instantsearch.js: specifier: 4.75.3 version: 4.75.3(algoliasearch@5.10.2) + lucide-react: + specifier: ^0.378.0 + version: 0.378.0(react@18.3.1) react-instantsearch: specifier: 7.13.3 version: 7.13.3(algoliasearch@5.10.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -2405,6 +2423,9 @@ importers: server-only: specifier: ^0.0.1 version: 0.0.1 + tailwind-merge: + specifier: ^2.3.0 + version: 2.3.0 ts-essentials: specifier: ^10.0.1 version: 10.0.1(typescript@5.4.3) @@ -2418,9 +2439,15 @@ importers: '@types/react-dom': specifier: ^18.2.18 version: 18.3.0 + autoprefixer: + specifier: ^10.4.16 + version: 10.4.19(postcss@8.4.31) next: specifier: npm:@fern-api/next@14.2.9-fork.2 version: '@fern-api/next@14.2.9-fork.2(@babel/core@7.24.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.0)' + postcss: + specifier: 8.4.31 + version: 8.4.31 react: specifier: ^18.2.0 version: 18.3.1 @@ -10094,9 +10121,6 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.4.761: - resolution: {integrity: sha512-PIbxpiJGx6Bb8dQaonNc6CGTRlVntdLg/2nMa1YhnrwYOORY9a3ZgGN0UQYE6lAcj/lkyduJN7BPt/JiY+jAQQ==} - electron-to-chromium@1.5.50: resolution: {integrity: sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==} @@ -12975,9 +12999,6 @@ packages: peerDependencies: webpack: 5.94.0 - node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} @@ -13741,6 +13762,10 @@ packages: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + engines: {node: ^10 || ^12 || >=14} + posthog-js@1.154.5: resolution: {integrity: sha512-YYhWckDIRObfCrQpiLq+fdcDTIbQp8ebiKi0ueGohMRgugIG9LJVSpBgCeCHZm2C7sOxDUNcAr3T5VBDUSQoOg==} @@ -14709,6 +14734,10 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} @@ -15777,12 +15806,6 @@ packages: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} engines: {node: '>=8'} - update-browserslist-db@1.0.15: - resolution: {integrity: sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - update-browserslist-db@1.1.1: resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true @@ -17228,7 +17251,7 @@ snapshots: dependencies: '@babel/helper-validator-identifier': 7.25.9 js-tokens: 4.0.0 - picocolors: 1.0.0 + picocolors: 1.1.1 '@babel/compat-data@7.24.4': {} @@ -17512,7 +17535,7 @@ snapshots: '@babel/helper-validator-identifier': 7.24.5 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.0 + picocolors: 1.1.1 '@babel/parser@7.24.5': dependencies: @@ -18819,13 +18842,13 @@ snapshots: '@clack/core@0.3.4': dependencies: - picocolors: 1.0.0 + picocolors: 1.1.1 sisteransi: 1.0.5 '@clack/prompts@0.6.3': dependencies: '@clack/core': 0.3.4 - picocolors: 1.0.0 + picocolors: 1.1.1 sisteransi: 1.0.5 '@colors/colors@1.6.0': {} @@ -23514,7 +23537,7 @@ snapshots: '@vue/shared': 3.4.27 entities: 4.5.0 estree-walker: 2.0.2 - source-map-js: 1.2.0 + source-map-js: 1.2.1 '@vue/compiler-core@3.5.12': dependencies: @@ -23522,7 +23545,7 @@ snapshots: '@vue/shared': 3.5.12 entities: 4.5.0 estree-walker: 2.0.2 - source-map-js: 1.2.0 + source-map-js: 1.2.1 '@vue/compiler-dom@3.4.27': dependencies: @@ -23556,7 +23579,7 @@ snapshots: estree-walker: 2.0.2 magic-string: 0.30.12 postcss: 8.4.31 - source-map-js: 1.2.0 + source-map-js: 1.2.1 '@vue/compiler-ssr@3.4.27': dependencies: @@ -24895,7 +24918,7 @@ snapshots: aria-hidden@1.2.4: dependencies: - tslib: 2.6.2 + tslib: 2.8.0 aria-query@5.1.3: dependencies: @@ -25039,24 +25062,34 @@ snapshots: autoprefixer@10.4.15(postcss@8.4.31): dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001617 + browserslist: 4.24.2 + caniuse-lite: 1.0.30001677 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.0 + picocolors: 1.1.1 postcss: 8.4.31 postcss-value-parser: 4.2.0 autoprefixer@10.4.19(postcss@8.4.31): dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001617 + browserslist: 4.24.2 + caniuse-lite: 1.0.30001677 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.0 + picocolors: 1.1.1 postcss: 8.4.31 postcss-value-parser: 4.2.0 + autoprefixer@10.4.19(postcss@8.4.47): + dependencies: + browserslist: 4.24.2 + caniuse-lite: 1.0.30001677 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.4.47 + postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -25351,10 +25384,10 @@ snapshots: browserslist@4.23.0: dependencies: - caniuse-lite: 1.0.30001617 - electron-to-chromium: 1.4.761 - node-releases: 2.0.14 - update-browserslist-db: 1.0.15(browserslist@4.23.0) + caniuse-lite: 1.0.30001677 + electron-to-chromium: 1.5.50 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.23.0) browserslist@4.24.2: dependencies: @@ -25459,8 +25492,8 @@ snapshots: caniuse-api@3.0.0: dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001617 + browserslist: 4.24.2 + caniuse-lite: 1.0.30001677 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 @@ -26017,7 +26050,7 @@ snapshots: css-tree@2.2.1: dependencies: mdn-data: 2.0.28 - source-map-js: 1.2.0 + source-map-js: 1.2.1 css-tree@2.3.1: dependencies: @@ -26032,7 +26065,7 @@ snapshots: cssnano-preset-default@6.1.2(postcss@8.4.31): dependencies: - browserslist: 4.23.0 + browserslist: 4.24.2 css-declaration-sorter: 7.2.0(postcss@8.4.31) cssnano-utils: 4.0.2(postcss@8.4.31) postcss: 8.4.31 @@ -26618,8 +26651,6 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.4.761: {} - electron-to-chromium@1.5.50: {} elliptic@6.5.7: @@ -30654,8 +30685,6 @@ snapshots: vm-browserify: 1.1.2 webpack: 5.94.0(@swc/core@1.5.7) - node-releases@2.0.14: {} - node-releases@2.0.18: {} nodemon@3.1.0: @@ -31146,7 +31175,7 @@ snapshots: postcss-colormin@6.1.0(postcss@8.4.31): dependencies: - browserslist: 4.23.0 + browserslist: 4.24.2 caniuse-api: 3.0.0 colord: 2.9.3 postcss: 8.4.31 @@ -31154,7 +31183,7 @@ snapshots: postcss-convert-values@6.1.0(postcss@8.4.31): dependencies: - browserslist: 4.23.0 + browserslist: 4.24.2 postcss: 8.4.31 postcss-value-parser: 4.2.0 @@ -31188,6 +31217,13 @@ snapshots: read-cache: 1.0.0 resolve: 1.22.8 + postcss-import@16.1.0(postcss@8.4.47): + dependencies: + postcss: 8.4.47 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + postcss-js@4.0.1(postcss@8.4.31): dependencies: camelcase-css: 2.0.1 @@ -31266,7 +31302,7 @@ snapshots: postcss-merge-rules@6.1.1(postcss@8.4.31): dependencies: - browserslist: 4.23.0 + browserslist: 4.24.2 caniuse-api: 3.0.0 cssnano-utils: 4.0.2(postcss@8.4.31) postcss: 8.4.31 @@ -31286,7 +31322,7 @@ snapshots: postcss-minify-params@6.1.0(postcss@8.4.31): dependencies: - browserslist: 4.23.0 + browserslist: 4.24.2 cssnano-utils: 4.0.2(postcss@8.4.31) postcss: 8.4.31 postcss-value-parser: 4.2.0 @@ -31353,7 +31389,7 @@ snapshots: postcss-normalize-unicode@6.1.0(postcss@8.4.31): dependencies: - browserslist: 4.23.0 + browserslist: 4.24.2 postcss: 8.4.31 postcss-value-parser: 4.2.0 @@ -31375,7 +31411,7 @@ snapshots: postcss-reduce-initial@6.1.0(postcss@8.4.31): dependencies: - browserslist: 4.23.0 + browserslist: 4.24.2 caniuse-api: 3.0.0 postcss: 8.4.31 @@ -31420,8 +31456,14 @@ snapshots: postcss@8.4.31: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.2.0 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + postcss@8.4.47: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.1 + source-map-js: 1.2.1 posthog-js@1.154.5: dependencies: @@ -32699,6 +32741,8 @@ snapshots: source-map-js@1.2.0: {} + source-map-js@1.2.1: {} + source-map-support@0.5.13: dependencies: buffer-from: 1.1.2 @@ -32981,7 +33025,7 @@ snapshots: stylehacks@6.1.1(postcss@8.4.31): dependencies: - browserslist: 4.23.0 + browserslist: 4.24.2 postcss: 8.4.31 postcss-selector-parser: 6.0.16 @@ -33145,7 +33189,7 @@ snapshots: css-tree: 2.3.1 css-what: 6.1.0 csso: 5.0.5 - picocolors: 1.0.0 + picocolors: 1.1.1 swr@2.2.5(react@18.3.1): dependencies: @@ -34000,11 +34044,11 @@ snapshots: untildify@4.0.0: {} - update-browserslist-db@1.0.15(browserslist@4.23.0): + update-browserslist-db@1.1.1(browserslist@4.23.0): dependencies: browserslist: 4.23.0 - escalade: 3.1.2 - picocolors: 1.0.0 + escalade: 3.2.0 + picocolors: 1.1.1 update-browserslist-db@1.1.1(browserslist@4.24.2): dependencies: @@ -34408,7 +34452,7 @@ snapshots: html-escaper: 2.0.2 is-plain-object: 5.0.0 opener: 1.5.2 - picocolors: 1.0.0 + picocolors: 1.1.1 sirv: 2.0.4 ws: 7.5.9 transitivePeerDependencies: