Draw the + on the pixel grid so it stays sharp on 1x screens
On a 1x display TDesign's + smeared at every small size: its 24-grid strokes are centred on the box's middle, which at 12 or 14px is a pixel boundary, so each ~1px bar covered two pixels at half ink. A thinner stroke alone keeps the bar on the boundary. This is not Electrobun: headless Chrome renders the same. pixelAdd (icons.ts) redraws the + on the 14px grid with 1px bars at 7.5, so they fill whole pixels at 1x and 2x, half a pixel off-centre. It replaces tdesignAdd in the tab bar, the shortcut rows, the connection manager and the tab menu. Checked at 1x in the real tab-bar and shortcut-row markup: single-pixel bars at full ink. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -372,8 +372,9 @@ component; tokens → `ui/src/styles.css`.
|
|||||||
walker check the flag themselves.
|
walker check the flag themselves.
|
||||||
- `file-icons.ts` — extension → category map driving glyphs, colors
|
- `file-icons.ts` — extension → category map driving glyphs, colors
|
||||||
(fixed `--icon-*` tokens from Oxide's hue scales) and the Kind column.
|
(fixed `--icon-*` tokens from Oxide's hue scales) and the Kind column.
|
||||||
- `icons.ts` — the one icon registry (TDesign, `@ng-icons/tdesign-icons`), passed to
|
- `icons.ts` — the one icon registry (TDesign, `@ng-icons/tdesign-icons`, plus one
|
||||||
`provideIcons` in `app.config.ts`. Icon names are plain strings in templates and
|
redrawn glyph: `pixelAdd`, TDesign's + on the 14px pixel grid so it stays sharp
|
||||||
|
on 1x screens), passed to `provideIcons` in `app.config.ts`. Icon names are plain strings in templates and
|
||||||
the build never checks them: an unregistered name renders nothing (console error
|
the build never checks them: an unregistered name renders nothing (console error
|
||||||
only), so every name used anywhere must be listed here.
|
only), so every name used anywhere must be listed here.
|
||||||
- `platform.ts` — preload-global readers (`PLATFORM`, `APP_MODE`,
|
- `platform.ts` — preload-global readers (`PLATFORM`, `APP_MODE`,
|
||||||
|
|||||||
@@ -82,6 +82,14 @@ touching the adjacent code.
|
|||||||
it. Per-template picks had drifted to 12 sizes, and neighbours stopped
|
it. Per-template picks had drifted to 12 sizes, and neighbours stopped
|
||||||
matching: a 14.4px cog beside a 12.8px +, and a 12px + beside 9.6px × in
|
matching: a 14.4px cog beside a 12.8px +, and a 12px + beside 9.6px × in
|
||||||
the shortcut chips.
|
the shortcut chips.
|
||||||
|
- **On a 1x screen, a TDesign line through the icon's centre smears at any
|
||||||
|
small size.** At 12 or 14px the centre is a pixel boundary, so a ~1px bar
|
||||||
|
covers two pixels at half ink. A 1px stroke alone doesn't help, because the
|
||||||
|
bar stays centred on the boundary. This is geometry, not Electrobun:
|
||||||
|
headless Chrome renders the same. So the + is `pixelAdd` (`icons.ts`),
|
||||||
|
redrawn on the 14px grid with 1px bars at 7.5, which fill whole pixels at 1x
|
||||||
|
and at 2x. It's tuned for `--icon-size-sm` only. Arrow shafts (↑ →) have
|
||||||
|
the same issue if it ever shows.
|
||||||
|
|
||||||
## The interface scale (root font-size lever)
|
## The interface scale (root font-size lever)
|
||||||
|
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ export class ContextMenuService {
|
|||||||
const t = (key: string) => this.i18n.t(key);
|
const t = (key: string) => this.i18n.t(key);
|
||||||
const last = ctx.tabCount <= 1;
|
const last = ctx.tabCount <= 1;
|
||||||
return [
|
return [
|
||||||
{ label: t('ctx.tabNew'), action: 'tab:new', shortcut: 'new-tab', icon: 'tdesignAdd' },
|
{ label: t('ctx.tabNew'), action: 'tab:new', shortcut: 'new-tab', icon: 'pixelAdd' },
|
||||||
{ type: 'separator' },
|
{ type: 'separator' },
|
||||||
{
|
{
|
||||||
label: t('ctx.tabClose'),
|
label: t('ctx.tabClose'),
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
// plain strings in templates — the build never checks them, so every name used
|
// plain strings in templates — the build never checks them, so every name used
|
||||||
// anywhere must be listed here (an unregistered one renders nothing).
|
// anywhere must be listed here (an unregistered one renders nothing).
|
||||||
import {
|
import {
|
||||||
tdesignAdd,
|
|
||||||
tdesignArrowLeft,
|
tdesignArrowLeft,
|
||||||
tdesignArrowRight,
|
tdesignArrowRight,
|
||||||
tdesignArrowUp,
|
tdesignArrowUp,
|
||||||
@@ -37,8 +36,15 @@ import {
|
|||||||
tdesignVideo,
|
tdesignVideo,
|
||||||
} from "@ng-icons/tdesign-icons";
|
} from "@ng-icons/tdesign-icons";
|
||||||
|
|
||||||
|
// TDesign's + redrawn on the pixel grid of --icon-size-sm (14px). Its own glyph
|
||||||
|
// centres 24-grid strokes on the box's middle, a pixel boundary at 14px, so on a
|
||||||
|
// 1x screen both bars smear over two pixels at half ink. These bars are 1px wide
|
||||||
|
// on a half pixel (7.5): whole pixels at 1x and 2x, half a pixel off-centre.
|
||||||
|
const pixelAdd =
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14"><path stroke="currentColor" d="M7.5 3v9M3 7.5h9"/></svg>';
|
||||||
|
|
||||||
export const APP_ICONS = {
|
export const APP_ICONS = {
|
||||||
tdesignAdd,
|
pixelAdd,
|
||||||
tdesignArrowLeft,
|
tdesignArrowLeft,
|
||||||
tdesignArrowRight,
|
tdesignArrowRight,
|
||||||
tdesignArrowUp,
|
tdesignArrowUp,
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
[title]="shortcuts.tip(i18n.t('connMgr.newConnectionHint'), 'conn-new')"
|
[title]="shortcuts.tip(i18n.t('connMgr.newConnectionHint'), 'conn-new')"
|
||||||
class="flex items-center gap-1 px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-foreground"
|
class="flex items-center gap-1 px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||||
>
|
>
|
||||||
<ng-icon name="tdesignAdd" size="var(--icon-size-sm)" /> {{ i18n.t('connMgr.newConnection') }}
|
<ng-icon name="pixelAdd" size="var(--icon-size-sm)" /> {{ i18n.t('connMgr.newConnection') }}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
(click)="newStack()"
|
(click)="newStack()"
|
||||||
|
|||||||
@@ -387,7 +387,7 @@
|
|||||||
class="grid size-5 shrink-0 place-items-center text-muted-foreground hover:bg-accent hover:text-foreground"
|
class="grid size-5 shrink-0 place-items-center text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||||
[class.text-primary]="capturing() === binding.id"
|
[class.text-primary]="capturing() === binding.id"
|
||||||
>
|
>
|
||||||
<ng-icon name="tdesignAdd" size="var(--icon-size-sm)" />
|
<ng-icon name="pixelAdd" size="var(--icon-size-sm)" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
(click)="resetRow(binding)"
|
(click)="resetRow(binding)"
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ import { UpdaterService } from '@core/updater.service';
|
|||||||
[title]="shortcuts.tip(i18n.t('tabBar.newTab'), 'new-tab')"
|
[title]="shortcuts.tip(i18n.t('tabBar.newTab'), 'new-tab')"
|
||||||
class="ml-0.5 grid size-6 place-items-center text-muted-foreground electrobun-webkit-app-region-no-drag hover:bg-accent hover:text-foreground"
|
class="ml-0.5 grid size-6 place-items-center text-muted-foreground electrobun-webkit-app-region-no-drag hover:bg-accent hover:text-foreground"
|
||||||
>
|
>
|
||||||
<ng-icon name="tdesignAdd" size="var(--icon-size-sm)" />
|
<ng-icon name="pixelAdd" size="var(--icon-size-sm)" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="flex-1"></div>
|
<div class="flex-1"></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user