constellation-analyzer/src/components/Nodes/Shapes/PillShape.tsx
Jan-Henrik Bruhn e0784ff3d8 feat: add node shape variants with five distinct shapes
Implements configurable shape variants for actor nodes, allowing visual
differentiation of node types beyond just color.

Features:
- Five shape options: rectangle, circle, rounded rectangle, ellipse, pill
- All shapes use pure CSS (border-radius) for consistent behavior
- Auto-grow with content
- Perfect shadow and selection/highlight effects
- Proper React Flow handle alignment
- Shape selector UI with visual previews
- Migration logic for existing documents (defaults to rectangle)

Shape characteristics:
- Rectangle: Standard, general purpose
- Circle: Round, for people and concepts
- Rounded Rectangle: Soft edges, friendly appearance
- Ellipse: Oval/horizontal, for processes and stages
- Pill: Capsule, compact for tags and labels

Technical approach:
- Uses border-radius for all shapes (no clip-path)
- Ensures boxShadow follows shape contours properly
- Each shape component maintains consistent props interface
- NodeShapeRenderer routes to appropriate shape component

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 15:34:24 +02:00

53 lines
1.4 KiB
TypeScript

import { ReactNode } from 'react';
interface PillShapeProps {
color: string;
borderColor: string;
textColor: string;
selected?: boolean;
isHighlighted?: boolean;
children: ReactNode;
className?: string;
}
/**
* PillShape - Capsule/pill node shape
*
* Best for: Tags, labels, flow elements, actions
* Characteristics: Fully rounded ends, compact, modern look
* Handles: Positioned at cardinal points (top, right, bottom, left) of bounding box
*/
const PillShape = ({
color,
borderColor,
textColor,
selected = false,
isHighlighted = false,
children,
className = '',
}: PillShapeProps) => {
const shadowStyle = selected
? `0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1), 0 0 0 3px ${color}40`
: isHighlighted
? `0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1), 0 0 0 3px ${color}80, 0 0 12px ${color}60`
: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)';
return (
<div
className={`px-6 py-3 min-w-[120px] flex items-center justify-center transition-shadow duration-200 ${className}`}
style={{
backgroundColor: color,
borderWidth: '3px',
borderStyle: 'solid',
borderColor: borderColor,
color: textColor,
borderRadius: '999px',
boxShadow: shadowStyle,
}}
>
{children}
</div>
);
};
export default PillShape;