All loaders

CSS / SVG · 3.6 KB gzip

Cyber Glitch

A fractured cyber frame with stepped displacement, scan-line motion, and chromatic pixel artifacts.

signaturecyberglitchpixeltechnology
Interactive preview

Usage

Download HTML

Packages are @vikast908/core and @vikast908/loaders. Prefer 0.1.1+ (0.1.0 loaders is broken on npm).

npm install @vikast908/loaders@0.1.1 @vikast908/core@0.1.1
import '@vikast908/loaders/cyber-glitch';

<orbux-cyber-glitch state="thinking"></orbux-cyber-glitch>

Browser-only alternative: Download HTML (self-contained) or load the hosted ESM bundle:

<script type="module" src="http://localhost:4321/orbux/cyber-glitch.js"></script>

<orbux-cyber-glitch state="thinking"></orbux-cyber-glitch>

Component source cyber-glitch.ts

import { OrbuxElement } from '@vikast908/core';

const STYLES = /* css */ `
:host { --_tone:var(--orbux-color,#22d3ee);--_tone-2:var(--orbux-color-2,#f43f5e);--_dur:1.15s; }
.glitch { position:relative;inline-size:100%;block-size:100%;display:grid;place-items:center;overflow:hidden; }
.frame { position:absolute;inset:18%;clip-path:polygon(14% 0,100% 0,100% 74%,84% 100%,0 100%,0 22%);background:linear-gradient(135deg,color-mix(in srgb,var(--_tone) 25%,transparent),transparent 48%,color-mix(in srgb,var(--_tone-2) 24%,transparent));border:2px solid var(--_tone);box-shadow:4px 0 0 color-mix(in srgb,var(--_tone-2) 75%,transparent),-3px 0 0 color-mix(in srgb,var(--_tone) 75%,transparent);animation:orbux-cyber-shift calc(var(--_dur) * var(--orbux-speed-scale)) steps(6,end) infinite; }
.frame::before { content:"";position:absolute;inset:12% 18%;background:repeating-linear-gradient(to bottom,var(--_tone) 0 2px,transparent 2px 8px);opacity:.68; }
.scan { position:absolute;inset:10% 8%;background:linear-gradient(to bottom,transparent 44%,color-mix(in srgb,var(--_tone) 72%,white) 48% 52%,transparent 56%);animation:orbux-cyber-scan calc(1.05s * var(--orbux-speed-scale)) linear infinite; }
.pixel { position:absolute;left:calc(10% + var(--_x));top:calc(14% + var(--_y));inline-size:calc(7% + var(--_i) * 1%);block-size:4%;background:var(--_color);animation:orbux-cyber-pixel calc((.7s + var(--_i) * .08s) * var(--orbux-speed-scale)) steps(3,end) infinite;animation-delay:calc(var(--_i) * -90ms); }
@keyframes orbux-cyber-shift { 0%,100% { transform:translate(0) skewX(0); } 22% { transform:translate(-4%,2%) skewX(5deg); } 28% { transform:translate(5%,-2%) skewX(-4deg); } 62% { transform:translate(0); } }
@keyframes orbux-cyber-scan { from { transform:translateY(-55%); } to { transform:translateY(55%); } }
@keyframes orbux-cyber-pixel { 50% { transform:translateX(80%);opacity:.2; } }
@keyframes orbux-cyber-done { 50% { transform:scale(1.055); } }
@keyframes orbux-cyber-error { 35% { transform:translateX(-4%); } 70% { transform:translateX(4%); } }
:host([data-state="streaming"]) { --_dur:.62s; }
:host([data-state="tool-calling"]) .frame { clip-path:polygon(0 0,78% 0,100% 22%,100% 100%,22% 100%,0 78%); }
:host([data-state="idle"]) .frame,:host([data-state="waiting"]) .frame,:host([data-state="idle"]) .scan,:host([data-state="waiting"]) .scan,:host([data-state="idle"]) .pixel,:host([data-state="waiting"]) .pixel { animation:none; }
:host([data-state="idle"]) .glitch { opacity:.5; }
:host([data-state="waiting"]) .pixel:nth-child(even) { opacity:.2; }
:host([data-state="done"]) { --_tone:var(--orbux-color-success,#22c55e);--_tone-2:#86efac; }
:host([data-state="error"]) { --_tone:var(--orbux-color-error,#ef4444);--_tone-2:#f97316; }
:host([data-state="done"]) .frame,:host([data-state="error"]) .frame,:host([data-state="done"]) .scan,:host([data-state="error"]) .scan,:host([data-state="done"]) .pixel,:host([data-state="error"]) .pixel { animation:none; }
:host([data-state="done"]) .glitch { animation:orbux-cyber-done 220ms cubic-bezier(.23,1,.32,1) 1; }
:host([data-state="error"]) .glitch { animation:orbux-cyber-error 200ms cubic-bezier(.23,1,.32,1) 1; }
:host([data-settled="true"]) .glitch { animation:none; }
:host([data-paused="true"]) * { animation-play-state:paused !important; }
:host([data-reduced-motion="true"]) * { animation:none !important; }
:host([data-reduced-motion="true"][data-state="streaming"]) .scan { transform:translateY(24%); }
`;

export class OrbuxCyberGlitch extends OrbuxElement {
  protected build(): void {
    const style = document.createElement('style');
    style.textContent = STYLES;
    const glitch = document.createElement('div');
    glitch.className = 'glitch';
    glitch.setAttribute('part', 'glitch');
    const points = [
      [2, 8],
      [61, 4],
      [14, 63],
      [70, 52],
      [38, 24],
      [4, 46],
    ];
    glitch.innerHTML = `<span class="frame"></span><span class="scan"></span>${points.map(([x, y], index) => `<i class="pixel" style="--_i:${index};--_x:${x}%;--_y:${y}%;--_color:${index % 2 ? 'var(--_tone-2)' : 'var(--_tone)'}"></i>`).join('')}`;
    this.root.append(style, glitch);
  }
}
if (typeof customElements !== 'undefined' && !customElements.get('orbux-cyber-glitch'))
  customElements.define('orbux-cyber-glitch', OrbuxCyberGlitch);
declare global {
  interface HTMLElementTagNameMap {
    'orbux-cyber-glitch': OrbuxCyberGlitch;
  }
}

Depends on @vikast908/core. Paste the source, add the base element, and set state from your agent code.

Attributes & properties

NameTypeDescription
stateAgentState idle · thinking · streaming · tool-calling · waiting · done · error
sizeCSS lengthOverall square size.
--orbux-widthCSS lengthOptional inline-size override.
--orbux-heightCSS lengthOptional block-size override.
speednumberAnimation speed multiplier (1 = default).
labelstringAccessible label (defaults per state).
pausedbooleanFreeze the animation.

Respects prefers-reduced-motion, exposes status/progressbar semantics with a live label, and auto-pauses (sets data-paused) when offscreen or the tab is hidden.