Skip to content

Commit 1a942f9

Browse files
authored
Merge pull request #82 from levelcodeai/feat/ascii-wordmark
feat(chat): a proper wordmark for the empty state
2 parents df1046d + b0717ae commit 1a942f9

2 files changed

Lines changed: 41 additions & 12 deletions

File tree

extensions/levelcode-ai/media/chat.html

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,18 +1259,17 @@
12591259
<body>
12601260
<div id="log">
12611261
<div id="empty">
1262-
<div class="lc-ascii-wrap"><pre class="lc-ascii" role="img" aria-label="LevelCode AI">██╗ ███████╗██╗ ██╗███████╗██╗
1263-
██║ ██╔════╝██║ ██║██╔════╝██║
1264-
██║ █████╗ ██║ ██║█████╗ ██║
1265-
██║ ██╔══╝ ╚██╗ ██╔╝██╔══╝ ██║
1266-
███████╗███████╗ ╚████╔╝ ███████╗███████╗
1267-
╚══════╝╚══════╝ ╚═══╝ ╚══════╝╚══════╝
1268-
██████╗ ██████╗ ██████╗ ███████╗
1269-
██╔════╝██╔═══██╗██╔══██╗██╔════╝
1270-
██║ ██║ ██║██║ ██║█████╗
1271-
██║ ██║ ██║██║ ██║██╔══╝
1272-
╚██████╗╚██████╔╝██████╔╝███████╗
1273-
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝</pre></div>
1262+
<div class="lc-ascii-wrap"><pre class="lc-ascii" role="img" aria-label="LevelCode AI">██ ███████ ██ ██ ███████ ██
1263+
██ ██ ██ ██ ██ ██
1264+
██ ██████ ██ ██ ██████ ██
1265+
██ ██ ██ ██ ██ ██
1266+
███████ ███████ ███ ███████ ███████
1267+
1268+
███████ ███████ ██████ ███████
1269+
██ ██ ██ ██ ██ ██
1270+
██ ██ ██ ██ ██ ██████
1271+
██ ██ ██ ██ ██ ██
1272+
███████ ███████ ██████ ███████</pre></div>
12741273
<div class="lc-ascii-sub">levelcode.ai</div>
12751274
<div class="empty-copy">Ask about your code, or describe what to build. The open file is sent as context; add a selection with <b>+</b> or ⌥⌘A.</div>
12761275
<div class="starters">

extensions/levelcode-ai/test/webviewCss.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,36 @@ test('TRANSCRIPT: the user bubble hugs its content, and is capped short of the c
578578
'tint is the secondary cue and still earns its place — side alone would drop on a wrapped log');
579579
});
580580

581+
test('WORDMARK: the empty-state logo is full blocks only, and fits its container', () => {
582+
// Drawn on a 10-row pixel grid with 2px strokes, then packed two pixel rows per text row. Because
583+
// every stroke is an even number of pixels, each pair collapses to a FULL block — no ▀ or ▄ survives.
584+
//
585+
// That is the property worth pinning, and it was learned the hard way. `▀` sits at the top of its
586+
// cell and `▄` at the bottom, so `▀` directly above `▄` leaves a full cell of empty space between
587+
// them: a seam straight through the letterform. A 1px-stroke font produces that constantly and
588+
// shatters. Full blocks tile seamlessly in any monospace font, so this art cannot develop seams no
589+
// matter what the user's editor font is.
590+
const m = /<pre class="lc-ascii"[^>]*>([\s\S]*?)<\/pre>/.exec(html);
591+
assert.ok(m, 'the empty-state wordmark is gone');
592+
const art = m[1].replace(/^\n/, '');
593+
const glyphs = new Set(art.replace(/[\n ]/g, ''));
594+
assert.deepStrictEqual([...glyphs], ['█'],
595+
'the wordmark uses partial blocks: ▀ above ▄ leaves a seam through the stroke in most fonts. '
596+
+ 'Found: ' + [...glyphs].join(''));
597+
598+
// It is sized by the container (clamp(5px, 3.6cqi, 13px)) inside #empty, which is capped at 560px.
599+
// Past ~44 columns it stops fitting and the pre grows a horizontal scrollbar under the logo.
600+
const lines = art.split('\n');
601+
const cols = Math.max(...lines.map((l) => l.length));
602+
assert.ok(cols <= 44, 'the wordmark is ' + cols + ' columns; wider than ~44 overflows #empty (max 560px)');
603+
assert.ok(lines.length <= 14, 'the wordmark is ' + lines.length + ' lines; it has to leave room for the prompt beneath it');
604+
605+
// The accessible name is the whole reason a picture made of text is not a wall of noise to a
606+
// screen reader.
607+
assert.match(m[0], /role="img"/, 'the wordmark must be exposed as an image, not read out block by block');
608+
assert.match(m[0], /aria-label="[^"]+"/, 'the wordmark has no accessible name');
609+
});
610+
581611
test('CODE: prose blocks get room, and nothing else that uses <pre> moves', () => {
582612
// docs/CHAT-TYPOGRAPHY.md D5/T3. `pre` is a GLOBAL selector in this file, and it draws four different
583613
// things: the empty state's ASCII logo, the MCP approval card's command block, the terminal output

0 commit comments

Comments
 (0)