Appearance
Button Components Analysis
These just cropped up, ad-hoc, at the beginning of the project. Might give it a sanity check.
Table of Contents
Overview
Webseriously uses a hierarchy of button components, from a base Button component to specialized variants. All buttons use S_Element for state management and support SVG icons through a centralized path generation system.
Component Hierarchy
Base Component: Button.svelte
The foundation for all button types. Handles:
- State Management: Uses
S_Element(s_button) for persistent state (hover, grab, disabled, inverted, editing) - Mouse Handling: Supports multiple detection modes (none, single, double, long, autorepeat)
- Styling: Computes styles reactively from
s_buttonproperties (fill, stroke, cursor) - Layout: Supports both
originandcenterpositioning with left/right alignment
Key Props:
s_button: S_Element- State object (owns stroke, fill, cursor)handle_s_mouse: (s_mouse: S_Mouse) => boolean- Click handlermouse_detection: T_Mouse_Detection- Detection modecenter | origin: Point- Positionheight, width, font_size- Dimensionsborder_thickness, border_color- Border styling
Slot Content: Text or SVG icons (rendered as children)
Specialized Variants
1. Triangle_Button.svelte
Wraps Button with triangle SVG icon.
Features:
- Uses
SVG_D3component for rendering - Supports optional
extraPathfor nested shapes hover_closurecallback for dynamic color changes- Reactive path generation based on
sizeandangle
SVG Flow:
angle → svgPaths.fat_polygon(size, angle) → trianglePath → SVG_D32. Glow_Button.svelte
Standalone button with gradient background and optional icon.
Features:
- Uses
SVG_Gradientfor background glow effect - Icon lookup via
svgPaths.fat_polygon_path_for(title) - Supports autorepeat detection
- Inline SVG rendering (not using SVG_D3)
SVG Flow:
title → svgPaths.fat_polygon_path_for(title) → icon_path → inline <svg>3. Breadcrumb_Button.svelte
Text-only button for breadcrumb navigation.
Features:
- Wraps base
Buttonwith breadcrumb-specific styling - No SVG icons (text-only)
- Reactive color updates based on grab/hover state
4. Buttons_Row.svelte
Container for horizontal button arrays.
Features:
- Optional row title (with or without separator)
- Generates
S_Elementinstances per button column - Uses
G_Repeaterfor layout calculations - Conditional SVG rendering via
has_svgprop
SVG Flow:
title → svgPaths.fat_polygon_path_for(title, svg_size) → inline <svg> in slot5. Buttons_Table.svelte
Container for multiple Buttons_Row instances.
Features:
- Manages rows of buttons
- Delegates to
Buttons_Rowfor each row - Visibility control via closure
6. Next_Previous.svelte
Specialized pair of buttons with custom SVG support.
Features:
- Two buttons (previous/next) with triangle arrows
- Supports
custom_svgPathsfor override (e.g., dash/cross for zoom) - Autorepeat enabled by default
- Custom transform/color logic for different icon types
SVG Flow:
title → get_path_for(title, index) → {
custom_svgPaths? → custom path + fat_polygon
default → svgPaths.fat_polygon_path_for(title, size)
} → inline <svg>SVG Configuration Data Flow
Path Generation System
All SVG paths flow through svgPaths utility (SVG_Paths.ts):
1. Name-Based Lookup (fat_polygon_path_for)
Button Title/Name → Angle.angle_from_name(name) → fat_polygon(size, angle) → SVG path stringUsed by:
Buttons_Row:svgPaths.fat_polygon_path_for(title, svg_size)Glow_Button:svgPaths.fat_polygon_path_for(title)Next_Previous:svgPaths.fat_polygon_path_for(String(title), size)
Angle Names: Maps string names (e.g., "up", "down", "left", "right") to angles via Angle.angle_from_name()
2. Direct Angle (fat_polygon)
size + angle → fat_polygon(size, angle) → SVG path stringUsed by:
Triangle_Button:svgPaths.fat_polygon(size, angle)Widget_Reveal:svgPaths.fat_polygon(k.height.dot, direction_ofReveal)
Parameters:
size: number- Icon sizeangle: number- Rotation angle in radiansonCenter: boolean- Center offset (default false)vertices: number- Polygon vertices (default 3 for triangles)
3. Custom Paths
Some components accept custom SVG paths directly:
Next_Previous:custom_svgPaths: { up?: string, down?: string }Primary_Controls: Custom dash/cross paths for zoom controls
Rendering Components
SVG_D3.svelte
Reusable SVG component used by Triangle_Button:
svgPath (string) → SVG_D3 → <svg><path d={svgPath}/></svg>Props:
svgPath: string- SVG path datastroke, fill- Colorswidth, height- DimensionsviewBox_width, left, top- Positioning
Inline SVG
Used by Buttons_Row, Glow_Button, Next_Previous:
path string → <svg><path d={path}/></svg>Complete Data Flow Example: Buttons_Row
1. Component receives: title="up", has_svg=true, svg_size=16
2. SVG Path Generation:
title → svgPaths.fat_polygon_path_for("up", 16)
→ Angle.angle_from_name("up") → angle (e.g., Math.PI/2)
→ svgPaths.fat_polygon(16, angle)
→ "M x,y C ... Z" (SVG path string)
3. Rendering:
<Button>
<svg class='svg-button-path-for-up'>
<path d={path_string} fill='white'/>
</svg>
</Button>
4. Button applies styling:
s_button.fill → background-color
s_button.stroke → color (text/SVG stroke)
s_button.cursor → cursor styleComplete Data Flow Example: Triangle_Button
1. Component receives: angle=Math.PI/2, size=24
2. SVG Path Generation:
angle + size → svgPaths.fat_polygon(24, Math.PI/2)
→ "M x,y C ... Z" (SVG path string)
3. State Updates:
$w_s_hover → isHovering → hover_closure(isHovering)
→ [fillColor, extraColor] (dynamic colors)
4. Rendering:
<Button>
<SVG_D3 svgPath={trianglePath} stroke={strokeColor} fill={fillColor}/>
{#if extraPath}
<SVG_D3 svgPath={extraPath} fill={extraColor}/>
{/if}
</Button>State Management
All buttons use S_Element for persistent state:
State Properties:
fill, stroke, cursor- Visual stylingisHovering, isGrabbed, isDisabled, isInverted, isEditing- State flagshandle_s_mouse- Mouse event handlermouse_detection- Detection modeautorepeat_callback, autorepeat_event- Autorepeat support
State Flow:
User Interaction → Hits.ts (centralized) → s_button.handle_s_mouse()
→ Component's handle_s_mouse prop → Business logic
→ s_button state update → Reactive style recomputationKey Patterns
1. Closure Pattern (Buttons_Row, Buttons_Table)
Buttons use closure functions for configuration:
typescript
closure: (t_request: T_Request, s_mouse: S_Mouse, column: number) => booleanHandles:
T_Request.handle_click- Click actionT_Request.is_disabled- Disabled stateT_Request.is_inverted- Inverted stateT_Request.name- Button name
2. Reactive Style Updates
All buttons recompute styles reactively:
svelte
$: {
const _ = `${$w_background_color}:::${$w_s_hover?.id}:::${s_button.fill}`;
recompute_style();
}3. SVG Conditional Rendering
Buttons conditionally render SVG vs text:
svelte
{#if has_svg && !!svgPaths.fat_polygon_path_for(title)}
<svg><path d={svgPath}/></svg>
{:else}
{title}
{/if}Reference
- Base:
src/lib/svelte/mouse/Button.svelte - Variants:
Triangle_Button,Glow_Button,Breadcrumb_Button,Buttons_Row,Buttons_Table,Next_Previous - SVG Utilities:
src/lib/ts/utilities/SVG_Paths.ts - Angle Mapping:
src/lib/ts/types/Angle.ts(angle_from_name) - State Objects:
src/lib/ts/state/S_Element.ts