.claude/skills/arwes-react/SKILL.md
Working with @arwes/react (1.0.0-next) sci-fi UI framework — frame components, Animator lifecycle, SVG styling, bleeps, and effects. Use this skill whenever modifying Arwes components, debugging invisible frames, styling frame SVGs, or adding new sci-fi UI elements. Also use when you see imports from @arwes/react or the arwes-compat.tsx compatibility layer.
npx skillsauth add starwards/starwards arwes-reactInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill covers the @arwes/react framework as used in Starwards, including hard-won debugging
lessons from actual development. The installed version is 1.0.0-next.25020502.
Not compatible with: React Strict Mode, React Server Components.
Starwards wraps raw Arwes components in modules/browser/src/components/arwes-compat.tsx. This
provides an alpha.19-style API (Button, Card, FrameCorners, Text, etc.) on top of the 1.0.0-next
primitives. Always check arwes-compat.tsx before modifying UI components.
Colors come from modules/browser/src/colors.ts (the HSL palette system). The theme object
in arwes-compat.tsx references hsl.primary, hsl.secondary, etc.
10 frame components available, all wrapping FrameBase:
| Component | Shape | Key Props |
|-----------|-------|-----------|
| FrameCorners | Corner brackets | cornerLength, strokeWidth |
| FrameOctagon | Clipped corners | squareSize, leftTop/rightTop/rightBottom/leftBottom |
| FrameNefrex | Asymmetric angled cuts + lines | squareSize, smallLineLength, largeLineLength |
| FrameKranox | Complex corner blocks | squareSize, bgStrokeWidth |
| FrameNero | Decorative corner blocks | cornerLength, cornerWidth |
| FrameLines | Horizontal/vertical lines | largeLineWidth, smallLineWidth |
| FrameHeader | Header decoration | direction, align, contentLength |
| FrameUnderline | Bottom underline | squareSize |
| FrameCircle | Circular with rotating deco | separation, sideWidth |
All frames share: styled, animated, padding, strokeWidth, elementRef, className.
The SVG element rendered by FrameBase gets class arwes-frames-frame plus a component-specific
class like arwes-frames-frameoctagon.
The class arwes-react-frames-framesvg does NOT exist. This was a phantom class name that
appeared in early code but never matched anything. If you see it in CSS selectors, it's broken.
Correct CSS targeting pattern:
/* Target frame SVG elements */
.my-wrapper .arwes-frames-frame [data-name=bg] { fill: ...; }
.my-wrapper .arwes-frames-frame [data-name=line] { stroke: ...; }
.my-wrapper .arwes-frames-frame [data-name=deco] { ... }
Frame SVGs contain elements with these data-name values:
bg — Background fill pathline — Border stroke paths (inside a <g> group)deco — Decorative flourishes (not all frames have these)styled PropControls whether Arwes applies its own inline styles via CSS variables.
styled={true} (default):
bg: fill: var(--arwes-frames-bg-color, currentcolor)
line: stroke: var(--arwes-frames-line-color, currentcolor); fill: none
deco: color: var(--arwes-frames-deco-color, currentcolor)
Frames inherit color from parent via currentcolor. This is the safe default — frames are always
visible as long as the parent has a non-black color.
styled={false}:
All inline styles become undefined. SVG elements get browser defaults: fill: black; stroke: none.
On a dark background, this means invisible frames.
styled={false}Only use it when you need full CSS control AND you have correct selectors targeting
arwes-frames-frame. Always verify frames are visible after switching to styled={false}.
If you just need to change colors, prefer keeping styled={true} and setting CSS variables:
.my-component {
--arwes-frames-bg-color: rgba(0, 255, 255, 0.1);
--arwes-frames-line-color: hsl(180, 100%, 37%);
}
animated PropControls entry/exit animations on frame elements.
animated={true} (default): bg fades in, lines draw in (stroke-dasharray), decos fade inanimated={false}: Frame appears instantly, no animationanimated={true}, the frame needs an Animator context to trigger animationsAnimation types used internally:
['fade'] — Opacity transition['draw'] — SVG stroke-dasharray draw effectFrames MUST be inside an <Animator> component for proper rendering. FrameBase calls
useAnimator() internally and the useEffect that calls createFrame() depends on the animator
reference.
// CORRECT
<Animator>
<FrameOctagon strokeWidth={2} squareSize={10} />
</Animator>
// BROKEN - frame may not render or animate
<FrameOctagon strokeWidth={2} squareSize={10} />
The parent element must have position: relative so the absolutely-positioned SVG frame fills it.
Optional hook for coordinated assembly animations. Subscribes to Animator state and triggers synchronized enter/exit across all frame sub-elements (bg, lines, decos staggered).
const frameRef = useRef<SVGSVGElement>(null);
useFrameAssembler(frameRef);
// ...
<FrameOctagon elementRef={frameRef} ... />
Requires Animator context. Without it, the hook early-returns and does nothing.
When a frame doesn't render, check in this order:
<Animator> wrapper? FrameBase needs animator context.styled={false}? If yes, are CSS selectors using the correct class arwes-frames-frame?position: absolute; inset: 0 — parent needs
position: relative and non-zero width/height. createFrame skips draw if width/height <= 0.styled={true}, frames use currentcolor. Check the parent's
color property. With custom CSS, check lightness values against the background.<svg class="arwes-frames-frame ..."> element. If it
exists but has no child paths, the createFrame render didn't run. If paths exist but are
invisible, it's a styling issue.The compiled source is readable. Key paths in node_modules/@arwes/:
react-frames/build/esm/FrameBase/FrameBase.js — SVG rendering, class names
react-frames/build/esm/Frame*/Frame*.js — Component props → settings
frames/build/esm/createFrame*/create*.js — SVG element definitions, styled/animated logic
frames/build/esm/createFrame/createFrame.js — render/draw/transition lifecycle
frames/build/esm/internal/renderFrameElements.js — data-name attributes, DOM creation
react-frames/build/esm/useFrameAssembler/ — Assembly animation hook
When documentation is unclear or missing, read the settings factory (e.g.,
createFrameOctagonSettings.js) to see exactly what SVG elements are created, what styles they
get, and what data-name values they use.
Mouse-follow glow effect. Renders a <div> with class arwes-frames-illuminator.
<Illuminator color="hsla(180, 100%, 26%, 0.1)" size={400} style={{ position: 'absolute', inset: 0 }} />
Use clipPath (e.g., styleFrameClipOctagon()) to constrain the glow to the frame shape.
Plays sounds on Animator state transitions. Renders nothing (null).
<BleepsOnAnimator transitions={{ entering: 'intro' }} continuous />
Animated text with character-by-character reveal. Wraps content in specified element.
<ArwesText as="h2" style={{ ... }}>{title}</ArwesText>
Sets default animation durations for all nested Animators. Durations are in seconds (not ms).
<ArwesAnimatorGeneralProvider duration={{ enter: 0.2, exit: 0.2, stagger: 0.04 }}>
Provides sound effects. Maps player names to audio sources, bleeps to players.
<div className="my-panel" style={{ position: 'relative', padding: '16px' }}>
<style>{`
.my-panel .arwes-frames-frame [data-name=bg] {
fill: hsla(180, 100%, 26%, 0.25);
}
.my-panel .arwes-frames-frame [data-name=line] {
stroke: hsl(180, 100%, 37%);
fill: none;
stroke-width: 2;
}
`}</style>
<Animator>
<FrameOctagon strokeWidth={2} styled={false} />
</Animator>
{children}
</div>
<div style={{
position: 'relative',
'--arwes-frames-line-color': 'hsl(180, 100%, 37%)',
'--arwes-frames-bg-color': 'hsla(180, 100%, 26%, 0.1)',
} as CSSProperties}>
<Animator>
<FrameCorners strokeWidth={2} />
</Animator>
{children}
</div>
Target the wrapper's hover state, not the frame itself:
.my-wrapper:hover .arwes-frames-frame [data-name=line] {
stroke: hsl(180, 100%, 84%);
filter: drop-shadow(0 0 4px hsl(180, 100%, 53%));
}
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.
development
End-to-end Parallels smoke, upgrade, and rerun workflow for OpenClaw across macOS, Windows, and Linux guests. Use when Codex needs to run, rerun, debug, or interpret VM-based install, onboarding, gateway smoke tests, latest-release-to-main upgrade checks, fresh snapshot retests, or optional Discord roundtrip verification under Parallels.