# Orbit CSS Framework — Complete LLM Reference
> Orbit builds radial and circular interfaces with CSS geometry and a small JavaScript runtime.
> CSS trigonometry and custom properties position elements; JavaScript maintains ring indices, spacing and SVG paths as layouts change.
> Package: @zumer/orbit | Version: 1.4.12 (current source build; see /orbit-docs/orbit/manifest.json) | License: MIT
> Docs: https://zumerlab.github.io/orbit-docs | Repo: https://github.com/zumerlab/orbit
---
## TABLE OF CONTENTS
1. Installation
2. Core Concept — How Orbit Works Internally
3. Mandatory HTML Structure
4. Structural Elements Reference
5. CSS Custom Properties Reference
6. How Angle Auto-Distribution Works (Runtime and CSS Fallback)
7. How Positioning Works (The Trigonometric Transform System)
8. Orbit Diameter Calculation
9. Utility Classes Reference
10. Web Components Reference
11. Color System
12. Themes
13. Responsive Sizing
14. Validation & Warning System
15. Nesting (Sub-orbits)
16. Common Patterns (Copy-Paste Recipes)
17. Advanced Real-World Examples
18. Framework Integrations (React, Vue, Svelte, Angular)
19. Critical Rules & Common LLM Mistakes
20. Quick Reference Card
---
## 1. INSTALLATION
### Matching site build (recommended for these examples)
```html
```
### npm
```bash
npm install @zumer/orbit
```
```js
import '@zumer/orbit/style' // CSS
import '@zumer/orbit' // Browser entrypoint: registers web components and layout runtime
```
### What the JS file does
- Registers `` custom element (SVG arc/wedge/sector segments)
- Registers `` custom element (SVG progress rings)
- Maintains ring numbering, child spacing and SVG geometry after DOM, ancestor style and size changes, batched in an animation frame
- Exposes `window.Orbit.resize(selectorOrElement)`, returning a cleanup function, and `Orbit.refresh(root)` for immediate layout updates
- The ES module exports `Orbit`, `OrbitArc`, `OrbitProgress` and `registerOrbit`; SSR imports are safe, but the module must also run in the browser
- A CSS-only fallback can position simple CSS elements (up to 24 levels / 60 children per type); arcs and progress require JavaScript
The site build contains runtime fixes that are not yet in the published npm 1.4.12 package. Use the matching site downloads to reproduce these examples. The manifest records the source commit and SHA-256 hashes; a package version alone does not identify this build.
### Alternative CSS Import
```css
@import url('https://zumerlab.github.io/orbit-docs/orbit/orbit.min.css');
```
---
## 2. CORE CONCEPT — HOW ORBIT WORKS INTERNALLY
Orbit uses a **solar-system metaphor**:
- **Big Bang** (.bigbang) = the universe container
- **Gravity Spot** (.gravity-spot) = the center of gravity, origin point
- **Orbits** (.orbit-N) = concentric circular rings at increasing radii
- **Satellites** (.satellite) = items placed on rings
- **Capsules** (.capsule) = content wrappers that counter-rotate to keep content upright
- **Gravitational Force** (--o-force) = the base diameter controlling the system size
### How positioning works at a high level:
1. `.gravity-spot` defines a zero-width center point
2. `.orbit-N` creates an absolutely-positioned circular container with diameter proportional to N
3. `.satellite` children are positioned using CSS `cos()` and `sin()` transforms
4. The runtime counts children, tracks ring levels and updates private layout properties
5. It divides the range (default 360°) by the count to get the angle between items
6. Each satellite's position = `from_angle + (angle × child_index)`
7. `.capsule` applies a counter-rotation so text stays upright regardless of satellite position
### Key insight for LLMs:
You do NOT need to calculate angles, positions, or transforms manually. Just add satellites to an orbit and they auto-distribute. The framework handles all trigonometry via CSS.
---
## 3. MANDATORY HTML STRUCTURE
Every Orbit layout MUST follow this exact nesting hierarchy:
```
.bigbang
└── .gravity-spot
├── .orbit-N (ring 1)
│ ├── .satellite
│ │ └── .capsule ← user content goes here
│ ├── .satellite
│ │ └── .capsule
│ ├── ← directly in orbit, NOT in satellite
│ ├── ← directly in orbit, NOT in satellite
│ ├── .vector ← directly in orbit, NOT in satellite
│ └── .side ← directly in orbit, NOT in satellite
├── .orbit-M (ring 2)
│ └── ...
└── .gravity-spot ← nested gravity-spot is allowed for sub-orbits
```
### Rules:
- `.bigbang` must contain ONLY `.gravity-spot` children
- `.gravity-spot` must contain ONLY `.orbit-N`, `.orbit`, or `.gravity-spot` children
- `.orbit-N` must contain ONLY `.satellite`, ``, ``, `.vector`, or `.side` children
- `.satellite` must contain ONLY `.capsule` or `.gravity-spot` children
- `.capsule` contains your actual content (text, images, other HTML)
- Breaking these rules triggers built-in CSS validation warnings (red dotted borders + warning emoji)
### Minimal valid example:
```html
Item 1
Item 2
Item 3
```
This places 3 items evenly spaced (120° apart) on a circular ring at orbit level 3.
---
## 4. STRUCTURAL ELEMENTS REFERENCE
### .bigbang
- Root container for any Orbit layout
- CSS: `display: flex; align-items: center; justify-content: center; width: 100%; height: 100%`
- When direct child of ``: automatically gets `height: 100vh`
- When child of a wrapper element: takes parent height
- Default alignment: centered (`.at-center`)
- Can use alignment classes: `.at-top`, `.at-bottom`, `.at-center-left`, `.at-center-right`, `.at-top-left`, `.at-top-right`, `.at-bottom-left`, `.at-bottom-right`
- Can be sized with a wrapper: `
...
`
### .gravity-spot
- The center point / origin of the coordinate system
- Has `width: 0; aspect-ratio: 1; position: relative`
- Holds all the CSS custom properties with their defaults
- All orbit calculations reference this element's variables
- Default size controlled by `--o-force: 500px`
- Can be nested within `.satellite` for sub-orbits
- Uses `container-name: gravityspot` for CSS container queries
- Alignment classes: `.at-center` (default), `.at-top`, `.at-bottom`, `.at-center-left`, `.at-center-right`, etc.
### .orbit-N (where N is a nonnegative integer)
- A ring at a specific radius level
- `.orbit-0` = center point (radius ≈ 0). Used for center content only.
- `.orbit-1` through `.orbit-12` = standard range (1 = smallest, 12 = 100% of --o-force)
- `.orbit-13` through `.orbit-24` = extended range (beyond --o-force, 108% to 200%)
- Invisible by default (transparent border). Customize with CSS border/background.
- CSS: `position: absolute; border-radius: 50%; pointer-events: none; container-name: orbit`
- Uses `container-name: orbit` for CSS container queries
**Approximate orbit sizes (relative to --o-force):**
- orbit-0: 0%, orbit-1: ~8%, orbit-2: ~17%, orbit-3: 25%, orbit-4: ~33%, orbit-5: ~42%
- orbit-6: 50%, orbit-7: ~58%, orbit-8: ~67%, orbit-9: 75%, orbit-10: ~83%, orbit-11: ~92%, orbit-12: 100%
- orbit-13 to orbit-24: 108% to 200% (beyond gravity-spot boundary)
### .orbit (without number)
- Auto-numbered based on DOM order among sibling `.orbit` elements
- First `.orbit` = orbit-1, second = orbit-2, etc. The runtime has no 24-level cap; 24 is the static CSS fallback limit.
- Can be mixed with numbered orbits, but numbered orbits are usually clearer
### .satellite
- An item placed on a ring (the runtime supports more than 60 per orbit)
- Positioned using CSS `transform: translate(cos(...), sin(...))`
- Size is calculated relative to the orbit: `radius / (orbit_number + initial_orbit) * size_ratio`
- CSS: `position: absolute; border-radius: 50%; pointer-events: all; container-name: satellite`
- Default appearance: transparent background, 1px solid currentColor border
- Auto-distributed evenly around the orbit
### .capsule
- Content wrapper inside `.satellite` (or `.side`)
- Applies counter-rotation so content stays upright (readable)
- CSS: `display: flex; position: absolute; align-items: center; justify-content: center`
- Put ALL your visible content here: text, icons, images, etc.
- Initially invisible (no border/background). Customize with CSS.
- Alignment within satellite: `.top-left`, `.top-center`, `.top-right`, `.center-left`, `.center-right`, `.bottom-left`, `.bottom-center`, `.bottom-right`
### .vector
- Tick mark / radial line placed on an orbit (the runtime supports more than 60 per orbit)
- Goes directly inside `.orbit-N` (not inside `.satellite`)
- Automatically rotated to point outward from center
- Height: 1px by default. Use CSS height/background to style. Use `!important` for overrides.
- Multiple vectors are auto-distributed like satellites
- Container name: `vector`
### .side
- Chord/tangent element that stretches between points on an orbit (the runtime supports more than 60 per orbit)
- Goes directly inside `.orbit-N` (not inside `.satellite`)
- Width calculated using trigonometry: `radius * cos(90deg - angle/2) * 2`
- Creates polygon shapes when multiple sides are used (e.g., 6 sides = hexagon)
- Can contain `.capsule` for text content
- `.side.outer-orbit` variant stretches to the outer edge
- Container name: `side`
---
## 5. CSS CUSTOM PROPERTIES REFERENCE
All properties are set on `.gravity-spot` by default. They can be overridden on individual `.orbit-N` or child elements.
### Layout Properties
| Property | Default | Type | Description |
|---|---|---|---|
| `--o-force` | `500px` | length | Base diameter of the entire system. All ring sizes are fractions of this. Use a length such as px, rem or cqw, not a percentage against the zero-width center. |
| `--o-force-ratio` | `1` | number | Multiplier for responsive scaling. Set by `Orbit.resize()`. |
| `--o-from` | `0deg` | angle | Starting angle offset. 0deg = top (12 o'clock position). |
| `--o-range` | `360deg` | angle | Total arc span. 360 = full circle, 180 = semicircle, 270 = three-quarter. |
| `--o-direction` | `1` | 1 or -1 | 1 = clockwise, -1 = counter-clockwise. |
| `--o-fit-range` | `0` | 0 or 1 | 0 = items can overlap at start/end; 1 = items distributed within range without overlap. |
| `--o-ellipse-x` | `1` | number | Horizontal compression ratio. >1 compresses width. |
| `--o-ellipse-y` | `1` | number | Vertical compression ratio. >1 compresses height. |
| `--o-initial-orbit` | `0` | integer | Offset added to orbit numbering. Effectively increases total orbits and makes orbit-1 start at a larger radius. |
| `--o-size-ratio` | `1` | number | Multiplier for satellite/element sizes. |
| `--o-orbit-ratio` | `0` | 0 to 1 | Shrinks spacing between orbits. 0 = normal spacing, 1 = all orbits collapse to same size. |
| `--o-gap` | `1` | number | Gap between arc segments (for ``). |
| `--o-aligment` | `0px` | length | Radial offset. Positive = inward (toward center), negative = outward. |
### Auto-calculated Properties (DO NOT set manually unless you know exactly what you're doing)
| Property | Description |
|---|---|
| `--o-orbit-number` | Set automatically by `.orbit-N` class or `:nth-child(N of .orbit)`. |
| `--o-orbit-child-number` | Set automatically per child via `:nth-child`. 0-indexed for satellites/arcs/vectors, starts at -1 for sides. |
| `--o-angle` | Defaults to runtime-provided spacing from child counts, or the static CSS fallback. Public overrides are supported. |
| `--o-angle-composite` | Computed final angle for positioning each child element. |
| `--o-diameter` | Computed diameter of the current orbit after shrink adjustments. |
| `--o-base-diameter` | Computed raw diameter before shrink: `(initial_orbit + orbit_number) * (force * force_ratio) / (12 + initial_orbit)`. |
| `--o-prev-diameter` | Diameter of the previous orbit (for shrink calculations). |
| `--o-radius` | Computed radius (diameter / 2). |
| `--o-transform` | The computed translate(cos, sin) transform for positioning. |
### Styling Properties (for Web Components)
| Property | Used by | Default | Description |
|---|---|---|---|
| `--o-fill` | ``, `` | `var(--o-gray-light)` | Fill color of the shape |
| `--o-stroke` | ``, `` | `var(--o-fill)` | Stroke color |
| `--o-stroke-width` | ``, `` | `1` | Stroke width |
| `--o-back-fill` | `` | `transparent` | Background track fill |
| `--o-back-stroke` | `` | `none` | Background track stroke |
| `--o-back-stroke-width` | `` | `1` | Background track stroke width |
| `--o-color` | `` | `currentcolor` | Text color (for arc text) |
---
## 6. HOW ANGLE AUTO-DISTRIBUTION WORKS (RUNTIME AND CSS FALLBACK)
The runtime discovers exact `.orbit` and `.orbit-N` class tokens within gravity spots. Application classes such as `orbit-card` are not rings. It maintains `data-orbit-ring`, `--o-layout-number`, `--o-layout-index` and `--o-layout-angle` as private defaults for CSS geometry.
Children are counted by type. The largest arc, satellite or vector group determines the common spacing; sides use their own count to close a polygon. `fit-range` subtracts an endpoint from the normal divisor. The runtime handles additions, removals and reordering, including more than 24 levels and 60 children per type.
Use public properties such as `--o-angle`, `--o-orbit-number` and `--o-orbit-child-number` to override defaults. Never write the private runtime fields. Arcs with a `value` auto-stack through a private `--o-arc-start`; `value="0"` is an empty segment, not a missing value.
A generated `:has()` / `:nth-child(... of ...)` CSS fallback supports simple layouts up to 24 levels and 60 children per type. That fallback does not render custom-element SVGs.
The final angle combines the starting angle, child index, direction and the 270° offset that makes `from-0` point to 12 o'clock. CSS performs the trigonometry; application code does not need to calculate positions manually.
---
## 7. HOW POSITIONING WORKS (THE TRIGONOMETRIC TRANSFORM SYSTEM)
### Satellite positioning:
```css
.satellite {
--o-angle-composite: (var(--o-angle) * var(--o-orbit-child-number) + 270deg) * var(--o-direction);
--o-transform: translate(
calc((var(--o-radius) - var(--o-aligment)) / var(--o-ellipse-x) * cos(var(--o-from) + var(--o-angle-composite))),
calc((var(--o-radius) - var(--o-aligment)) / var(--o-ellipse-y) * sin(var(--o-from) + var(--o-angle-composite)))
);
transform: var(--o-transform);
}
```
### Vector positioning (includes rotation):
```css
.vector {
transform: translate(
calc((var(--o-radius) - var(--o-aligment)) / var(--o-ellipse-x) * cos(var(--o-from) + var(--o-angle-composite))),
calc((var(--o-radius) - var(--o-aligment)) / var(--o-ellipse-y) * sin(var(--o-from) + var(--o-angle-composite)))
) rotate(calc(var(--o-from) + var(--o-angle-composite)));
}
```
### Capsule counter-rotation:
```css
.capsule {
rotate: calc((var(--o-from) + var(--o-angle-composite)) * var(--o-direction) * -1);
}
```
This cancels out the satellite's angular position so content stays upright.
---
## 8. ORBIT DIAMETER CALCULATION
The diameter of each orbit ring is calculated as:
```
base_diameter = (initial_orbit + orbit_number) × (force × force_ratio) / (12 + initial_orbit)
```
Where:
- `initial_orbit` = `--o-initial-orbit` (default 0)
- `orbit_number` = the N in `.orbit-N`
- `force` = `--o-force` (default 500px)
- `force_ratio` = `--o-force-ratio` (default 1)
Then shrinking is applied:
```
diameter = base_diameter - ((base_diameter - prev_diameter) × orbit_ratio)
```
Where `orbit_ratio` is set by `.shrink-N` on the orbit (0 = no shrink, 1 = full shrink to previous orbit size).
---
## 9. UTILITY CLASSES REFERENCE
### Positioning (apply to .orbit-N, .satellite, .bigbang, or .gravity-spot)
| Class | Effect |
|---|---|
| `.at-top-left` | Top-left corner |
| `.at-top` | Top center |
| `.at-top-right` | Top-right corner |
| `.at-center-left` | Center-left |
| `.at-center` | Dead center (used for center content in orbit-0) |
| `.at-center-right` | Center-right |
| `.at-bottom-left` | Bottom-left |
| `.at-bottom` | Bottom center |
| `.at-bottom-right` | Bottom-right |
### Range & Angle (apply to .orbit-N)
| Class pattern | Values | Effect |
|---|---|---|
| `.range-{0-360}` | 0 to 360 (step varies) | Sets `--o-range`. E.g., `.range-180` = semicircle. Available: 0,45,90,135,180,225,270,315,360. |
| `.from-{0-360}` | 0 to 360 (step varies) | Sets `--o-from`. Starting angle. E.g., `.from-180` = start from bottom. |
| `.angle-{0-360}` | 0 to 360 | Sets fixed angle for a specific element. Overrides auto-calculation. For regular elements: resets --o-from to 0. For o-arc/o-progress: does NOT reset --o-from. |
| `.fit-range` | — | Sets `--o-fit-range: 1`. Distributes items across range without overlap at boundaries. |
| `.ccw` | — | Counter-clockwise direction (`--o-direction: -1`). |
| `.cw` | — | Clockwise direction (`--o-direction: 1`). Default. |
**Important angle reference:**
- `from-0` = 12 o'clock (top), items go clockwise
- `from-90` = 3 o'clock (right)
- `from-180` = 6 o'clock (bottom)
- `from-270` = 9 o'clock (left)
### Initial Orbit (apply to .gravity-spot)
| Class | Effect |
|---|---|
| `.from-1x` to `.from-12x` | Sets `--o-initial-orbit` to N. Makes orbit-1 start at a larger radius. |
### Orbit Shrink (apply to .orbit-N)
| Class | Effect |
|---|---|
| `.shrink-0` to `.shrink-100` (step 5) | On `.orbit-N`: sets `--o-orbit-ratio`. Reduces spacing between this orbit and the previous one. `.shrink-0` = normal, `.shrink-100` = fully collapsed to previous orbit. |
### Element Size (apply to .satellite, .vector, o-arc, o-progress)
| Class | Effect |
|---|---|
| `.shrink-0` to `.shrink-100` (step 5) | On elements: sets `--o-size-ratio` to `1 - N/100`. Reduces element size. |
| `.grow-0.1x` to `.grow-0.9x` | Slightly increase size (multiplier: 1.1x to 1.9x) |
| `.grow-1x` to `.grow-12x` | Significantly increase size (multiplier: 2x to 24x+) |
**Note:** `.shrink-N` has dual behavior depending on context:
- On `.orbit-N`: reduces ring spacing (orbit-ratio)
- On other elements (.satellite, .vector, etc.): reduces element size (size-ratio)
- Cannot use `.shrink-*` and `.grow-*` together on the same element.
### Gap (apply to ``)
| Class | Effect |
|---|---|
| `.gap-0` to `.gap-30` | Sets `--o-gap` on ``. Controls spacing between arc segments. |
### Radial Alignment (apply to .satellite, .vector, or )
| Class | Effect |
|---|---|
| `.inner-orbit` | Shifts element inward (toward center) by half its size |
| `.quarter-inner-orbit` | Shifts slightly inward (by ~27% of its size) |
| `.quarter-outer-orbit` | Shifts slightly outward (by ~27% of its size) |
| `.outer-orbit` | Shifts element outward (away from center) by half its size |
### Capsule Modifiers (apply to .capsule)
| Class | Effect |
|---|---|
| `.flip` | Rotates capsule content 180° |
| `.turn-left` | Rotates capsule 90° left |
| `.turn-right` | Rotates capsule 90° right (270°) |
| `.horizontal` | Inside `.side > .capsule`: keeps text horizontal |
### Capsule Alignment (apply to .capsule)
| Class | Effect |
|---|---|
| `.top-left` | Align content to top-left |
| `.top-center` | Align content to top-center |
| `.top-right` | Align content to top-right |
| `.center-left` | Align content to center-left |
| `.center-right` | Align content to center-right |
| `.bottom-left` | Align content to bottom-left |
| `.bottom-center` | Align content to bottom-center |
| `.bottom-right` | Align content to bottom-right |
### Satellite Modifiers
| Class | Effect |
|---|---|
| `.spin-lock` | Keeps satellite rotation aligned with orbit (gyroscope effect — points toward center) |
| `.circle` | Forces circular shape (border-radius: 50%) — default |
| `.box` | Forces square shape (border-radius: 0) |
| `.rounded-box` | Rounded rectangle shape |
### Special Effects (apply to any container)
| Class | Effect |
|---|---|
| `.gooey-fx-light` | Light blob/gooey merge effect between nearby elements (stdDeviation: 2) |
| `.gooey-fx-medium` | Medium gooey effect (stdDeviation: 5) |
| `.gooey-fx-max` | Strong gooey effect (stdDeviation: 9) |
**Note:** Gooey effects do NOT work in Safari. They use inline SVG filters with `feGaussianBlur` + `feColorMatrix`.
---
## 10. WEB COMPONENTS REFERENCE
### — Arc / Wedge / Sector
Creates SVG arc segments. Used for: pie charts, donut charts, gauge needles, radial menus, curved text.
**Placement:** Directly inside `.orbit-N`. NEVER inside `.satellite`.
**HTML Attributes:**
| Attribute | Type | Default | Description |
|---|---|---|---|
| `value` | 0-100 | (none) | Percentage of the range this arc covers. When set, arcs auto-stack (donut mode). |
| `shape` | string | `none` | Shape variant. See shape table below. |
| `flip` | boolean | false | Flips the arc (reverses text direction along path). |
| `fit-range` | boolean | false | Stretches text to fill the entire arc path via SVG textLength. |
| `text-anchor` | start\|middle\|end | middle | Text alignment along the arc path. |
**Shape values:**
| Shape | Description |
|---|---|
| `none` (default) | Standard flat-edged arc segment |
| `rounded` | Arc with rounded corners (quadratic Bezier curves at ends) |
| `circle` / `circle-a` | Arc with circular end caps (both ends rounded outward) |
| `circle-b` | Arc with more pronounced circular end caps (segment × 1.36) |
| `bullet` | Arc with one rounded end, one flat end |
| `arrow` | Arrow/pointer shape (like a gauge needle, uses middle radius for tip) |
| `slash` | Slanted edge on one side (diagonal from bottom-left to top-right) |
| `backslash` | Slanted edge on the other side (diagonal from top-left to bottom-right) |
| `zigzag` | Zigzag pattern on the connecting edges (multiple zig-zag points) |
**CSS Custom Properties:**
| Property | Default | Description |
|---|---|---|
| `--o-fill` | `var(--o-gray-light)` | Fill color |
| `--o-stroke` | `var(--o-fill)` | Stroke color |
| `--o-stroke-width` | `1` | Stroke width |
| `--o-color` | `currentcolor` | Text color |
**Text along arc:**
```html
This text follows the arc path
```
Text renders along the curved SVG path. Font size scales with `--o-force`.
**Colored text on arc (no background):**
```html
Curved text here
```
**Text with background:**
```html
Text on purple arc
```
**Stacking / Donut chart (with value):**
When multiple `` elements have `value` attributes, they auto-stack end-to-end:
```html
```
Values are percentages of the parent range: sum to 100 for a complete ring or less for a partial ring. They are not normalized automatically. The runtime maintains cumulative offsets in private `--o-arc-start` / `--o_stack` fields. Add `interactive` to an arc or progress element when it needs to receive pointer events.
**Equal segments (without value):**
Without `value`, arcs auto-divide the range equally (just like satellites):
```html
```
This creates 3 equal segments of 120° each with gaps between them.
**How the SVG works internally:**
- Uses a 100×100 viewBox centered at (50,50)
- Arc points calculated with: `x = 50 + radius × cos(angle)`, `y = 50 + radius × sin(angle)`
- Inner and outer arcs create the ring segment
- Text path is a separate invisible arc between the two radii
- MutationObserver watches attributes and children for dynamic updates
---
### — Progress Ring
Creates SVG progress bars along an orbit ring, with a background track and a foreground bar.
**Placement:** Directly inside `.orbit-N`. NEVER inside `.satellite`. Maximum ONE per orbit.
**HTML Attributes:**
| Attribute | Type | Default | Description |
|---|---|---|---|
| `value` | number | 0 | Current progress value |
| `max` | number | 100 | Maximum value |
| `shape` | string | none | Same shapes as `` |
**CSS Custom Properties:**
| Property | Default | Description |
|---|---|---|
| `--o-fill` | `var(--o-gray-light)` | Progress bar fill |
| `--o-stroke` | `var(--o-fill)` | Progress bar stroke |
| `--o-stroke-width` | `1` | Progress bar stroke width |
| `--o-back-fill` | `transparent` | Background track fill |
| `--o-back-stroke` | `none` | Background track stroke |
| `--o-back-stroke-width` | `1` | Background track stroke width |
**Updating progress dynamically:**
```js
document.querySelector('o-progress').setAttribute('value', 75);
// The component uses MutationObserver and updates automatically
```
**How it works internally:**
- SVG with two `` elements: `.progress-bg` (full background track) and `.progress-bar` (progress arc)
- Background arc: always shows full range
- Progress arc angle: `(value / max) × range`
- Both paths use the same shape generator as ``
---
## 11. COLOR SYSTEM
### Base colors (CSS custom properties on :root)
| Variable | Color |
|---|---|
| `--o-red` | hsl(3, 100%, 61%) |
| `--o-orange` | hsl(36, 100%, 51%) |
| `--o-yellow` | hsl(49, 100%, 51%) |
| `--o-green` | hsl(129, 67%, 51%) |
| `--o-cyan` | hsl(197, 88%, 65%) |
| `--o-blue` | hsl(210, 100%, 51%) |
| `--o-indigo` | hsl(240, 73%, 63%) |
| `--o-purple` | hsl(279, 85%, 65%) |
| `--o-pink` | hsl(348, 100%, 60%) |
| `--o-gray` | hsl(240, 2%, 60%) |
### Color variants (available for each base color)
Generated using `color-mix()` in `oklab` color space:
| Variant | Mixing | Example |
|---|---|---|
| `-white` | 95% white | `--o-red-white` |
| `-lighter` | 75% white | `--o-red-lighter` |
| `-light` | 30% white | `--o-red-light` |
| `-dark` | 20% black | `--o-red-dark` |
| `-darker` | 40% black | `--o-red-darker` |
| `-black` | 78% black | `--o-red-black` |
### Dynamic color (set your own)
Set `--o-color` to any color, then use the auto-generated variants:
```css
.my-element {
--o-color: #ff6600;
background: var(--o-color-light);
border-color: var(--o-color-dark);
}
```
---
## 12. THEMES
Apply theme classes to `.bigbang`:
### Default theme (no class needed)
- Orbits: transparent borders
- Satellites: transparent background, 1px solid currentColor border
- Vectors/sides: currentColor background
- Arcs: gray-light fill
### .theme-cyan
- Satellites: cyan borders
- Vectors/sides: cyan background
- Arcs: cyan-light fill, cyan-lighter on hover
### .dev-orbit (debugging)
- All elements: red dashed borders
- Arcs: red-lighter fill at 50% opacity
- Use during development to see all orbit rings and element positions
- Example: `
...
`
---
## 13. RESPONSIVE SIZING
### Orbit.resize(selectorOrElement)
Makes Orbit layouts responsive by setting `--o-force-ratio = containerWidth / 500`. The default `--o-force` is 500px, so a 250px container gets a ratio of 0.5.
```js
const stopResizing = Orbit.resize(document.querySelector('.container'));
// Dispose when the container unmounts:
stopResizing();
```
Call after mounting the container. It accepts an element or selector, applies an initial ratio, then observes width changes with ResizeObserver. A repeated call for the same element disconnects the previous observer. Cleanup disconnects observation and leaves the last applied CSS ratio in place.
### Orbit.refresh(root)
`Orbit.refresh()` synchronously updates the document; pass an element or shadow root to scope it. DOM, ancestor attribute and resize changes are otherwise batched automatically. After CSSOM edits or state driven by an unrelated sibling/control, call `Orbit.refresh(chart)` explicitly. Orbit does not infer arbitrary selector dependencies across unrelated elements.
Arc and progress elements register layouts inside open or closed shadow roots. Include the stylesheet inside each root. For a root containing only CSS elements, call `Orbit.refresh(shadowRoot)` to register it. Detaching a shadow host releases its observers; reconnecting components restores them.
**Alternative: manual CSS**
```css
.gravity-spot {
--o-force: 300px; /* fixed smaller size */
}
```
**Resizable container example:**
```html
```
---
## 14. VALIDATION & WARNING SYSTEM
Orbit includes opt-in CSS validation for common structure mistakes. Add `dev-orbit` to `.bigbang` to enable dotted borders, dimming and warning icons. Warning animations respect reduced-motion preferences.
### Browser feature detection
Missing CSS `cos()` / `sin()` support shows an upgrade message. Missing `:has()` support disables the static fallback and visual diagnostics, but does not block the JavaScript runtime.
### Structure validation
- `.gravity-spot` accepts `.gravity-spot`, `.orbit` or an exact integer `.orbit-N` class.
- Orbits cannot be nested directly inside other orbits.
- `.satellite` accepts `.capsule` or `.gravity-spot` children.
**o-arc/o-progress in elliptical layouts:**
```css
/* Hides arc/progress when ellipse is active */
@container oslice not style(--o-ellipse-x: 1) {
o-arc, o-progress { display: none; }
}
```
---
## 15. NESTING (SUB-ORBITS)
To create nested radial systems (e.g., a planet with moons), create a new `.bigbang > .gravity-spot` inside a `.capsule`:
```html
Moon
```
**Alternative (simpler):** You can also place `.gravity-spot` directly inside `.satellite` (without `.capsule` wrapper):
```html
Moon
```
**Key:** Set a smaller `--o-force` on the inner `.gravity-spot` to control the sub-system size.
**IMPORTANT:** Never nest `.orbit-N` directly inside another `.orbit-N`. Always use the `.gravity-spot` nesting pattern.
---
## 16. COMMON PATTERNS (COPY-PASTE RECIPES)
### Pattern 1: Simple Progress Ring with Center Label
```html
```
### Pattern 3: Radial Menu (Equal Arc Segments with Text)
```html
HomeEditSaveDelete
MENU
```
### Pattern 4: Speedometer / Gauge with Needle
```html
125 km/h
```
### Pattern 5: Semicircle Gauge
```html
75%
```
Note: `from-180` starts from bottom, making the semicircle open upward. Use `aspect-ratio: 2/1` on .bigbang to clip the bottom half.
### Pattern 6: Multi-Ring Satellites
```html
A
B
C
D
E
F
G
H
Center
```
### Pattern 7: Compass
```html
N
E
S
W
000°
```
### Pattern 8: Nested Orbits (Planet with Moon)
```html
```
### Pattern 9: Radar / Concentric Ring Outlines
```html
SCAN
```
### Pattern 10: Knob Control
```html
65%
```
### Pattern 11: Polygon (Hexagon with Sides)
```html
```
6 sides = hexagon, 3 sides = triangle, 8 sides = octagon, etc.
---
## 17. ADVANCED REAL-WORLD EXAMPLES
### Knob with Progress Bar and Tick Marks
```html
```
---
## 18. FRAMEWORK INTEGRATIONS
These imports belong in client entrypoints. With server rendering, load the published package in the framework's browser mount lifecycle; the current site's downloadable ES module is SSR-safe.
### React
```jsx
import '@zumer/orbit/style';
import '@zumer/orbit';
function App() {
return (
A
B
C
);
}
```
Note for React: Use `className` on standard HTML elements; React 18 custom elements use the `class` attribute. Preserve CSS custom property names as quoted object keys, e.g. `style={{"--o-fill": "cyan"}}`.
### Vue
```vue
{{ item }}
```
Note for Vue: Configure `compilerOptions.isCustomElement` as `(tag) => ["o-arc", "o-progress"].includes(tag)` before mounting, or in the Vue compiler configuration when using single-file components.
### Svelte
```svelte
A
B
```
### Angular
In `angular.json`, add to `styles` and `scripts`:
```json
{
"styles": ["node_modules/@zumer/orbit/dist/orbit.css"],
"scripts": ["node_modules/@zumer/orbit/dist/orbit.js"]
}
```
In your module, add `CUSTOM_ELEMENTS_SCHEMA`:
```typescript
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
```
Then use in templates:
```html
{{ item }}
```
---
## 19. CRITICAL RULES & COMMON LLM MISTAKES
### MUST DO:
1. Always follow the hierarchy: `.bigbang > .gravity-spot > .orbit-N > .satellite > .capsule`
2. Put all visible content inside `.capsule`
3. Place ``, ``, `.vector`, `.side` directly in `.orbit-N`
4. Include both CSS and JS files for the current layout runtime and web components
5. Use `.orbit-0` with `.satellite.at-center` for center content
6. Use `.fit-range` when you want items evenly spaced without overlap at 0°/360°
### MUST NOT DO:
1. DO NOT put `` or `` inside `.satellite` — they go directly in `.orbit-N`
2. DO NOT nest `.orbit-N` inside another `.orbit-N` — create a new `.bigbang > .gravity-spot` inside `.capsule` instead
3. DO NOT put content directly in `.satellite` — always wrap in `.capsule`
4. DO NOT put anything other than `.gravity-spot` inside `.bigbang`
5. DO NOT put anything other than `.orbit-N`, `.orbit`, or `.gravity-spot` inside `.gravity-spot`
6. DO NOT use `` or `` in elliptical layouts (--o-ellipse-x or --o-ellipse-y ≠ 1) — they will be hidden
7. DO NOT write internal `--o-layout-*`, `--o-arc-start` or `data-orbit-ring` fields. Public properties such as `--o-angle` are supported overrides
8. DO NOT use `.from-N` (start angle) and `.angle-N` on the same regular element — `.angle-N` resets `--o-from` to 0 (exception: on ``/``, `.angle-N` does NOT reset `--o-from`)
9. DO NOT forget that `from-0` means top/12 o'clock, not right/3 o'clock
10. DO NOT use `transform` on `.satellite` directly — it will override the positioning transform
11. DO NOT use percentage values against the zero-width center for `--o-force`; use a CSS length such as `500px`, `30rem` or container-relative units
12. DO NOT use `.shrink-*` and `.grow-*` together on the same element
### COMMON MISTAKES LLMs MAKE:
- **Putting text directly in `.satellite`** instead of `.capsule` → text won't be upright
- **Creating classes that don't exist** (e.g., `.orbit-ring`, `.orbit-item`, `.orbit-center`) → use the exact class names from this reference
- **Forgetting `.at-center`** on the center satellite → it won't be centered
- **Using `transform` on `.satellite`** directly → will override the positioning transform. Style the `.capsule` or its children instead.
- **Nesting orbits inside orbits** → use the nested `.bigbang > .gravity-spot` pattern instead
- **Using `--o-radius` directly** → it's auto-calculated, don't set it
- **Placing `` inside `.satellite`** → arc won't render correctly
- **Using percentage values for `--o-force`** → use a CSS length, not a percentage against the zero-width center
- **Expecting `.orbit-0` to be a visible ring** → it's just a center point for placing centered content
- **Forgetting to include the JS file** → `` and `` won't work without it
- **Setting `value` on `` when wanting equal segments** → omit `value` for equal auto-distribution, use `value` only for donut/pie charts
---
## 20. QUICK REFERENCE CARD
```
Structure: .bigbang > .gravity-spot > .orbit-N > .satellite > .capsule
Center content: .orbit-0 > .satellite.at-center > .capsule
Arc segments: .orbit-N >
Equal arcs: .orbit-N > (no value = auto-divide)
Arc text: .orbit-N > text here
Progress ring: .orbit-N >
Tick marks: .orbit-N > .vector
Polygon sides: .orbit-N > .side (6 sides = hexagon)
Semicircle: .orbit-N.range-180.from-180
3/4 circle: .orbit-N.range-270.from-225
Even spacing: .orbit-N.fit-range
CCW: .orbit-N.ccw
Nested: .capsule > .bigbang > .gravity-spot (new --o-force)
Responsive: Orbit.resize('.parent')
Debug: .bigbang.dev-orbit
Angles: from-0=top, from-90=right, from-180=bottom, from-270=left
Sizing: .shrink-50 (half size), .grow-2x (triple size)
Shapes: .circle, .box, .rounded-box (on .satellite)
Arc shapes: none, rounded, circle, circle-b, bullet, arrow, slash, backslash, zigzag
Colors: --o-red, --o-orange, --o-yellow, --o-green, --o-cyan,
--o-blue, --o-indigo, --o-purple, --o-pink, --o-gray
Each with: -white, -lighter, -light, -dark, -darker, -black
```
---
## END OF REFERENCE
For interactive examples and live demos, visit: https://zumerlab.github.io/orbit-docs