diff --git a/frontend/DESIGN.md b/frontend/DESIGN.md
index 81a41e0c..005438b1 100644
--- a/frontend/DESIGN.md
+++ b/frontend/DESIGN.md
@@ -23,23 +23,23 @@ through `@theme inline`, so `bg-`, `text-`, `border-`, `ring-`, `fill-` and
`stroke-` all accept them, including opacity modifiers such as
`bg-success/10`. One token class replaces a light + dark pair.
-| Token | Use for | Replaces |
-| --------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------- |
-| `background`, `foreground` | page surface and primary text | `bg-white`, `text-gray-700/800/900`, `dark:text-gray-200/300` |
-| `card`, `card-foreground` | raised surfaces (cards, dialogs, dropdowns) | `bg-white dark:bg-[#2b2c31]` |
-| `popover`, `popover-foreground` | floating menus and popovers | same as card |
-| `muted`, `muted-foreground` | quiet fills and secondary text, icons, placeholders, timestamps | `bg-gray-100/200`, `text-gray-400/500/600`, `dark:text-gray-400` |
-| `accent`, `accent-foreground` | hover and selected fills | `hover:bg-gray-100`, `dark:hover:bg-gray-700` |
-| `border`, `input`, `ring` | dividers, field borders, focus rings | `border-gray-200/300`, `dark:border-gray-600/700` |
-| `primary`, `primary-foreground` | brand purple: primary actions, links, selected states | `bg-purple-*`, `text-purple-*`, `#7D54D1`, `#A076F6` |
+| Token | Use for | Replaces |
+| --------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
+| `background`, `foreground` | page surface and primary text | `bg-white`, `text-gray-700/800/900`, `dark:text-gray-200/300` |
+| `card`, `card-foreground` | raised surfaces (cards, dialogs, dropdowns) | `bg-white dark:bg-[#2b2c31]` |
+| `popover`, `popover-foreground` | floating menus and popovers | same as card |
+| `muted`, `muted-foreground` | quiet fills and secondary text, icons, placeholders, timestamps | `bg-gray-100/200`, `text-gray-400/500/600`, `dark:text-gray-400` |
+| `accent`, `accent-foreground` | hover and selected fills | `hover:bg-gray-100`, `dark:hover:bg-gray-700` |
+| `border`, `input`, `ring` | dividers, field borders, focus rings | `border-gray-200/300`, `dark:border-gray-600/700` |
+| `primary`, `primary-foreground` | brand purple: primary actions, links, selected states | `bg-purple-*`, `text-purple-*`, `#7D54D1`, `#A076F6` |
| `secondary`, `secondary-foreground` | pressed and active toggles (a brand tint), secondary buttons, the question bubble | `bg-accent` on an active icon button |
-| `destructive`, `destructive-foreground` | errors, failed states, dangerous actions | `text-red-*`, `bg-red-50/100`, `#B42318`, `#E60000` |
-| `success`, `success-foreground` | completed, active, healthy | `text-green-*`, `text-emerald-*`, `bg-green-50/100` |
-| `warning`, `warning-foreground` | paused, pending review, degraded | `text-amber-*`, `text-yellow-*`, `text-orange-*`, `bg-amber-50/100` |
-| `info`, `info-foreground` | running, informational | `text-blue-*`, `bg-blue-50/100` |
-| `sidebar-*` | the navigation rail | |
-| `chart-1` to `chart-5` | data series only, never UI chrome (see below) | |
-| `answer-bubble` | assistant message background | |
+| `destructive`, `destructive-foreground` | errors, failed states, dangerous actions | `text-red-*`, `bg-red-50/100`, `#B42318`, `#E60000` |
+| `success`, `success-foreground` | completed, active, healthy | `text-green-*`, `text-emerald-*`, `bg-green-50/100` |
+| `warning`, `warning-foreground` | paused, pending review, degraded | `text-amber-*`, `text-yellow-*`, `text-orange-*`, `bg-amber-50/100` |
+| `info`, `info-foreground` | running, informational | `text-blue-*`, `bg-blue-50/100` |
+| `sidebar-*` | the navigation rail | |
+| `chart-1` to `chart-5` | data series only, never UI chrome (see below) | |
+| `answer-bubble` | assistant message background | |
Status colours are tuned to stay vivid rather than turning brown or olive,
so their contrast is low. Against white in light mode, `destructive` and
@@ -89,11 +89,11 @@ Patterns:
### Button (`ui/button.tsx`)
-| Prop | Values |
-| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `variant` | `default`, `secondary`, `outline`, `outline-primary`, `ghost`, `ghost-muted`, `ghost-destructive`, `link`, `destructive`, `destructive-outline`, `combobox`, `sidebar-item`, `tab`, `section-toggle` |
-| `size` | `xs`, `sm`, `default`, `lg`, `field`, `icon-xs`, `icon-sm`, `icon`, `icon-lg`, `inline` |
-| `shape` | `default` (rounded-md), `pill` (rounded-full, wider padding) |
+| Prop | Values |
+| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `variant` | `default`, `secondary`, `outline`, `outline-primary`, `ghost`, `ghost-muted`, `ghost-destructive`, `ghost-on-accent`, `ghost-destructive-on-accent`, `link`, `destructive`, `destructive-outline`, `combobox`, `sidebar-item`, `tab`, `section-toggle` |
+| `size` | `xs`, `sm`, `default`, `lg`, `field`, `icon-xs`, `icon-sm`, `icon`, `icon-lg`, `inline` |
+| `shape` | `default` (rounded-md), `pill` (rounded-full, wider padding) |
- Round brand buttons (`rounded-3xl px-5`, `rounded-full px-6`): `shape="pill"`,
plus `size="lg"` if they were `px-6`.
@@ -102,6 +102,14 @@ Patterns:
- Icon actions that remove something (a trash can on a member or shared
resource row) are `variant="ghost-destructive"`: muted at rest, red on
hover, so the warning shows even where the click deletes without asking.
+- Icon buttons on a row that is already `bg-accent` or `bg-sidebar-accent`
+ while you point at it (a highlighted Command item, a card or tile with
+ `hover:bg-accent`, a hovered sidebar row) are `variant="ghost-on-accent"`
+ (delete: `ghost-destructive-on-accent`). They hover with a
+ `foreground/15` (`destructive/15`) tint, which shows on accent where
+ ghost's accent square would not.
+- Icons are `lucide-react` at the default stroke (2). Don't pass
+ `strokeWidth`, and don't use an `` for a glyph lucide has.
- Bordered purple buttons (`border-primary text-primary hover:bg-primary`):
`variant="outline-primary"`.
- Tiny inline actions (`h-auto px-2 py-1 text-xs`): `size="xs"`.
@@ -117,9 +125,10 @@ Patterns:
while `data-placeholder` is set (`data-placeholder={value ? undefined : ''}`).
Pass only layout (`w-full justify-between`) and keep the chevron as the
last child.
-- A button or picker that sits in a row of fields is `size="field"`: 42px,
- the height of `Input` (default) and `SelectTrigger size="lg"`, so a form
- column has one height. With `shape="pill"` its text starts 21px in, like
+- A button or picker that sits in a row of fields is `size="field"`: 42px.
+ `Input` and `SelectTrigger` take `size="field"` too (the same 42px as
+ Input `default` and SelectTrigger `lg`), so a form column has one name for
+ one height; prefer `field` in new form rows. With `shape="pill"` its text starts 21px in, like
the Input and Select pills beside it. The agent form's pickers are
`combobox field pill`, its Add button `outline-primary field pill`.
- Rows in the navigation sidebar (`hover:bg-sidebar-accent … pl-3 gap-2.5
@@ -136,20 +145,37 @@ rounded-3xl`) are `variant="sidebar-item"`: left-aligned, full-radius, normal
gives it `foreground` text and a `primary` underline. Padding-free tabs (a
sub-nav with `gap-6`) add `size="inline"`, which keeps 4px above the line;
the row draws the 1px baseline, and `-mb-px` lays the underline over it.
- Tabs that switch a panel in place use `ui/tabs` instead.
+ Use them for a row of route links (the agent sub-nav: a `
@@ -688,11 +674,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
)}
title={t('modals.searchConversations.searchPlaceholder')}
>
-
@@ -849,7 +830,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { onClick={() => setNavOpen(true)} aria-label="Toggle mobile menu" > -
+{label}
-+
{value}
{sub ?{sub}
: null} diff --git a/frontend/src/admin/Usage.tsx b/frontend/src/admin/Usage.tsx index dbaf9c39..df3406eb 100644 --- a/frontend/src/admin/Usage.tsx +++ b/frontend/src/admin/Usage.tsx @@ -176,9 +176,9 @@ export default function Usage() { />+
{metric === 'cost' ? 'Spend' : 'Token usage'}
- Top users -
+Top users
{topUsers.length === 0 ? (No usage.
) : ( diff --git a/frontend/src/admin/Users.tsx b/frontend/src/admin/Users.tsx index dda2fd60..eedc557a 100644 --- a/frontend/src/admin/Users.tsx +++ b/frontend/src/admin/Users.tsx @@ -1,4 +1,5 @@ import { + ChevronDown, Eye, Gauge, LogOut, @@ -11,14 +12,15 @@ import { useCallback, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import adminService from '../api/services/adminService'; -import ThreeDots from '../assets/three-dots.svg'; import { Badge } from '../components/ui/badge'; import { Button } from '../components/ui/button'; import { + ActionMenu, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, + type MenuOption, } from '../components/ui/dropdown-menu'; import { Input } from '../components/ui/input'; import { Modal } from '../components/ui/modal'; @@ -337,56 +339,31 @@ export default function Users() { className="flex items-center justify-end" onClick={(e) => e.stopPropagation()} > -- {t('agents.form.advanced.tokenLimitingDescription')} -
-- {t('agents.form.advanced.requestLimitingDescription')} -
-- {t( - 'agents.form.advanced.systemPromptOverrideDescription', - )} -
-- {t('agents.form.guardrails.enableDescription')} -
-{t('agents.form.guardrails.monitorHint')} @@ -394,10 +396,11 @@ export default function GuardrailsSection({
- {t('agents.form.guardrails.blockMessageDescription')} -
-- {t('agents.form.guardrails.failOpenDescription')} -
-- {t('agents.form.guardrails.confidenceHint')} -
-{error}
} - -- Image updates are included the next time you save. -
-- {t( - 'agents.form.advanced.systemPromptOverrideDescription', - )} -
-- Auto: send native when the model supports - it, otherwise extract text. -
-+
Selected model does not support structured output.
@@ -2342,29 +2304,12 @@ function WorkflowBuilderInner() { "required": ["summary"] }`} /> - {selectedAgentJsonSchemaText.trim() !== - '' && ( -- {selectedAgentJsonSchemaError - ? `Invalid JSON schema: ${selectedAgentJsonSchemaError}` - : 'Valid JSON schema'} -
- )} -Artifacts
-{helpText}
- )} -{errors[key]}
- )} -{errors[key]}
- )} -
{t('settings.sources.graphrag.view.title')}
@@ -195,7 +189,7 @@ const GraphView: React.FC {t('settings.sources.graphrag.view.empty')}
+
+
{t('settings.sources.wiki.livingTitle')}
@@ -305,11 +300,12 @@ const WikiViewer: React.FC