logo
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
# SoftLAN — Logo handoff
|
||||
|
||||
The SoftLAN mark is a pixelated **“S”** (5×5 grid) that, at rest, is a static
|
||||
icon — but periodically and on hover it **comes alive**: it dissolves into a
|
||||
single segment that slithers across the board like the game *Snake*, then
|
||||
re-lays itself back into the S. Two shorter “glitch” flickers add variety.
|
||||
|
||||
This folder is everything an engineer/agent needs to ship it.
|
||||
|
||||
```
|
||||
logo_handoff/
|
||||
├── pixel-live.jsx ← the live React component (the deliverable)
|
||||
├── demo.html ← open in a browser to see it in motion + in context
|
||||
├── INTEGRATION.md ← this file
|
||||
└── assets/
|
||||
├── softlan-mark.svg static S, fill="currentColor" (inline use)
|
||||
├── softlan-mark-blue.svg static S, fixed #3b82f6 (img/favicon use)
|
||||
├── softlan-tile.svg rounded app-icon tile, gradient + white S
|
||||
└── favicon.svg = tile (drop-in favicon)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. The live component — `pixel-live.jsx`
|
||||
|
||||
A single React component, `LiveLogo`. No build step assumed in the demo (it’s
|
||||
loaded via Babel-in-browser), but the source is plain JSX — drop it into your
|
||||
normal React/TS toolchain and it compiles as-is.
|
||||
|
||||
### Props
|
||||
|
||||
| prop | type | default | notes |
|
||||
|-------------|----------|-------------|-------|
|
||||
| `accent` | string | `#3b82f6` | the S color (any CSS color). Wire this to your theme accent. |
|
||||
| `size` | number | `140` | rendered width/height in px (it’s a square SVG). |
|
||||
| `idleAuto` | boolean | `true` | when true, plays a random trick by itself every `idleMin`–`idleMax` ms. |
|
||||
| `idleMin` | number | `5000` | min ms between idle auto-plays. |
|
||||
| `idleMax` | number | `11000` | max ms between idle auto-plays. |
|
||||
|
||||
### Behavior (built in)
|
||||
- **Rest:** renders the static pixel S in `accent`.
|
||||
- **Hover:** plays a random trick (snake-weighted).
|
||||
- **Click:** plays the snake trick.
|
||||
- **Idle:** if `idleAuto`, fires a random trick on a 5–11s jitter — but only
|
||||
while the tab is visible (`document.hidden` guard), so background tabs stay quiet.
|
||||
- It never overlaps plays (a `playing` guard ignores triggers mid-animation).
|
||||
|
||||
### Imperative API (ref)
|
||||
```jsx
|
||||
const logo = useRef(null);
|
||||
// ...
|
||||
<LiveLogo ref={logo} accent="#3b82f6" size={32} />
|
||||
// trigger a specific trick on demand:
|
||||
logo.current.play('snake'); // 'snake' | 'rgb' | 'glitch'
|
||||
logo.current.isPlaying(); // boolean
|
||||
```
|
||||
|
||||
### Tricks
|
||||
- `snake` (~2.6s) — the headline animation. S → slither across the 5×5 board → S.
|
||||
- `rgb` (~1.35s) — chromatic-aberration split that settles back to clean.
|
||||
- `glitch` (~1.1s) — rows tear/kick sideways, then snap back.
|
||||
|
||||
Edit the `POOL` array near the bottom of the file to change which tricks the
|
||||
random picker uses (and their weighting), and `TRICK_DUR` to retune durations.
|
||||
|
||||
---
|
||||
|
||||
## 2. Wiring it into the launcher
|
||||
|
||||
The current brand mark in `launcher.jsx` is a placeholder div:
|
||||
|
||||
```jsx
|
||||
// BEFORE — both the 'single' and 'two' topbar variants:
|
||||
<div className="brand-mark" style={{ background: accent }}>S</div>
|
||||
```
|
||||
|
||||
Replace each with the live component:
|
||||
|
||||
```jsx
|
||||
// AFTER:
|
||||
<LiveLogo accent={accent} size={28} />
|
||||
```
|
||||
|
||||
- Pass the existing `accent` tweak straight through — the mark recolors live.
|
||||
- `size={28}` matches the current 28px brand-mark box; adjust to taste.
|
||||
- Drop the old `.brand-mark` background/letter CSS (the SVG is self-contained).
|
||||
- The component is small and animates only on hover/idle, so it’s fine to mount
|
||||
one instance per topbar. If you want the whole header to react to a single
|
||||
event, share one `ref` and call `.play()`.
|
||||
|
||||
Import at the top of the file (or via your bundler):
|
||||
```jsx
|
||||
import { LiveLogo } from './pixel-live'; // if you convert exports to ES modules
|
||||
```
|
||||
The file currently attaches `LiveLogo` to `window` for the no-build demo —
|
||||
swap the final `Object.assign(window, …)` line for `export { LiveLogo }` in a
|
||||
module build.
|
||||
|
||||
---
|
||||
|
||||
## 3. Static assets (`assets/`)
|
||||
|
||||
For places that must be static — favicons, OS app icons, store listings,
|
||||
loading splash, OG images, anywhere JS isn’t running:
|
||||
|
||||
- **`softlan-tile.svg`** — the rounded app-icon tile (gradient + white S). Use
|
||||
this for the favicon, dock/taskbar icon, and installer art. `favicon.svg` is
|
||||
an identical copy for convenient `<link rel="icon">`.
|
||||
- **`softlan-mark-blue.svg`** — just the S in brand blue, transparent bg. Use in
|
||||
`<img>` tags and anywhere you need a fixed color.
|
||||
- **`softlan-mark.svg`** — the S with `fill="currentColor"`. **Only inherits
|
||||
color when inlined into the DOM** (inline `<svg>` or an SVG-as-component); via
|
||||
`<img src>` it won’t pick up `currentColor`. Best for inline React/JSX use
|
||||
where you want it to follow text/theme color.
|
||||
|
||||
Geometry note: all static marks use the exact same grid as the live component
|
||||
(viewBox `0 0 100 100`, cell 17, offset 7.5, gap 2.4, radius 3), so the static
|
||||
and animated S are pixel-identical — no jump when the live one mounts.
|
||||
|
||||
### Generating raster PNGs (if your pipeline needs them)
|
||||
```bash
|
||||
# requires librsvg (rsvg-convert) or Inkscape
|
||||
rsvg-convert -w 512 -h 512 assets/softlan-tile.svg > icon-512.png
|
||||
rsvg-convert -w 256 -h 256 assets/softlan-tile.svg > icon-256.png
|
||||
rsvg-convert -w 32 -h 32 assets/favicon.svg > favicon-32.png
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Accessibility & motion
|
||||
|
||||
- The static SVGs carry `role="img"` + `aria-label="SoftLAN"`. Give the live
|
||||
component an accessible label in its host (e.g. wrap with `aria-label`), since
|
||||
it’s decorative motion over a brand mark.
|
||||
- The idle auto-play already pauses in hidden tabs. If you want to fully respect
|
||||
`prefers-reduced-motion`, gate the triggers:
|
||||
```jsx
|
||||
const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
<LiveLogo idleAuto={!reduce} /* and skip the hover/click play when reduce */ />
|
||||
```
|
||||
At rest it’s a clean static S, so reduced-motion users simply get the icon.
|
||||
|
||||
---
|
||||
|
||||
## 5. Quick check
|
||||
|
||||
Open `demo.html` in any browser: hover the big mark (or wait), use the trick
|
||||
buttons, and try the accent swatches. The small mark in the mock top bar is the
|
||||
same component at `size={30}` — that’s exactly how it looks in the launcher.
|
||||
Reference in New Issue
Block a user