When to use this skill
Use this skill when:
- •Creating or modifying UI components in RestMan
- •Implementing focus states, borders, or color schemes
- •Ensuring visual consistency across components
- •Working with OpenTUI styling in RestMan
- •Questions about RestMan's design system or theme
- •Adding new visual elements to the application
RestMan Theme Overview
RestMan uses a warm, earthy color palette with orange/brown tones as the primary colors. The design emphasizes clear focus states, consistent borders, and readable text against a dark background.
Design Tokens
All design tokens are centralized in src/tokens.ts:
Color Palette
export const colors = {
// Primary colors
primary: '#CC8844', // Warm orange - main brand color
secondary: '#BB7733', // Brown-orange - secondary actions
// Text colors
textActive: '#FFFFFF', // White - active/editing text
textMuted: '#999999', // Light gray - normal/read-only text
textPlaceholder: '#666666', // Dark gray - placeholder text
// Border colors
borderDefault: '#555555', // Gray - default borders
borderFocused: '#CC8844', // Primary - focused elements
borderEdit: '#BB7733', // Secondary - edit mode
// Background colors
backgroundDefault: '#1a1a1a', // Dark background
} as const;
Color Usage Guidelines
Primary Color (#CC8844)
- •Main brand color used throughout the app
- •Focus indicators on selected fields
- •Active tab labels
- •Header text ("RestMan v1.0")
- •Toast messages
- •Emphasis elements
Secondary Color (#BB7733)
- •Edit mode borders
- •Secondary focus states
- •Toast border
- •Alternative accent color
Text Colors
- •Active (
#FFFFFF): Text being edited or in active input fields - •Muted (
#999999): Read-only content, inactive text - •Placeholder (
#666666): Empty field hints
Border Colors
- •Default (
#555555): Unfocused component borders - •Focused (
#CC8844): Currently selected component - •Edit (
#BB7733): Component in edit mode
Background
- •Default (
#1a1a1a): Dark background for toast overlays and modals
Helper Functions
The tokens file provides utility functions for common styling patterns:
getBorderColor
/**
* Get the border color based on focus and edit mode states
*/
export function getBorderColor(focused: boolean, editMode: boolean): string {
if (focused) return colors.borderFocused;
if (editMode) return colors.borderEdit;
return colors.borderDefault;
}
Usage example:
const borderColor = getBorderColor(focused, editMode);
getTextColor
/**
* Get the text color based on edit mode and whether content exists
* @param editMode - Whether the field is in edit mode
* @param hasValue - Whether the field has a value
*/
export function getTextColor(editMode: boolean, hasValue: boolean): string {
if (editMode) return colors.textActive;
return hasValue ? colors.textMuted : colors.textPlaceholder;
}
Usage example:
const textColor = getTextColor(editMode, !!value);
Component Styling Patterns
Input Components
All input components follow this pattern:
// Import tokens
import { colors, getBorderColor } from '../tokens';
// In component
const borderColor = getBorderColor(focused, editMode);
return (
<box
style={{
border: true,
borderColor,
paddingLeft: 1,
paddingRight: 1,
}}
>
<text fg={editMode ? colors.textActive : colors.textMuted}>
{value || placeholder}
</text>
</box>
);
Tab Headers
Tab headers use specific colors for each tab type:
const tabs = [
{ name: 'headers', label: 'Headers', color: '#CC8844' }, // Primary
{ name: 'params', label: 'Params', color: '#9988BB' }, // Purple
{ name: 'body', label: 'Body', color: '#99AA77' }, // Green
];
// Render with active/inactive states
tabs.map((tab) => (
<text key={tab.name} fg={activeTab === tab.name ? tab.color : '#666666'}>
{tab.label}
</text>
))
Modals and Overlays
Modals use borders and backgrounds for visual hierarchy:
<box
style={{
position: 'absolute',
top: 2,
left: 2,
right: 2,
bottom: 2,
border: true,
borderColor: colors.primary, // Primary border
backgroundColor: colors.backgroundDefault,
paddingLeft: 2,
paddingRight: 2,
}}
>
{/* Modal content */}
</box>
Toast Notifications
<box
style={{
position: 'absolute',
bottom: 2,
left: 2,
right: 2,
border: true,
borderColor: colors.secondary, // Secondary border
paddingLeft: 2,
paddingRight: 2,
backgroundColor: colors.backgroundDefault,
}}
>
<text fg={colors.primary}>{message}</text>
</box>
OpenTUI Style Properties
RestMan uses kebab-case for style properties:
style={{
flexDirection: 'column',
gap: 1,
paddingLeft: 1,
paddingRight: 1,
paddingTop: 1,
paddingBottom: 1,
backgroundColor: 'black',
border: true,
borderColor: '#555555',
flexGrow: 1,
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
State-Based Styling
Components use three primary states:
1. Default State
- •Border:
colors.borderDefault(#555555) - •Text:
colors.textMuted(#999999) - •No special indicators
2. Focused State
- •Border:
colors.borderFocused(#CC8844) - •Text:
colors.textMuted(#999999) - •Indicates current selection
3. Edit Mode State
- •Border:
colors.borderEdit(#BB7733) - •Text:
colors.textActive(#FFFFFF) - •Indicates active editing
Component Examples
Basic Input Component
import { colors, getBorderColor } from '../tokens';
interface InputProps {
value: string;
onChange: (value: string) => void;
focused: boolean;
editMode: boolean;
placeholder?: string;
}
export function Input({ value, onChange, focused, editMode, placeholder }: InputProps) {
const borderColor = getBorderColor(focused, editMode);
const textColor = getTextColor(editMode, !!value);
return (
<box
style={{
border: true,
borderColor,
paddingLeft: 1,
paddingRight: 1,
}}
>
<text fg={textColor}>{value || placeholder}</text>
</box>
);
}
Tabbed Panel
import { colors } from '../tokens';
interface TabbedPanelProps {
focused: boolean;
editMode: boolean;
activeTab: string;
tabs: Array<{ name: string; label: string; color: string }>;
}
export function TabbedPanel({ focused, editMode, activeTab, tabs }: TabbedPanelProps) {
const borderColor = getBorderColor(focused, editMode);
return (
<box
style={{
flexDirection: 'column',
border: true,
borderColor,
paddingLeft: 1,
paddingRight: 1,
}}
>
{/* Tab header */}
<box style={{ flexDirection: 'row', gap: 1 }}>
{tabs.map((tab) => (
<text key={tab.name} fg={activeTab === tab.name ? tab.color : colors.textPlaceholder}>
{tab.label}
</text>
))}
</box>
{/* Tab content */}
<box style={{ flexGrow: 1 }}>
{/* Content here */}
</box>
</box>
);
}
Best Practices
- •
Always import from tokens: Never hardcode colors directly
typescript// Good import { colors } from '../tokens'; const color = colors.primary; // Bad const color = '#CC8844'; - •
Use helper functions: Leverage
getBorderColorandgetTextColortypescript// Good const borderColor = getBorderColor(focused, editMode); // Bad const borderColor = focused ? '#CC8844' : editMode ? '#BB7733' : '#555555';
- •
Consistent padding: Use padding values of 1 or 2 for consistency
typescriptpaddingLeft: 1, paddingRight: 1,
- •
Gap for spacing: Use
gap: 1for spacing between flex childrentypescriptstyle={{ flexDirection: 'row', gap: 1 }} - •
Black background for root: Main app container uses
blackbackgroundtypescriptbackgroundColor: 'black'
- •
Focus indication: Always show clear focus states with primary color border
- •
Edit mode distinction: Edit mode uses secondary color to differentiate from focus
Color Accessibility
The RestMan color scheme follows these principles:
- •High contrast: White text (
#FFFFFF) on dark backgrounds - •Muted for read-only: Gray text (
#999999) reduces visual weight - •Clear focus: Orange borders (
#CC8844) stand out against gray defaults - •Distinct edit state: Brown-orange (
#BB7733) distinguishes edit from focus
Testing Theme Changes
When modifying the theme:
- •Check
src/tokens.tsfor color definitions - •Update helper functions if adding new states
- •Test across all component types:
- •Input fields (TextInput, URLInput, MethodInput)
- •Panels (RequestEditor, ResponseViewer)
- •Modals (all modal components)
- •Toast notifications
- •Verify focus states with keyboard navigation (Tab, Shift+Tab)
- •Test edit mode activation (press 'e' on focused fields)
- •Ensure consistent appearance across light/dark terminals
Common Pitfalls
- •Hardcoding colors: Always import from tokens
- •Inconsistent borders: Use
getBorderColorhelper - •Wrong text colors: Use
getTextColorhelper - •Missing focus indicators: Always show visual feedback for focused elements
- •Confusing states: Edit and focus states should be visually distinct
Reference Files
- •Design tokens:
src/tokens.ts - •Example components:
src/components/TextInput.tsx,src/components/RequestEditor.tsx - •Main app styling:
src/App.tsx