Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions docs/agents/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The visual design system for Graph Explorer. Read this before modifying UI styling, adding color tokens, or writing Tailwind classes in components.

> [!NOTE]
> **Migration in progress.** This document describes the _target_ state; the cleanup is tracked in [#1952](https://github.com/aws/graph-explorer/issues/1952). Until it completes, the codebase deviates in known ways: legacy color aliases (`text-text-primary`, `bg-background-default`, `primary-main`, etc.) are still in use pending migration to the canonical tokens below; and a few `dark:` classes and shadcn compat tokens (`destructive`, `popover`) remain pending removal. When touching styled code during the transition, migrate toward this document, not away from it.
> **Migration in progress.** This document describes the _target_ state; the cleanup is tracked in [#1952](https://github.com/aws/graph-explorer/issues/1952). Until it completes, the codebase deviates in known ways: legacy color aliases (`text-text-primary`, `bg-background-default`, `primary-main`, etc.) are still in use pending migration to the canonical tokens below. When touching styled code during the transition, migrate toward this document, not away from it.

## Color Architecture

Expand Down Expand Up @@ -46,8 +46,6 @@ The Tailwind neutral scales (`slate`, `zinc`, `neutral`, `stone`) are removed. `

Roles: `primary`, `danger`, `warning`, `success`, `neutral`.

**Accent** is an alias group used for highlight/selection states — `accent` → `primary-subtle`, `accent-hover` → `primary-subtle-hover`, `accent-foreground` → `primary-foreground`. Whether it survives as a distinct abstraction or gets inlined to the primary tokens is an open question for the migration ([#1956](https://github.com/aws/graph-explorer/issues/1956)).

### Using color in components

**Strong preference: use semantic tokens.** Write `bg-primary-subtle text-primary-foreground`, not `bg-brand-50 text-brand-700`.
Expand All @@ -66,7 +64,7 @@ Roles: `primary`, `danger`, `warning`, `success`, `neutral`.

Dark mode is a planned future feature. The semantic token structure is designed to support it via CSS `light-dark()` on the token definitions — when dark mode arrives, components should not need `dark:` classes because the semantic tokens themselves will resolve to appropriate values per mode.

**Policy:** Do not add new `dark:` variant classes. A few legacy usages remain pending removal ([#1955](https://github.com/aws/graph-explorer/issues/1955)).
**Policy:** Do not add `dark:` variant classes.

## Tailwind Conventions

Expand Down
2 changes: 1 addition & 1 deletion packages/graph-explorer/src/components/AlertDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function AlertDialogContent({
data-slot="alert-dialog-content"
data-size={size}
className={cn(
"group/alert-dialog-content bg-popover text-popover-foreground ring-foreground/10 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 flex max-h-full w-full flex-col gap-6 overflow-hidden rounded-xl p-6 shadow-lg ring-1 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg",
"group/alert-dialog-content bg-background text-foreground ring-foreground/10 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 flex max-h-full w-full flex-col gap-6 overflow-hidden rounded-xl p-6 shadow-lg ring-1 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg",
className,
)}
{...props}
Expand Down
14 changes: 7 additions & 7 deletions packages/graph-explorer/src/components/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function DropdownMenuContent({
sideOffset={sideOffset}
align={align}
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg p-1 shadow-lg ring-1 duration-100 data-[state=closed]:overflow-hidden",
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-background text-foreground z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg p-1 shadow-lg ring-1 duration-100 data-[state=closed]:overflow-hidden",
className,
)}
{...props}
Expand Down Expand Up @@ -74,7 +74,7 @@ function DropdownMenuItem({
data-inset={inset}
data-variant={variant}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-3 py-2 text-base outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-primary-subtle focus:text-primary-foreground data-[variant=destructive]:text-danger data-[variant=destructive]:focus:bg-danger/10 data-[variant=destructive]:focus:text-danger data-[variant=destructive]:*:[svg]:text-danger not-data-[variant=destructive]:focus:**:text-primary-foreground group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-3 py-2 text-base outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className,
)}
{...props}
Expand All @@ -96,7 +96,7 @@ function DropdownMenuCheckboxItem({
data-slot="dropdown-menu-checkbox-item"
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex cursor-default items-center gap-1.5 rounded-md py-2 pr-8 pl-3 text-base outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-primary-subtle focus:text-primary-foreground focus:**:text-primary-foreground relative flex cursor-default items-center gap-1.5 rounded-md py-2 pr-8 pl-3 text-base outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className,
)}
checked={checked}
Expand Down Expand Up @@ -139,7 +139,7 @@ function DropdownMenuRadioItem({
data-slot="dropdown-menu-radio-item"
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground relative flex cursor-default items-center gap-1.5 rounded-md py-2 pr-8 pl-3 text-base outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-primary-subtle focus:text-primary-foreground focus:**:text-primary-foreground relative flex cursor-default items-center gap-1.5 rounded-md py-2 pr-8 pl-3 text-base outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className,
)}
{...props}
Expand Down Expand Up @@ -198,7 +198,7 @@ function DropdownMenuShortcut({
<span
data-slot="dropdown-menu-shortcut"
className={cn(
"text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-xs tracking-widest",
"text-muted-foreground group-focus/dropdown-menu-item:text-primary-foreground ml-auto text-xs tracking-widest",
className,
)}
{...props}
Expand All @@ -225,7 +225,7 @@ function DropdownMenuSubTrigger({
data-slot="dropdown-menu-sub-trigger"
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground flex cursor-default items-center gap-1.5 rounded-md px-3 py-2 text-base outline-hidden select-none data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-primary-subtle focus:text-primary-foreground data-open:bg-primary-subtle data-open:text-primary-foreground not-data-[variant=destructive]:focus:**:text-primary-foreground flex cursor-default items-center gap-1.5 rounded-md px-3 py-2 text-base outline-hidden select-none data-inset:pl-7 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className,
)}
{...props}
Expand All @@ -244,7 +244,7 @@ function DropdownMenuSubContent({
<DropdownMenuPrimitive.SubContent
data-slot="dropdown-menu-sub-content"
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground z-50 min-w-[96px] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md p-1 shadow-lg ring-1 duration-100",
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-background text-foreground z-50 min-w-[96px] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md p-1 shadow-lg ring-1 duration-100",
className,
)}
{...props}
Expand Down
4 changes: 2 additions & 2 deletions packages/graph-explorer/src/components/Field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function FieldGroup({ className, ...props }: ComponentPropsWithRef<"div">) {
}

const fieldVariants = cva({
base: "group/field data-[invalid=true]:text-destructive flex w-full gap-3",
base: "group/field data-[invalid=true]:text-danger flex w-full gap-3",
variants: {
orientation: {
vertical: ["flex-col *:w-full [&>.sr-only]:w-auto"],
Expand Down Expand Up @@ -223,7 +223,7 @@ function FieldError({
<div
role="alert"
data-slot="field-error"
className={cn("text-destructive text-sm font-normal", className)}
className={cn("text-danger text-sm font-normal", className)}
{...props}
>
{content}
Expand Down
4 changes: 2 additions & 2 deletions packages/graph-explorer/src/components/Toaster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export function Toaster() {
}}
style={
{
"--normal-bg": "var(--color-popover)",
"--normal-text": "var(--color-popover-foreground)",
"--normal-bg": "var(--color-background)",
"--normal-text": "var(--color-foreground)",
"--normal-border": "var(--color-border)",
"--border-radius": "var(--radius-lg)",
} as React.CSSProperties
Expand Down
11 changes: 0 additions & 11 deletions packages/graph-explorer/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,6 @@
--color-muted-foreground: var(--color-gray-500);
--color-muted: var(--color-gray-100);

/* Used for highlights and selections */
--color-accent-foreground: var(--color-primary-foreground);
--color-accent: var(--color-primary-subtle);
--color-accent-hover: var(--color-primary-subtle-hover);

--color-neutral-foreground: var(--color-gray-900);
--color-neutral: var(--color-gray-900);
--color-neutral-hover: var(--color-gray-700);
Expand Down Expand Up @@ -130,12 +125,6 @@
--color-input-background: var(--color-white);
--color-input-border: var(--color-gray-300);

/* Semantic colors for shadcn/ui components */

--color-destructive: var(--color-danger);
--color-popover: var(--color-background);
--color-popover-foreground: var(--color-foreground);

/* Legacy colors */

--color-text-primary: var(--color-foreground);
Expand Down
Loading