This page covers the frontend styling architecture for the Langflow visual editor: how Tailwind CSS is configured, how CSS variables implement light/dark theming, how component-level utility classes are organized, and how runtime style constants (node colors, gradients, icons) work.
For settings UI pages that happen to display style-related options, see Settings and Configuration. For how GenericNode applies these styles visually, see GenericNode Component.
The styling system has four layers:
Sources: src/frontend/tailwind.config.mjs1-10 src/frontend/src/style/index.css1-10 src/frontend/src/style/applies.css1-5 src/frontend/src/App.css1-10 src/frontend/src/utils/styleUtils.ts1-20
File: src/frontend/tailwind.config.mjs
| Plugin | Purpose |
|---|---|
@tailwindcss/forms | Normalize form element appearance |
@tailwindcss/typography | prose classes for Markdown content |
@tailwindcss/container-queries | Container-based responsive classes |
tailwindcss-animate | Keyframe animation utilities |
tailwindcss-dotted-background | Canvas dot-grid background |
Dark mode is toggled by a class on a parent element (not prefers-color-scheme). The .dark class is set on <html> or a root wrapper:
darkMode: ["class"],
src/frontend/tailwind.config.mjs18
src/frontend/tailwind.config.mjs41-46
| Token | Value |
|---|---|
mdd | 45rem |
xl | 1200px |
2xl | 1400px |
3xl | 1500px |
All semantic colors are defined as references to CSS variables. Examples from src/frontend/tailwind.config.mjs119-260:
| Tailwind token | CSS variable |
|---|---|
border | hsl(var(--border)) |
background | hsl(var(--background)) |
foreground | hsl(var(--foreground)) |
muted | hsl(var(--muted)) |
muted-foreground | hsl(var(--muted-foreground)) |
primary | hsl(var(--primary)) |
destructive | hsl(var(--destructive)) |
status-green | var(--status-green) |
status-red | var(--status-red) |
status-yellow | var(--status-yellow) |
build-trigger | var(--build-trigger) |
canvas | hsl(var(--canvas)) |
canvas-dot | hsl(var(--canvas-dot)) |
note-amber | hsl(var(--note-amber)) |
frozen-blue | rgba(128, 190, 219, 0.86) |
datatype-* colors for data type badges are similarly tokenized. The safelist array ensures status background classes are never purged from the CSS build:
src/frontend/tailwind.config.mjs25-30
src/frontend/tailwind.config.mjs47-118
| Animation name | Description |
|---|---|
wiggle | Node status icon pop (scale 100%→120%→100%) |
jiggle | Rotate ±1 deg, infinite |
overlayShow / overlayHide | Modal overlay fade |
contentShow / contentHide | Modal content scale + clip |
border-beam | Animated offset-path border effect |
pulse-pink | Accent-pink pulsation |
File: src/frontend/src/style/index.css
All theme values are expressed as raw HSL channel values (no hsl() wrapper), so they can be composed with alpha transparency in Tailwind: hsl(var(--border) / 50%).
Diagram: CSS Variable Namespace Map
Sources: src/frontend/src/style/index.css8-203 src/frontend/src/style/index.css205-464
The :root block defines the light theme. The .dark selector overrides every semantic value. Key inversions:
| Variable | Light | Dark |
|---|---|---|
--foreground | 0 0% 0% (black) | 0 0% 100% (white) |
--background | 0 0% 100% (white) | 240 6% 10% (near-black) |
--muted | 240 5% 96% | 240 4% 16% |
--primary | 0 0% 0% (black) | 0 0% 100% (white) |
--canvas | 240 5% 96% (light gray) | 0 0% 0% (black) |
--canvas-dot | 240 5% 65% | 240 5.3% 26.1% |
src/frontend/src/style/index.css13-38 src/frontend/src/style/index.css206-230
Some colors are intentionally shared across both themes (defined only in :root), such as:
--status-red: #ef4444--status-green: #4ade80--build-trigger: #dc735bsrc/frontend/src/style/index.css107-118
src/frontend/src/style/index.css9-11
applies.css)File: src/frontend/src/style/applies.css
All custom classes are declared inside @layer components, which means they can be overridden by Tailwind utility classes but take precedence over the base layer. This file is the main location for multi-property reusable class groups.
Diagram: Major @layer components Class Groups
Sources: src/frontend/src/style/applies.css67-900
primary-input — the standard text input style across the app:
src/frontend/src/style/applies.css181-182
frozen / border-ring-frozen — applied to nodes in the "frozen" execution state. Creates a frosted-glass visual effect using ::before and ::after pseudo-elements:
src/frontend/src/style/applies.css117-158
generic-node-div — base wrapper for every node card on the canvas:
src/frontend/src/style/applies.css325-327
green-status / red-status / yellow-status / gray-status — all extend generic-node-status and set a text-status-* color:
src/frontend/src/style/applies.css344-354
App.cssFile: src/frontend/src/App.css
Contains rules that must be at document scope:
--connection), selected edge highlight (--selected), node handle positioning, resize handle appearance.::-webkit-scrollbar-* pseudo-elements referencing --muted, --border, and --placeholder-foreground CSS variables..sticky-note-scroll variant with translucent thumb.text-security-disc.woff for masking password-like inputs visually.src/frontend/src/App.css32-219
classes.cssFile: src/frontend/src/style/classes.css
Inter family with antialiasing.pointer-events: all and default cursor..AccordionContent[data-state="open"] references the slideDown keyframe..gradient-start / .gradient-end apply gradient-motion-start / gradient-motion-end keyframes.jse-* component classes.pre code uses hsl(var(--muted)) background; dark mode uses --code-foreground..card-shine-effect produces a hover shimmer using a linear gradient background-position animation.src/frontend/src/style/classes.css19-232
styleUtils.ts)File: src/frontend/src/utils/styleUtils.ts
This module exports JavaScript constants and functions used by React components to compute styles at runtime.
nodeColorsMaps component type keys (matching the backend category field) to hex color strings. Used to set the left-border color of node cards and handle ports.
src/frontend/src/utils/styleUtils.ts85-134
Selected entries:
| Key | Color |
|---|---|
inputs | #10B981 (emerald) |
outputs | #AA2411 (dark red) |
models | #ab11ab (magenta) |
agents | #903BBE (purple) |
tools | #00fbfc (cyan) |
embeddings | #42BAA7 (teal) |
vectorstores | #AA8742 (amber) |
Message | #4f46e5 (indigo) |
Data | #dc2626 (red) |
nodeColorsNameThe same keys as nodeColors, but mapped to Tailwind color names (e.g., "emerald", "purple"). Used when constructing Tailwind class strings dynamically.
src/frontend/src/utils/styleUtils.ts136-189
gradientsAn array of 31 Tailwind gradient class strings (bg-gradient-to-br from-... via-... to-...). Used for randomly assigning visual gradients to flow cards and avatars.
src/frontend/src/utils/styleUtils.ts15-47
flowGradientsAn array of 9 CSS linear-gradient strings in horizontal direction. Used for flow card backgrounds in the store and management pages.
src/frontend/src/utils/styleUtils.ts61-71
toolModeGradientApplied to nodes when tool_mode is enabled (a pink-to-magenta gradient). References --tool-mode-gradient-1 and --tool-mode-gradient-2 CSS variables.
src/frontend/src/utils/styleUtils.ts73-74
swatchColorsSix Tailwind class string pairs (bg-* text-*) using custom named colors (neon-fuschia, digital-orchid, plasma-purple, etc.):
src/frontend/src/utils/styleUtils.ts76-83
These custom colors are declared in index.css under names like --neon-fuschia, --digital-orchid.
src/frontend/src/style/index.css184-191
FILE_ICONSMaps file extensions to { icon, color } pairs. The color field uses text-datatype-* Tailwind classes:
src/frontend/src/utils/styleUtils.ts191-276
Example:
| Extension | Icon | Color class |
|---|---|---|
json | FileJson | text-datatype-indigo |
pdf | File | text-datatype-red |
py / js / ts | FileCode | text-datatype-blue |
yaml | FileJson | text-datatype-violet |
Diagram: getNodeIcon Resolution Chain
Sources: src/frontend/src/utils/styleUtils.ts616-662
eagerLoadedIconsMap: Pre-loaded icons including GradientSave, BotMessageSquareIcon, and React Icons (FaApple, FaDiscord, FaGithub).iconMappingsPromise: Lazily imports lazyIconImports.ts — a generated module mapping custom integration icon names to dynamic imports.dynamicIconImports: Lucide's built-in dynamic icon loader.getLucideIconName: Converts PascalCase icon names to kebab-case for Lucide lookup.src/frontend/src/utils/styleUtils.ts599-614
constants.ts)File: src/frontend/src/constants/constants.ts
Style-affecting constants defined here:
| Constant | Value | Purpose |
|---|---|---|
NODE_WIDTH | 384 | Default node width in px |
NODE_HEIGHT | NODE_WIDTH * 3 | Default node height |
NOTE_NODE_MIN_WIDTH | 280 | Minimum sticky note width |
NOTE_NODE_MIN_HEIGHT | 140 | Minimum sticky note height |
DEFAULT_NOTE_SIZE | 324 | Default sticky note size |
ICON_STROKE_WIDTH | 1.5 | Default Lucide stroke width |
COLOR_OPTIONS | { amber, neutral, rose, blue, lime, transparent } | Sticky note color keys → CSS variable references |
MODAL_CLASSES | Long Tailwind string | Base overlay class for modals |
GRADIENT_CLASS | linear-gradient(...) | Right-edge fade using --background |
GRADIENT_CLASS_DISABLED | linear-gradient(...) | Right-edge fade using --muted |
src/frontend/src/constants/constants.ts884-929
COLOR_OPTIONS and Note Node Colorssrc/frontend/src/constants/constants.ts903-910
NoteNode reads the backgroundColor field from node template data, resolves it through COLOR_OPTIONS, and dynamically computes whether text should be light or dark using the WCAG luminance formula in getContrastTextColor.
src/frontend/src/CustomNodes/NoteNode/index.tsx24-57
Diagram: How a Color Token Flows from Config to Component
Sources: src/frontend/src/style/index.css114 src/frontend/tailwind.config.mjs167 src/frontend/src/style/applies.css344-345 src/frontend/src/CustomNodes/GenericNode/components/NodeStatus/index.tsx312-317
The pattern is consistent throughout:
index.css.tailwind.config.mjs exposes them as named tokens.applies.css composes them into reusable multi-property class names.styleUtils.ts provides JS-side constants (hex values, gradient strings) for cases where styles must be computed at runtime rather than declared statically.Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.