Compare commits

..

2 Commits

Author SHA1 Message Date
Jamison Lahman
d2deefd1f1 chore(whitelabeling): always show sidebar icon without logo icon (#8860)
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-27 20:36:11 +00:00
Jamison Lahman
18b90d405d chore(deps): upgrade fastapi: 0.128.0->0.133.1 (#8862) 2026-02-27 20:26:27 +00:00
33 changed files with 450 additions and 352 deletions

View File

@@ -257,7 +257,7 @@ exceptiongroup==1.3.0
# via
# braintrust
# fastmcp
fastapi==0.128.0
fastapi==0.133.1
# via
# fastapi-limiter
# fastapi-users
@@ -1155,6 +1155,7 @@ typing-inspect==0.9.0
# via dataclasses-json
typing-inspection==0.4.2
# via
# fastapi
# mcp
# pydantic
# pydantic-settings

View File

@@ -125,7 +125,7 @@ executing==2.2.1
# via stack-data
faker==40.1.2
# via onyx
fastapi==0.128.0
fastapi==0.133.1
# via
# onyx
# onyx-devtools
@@ -619,6 +619,7 @@ typing-extensions==4.15.0
# typing-inspection
typing-inspection==0.4.2
# via
# fastapi
# mcp
# pydantic
# pydantic-settings

View File

@@ -90,7 +90,7 @@ docstring-parser==0.17.0
# via google-cloud-aiplatform
durationpy==0.10
# via kubernetes
fastapi==0.128.0
fastapi==0.133.1
# via onyx
fastavro==1.12.1
# via cohere
@@ -398,6 +398,7 @@ typing-extensions==4.15.0
# typing-inspection
typing-inspection==0.4.2
# via
# fastapi
# mcp
# pydantic
# pydantic-settings

View File

@@ -108,7 +108,7 @@ durationpy==0.10
# via kubernetes
einops==0.8.1
# via onyx
fastapi==0.128.0
fastapi==0.133.1
# via
# onyx
# sentry-sdk
@@ -525,6 +525,7 @@ typing-extensions==4.15.0
# typing-inspection
typing-inspection==0.4.2
# via
# fastapi
# mcp
# pydantic
# pydantic-settings

View File

@@ -10,7 +10,7 @@ requires-python = ">=3.11"
dependencies = [
"aioboto3==15.1.0",
"cohere==5.6.1",
"fastapi==0.128.0",
"fastapi==0.133.1",
"google-cloud-aiplatform==1.121.0",
"google-genai==1.52.0",
"litellm==1.81.6",

9
uv.lock generated
View File

@@ -1688,17 +1688,18 @@ wheels = [
[[package]]
name = "fastapi"
version = "0.128.0"
version = "0.133.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "annotated-doc" },
{ name = "pydantic" },
{ name = "starlette" },
{ name = "typing-extensions" },
{ name = "typing-inspection" },
]
sdist = { url = "https://files.pythonhosted.org/packages/52/08/8c8508db6c7b9aae8f7175046af41baad690771c9bcde676419965e338c7/fastapi-0.128.0.tar.gz", hash = "sha256:1cc179e1cef10a6be60ffe429f79b829dce99d8de32d7acb7e6c8dfdf7f2645a", size = 365682, upload-time = "2025-12-27T15:21:13.714Z" }
sdist = { url = "https://files.pythonhosted.org/packages/22/6f/0eafed8349eea1fa462238b54a624c8b408cd1ba2795c8e64aa6c34f8ab7/fastapi-0.133.1.tar.gz", hash = "sha256:ed152a45912f102592976fde6cbce7dae1a8a1053da94202e51dd35d184fadd6", size = 378741, upload-time = "2026-02-25T18:18:17.398Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5c/05/5cbb59154b093548acd0f4c7c474a118eda06da25aa75c616b72d8fcd92a/fastapi-0.128.0-py3-none-any.whl", hash = "sha256:aebd93f9716ee3b4f4fcfe13ffb7cf308d99c9f3ab5622d8877441072561582d", size = 103094, upload-time = "2025-12-27T15:21:12.154Z" },
{ url = "https://files.pythonhosted.org/packages/d2/c9/a175a7779f3599dfa4adfc97a6ce0e157237b3d7941538604aadaf97bfb6/fastapi-0.133.1-py3-none-any.whl", hash = "sha256:658f34ba334605b1617a65adf2ea6461901bdb9af3a3080d63ff791ecf7dc2e2", size = 109029, upload-time = "2026-02-25T18:18:18.578Z" },
]
[[package]]
@@ -4612,7 +4613,7 @@ requires-dist = [
{ name = "einops", marker = "extra == 'model-server'", specifier = "==0.8.1" },
{ name = "exa-py", marker = "extra == 'backend'", specifier = "==1.15.4" },
{ name = "faker", marker = "extra == 'dev'", specifier = "==40.1.2" },
{ name = "fastapi", specifier = "==0.128.0" },
{ name = "fastapi", specifier = "==0.133.1" },
{ name = "fastapi-limiter", marker = "extra == 'backend'", specifier = "==0.1.6" },
{ name = "fastapi-users", marker = "extra == 'backend'", specifier = "==15.0.4" },
{ name = "fastapi-users-db-sqlalchemy", marker = "extra == 'backend'", specifier = "==7.0.0" },

View File

@@ -58,7 +58,7 @@ function ContentAction({
return (
<div className="flex flex-row items-stretch w-full">
<div className={cn("flex-1 min-w-0 self-center", padding)}>
<div className={cn("flex-1 min-w-0", padding)}>
<Content {...contentProps} />
</div>
{rightChildren && (

View File

@@ -2,8 +2,7 @@
import { useState } from "react";
import Link from "next/link";
import { Section } from "@/layouts/general-layouts";
import { Content } from "@opal/layouts";
import { Section, LineItemLayout } from "@/layouts/general-layouts";
import * as InputLayouts from "@/layouts/input-layouts";
import Card from "@/refresh-components/cards/Card";
import Button from "@/refresh-components/buttons/Button";
@@ -373,11 +372,9 @@ function SeatsCard({
padding={1}
height="auto"
>
<Content
<LineItemLayout
title="Update Seats"
description="Add or remove seats to reflect your team size."
sizePreset="main-content"
variant="section"
/>
<Button main secondary onClick={handleCancel} disabled={isSubmitting}>
Cancel

View File

@@ -12,7 +12,6 @@ import Tabs from "@/refresh-components/Tabs";
import { useFormikContext } from "formik";
import * as GeneralLayouts from "@/layouts/general-layouts";
import * as InputLayouts from "@/layouts/input-layouts";
import { Content } from "@opal/layouts";
import CheckboxField from "@/refresh-components/form/LabeledCheckboxField";
import InputTextAreaField from "@/refresh-components/form/InputTextAreaField";
import Text from "@/refresh-components/texts/Text";
@@ -47,11 +46,9 @@ const TabsField: FC<TabsFieldProps> = ({
return (
<GeneralLayouts.Section gap={0.5} alignItems="start">
{tabField.label && (
<Content
<InputLayouts.Title
title={resolvedLabel ?? ""}
description={resolvedDescription}
sizePreset="main-content"
variant="section"
/>
)}

View File

@@ -5,8 +5,7 @@ import { cn } from "@/lib/utils";
import { ThreeDotsLoader } from "@/components/Loading";
import { ErrorCallout } from "@/components/ErrorCallout";
import { toast } from "@/hooks/useToast";
import { Section } from "@/layouts/general-layouts";
import { ContentAction } from "@opal/layouts";
import { Section, LineItemLayout } from "@/layouts/general-layouts";
import * as SettingsLayouts from "@/layouts/settings-layouts";
import Text from "@/refresh-components/texts/Text";
import Card from "@/refresh-components/cards/Card";
@@ -90,11 +89,9 @@ function GuildDetailContent({
)}
<Card variant={disabled ? "disabled" : "primary"}>
<ContentAction
<LineItemLayout
title="Channel Configuration"
description="Run !sync-channels in Discord to update the channel list."
sizePreset="main-content"
variant="section"
rightChildren={
isRegistered && !channelsLoading && !channelsError ? (
<Section
@@ -342,11 +339,9 @@ export default function Page({ params }: Props) {
<SettingsLayouts.Body>
{/* Default Persona Selector */}
<Card variant={!guild?.enabled ? "disabled" : "primary"}>
<ContentAction
<LineItemLayout
title="Default Agent"
description="The agent used by the bot in all channels unless overridden."
sizePreset="main-content"
variant="section"
rightChildren={
<InputSelect
value={guild?.default_persona_id?.toString() ?? "default"}

View File

@@ -5,7 +5,7 @@ import useSWR from "swr";
import { SvgArrowExchange } from "@opal/icons";
import * as SettingsLayouts from "@/layouts/settings-layouts";
import Card from "@/refresh-components/cards/Card";
import { Content, ContentAction } from "@opal/layouts";
import { LineItemLayout } from "@/layouts/general-layouts";
import Text from "@/refresh-components/texts/Text";
import InputSelect from "@/refresh-components/inputs/InputSelect";
import Button from "@/refresh-components/buttons/Button";
@@ -72,10 +72,9 @@ function MigrationStatusSection() {
<Card>
<Text headingH3>Migration Status</Text>
<ContentAction
<LineItemLayout
title="Started"
sizePreset="main-ui"
variant="section"
variant="secondary"
rightChildren={
<Text mainUiBody>
{hasStarted ? formatTimestamp(data.created_at!) : "Not started"}
@@ -83,10 +82,9 @@ function MigrationStatusSection() {
}
/>
<ContentAction
<LineItemLayout
title="Chunks Migrated"
sizePreset="main-ui"
variant="section"
variant="secondary"
rightChildren={
<Text mainUiBody>
{progressPercentage !== null
@@ -98,10 +96,9 @@ function MigrationStatusSection() {
}
/>
<ContentAction
<LineItemLayout
title="Completed"
sizePreset="main-ui"
variant="section"
variant="secondary"
rightChildren={
<Text mainUiBody>
{hasCompleted
@@ -177,11 +174,10 @@ function RetrievalSourceSection() {
return (
<Card>
<Content
<LineItemLayout
title="Retrieval Source"
description="Controls which document index is used for retrieval."
sizePreset="main-ui"
variant="section"
variant="secondary"
/>
<InputSelect

View File

@@ -6,8 +6,7 @@ import { Button } from "@opal/components";
import Tag from "@/refresh-components/buttons/Tag";
import Text from "@/refresh-components/texts/Text";
import SimpleTooltip from "@/refresh-components/SimpleTooltip";
import { Section } from "@/layouts/general-layouts";
import { ContentAction } from "@opal/layouts";
import { Section, LineItemLayout } from "@/layouts/general-layouts";
import { formatDurationSeconds } from "@/lib/time";
import { noProp } from "@/lib/utils";
import MemoriesModal from "@/refresh-components/modals/MemoriesModal";
@@ -62,12 +61,10 @@ function MemoryTagWithTooltip({
{memoryText}
</Text>
</div>
<ContentAction
<LineItemLayout
variant="mini"
icon={SvgAddLines}
title={operationLabel}
sizePreset="secondary"
variant="body"
prominence="muted"
rightChildren={
<Button
prominence="tertiary"

View File

@@ -9,8 +9,7 @@ import type { SharingScope } from "@/app/craft/types/streamingTypes";
import { cn } from "@/lib/utils";
import Popover from "@/refresh-components/Popover";
import Truncated from "@/refresh-components/texts/Truncated";
import { Section } from "@/layouts/general-layouts";
import { ContentAction } from "@opal/layouts";
import { Section, LineItemLayout } from "@/layouts/general-layouts";
interface ShareButtonProps {
sessionId: string;
@@ -134,12 +133,11 @@ export default function ShareButton({
: "hover:bg-background-tint-02"
)}
>
<ContentAction
<LineItemLayout
title={opt.label}
description={opt.description}
sizePreset="main-ui"
variant="section"
paddingVariant="sm"
variant="tertiary"
reducedPadding
/>
</div>
))}

View File

@@ -3,7 +3,7 @@
import { useState } from "react";
import Card from "@/refresh-components/cards/Card";
import Text from "@/refresh-components/texts/Text";
import { Content } from "@opal/layouts";
import { LineItemLayout } from "@/layouts/general-layouts";
import Separator from "@/refresh-components/Separator";
import { ValidSources } from "@/lib/types";
import { getSourceMetadata } from "@/lib/sources";
@@ -99,15 +99,14 @@ export default function ComingSoonConnectors() {
const card = (
<div key={type} className="opacity-60">
<Card variant="secondary">
<Content
<LineItemLayout
icon={
type === ValidSources.Imap
? OutlookIcon
: sourceMetadata.icon
}
title={displayName}
sizePreset="main-ui"
variant="body"
center
/>
</Card>
</div>
@@ -119,12 +118,7 @@ export default function ComingSoonConnectors() {
card,
<div key="onedrive" className="opacity-60">
<Card variant="secondary">
<Content
icon={OneDriveIcon}
title="OneDrive"
sizePreset="main-ui"
variant="body"
/>
<LineItemLayout icon={OneDriveIcon} title="OneDrive" center />
</Card>
</div>,
];
@@ -136,12 +130,7 @@ export default function ComingSoonConnectors() {
card,
<div key="box" className="opacity-60">
<Card variant="secondary">
<Content
icon={BoxIcon}
title="Box"
sizePreset="main-ui"
variant="body"
/>
<LineItemLayout icon={BoxIcon} title="Box" center />
</Card>
</div>,
];
@@ -152,23 +141,13 @@ export default function ComingSoonConnectors() {
{/* Enterprise/ERP */}
<div className="opacity-60">
<Card variant="secondary">
<Content
icon={ServiceNowIcon}
title="ServiceNow"
sizePreset="main-ui"
variant="body"
/>
<LineItemLayout icon={ServiceNowIcon} title="ServiceNow" center />
</Card>
</div>
{/* Project Management */}
<div className="opacity-60">
<Card variant="secondary">
<Content
icon={TrelloIcon}
title="Trello"
sizePreset="main-ui"
variant="body"
/>
<LineItemLayout icon={TrelloIcon} title="Trello" center />
</Card>
</div>
</div>

View File

@@ -4,7 +4,8 @@ import { useState } from "react";
import Card from "@/refresh-components/cards/Card";
import Popover from "@/refresh-components/Popover";
import LineItem from "@/refresh-components/buttons/LineItem";
import { ContentAction } from "@opal/layouts";
import Text from "@/refresh-components/texts/Text";
import { Section, LineItemLayout } from "@/layouts/general-layouts";
import { ValidSources } from "@/lib/types";
import { getSourceMetadata } from "@/lib/sources";
import { SvgMoreHorizontal, SvgPlug, SvgSettings, SvgTrash } from "@opal/icons";
@@ -40,6 +41,15 @@ interface ConnectorCardProps {
onDelete: () => void;
}
const STATUS_COLORS: Record<ConnectorStatus, string> = {
connected: "bg-status-success-05",
connected_with_errors: "bg-status-warning-05",
indexing: "bg-status-warning-05 animate-pulse",
error: "bg-status-error-05",
deleting: "bg-status-error-05 animate-pulse",
not_connected: "bg-background-neutral-03",
};
function getStatusText(status: ConnectorStatus, docsIndexed: number): string {
switch (status) {
case "connected":
@@ -62,6 +72,29 @@ function getStatusText(status: ConnectorStatus, docsIndexed: number): string {
}
}
function StatusDescription({
status,
docsIndexed,
}: {
status: ConnectorStatus;
docsIndexed: number;
}) {
return (
<Section
flexDirection="row"
alignItems="center"
gap={0.375}
width="fit"
height="fit"
>
<div className={cn(STATUS_COLORS[status], "w-2 h-2 rounded-full")} />
<Text secondaryBody text03>
{getStatusText(status, docsIndexed)}
</Text>
</Section>
);
}
export default function ConnectorCard({
connectorType,
config,
@@ -147,8 +180,17 @@ export default function ConnectorCard({
const cardVariant =
isAlwaysConnected || isConnected ? "primary" : "secondary";
const descriptionText =
customDescription ?? getStatusText(status, config?.docs_indexed || 0);
// Use custom description if provided, otherwise show status
const descriptionContent = customDescription ? (
<Text secondaryBody text03>
{customDescription}
</Text>
) : (
<StatusDescription
status={status}
docsIndexed={config?.docs_indexed || 0}
/>
);
return (
<div
@@ -156,13 +198,12 @@ export default function ConnectorCard({
onClick={handleCardClick}
>
<Card variant={cardVariant}>
<ContentAction
<LineItemLayout
icon={sourceMetadata.icon}
title={sourceMetadata.displayName}
description={descriptionText}
sizePreset="main-content"
variant="section"
description={descriptionContent}
rightChildren={rightContent}
center
/>
</Card>
</div>

View File

@@ -1,6 +1,6 @@
import { ConnectorStatus } from "@/lib/types";
import { ConnectorTitle } from "@/components/admin/connectors/ConnectorTitle";
import { Content } from "@opal/layouts";
import * as InputLayouts from "@/layouts/input-layouts";
import Text from "@/refresh-components/texts/Text";
import { SvgLock } from "@opal/icons";
interface NonSelectableConnectorsProps {
@@ -20,12 +20,7 @@ export const NonSelectableConnectors = ({
return (
<div className="mt-6 mb-4">
<Content
title={title}
description={description}
sizePreset="main-content"
variant="section"
/>
<InputLayouts.Title title={title} description={description} />
<div className="p-3 border border-dashed border-border-02 rounded-12 bg-background-neutral-01">
<div className="mb-2 flex items-center gap-1.5">

View File

@@ -9,7 +9,7 @@ import { getSourceMetadata } from "@/lib/sources";
import useFederatedOAuthStatus from "@/hooks/useFederatedOAuthStatus";
import { SvgLink } from "@opal/icons";
import { Card } from "@/refresh-components/cards";
import { ContentAction } from "@opal/layouts";
import { LineItemLayout } from "@/layouts/general-layouts";
export interface FederatedConnectorOAuthStatus {
federated_connector_id: number;
@@ -136,12 +136,10 @@ export default function FederatedOAuthModal() {
return (
<Card key={connector.federated_connector_id}>
<ContentAction
<LineItemLayout
icon={sourceMetadata.icon}
title={sourceMetadata.displayName}
description={sourceMetadata.category}
sizePreset="main-content"
variant="section"
rightChildren={
<Button
secondary
@@ -151,6 +149,7 @@ export default function FederatedOAuthModal() {
Connect
</Button>
}
center
/>
</Card>
);

View File

@@ -56,7 +56,7 @@
import React, { HtmlHTMLAttributes } from "react";
import type { IconProps } from "@opal/types";
import { WithoutStyles } from "@/types";
import { ContentAction } from "@opal/layouts";
import { LineItemLayout } from "@/layouts/general-layouts";
import * as ExpandableCard from "@/layouts/expandable-card-layouts";
import { Card } from "@/refresh-components/cards";
import Label from "@/refresh-components/form/Label";
@@ -119,14 +119,11 @@ function ActionsHeader({
<div className="flex flex-col gap-2 pt-4 pb-2">
<div className="px-4">
<Label name={name}>
<ContentAction
<LineItemLayout
icon={Icon}
title={title}
description={description}
sizePreset="section"
variant="section"
rightChildren={rightChildren}
paddingVariant="fit"
/>
</Label>
</div>
@@ -240,14 +237,12 @@ function ActionsTool({
return (
<Card padding={0.75} variant={disabled ? "disabled" : undefined}>
<Label name={name} disabled={disabled}>
<ContentAction
<LineItemLayout
icon={icon}
title={title}
description={description}
sizePreset="main-ui"
variant="section"
rightChildren={rightChildren}
paddingVariant="fit"
variant="secondary"
/>
</Label>
</Card>

View File

@@ -48,6 +48,7 @@ import { PopoverSearchInput } from "@/sections/sidebar/ChatButton";
import SimplePopover from "@/refresh-components/SimplePopover";
import { Interactive } from "@opal/core";
import { Button, OpenButton } from "@opal/components";
import { LineItemLayout } from "@/layouts/general-layouts";
import { useAppSidebarContext } from "@/providers/AppSidebarProvider";
import useScreenSize from "@/hooks/useScreenSize";
import {

View File

@@ -2,7 +2,6 @@ import { cn } from "@/lib/utils";
import Text from "@/refresh-components/texts/Text";
import Truncated from "@/refresh-components/texts/Truncated";
import { WithoutStyles } from "@/types";
import { Content } from "@opal/layouts";
import { IconProps } from "@opal/types";
import React from "react";
@@ -161,6 +160,152 @@ function Section({
);
}
/**
* LineItemLayout - A layout for icon + title + description rows
*
* Structure:
* Flexbox Row [
* Grid [
* [Icon] [Title ]
* [ ] [Description]
* ],
* rightChildren
* ]
*
* - Icon column auto-sizes to icon width
* - Icon vertically centers with title
* - Description aligns with title's left edge (both in grid column 2)
* - rightChildren is outside the grid, in the outer flexbox
*
* Variants:
* - `primary`: Standard size (20px icon) with emphasized text. The default for prominent list items.
* - `secondary`: Compact size (16px icon) with standard text. Use for denser lists or nested items.
* - `tertiary`: Compact size (16px icon) with standard text. Use for less prominent items in tight layouts.
* - `tertiary-muted`: Compact size (16px icon) with muted text styling. Use for de-emphasized or secondary information.
* - `mini`: Smallest size (12px icon) with muted secondary text. Use for metadata labels (e.g., owner, action count).
*
* @param icon - Optional icon component to display on the left
* @param title - The main title text (required)
* @param description - Optional description content below the title (string or ReactNode)
* @param rightChildren - Optional content to render on the right side
* @param variant - Visual variant. Default: "primary"
* @param strikethrough - If true, applies line-through style to title. Default: false
* @param loading - If true, renders skeleton placeholders instead of content. Default: false
* @param center - If true, vertically centers items; otherwise aligns to start. Default: false
*/
type LineItemLayoutVariant =
| "primary"
| "secondary"
| "tertiary"
| "tertiary-muted"
| "mini";
export interface LineItemLayoutProps {
icon?: React.FunctionComponent<IconProps>;
title: string;
description?: React.ReactNode;
middleText?: string;
rightChildren?: React.ReactNode;
variant?: LineItemLayoutVariant;
width?: Length;
strikethrough?: boolean;
loading?: boolean;
center?: boolean;
reducedPadding?: boolean;
}
function LineItemLayout({
icon: Icon,
title,
description,
middleText,
rightChildren,
variant = "primary",
width,
strikethrough,
loading,
center,
reducedPadding,
}: LineItemLayoutProps) {
// Derive styling from variant
const isMini = variant === "mini";
const isCompact =
variant === "secondary" ||
variant === "tertiary" ||
variant === "tertiary-muted";
const isMuted = variant === "tertiary-muted" || isMini;
// Determine icon size: mini=12px, compact=16px, primary=20px
const iconSize = isMini ? 12 : isCompact ? 16 : 20;
// Determine gap: mini=0.25rem, others=1.5rem
const gap = isMini ? 0.25 : 1.5;
return (
<Section
flexDirection="row"
justifyContent="between"
alignItems={center || isMini ? "center" : "start"}
gap={gap}
width={width}
>
<div
className="line-item-layout"
data-variant={variant}
data-has-icon={Icon ? "true" : undefined}
data-loading={loading ? "true" : undefined}
data-strikethrough={strikethrough ? "true" : undefined}
data-reduced-padding={reducedPadding ? "true" : undefined}
>
{/* Row 1: Icon, Title */}
{Icon && <Icon size={iconSize} className="line-item-layout-icon" />}
{loading ? (
<div className="line-item-layout-skeleton-title" />
) : (
<Truncated
mainContentEmphasis={!isCompact && !isMini}
secondaryBody={isMini}
mainUiAction={variant === "secondary"}
text03={isMuted}
className="line-item-layout-title"
>
{title}
</Truncated>
)}
{/* Row 2: Description (column 2, or column 1 if no icon) */}
{loading && description ? (
<div className="line-item-layout-skeleton-description" />
) : description ? (
<div className="line-item-layout-description">
{typeof description === "string" ? (
<Text secondaryBody text03>
{description}
</Text>
) : (
description
)}
</div>
) : undefined}
</div>
{!loading && middleText && (
<div className="flex-1">
<Truncated text03 secondaryBody>
{middleText}
</Truncated>
</div>
)}
{loading && rightChildren ? (
<div className="line-item-layout-skeleton-right" />
) : rightChildren ? (
<div className="flex-shrink-0">{rightChildren}</div>
) : undefined}
</Section>
);
}
export interface AttachmentItemLayoutProps {
title: string;
description: string;
@@ -184,29 +329,18 @@ function AttachmentItemLayout({
</div>
</Section>
</div>
<Section
flexDirection="row"
justifyContent="between"
alignItems="center"
gap={1.5}
>
<Content
title={title}
description={description}
sizePreset="main-ui"
variant="section"
/>
{middleText && (
<div className="flex-1">
<Truncated text03 secondaryBody>
{middleText}
</Truncated>
</div>
)}
{rightChildren && (
<div className="flex-shrink-0 px-1">{rightChildren}</div>
)}
</Section>
<LineItemLayout
title={title}
description={description}
middleText={middleText}
rightChildren={
rightChildren ? (
<div className="px-1">{rightChildren}</div>
) : undefined
}
center
variant="secondary"
/>
</Section>
);
}
@@ -279,4 +413,4 @@ function CardItemLayout({
</div>
);
}
export { Section, CardItemLayout, AttachmentItemLayout };
export { Section, LineItemLayout, CardItemLayout, AttachmentItemLayout };

View File

@@ -4,18 +4,13 @@ import Text from "@/refresh-components/texts/Text";
import { SvgXOctagon, SvgAlertCircle } from "@opal/icons";
import { useField, useFormikContext } from "formik";
import { Section } from "@/layouts/general-layouts";
import { Content } from "@opal/layouts";
import Label from "@/refresh-components/form/Label";
interface OrientationLayoutProps {
interface OrientationLayoutProps extends TitleLayoutProps {
name?: string;
disabled?: boolean;
nonInteractive?: boolean;
children?: React.ReactNode;
title: string;
description?: string;
optional?: boolean;
sizePreset?: "main-content" | "main-ui";
}
/**
@@ -49,20 +44,11 @@ function VerticalInputLayout({
nonInteractive,
children,
subDescription,
title,
description,
optional,
sizePreset = "main-content",
...titleLayoutProps
}: VerticalLayoutProps) {
const content = (
<Section gap={0.25} alignItems="start">
<Content
title={title}
description={description}
optional={optional}
sizePreset={sizePreset}
variant="section"
/>
<TitleLayout {...titleLayoutProps} />
{children}
{name && <ErrorLayout name={name} />}
{subDescription && (
@@ -124,10 +110,7 @@ function HorizontalInputLayout({
nonInteractive,
children,
center,
title,
description,
optional,
sizePreset = "main-content",
...titleLayoutProps
}: HorizontalLayoutProps) {
const content = (
<Section gap={0.25} alignItems="start">
@@ -137,13 +120,7 @@ function HorizontalInputLayout({
alignItems={center ? "center" : "start"}
>
<div className="flex flex-col flex-1 self-stretch">
<Content
title={title}
description={description}
optional={optional}
sizePreset={sizePreset}
variant="section"
/>
<TitleLayout {...titleLayoutProps} />
</div>
<div className="flex flex-col items-end">{children}</div>
</Section>
@@ -159,6 +136,80 @@ function HorizontalInputLayout({
);
}
/**
* TitleLayout - A reusable title/description component for form fields
*
* Renders a title with an optional description and "Optional" indicator.
* This is a pure presentational component — it does not render a `<label>`
* element. Label semantics are handled by the parent orientation layout
* (Vertical/Horizontal) or by the caller.
*
* Exported as `Title` for convenient usage.
*
* @param title - The main label text
* @param description - Additional helper text shown below the title
* @param optional - Whether to show "(Optional)" indicator
* @param center - If true, centers the title and description text. Default: false
*
* @example
* ```tsx
* import { Title } from "@/layouts/input-layouts";
*
* <Title
* name="username"
* title="Username"
* description="Choose a unique username"
* optional
* />
* ```
*/
type TitleLayoutVariants = "primary" | "secondary";
export interface TitleLayoutProps {
title: string;
description?: string;
optional?: boolean;
center?: boolean;
variant?: TitleLayoutVariants;
}
function TitleLayout({
title,
description,
optional,
center,
variant = "primary",
}: TitleLayoutProps) {
return (
<Section gap={0} height="fit">
<Section
flexDirection="row"
justifyContent={center ? "center" : "start"}
gap={0.25}
>
<Text
mainContentEmphasis={variant === "primary"}
mainUiAction={variant === "secondary"}
text04
>
{title}
</Text>
{optional && (
<Text text03 mainContentMuted>
(Optional)
</Text>
)}
</Section>
{description && (
<Section alignItems={center ? "center" : "start"}>
<Text secondaryBody text03>
{description}
</Text>
</Section>
)}
</Section>
);
}
/**
* ErrorLayout - Displays Formik field validation errors
*
@@ -229,6 +280,7 @@ function ErrorTextLayout({ children, type = "error" }: ErrorTextLayoutProps) {
export {
VerticalInputLayout as Vertical,
HorizontalInputLayout as Horizontal,
TitleLayout as Title,
ErrorLayout as Error,
ErrorTextLayout,
};

View File

@@ -30,8 +30,7 @@
import { SvgEmpty } from "@opal/icons";
import Card from "@/refresh-components/cards/Card";
import Text from "@/refresh-components/texts/Text";
import { Content } from "@opal/layouts";
import { LineItemLayout } from "@/layouts/general-layouts";
import { IconProps } from "@opal/types";
export interface EmptyMessageProps {
@@ -47,18 +46,12 @@ export default function EmptyMessage({
}: EmptyMessageProps) {
return (
<Card variant="tertiary">
<Content
<LineItemLayout
icon={Icon}
title={title}
sizePreset="main-ui"
variant="body"
prominence="muted"
description={description}
variant="tertiary-muted"
/>
{description && (
<Text secondaryBody text03>
{description}
</Text>
)}
</Card>
);
}

View File

@@ -48,7 +48,7 @@ import {
CollapsibleTrigger,
} from "@/refresh-components/Collapsible";
import { Button } from "@opal/components";
import { Content } from "@opal/layouts";
import Text from "@/refresh-components/texts/Text";
import { SvgFold, SvgExpand } from "@opal/icons";
import { WithoutStyles } from "@/types";
@@ -198,13 +198,15 @@ const Header = React.forwardRef<HTMLDivElement, SimpleCollapsibleHeaderProps>(
className="flex flex-row items-center justify-between gap-4 cursor-pointer select-none"
{...props}
>
<div ref={boundingRef} className="w-full">
<Content
title={title}
description={description}
sizePreset="main-content"
variant="section"
/>
<div ref={boundingRef} className="flex flex-col w-full">
<Text mainContentEmphasis text04>
{title}
</Text>
{description && (
<Text secondaryBody text03>
{description}
</Text>
)}
</div>
<Button
icon={open ? SvgFold : SvgExpand}
@@ -235,7 +237,7 @@ Header.displayName = "SimpleCollapsible.Header";
* </SimpleCollapsible>
* ```
*/
const ContentPanel = React.forwardRef<
const Content = React.forwardRef<
HTMLDivElement,
WithoutStyles<React.HTMLAttributes<HTMLDivElement>>
>(({ children, ...props }, ref) => {
@@ -247,9 +249,9 @@ const ContentPanel = React.forwardRef<
</CollapsibleContent>
);
});
ContentPanel.displayName = "SimpleCollapsible.Content";
Content.displayName = "SimpleCollapsible.Content";
export default Object.assign(Root, {
Header,
Content: ContentPanel,
Content,
});

View File

@@ -136,8 +136,8 @@ const InputTypeIn = React.forwardRef<HTMLInputElement, InputTypeInProps>(
}}
>
{leftSearchIcon && (
<div className="pr-2 pl-1">
<div className="pl-[2px]">
<div className="pr-2">
<div className="pl-1">
<SvgSearch className="w-[1rem] h-[1rem] stroke-text-02" />
</div>
</div>

View File

@@ -10,8 +10,7 @@ import Button from "@/refresh-components/buttons/Button";
import { Button as OpalButton } from "@opal/components";
import { SvgProgressCircle, SvgX } from "@opal/icons";
import { Card } from "@/refresh-components/cards";
import { Section } from "@/layouts/general-layouts";
import { ContentAction } from "@opal/layouts";
import { LineItemLayout, Section } from "@/layouts/general-layouts";
interface OnboardingHeaderProps {
state: OnboardingState;
@@ -41,15 +40,11 @@ const OnboardingHeader = React.memo(
return (
<Card padding={0.5} data-label="onboarding-header">
<ContentAction
<LineItemLayout
icon={(props) => (
<SvgProgressCircle value={iconPercentage} {...props} />
)}
title={STEP_CONFIG[onboardingState.currentStep].title}
sizePreset="main-ui"
variant="body"
prominence="muted"
paddingVariant="sm"
rightChildren={
stepButtonText ? (
<Section flexDirection="row">
@@ -75,6 +70,9 @@ const OnboardingHeader = React.memo(
/>
)
}
variant="tertiary-muted"
reducedPadding
center
/>
</Card>
);

View File

@@ -5,8 +5,7 @@ import Button from "@/refresh-components/buttons/Button";
import { FINAL_SETUP_CONFIG } from "@/refresh-components/onboarding/constants";
import { FinalStepItemProps } from "@/refresh-components/onboarding/types";
import { SvgExternalLink } from "@opal/icons";
import { Section } from "@/layouts/general-layouts";
import { ContentAction } from "@opal/layouts";
import { LineItemLayout, Section } from "@/layouts/general-layouts";
import { Card } from "@/refresh-components/cards";
const FinalStepItem = React.memo(
@@ -24,13 +23,10 @@ const FinalStepItem = React.memo(
return (
<Card padding={0.25} variant="secondary">
<ContentAction
<LineItemLayout
icon={Icon}
title={title}
description={description}
sizePreset="main-ui"
variant="section"
paddingVariant="sm"
rightChildren={
<Link href={buttonHref as Route} {...linkProps}>
<Button tertiary rightIcon={SvgExternalLink}>
@@ -38,6 +34,8 @@ const FinalStepItem = React.memo(
</Button>
</Link>
}
reducedPadding
variant="tertiary"
/>
</Card>
);

View File

@@ -89,7 +89,6 @@ import AgentKnowledgePane from "@/sections/knowledge/AgentKnowledgePane";
import { ValidSources } from "@/lib/types";
import { useSettingsContext } from "@/providers/SettingsProvider";
import { useUser } from "@/providers/UserProvider";
import SimpleLoader from "@/refresh-components/loaders/SimpleLoader";
interface AgentIconEditorProps {
existingAgent?: FullPersona | null;
@@ -314,11 +313,7 @@ function MCPServerCard({
description={server.description}
icon={getActionIcon(server.server_url, server.name)}
rightChildren={
<GeneralLayouts.Section
flexDirection="row"
gap={0.5}
alignItems="start"
>
<GeneralLayouts.Section flexDirection="row" gap={0.5}>
<EnabledCount
enabledCount={enabledCount}
totalCount={enabledTools.length}
@@ -357,9 +352,18 @@ function MCPServerCard({
</ActionsLayouts.Header>
{isLoading ? (
<ActionsLayouts.Content>
<GeneralLayouts.Section padding={1}>
<SimpleLoader />
</GeneralLayouts.Section>
{Array.from({ length: 3 }).map((_, index) => (
<Card key={index} padding={0.75}>
<GeneralLayouts.LineItemLayout
// We provide dummy values here.
// The `loading` prop will always render a pulsing box instead, so the dummy-values will actually NOT be rendered at all.
title="..."
description="..."
rightChildren={<></>}
loading
/>
</Card>
))}
</ActionsLayouts.Content>
) : (
enabledTools.length > 0 &&
@@ -1164,6 +1168,7 @@ export default function AgentEditorPage({
<InputLayouts.Vertical
name="agent_avatar"
title="Agent Avatar"
center
>
<AgentIconEditor existingAgent={existingAgent} />
</InputLayouts.Vertical>

View File

@@ -3,8 +3,11 @@
import { useRef, useCallback, useEffect, useState } from "react";
import { usePathname, useRouter } from "next/navigation";
import * as InputLayouts from "@/layouts/input-layouts";
import { Section, AttachmentItemLayout } from "@/layouts/general-layouts";
import { Content, ContentAction } from "@opal/layouts";
import {
LineItemLayout,
Section,
AttachmentItemLayout,
} from "@/layouts/general-layouts";
import { Formik, Form } from "formik";
import * as Yup from "yup";
import {
@@ -260,12 +263,7 @@ function GeneralSettings() {
<Section gap={2}>
<Section gap={0.75}>
<Content
title="Profile"
sizePreset="main-content"
variant="section"
widthVariant="full"
/>
<InputLayouts.Title title="Profile" />
<Card>
<InputLayouts.Horizontal
title="Full Name"
@@ -321,12 +319,7 @@ function GeneralSettings() {
</Section>
<Section gap={0.75}>
<Content
title="Appearance"
sizePreset="main-content"
variant="section"
widthVariant="full"
/>
<InputLayouts.Title title="Appearance" />
<Card>
<InputLayouts.Horizontal
title="Color Mode"
@@ -431,12 +424,7 @@ function GeneralSettings() {
<Separator noPadding />
<Section gap={0.75}>
<Content
title="Danger Zone"
sizePreset="main-content"
variant="section"
widthVariant="full"
/>
<InputLayouts.Title title="Danger Zone" />
<Card>
<InputLayouts.Horizontal
title="Delete All Chats"
@@ -781,12 +769,7 @@ function ChatPreferencesSettings() {
return (
<Section gap={2}>
<Section gap={0.75}>
<Content
title="Chats"
sizePreset="main-content"
variant="section"
widthVariant="full"
/>
<InputLayouts.Title title="Chats" />
<Card>
<InputLayouts.Horizontal
title="Default Model"
@@ -866,12 +849,7 @@ function ChatPreferencesSettings() {
limit={500}
/>
</InputLayouts.Vertical>
<Content
title="Memory"
sizePreset="main-content"
variant="section"
widthVariant="full"
/>
<InputLayouts.Title title="Memory" />
<Card>
<InputLayouts.Horizontal
title="Reference Stored Memories"
@@ -912,12 +890,7 @@ function ChatPreferencesSettings() {
</Section>
<Section gap={0.75}>
<Content
title="Prompt Shortcuts"
sizePreset="main-content"
variant="section"
widthVariant="full"
/>
<InputLayouts.Title title="Prompt Shortcuts" />
<Card>
<InputLayouts.Horizontal
title="Use Prompt Shortcuts"
@@ -1242,12 +1215,7 @@ function AccountsAccessSettings() {
<Section gap={2}>
<Section gap={0.75}>
<Content
title="Accounts"
sizePreset="main-content"
variant="section"
widthVariant="full"
/>
<InputLayouts.Title title="Accounts" />
<Card>
<InputLayouts.Horizontal
title="Email"
@@ -1279,12 +1247,7 @@ function AccountsAccessSettings() {
{showTokensSection && (
<Section gap={0.75}>
<Content
title="Access Tokens"
sizePreset="main-content"
variant="section"
widthVariant="full"
/>
<InputLayouts.Title title="Access Tokens" />
{canCreateTokens ? (
<Card padding={0.25}>
<Section gap={0}>
@@ -1400,12 +1363,10 @@ function IndexedConnectorCard({ source, isActive }: IndexedConnectorCardProps) {
return (
<Card>
<Content
<LineItemLayout
icon={sourceMetadata.icon}
title={sourceMetadata.displayName}
description={isActive ? "Connected" : "Paused"}
sizePreset="main-content"
variant="section"
/>
</Card>
);
@@ -1479,15 +1440,12 @@ function FederatedConnectorCard({
)}
<Card padding={0.5}>
<ContentAction
<LineItemLayout
icon={sourceMetadata.icon}
title={sourceMetadata.displayName}
description={
connector.has_oauth_token ? "Connected" : "Not connected"
}
sizePreset="main-content"
variant="section"
paddingVariant="sm"
rightChildren={
connector.has_oauth_token ? (
<OpalButton
@@ -1508,6 +1466,7 @@ function FederatedConnectorCard({
</Button>
) : undefined
}
reducedPadding
/>
</Card>
</>
@@ -1556,12 +1515,7 @@ function ConnectorsSettings() {
return (
<Section gap={2}>
<Section gap={0.75} justifyContent="start">
<Content
title="Connectors"
sizePreset="main-content"
variant="section"
widthVariant="full"
/>
<InputLayouts.Title title="Connectors" />
{hasConnectors ? (
<>
{/* Indexed Connectors */}

View File

@@ -7,7 +7,7 @@ import useSWR from "swr";
import { errorHandlingFetcher } from "@/lib/fetcher";
import * as SettingsLayouts from "@/layouts/settings-layouts";
import * as InputLayouts from "@/layouts/input-layouts";
import { Section } from "@/layouts/general-layouts";
import { Section, LineItemLayout } from "@/layouts/general-layouts";
import Card from "@/refresh-components/cards/Card";
import Separator from "@/refresh-components/Separator";
import SimpleCollapsible from "@/refresh-components/SimpleCollapsible";
@@ -400,11 +400,7 @@ function ChatPreferencesForm() {
{/* Features */}
<Section gap={0.75}>
<Content
title="Features"
sizePreset="main-content"
variant="section"
/>
<InputLayouts.Title title="Features" />
<Card>
<SimpleTooltip
tooltip={
@@ -464,11 +460,7 @@ function ChatPreferencesForm() {
<Section gap={1.5}>
{/* Connectors */}
<Section gap={0.75}>
<Content
title="Connectors"
sizePreset="main-content"
variant="section"
/>
<InputLayouts.Title title="Connectors" />
<Section
flexDirection="row"

View File

@@ -31,8 +31,7 @@ import { useCreateModal } from "@/refresh-components/contexts/ModalContext";
import ShareAgentModal from "@/sections/modals/ShareAgentModal";
import AgentViewerModal from "@/sections/modals/AgentViewerModal";
import { toast } from "@/hooks/useToast";
import { CardItemLayout } from "@/layouts/general-layouts";
import { Content } from "@opal/layouts";
import { LineItemLayout, CardItemLayout } from "@/layouts/general-layouts";
import { Interactive } from "@opal/core";
import { Card } from "@/refresh-components/cards";
@@ -194,14 +193,12 @@ export default function AgentCard({ agent }: AgentCardProps) {
<div className="bg-background-tint-01 p-1 flex flex-row items-end justify-between w-full">
{/* Left side - creator and actions */}
<div className="flex flex-col gap-1 py-1 px-2">
<Content
<LineItemLayout
icon={SvgUser}
title={agent.owner?.email || "Onyx"}
sizePreset="secondary"
variant="body"
prominence="muted"
variant="mini"
/>
<Content
<LineItemLayout
icon={SvgActions}
title={
agent.tools.length > 0
@@ -210,9 +207,7 @@ export default function AgentCard({ agent }: AgentCardProps) {
}`
: "No Actions"
}
sizePreset="secondary"
variant="body"
prominence="muted"
variant="mini"
/>
</div>

View File

@@ -9,7 +9,6 @@ import React, {
useEffect,
} from "react";
import * as GeneralLayouts from "@/layouts/general-layouts";
import { Content } from "@opal/layouts";
import * as TableLayouts from "@/layouts/table-layouts";
import * as InputLayouts from "@/layouts/input-layouts";
import { Card } from "@/refresh-components/cards";
@@ -319,11 +318,10 @@ function DocumentSetsTableContent({
header: "Name",
sortable: true,
render: (ds) => (
<Content
<GeneralLayouts.LineItemLayout
icon={SvgFolder}
title={ds.name}
sizePreset="main-ui"
variant="section"
variant="secondary"
/>
),
},
@@ -445,11 +443,10 @@ function RecentFilesTableContent({
header: "Name",
sortable: true,
render: (file) => (
<Content
<GeneralLayouts.LineItemLayout
icon={SvgFiles}
title={file.name}
sizePreset="main-ui"
variant="section"
variant="secondary"
/>
),
},
@@ -1138,11 +1135,9 @@ export default function AgentKnowledgePane({
return (
<GeneralLayouts.Section gap={0.5} alignItems="stretch" height="auto">
<Content
<InputLayouts.Title
title="Knowledge"
description="Add specific connectors and documents for this agent to use to inform its responses."
sizePreset="main-content"
variant="section"
/>
<Card>

View File

@@ -6,8 +6,7 @@ import type { Route } from "next";
import { FullPersona } from "@/app/admin/assistants/interfaces";
import { useModal } from "@/refresh-components/contexts/ModalContext";
import Modal from "@/refresh-components/Modal";
import { Section } from "@/layouts/general-layouts";
import { Content, ContentAction } from "@opal/layouts";
import { Section, LineItemLayout } from "@/layouts/general-layouts";
import Text from "@/refresh-components/texts/Text";
import AgentAvatar from "@/refresh-components/avatars/AgentAvatar";
import Separator from "@/refresh-components/Separator";
@@ -27,7 +26,7 @@ import useMcpServersForAgentEditor from "@/hooks/useMcpServersForAgentEditor";
import { getActionIcon } from "@/lib/tools/mcpUtils";
import { MCPServer, ToolSnapshot } from "@/lib/tools/interfaces";
import EmptyMessage from "@/refresh-components/EmptyMessage";
import { Horizontal } from "@/layouts/input-layouts";
import { Horizontal, Title } from "@/layouts/input-layouts";
import Switch from "@/refresh-components/inputs/Switch";
import Button from "@/refresh-components/buttons/Button";
import { SEARCH_PARAM_NAMES } from "@/app/app/services/searchParams";
@@ -37,7 +36,10 @@ import { formatMmDdYyyy } from "@/lib/dateUtils";
import { useProjectsContext } from "@/providers/ProjectsContext";
import { FileCard } from "@/sections/cards/FileCard";
import DocumentSetCard from "@/sections/cards/DocumentSetCard";
import { getDisplayName } from "@/lib/llm/utils";
import {
getLLMProviderOverrideForPersona,
getDisplayName,
} from "@/lib/llm/utils";
import { useLLMProviders } from "@/lib/hooks/useLLMProviders";
import { Interactive } from "@opal/core";
@@ -58,12 +60,11 @@ function ViewerMCPServerCard({ server, tools }: ViewerMCPServerCardProps) {
<ExpandableCard.Root isFolded={folded} onFoldedChange={setFolded}>
<ExpandableCard.Header>
<div className="p-2">
<ContentAction
<LineItemLayout
icon={serverIcon}
title={server.name}
description={server.description}
sizePreset="main-ui"
variant="section"
variant="secondary"
rightChildren={
<Button
internal
@@ -73,6 +74,7 @@ function ViewerMCPServerCard({ server, tools }: ViewerMCPServerCardProps) {
{folded ? "Expand" : "Fold"}
</Button>
}
center
/>
</div>
</ExpandableCard.Header>
@@ -80,11 +82,10 @@ function ViewerMCPServerCard({ server, tools }: ViewerMCPServerCardProps) {
<ActionsLayouts.Content>
{tools.map((tool) => (
<Section key={tool.id} padding={0.25}>
<Content
<LineItemLayout
title={tool.display_name}
description={tool.description}
sizePreset="main-ui"
variant="section"
variant="secondary"
/>
</Section>
))}
@@ -103,12 +104,12 @@ function ViewerOpenApiToolCard({ tool }: { tool: ToolSnapshot }) {
<ExpandableCard.Root>
<ExpandableCard.Header>
<div className="p-2">
<Content
<LineItemLayout
icon={SvgActions}
title={tool.display_name}
description={tool.description}
sizePreset="main-ui"
variant="section"
variant="secondary"
center
/>
</div>
</ExpandableCard.Header>
@@ -257,27 +258,25 @@ export default function AgentViewerModal({ agent }: AgentViewerModalProps) {
{/* Metadata */}
<Section flexDirection="row" justifyContent="start">
{!agent.is_default_persona && (
<Content
<LineItemLayout
icon={SvgStar}
title="Featured"
sizePreset="main-ui"
variant="body"
variant="tertiary"
width="fit"
/>
)}
<Content
<LineItemLayout
icon={SvgUser}
title={agent.owner?.email ?? "Onyx"}
sizePreset="main-ui"
variant="body"
prominence="muted"
variant="tertiary-muted"
width="fit"
/>
{agent.is_public && (
<Content
<LineItemLayout
icon={SvgOrganization}
title="Public to your organization"
sizePreset="main-ui"
variant="body"
prominence="muted"
variant="tertiary-muted"
width="fit"
/>
)}
</Section>
@@ -288,11 +287,7 @@ export default function AgentViewerModal({ agent }: AgentViewerModalProps) {
{/* Knowledge */}
<Separator noPadding />
<Section gap={0.5} alignItems="start">
<Content
title="Knowledge"
sizePreset="main-content"
variant="section"
/>
<Title title="Knowledge" />
{hasKnowledge ? (
<Section
gap={0.5}
@@ -345,11 +340,10 @@ export default function AgentViewerModal({ agent }: AgentViewerModalProps) {
<SimpleCollapsible.Content>
<Section gap={0.5} alignItems="start">
{agent.system_prompt && (
<Content
<LineItemLayout
title="Instructions"
description={agent.system_prompt}
sizePreset="main-ui"
variant="section"
variant="secondary"
/>
)}
{defaultModel && (
@@ -357,7 +351,7 @@ export default function AgentViewerModal({ agent }: AgentViewerModalProps) {
title="Default Model"
description="This model will be used by Onyx by default in your chats."
nonInteractive
sizePreset="main-ui"
variant="secondary"
>
<Text>{defaultModel}</Text>
</Horizontal>
@@ -367,7 +361,7 @@ export default function AgentViewerModal({ agent }: AgentViewerModalProps) {
title="Knowledge Cutoff Date"
description="Documents with a last-updated date prior to this will be ignored."
nonInteractive
sizePreset="main-ui"
variant="secondary"
>
<Text mainUiMono>
{formatMmDdYyyy(agent.search_start_date)}
@@ -378,7 +372,7 @@ export default function AgentViewerModal({ agent }: AgentViewerModalProps) {
title="Overwrite System Prompts"
description='Remove the base system prompt which includes useful instructions (e.g. "You can use Markdown tables"). This may affect response quality.'
nonInteractive
sizePreset="main-ui"
variant="secondary"
>
<Switch disabled checked={agent.replace_base_system_prompt} />
</Horizontal>
@@ -390,12 +384,7 @@ export default function AgentViewerModal({ agent }: AgentViewerModalProps) {
{agent.task_prompt && (
<>
<Separator noPadding />
<Content
title="Prompt Reminders"
description={agent.task_prompt}
sizePreset="main-content"
variant="section"
/>
<Title title="Prompt Reminders" description={agent.task_prompt} />
</>
)}
@@ -403,11 +392,7 @@ export default function AgentViewerModal({ agent }: AgentViewerModalProps) {
{agent.starter_messages && agent.starter_messages.length > 0 && (
<>
<Separator noPadding />
<Content
title="Conversation Starters"
sizePreset="main-content"
variant="section"
/>
<Title title="Conversation Starters" />
<div className="grid grid-cols-2 gap-1 w-full">
{agent.starter_messages.map((starter, index) => (
<Interactive.Base
@@ -416,13 +401,10 @@ export default function AgentViewerModal({ agent }: AgentViewerModalProps) {
prominence="tertiary"
>
<Interactive.Container>
<Content
<LineItemLayout
icon={SvgBubbleText}
title={starter.message}
sizePreset="main-ui"
variant="body"
prominence="muted"
widthVariant="full"
variant="tertiary-muted"
/>
</Interactive.Container>
</Interactive.Base>

View File

@@ -13,6 +13,7 @@ interface LogoSectionProps {
function LogoSection({ folded, onFoldClick }: LogoSectionProps) {
const settings = useSettingsContext();
const applicationName = settings.enterpriseSettings?.application_name;
const logoDisplayStyle = settings.enterpriseSettings?.logo_display_style;
const logo = useCallback(
(className?: string) => <Logo folded={folded} className={className} />,
@@ -43,7 +44,7 @@ function LogoSection({ folded, onFoldClick }: LogoSectionProps) {
>
{folded === undefined ? (
<div className="p-1">{logo()}</div>
) : folded ? (
) : folded && logoDisplayStyle !== "name_only" ? (
<>
<div className="group-hover/SidebarWrapper:hidden pt-1.5">
{logo()}
@@ -52,6 +53,8 @@ function LogoSection({ folded, onFoldClick }: LogoSectionProps) {
{closeButton(false)}
</div>
</>
) : folded ? (
<div className="flex w-full justify-center">{closeButton(false)}</div>
) : (
<>
<div className="p-1"> {logo()}</div>