# Node Style Guide
Design guidelines for creating consistent, professional nodes in iced_nodegraph.
## 1. Color System
### Semantic Pin Colors
Pin colors communicate data types at a glance. Use consistent colors across all nodes.
```rust
use iced::Color;
// Data type colors
pub const PIN_NUMBER: Color = Color::from_rgb(0.20, 0.83, 0.60); // Emerald #34D399
pub const PIN_STRING: Color = Color::from_rgb(0.98, 0.75, 0.14); // Amber #FBBF24
pub const PIN_BOOL: Color = Color::from_rgb(0.98, 0.57, 0.24); // Orange #FB923C
pub const PIN_COLOR: Color = Color::from_rgb(0.96, 0.45, 0.71); // Pink #F472B6
pub const PIN_DATETIME: Color = Color::from_rgb(0.65, 0.55, 0.98); // Violet #A78BFA
pub const PIN_EMAIL: Color = Color::from_rgb(0.22, 0.74, 0.97); // Sky #38BDF8
pub const PIN_ANY: Color = Color::from_rgb(0.58, 0.64, 0.72); // Slate #94A3B8
pub const PIN_CONFIG: Color = Color::from_rgb(0.13, 0.83, 0.93); // Cyan #22D3EE
```
### Surface Colors
```rust
pub const SURFACE_ELEVATED: Color = Color::from_rgb(0.165, 0.165, 0.235); // #2A2A3C
pub const BORDER_SUBTLE: Color = Color::from_rgb(0.227, 0.227, 0.298); // #3A3A4C
pub const TEXT_PRIMARY: Color = Color::from_rgb(0.894, 0.894, 0.906); // #E4E4E7
pub const TEXT_MUTED: Color = Color::from_rgb(0.631, 0.631, 0.667); // #A1A1AA
```
### Theme Integration
Derive interior colors from the active theme's palette so nodes adapt to every theme:
```rust
let palette = theme.extended_palette();
let title_background = palette.primary.base.color;
let title_text = palette.background.base.text;
```
The demos wrap this in a `demo_common::NodeContentStyle` convenience
(`::input(theme)`, `::process(theme)`, ...); it lives in the demos, not the widget,
since interior theming is the application's concern.
---
## 2. Typography
### Font Size Hierarchy
| Title | 13px | Node header text |
| Label | 11px | Pin labels, field names |
| Value | 10px | Slider values, small text |
| Meta | 9px | Tooltips, secondary info |
### Text Colors
- **Primary**: Main content, important labels
- **Muted**: Secondary labels, hints, less important info
- **Accent**: Highlights, active states (use pin colors)
---
## 3. Spacing & Padding
### Constants
```rust
pub const SPACING_PIN: f32 = 6.0; // Between pin rows
pub const SPACING_ROW: f32 = 8.0; // Between content rows
pub const PADDING_CONTENT: [u16; 2] = [10, 12]; // [vertical, horizontal]
pub const PADDING_TITLE: [u16; 2] = [4, 8]; // Compact title padding
```
### Guidelines
- Minimum spacing between interactive elements: 6px
- Generous horizontal padding (12px) for edge clearance
- Consistent vertical rhythm with 6-8px spacing
---
## 4. Node Dimensions
### Width Guidelines
| Simple (1 pin) | 120-150 | Minimal nodes |
| Standard | 160-200 | Most nodes |
| Complex | 200-250 | Multiple controls |
| Wide | 250-320 | Multi-column layouts |
### Height
Always auto (content-driven). Never set fixed heights.
---
## 5. Border & Corner Radius
```rust
pub const CORNER_RADIUS_NODE: f32 = 6.0; // Node container
pub const CORNER_RADIUS_CONTROL: f32 = 4.0; // Buttons, inputs
pub const CORNER_RADIUS_PILL: f32 = 10.0; // Pill buttons
pub const CORNER_RADIUS_SWATCH: f32 = 2.0; // Color swatches
```
---
## 6. Shadows
Use shadows sparingly. Available via `ShadowConfig`:
```rust
// Subtle - for depth
ShadowConfig::subtle() // offset: (2, 2), blur: 4, color: 0.3 opacity
// Glow - for selection/hover
ShadowConfig::glow(color) // offset: (0, 0), blur: 8, spread: 2
```
---
## 7. Pin Layout & Design
### Pin Mechanism
The `pin!` macro creates an invisible container that marks an anchor point:
- `Left` pins anchor to the left edge of the node
- `Right` pins anchor to the right edge of the node
- Position is calculated from the NodePin widget bounds
### Pattern 1: Horizontal Pairing
Place input and output on the same row to save vertical space:
```
┌─────────────────────────┐
│ Add │
├─────────────────────────┤
│ ○ a sum ○ │ ← Input + Output on same row
│ ○ b │
└─────────────────────────┘
```
```rust
column![
row![
pin!(Left, text("a"), Input, "float", PIN_NUMBER),
container(()).width(Fill), // spacer
pin!(Right, text("sum"), Output, "float", PIN_NUMBER),
],
pin!(Left, text("b"), Input, "float", PIN_NUMBER),
]
```
### Pattern 2: Control-Wrapping Pins
Wrap controls with pins instead of separate rows:
```
┌─────────────────────────┐
│ Float Slider │
├─────────────────────────┤
│ [━━━━━●━━━] 5.2 ○ │ ← Pin wraps slider row
└─────────────────────────┘
```
```rust
row![
slider_widget,
pin!(Right, value_display, Output, "float", PIN_NUMBER)
]
```
AVOID separate pin rows:
```
│ [━━━━━●━━━━━] 5.2 │ ← Slider
│ value ○ │ ← BAD: separate row with generic label
```
### Pattern 3: Label Guidelines
**AVOID generic labels:**
- `value`, `output`, `result`, `input`, `data`
**PREFER meaningful labels:**
- `sum`, `product`, `color`, `texture`, `a`, `b`, `min`, `max`
**OMIT when obvious:**
- When a control makes the purpose clear (slider = number output)
- When there's only one pin of that type
### Pattern 4: Pass-through Nodes
Symmetric input/output on first row:
```
┌─────────────────────────┐
│ Clamp │
├─────────────────────────┤
│ ○ in out ○ │ ← Symmetric I/O
│ min [━━●━━] 0.0 │
│ max [━━━━●] 1.0 │
└─────────────────────────┘
```
### Pin Shapes
| Circle | Data flow (default)| Numbers, strings, colors, etc. |
| Diamond | Control flow | Triggers, events |
| Square | Arrays/Collections | Lists, buffers |
| Triangle | References | Pointers, handles |
---
## 8. Animation & Edge Styling
### Edge Types
| Bezier | Default - smooth data flow |
| Step | Control flow, state machines |
| Line | Simple connections |
### Flow Animation
Use sparingly for active connections. Default speed: 1.0
---
## 9. Node Type Categories
Visual hierarchy through consistent title bar colors:
| Input | Blue tint | Sliders, pickers, triggers|
| Process | Green tint | Math, filters, transforms |
| Output | Orange tint | Display, export, actions |
| Config | Cyan tint | Settings, parameters |
| Comment | Gray | Notes, documentation |
The demos' `demo_common::NodeContentStyle::input(theme)`, `.process(theme)`, etc. provide ready-made palettes for these categories.
---
## 10. Code Patterns
### Node Builder Function
Standard signature:
```rust
pub fn my_node<'a, Message>(
theme: &'a iced::Theme,
// node-specific params...
) -> iced::Element<'a, Message>
where
Message: Clone + 'a,
{
let header_bg = theme.extended_palette().primary.base.color;
column![
// node_header(content, background, radii) rounds the top corners to
// match the node's rendered silhouette.
node_header(text(title), header_bg, 5.0),
container(content).padding(PADDING_CONTENT),
// optional: node_footer(...)
]
.width(180.0)
.into()
}
```
### Colors Module
Create a `colors` module in your demo:
```rust
pub mod colors {
use iced::Color;
// Pin colors
pub const PIN_NUMBER: Color = Color::from_rgb(0.20, 0.83, 0.60);
pub const PIN_STRING: Color = Color::from_rgb(0.98, 0.75, 0.14);
// ... etc
// Surface colors
pub const SURFACE_ELEVATED: Color = Color::from_rgb(0.165, 0.165, 0.235);
pub const TEXT_MUTED: Color = Color::from_rgb(0.631, 0.631, 0.667);
}
```
### Naming Conventions
- `PIN_*` for pin type colors
- `SURFACE_*` for backgrounds
- `TEXT_*` for text colors
- `BORDER_*` for borders
- `SPACING_*` for spacing values
- `PADDING_*` for padding arrays
---
## Quick Reference
```
Node Structure:
┌─────────────────────────┐
│ Title Bar (13px) │ ← node_header()
├─────────────────────────┤
│ ○ pin [control] ○ │ ← padding: [10, 12]
│ ○ pin │ ← spacing: 6px
│ value: 0.5 │
├─────────────────────────┤
│ [ Footer ] │ ← node_footer() (optional)
└─────────────────────────┘
│ │
└── 160-200px ───┘
```
Pin Colors Quick Chart:
```
Number ████ Emerald
String ████ Amber
Bool ████ Orange
Color ████ Pink
DateTime ████ Violet
Email ████ Sky
Any ████ Slate
Config ████ Cyan
```