diff --git a/src/components/ColGrid.tsx b/src/components/ColGrid.tsx new file mode 100644 index 0000000000..6051d5d66d --- /dev/null +++ b/src/components/ColGrid.tsx @@ -0,0 +1,39 @@ +import * as React from "react"; +import clsx from "clsx"; + +export type GridColCount = 1 | 2 | 3; + +export interface ColGridProps extends React.HTMLAttributes { + children: React.ReactNode; + className?: string; + colCount: GridColCount; +} + +function getGridColsClass(colCount: GridColCount): string { + if (colCount === 1) { + return "grid grid-cols-1"; + } + if (colCount === 2) { + return "grid grid-cols-1 sm:grid-cols-2"; + } + if (colCount === 3) { + return "grid grid-cols-1 xl:grid-cols-3"; + } + return ""; +} + +export default function ColGrid({ + children, + className = "", + colCount = 1, + ...props +}: ColGridProps) { + return ( +
+ {children} +
+ ); +} diff --git a/src/components/Common/Badge.tsx b/src/components/Common/Badge.tsx new file mode 100644 index 0000000000..7a6c055d98 --- /dev/null +++ b/src/components/Common/Badge.tsx @@ -0,0 +1,58 @@ +import * as React from "react"; +import clsx from "clsx"; +import { Icon } from "./Icon"; +import { IconName } from "@site/src/typescript/iconName"; + +export interface BadgeProps extends React.HTMLAttributes { + children: React.ReactNode; + className?: string; + variant?: "default" | "secondary" | "outline" | "success" | "warning" | "destructive"; + size?: "sm" | "md"; + iconName?: IconName; + iconPosition?: "left" | "right"; +} + +const variantClasses: Record, string> = { + default: "bg-primary-light/80 backdrop-blur-xs text-white border border-primary/10 dark:text-black", + secondary: "bg-gray-200/70 backdrop-blur-xs text-black dark:bg-secondary/70 dark:text-black border border-gray-300/10 dark:border-secondary/10", + outline: "bg-stone-100/30 backdrop-blur-xs text-black border border-black/70", + success: "bg-green-300/80 backdrop-blur-xs text-green-950 border border-green-400/10", + warning: "bg-orange-300/80 backdrop-blur-xs text-orange-950 border border-orange-400/10", + destructive: "bg-red-300/80 backdrop-blur-xs text-red-950 border border-red-400/10", +} + +const sizeClasses: Record, string> = { + sm: "text-[11px] leading-4 h-5 px-2", + md: "text-xs leading-5 h-6 px-2.5", +}; + +export default function Badge({ + children, + className = "", + variant = "secondary", + size = "sm", + iconName, + iconPosition = "left", + ...props +}: BadgeProps) { + const baseClasses = clsx( + "inline-flex items-center gap-1 select-none", + "font-medium", + "rounded-full", + variantClasses[variant], + sizeClasses[size], + className, + ); + + const iconElement = iconName ? : null; + + return ( + + {iconElement && iconPosition === "left" && iconElement} + {children} + {iconElement && iconPosition === "right" && iconElement} + + ); +} + + diff --git a/src/components/Common/Button.tsx b/src/components/Common/Button.tsx index abe594dfe8..286540468d 100644 --- a/src/components/Common/Button.tsx +++ b/src/components/Common/Button.tsx @@ -1,18 +1,31 @@ import * as React from "react"; import Link from "@docusaurus/Link"; import clsx from "clsx"; +import { IconName } from "@site/src/typescript/iconName"; +import { Icon } from "./Icon"; +import isInternalUrl from "@docusaurus/isInternalUrl"; + +export type ButtonVariant = +| "default" +| "outline" +| "ghost" +| "destructive" +| "secondary"; + export interface ButtonProps extends React.ButtonHTMLAttributes { children: React.ReactNode; url?: string; className?: string; - variant?: "default" | "outline" | "ghost" | "destructive"; + variant?: ButtonVariant; size?: "sm" | "md" | "lg"; + iconName?: IconName; } -const variantClasses: Record, string> = { +const variantClasses: Record = { default: "bg-primary !text-white dark:!text-black hover:bg-primary-darker", + secondary: "bg-gray-300 hover:bg-gray-400 dark:bg-secondary !text-black dark:hover:bg-secondary-darker", outline: "border !text-black border-black/25 !text-foreground hover:bg-black/5 dark:!text-white dark:border-white/25 dark:hover:bg-white/5", ghost: "hover:bg-muted !text-foreground", @@ -29,8 +42,9 @@ export default function Button({ children, url, className = "", - variant = "default", + variant = "secondary", size = "md", + iconName, ...props }: ButtonProps) { const baseClasses = clsx( @@ -43,16 +57,21 @@ export default function Button({ ); if (url) { + const isExternal = !isInternalUrl(url); return ( - - {children} + + {children} {iconName && } + {isExternal && } ); } return ( ); } diff --git a/src/components/Common/CardWithImage.tsx b/src/components/Common/CardWithImage.tsx index 4045f25c5b..d1012f23fb 100644 --- a/src/components/Common/CardWithImage.tsx +++ b/src/components/Common/CardWithImage.tsx @@ -1,6 +1,10 @@ import React, { ReactNode } from "react"; import Heading from "@theme/Heading"; -import Button from "@site/src/components/Common/Button"; +import Button, { type ButtonVariant } from "@site/src/components/Common/Button"; +import { Icon } from "@site/src/components/Common/Icon"; +import { IconName } from "@site/src/typescript/iconName"; +import Badge from "@site/src/components/Common/Badge"; +import isInternalUrl from "@docusaurus/isInternalUrl"; export interface CardWithImageProps { title: string; @@ -8,7 +12,10 @@ export interface CardWithImageProps { imgSrc: string; imgAlt?: string; url?: string; + buttonVariant?: ButtonVariant; ctaLabel?: string; + iconName?: IconName; + imgIcon?: IconName; } export default function CardWithImage({ @@ -17,23 +24,36 @@ export default function CardWithImage({ imgSrc, imgAlt = "", url, + buttonVariant = "secondary", ctaLabel = "Read now", + iconName, + imgIcon, }: CardWithImageProps) { + const hasImage = Boolean(imgSrc); return (
-
- {imgAlt} +
+ {hasImage ? ( + {imgAlt} + ) : ( + + )} + {url && !isInternalUrl(url) && ( + + External + + )}
{title}

{description}

{url && ( - )} diff --git a/src/components/Common/CardWithImageHorizontal.tsx b/src/components/Common/CardWithImageHorizontal.tsx new file mode 100644 index 0000000000..6b21d6271f --- /dev/null +++ b/src/components/Common/CardWithImageHorizontal.tsx @@ -0,0 +1,59 @@ +import React, { ReactNode } from "react"; +import Heading from "@theme/Heading"; +import Button, { type ButtonVariant } from "@site/src/components/Common/Button"; +import { IconName } from "@site/src/typescript/iconName"; +import Badge from "@site/src/components/Common/Badge"; +import isInternalUrl from "@docusaurus/isInternalUrl"; + +export interface CardWithImageHorizontalProps { + title: string; + description: ReactNode; + imgSrc: string; + imgAlt?: string; + url?: string; + buttonVariant?: ButtonVariant; + ctaLabel?: string; + iconName?: IconName; +} + +export default function CardWithImageHorizontal({ + title, + description, + imgSrc, + imgAlt = "", + url, + buttonVariant = "secondary", + ctaLabel = "Read now", +}: CardWithImageHorizontalProps) { + return ( +
+
+ {imgAlt} + {url && !isInternalUrl(url) && ( + + External + + )} +
+
+ + {title} + +

{description}

+ {url && ( + + )} +
+
+ ); +} diff --git a/src/components/Homepage/UseCases/UseCaseItem.tsx b/src/components/Homepage/UseCases/UseCaseItem.tsx index af74916178..e4c4273b89 100644 --- a/src/components/Homepage/UseCases/UseCaseItem.tsx +++ b/src/components/Homepage/UseCases/UseCaseItem.tsx @@ -12,6 +12,7 @@ export default function UseCaseItem(props: CardWithImageProps) { imgSrc={imgSrc} imgAlt={imgAlt} ctaLabel={ctaLabel} - /> + buttonVariant="default" + /> ); } diff --git a/src/components/VersionConditional.tsx b/src/components/VersionConditional.tsx new file mode 100644 index 0000000000..7887ec2b69 --- /dev/null +++ b/src/components/VersionConditional.tsx @@ -0,0 +1,25 @@ +import { ReactNode } from "react"; +import { useActiveDocContext } from "@docusaurus/plugin-content-docs/client"; + +interface VersionConditionalProps { + minimumVersion: string; + children: ReactNode; +} + +export default function VersionConditional({ + minimumVersion, + children, +}: VersionConditionalProps) { + const pluginId = "default"; + const { activeVersion } = useActiveDocContext(pluginId); + + if ( + activeVersion.label.localeCompare(minimumVersion, undefined, { + numeric: true, + }) < 0 + ) { + return null; + } + + return <>{children}; +} diff --git a/src/css/custom.css b/src/css/custom.css index 13d5118bf9..8e2b9bcca5 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -103,6 +103,8 @@ --color-primary-light: var(--ifm-color-primary-light); --color-primary-lighter: var(--ifm-color-primary-lighter); --color-primary-lightest: var(--ifm-color-primary-lightest); + --color-secondary: var(--ifm-color-secondary); + --color-secondary-darker: var(--ifm-color-secondary-darker); --color-ifm-background: var(--ifm-background-color); --color-ifm-background-surface: var(--ifm-background-surface-color); --color-ifm-menu: var(--ifm-menu-color); diff --git a/templates/introduction.mdx b/templates/introduction.mdx new file mode 100644 index 0000000000..a8224b87d9 --- /dev/null +++ b/templates/introduction.mdx @@ -0,0 +1,97 @@ +--- +title: "AI Overview" +hide_table_of_contents: true +sidebar_label: AI Overview +--- + +import CardWithImage from "@site/src/components/Common/CardWithImage"; +import CardWithImageHorizontal from "@site/src/components/Common/CardWithImageHorizontal"; +import ColGrid from "@site/src/components/ColGrid"; + +# AI Overview + +Use RavenDB to ship AI functionalities faster + +## Keep AI data flow in your database layer + +RavenDB lets you ship AI features without any duct-taped extra services. Our AI ecosystem keeps your data, AI +pipelines, and retrieval in one place, effectively keeping your application layer thin - and letting you to focus on +improving your app, not on reinventing the wheel. + +Our database offers plenty of **robust, flexible, and easy-to-use** AI features tailored to your needs. You can either use +one or combine them - on top of both new and existing databases. + +## Use cases + +RavenDB AI Integration can help to ship any AI-related scenarios, including: + +- **Search & discovery** - Help users find things by meaning across docs, products, and media +- **Conversational interfaces** - Natural-language access to your data with safe, scoped actions +- **Content understanding & classification** - Auto-tagging, topic extraction, taxonomy mapping, entity linking +- **Workflow automation** - Trigger safe actions from AI insights (drafts, exports, updates) +- **Knowledge management (RAG)** - Ask questions over policies, wikis, and PDFs; store answers + citations +- **Personalization & recommendations** - Behavioral + semantic relevance for feeds, items, and knowledge +- & many more... + +Inspire yourself with our articles & learn more: + + + + + + +## AI Agents + +Conversational interfaces made simple - give your app a safe, tool-driven assistant that reads only what you allow and performs supervised actions right on top of your RavenDB data (7.1.2+) + + + + + + +## GenAI + +Use reasoning at scale - run LLM jobs inside the database: define context, prompt, and output schema then write results back with update scripts for governed, repeatable transforms (7.1+) + + + + + + +## Vector Search + +Search by meaning - perform semantic queries in RavenDB whether on-the-fly with dynamic RQL, via precomputed static indexes, or by indexing attachment contents to unlock fast, context-aware insights. (7.0+) + + + + + + +## Embeddings generation + +Keep your collections semantic-ready with a server-side task that batches, caches, and stores embeddings from your chosen model/provider (7.0.1+) + + + + + + +## Lives & videos + +Explore our engaging livestreams and videos that delve into the fascinating world of AI integration. + + + + + + + +## Deep dives, content & resources + +Here, you ll find a wealth of materials designed to enhance your knowledge and skills. + + + + + +