feat(home): render social icon row from [[menu.social]] - #55
Merged
Conversation
4 tasks
Mirrors the legacy LoveIt social-link row, but driven by kiln's typed menu groups (no `social.yml` preset, no shorthand syntax). The theme treats `[[menu.social]]` entries as opaque MenuItem records: each one becomes an `<a>` with an icon, accessible label from `t(item.name)`, and `rel="me noopener noreferrer" target="_blank"` when external. `rel="me"` follows the IndieAuth / verified-profile microformats convention for outbound social links. `min_kiln_version` bumps to `0.3.0-rc.1` (the kiln release that ships named menu groups + literal-friendly `t()`).
hakula139
force-pushed
the
feat/profile-socials
branch
from
May 9, 2026 15:46
ec4bb24 to
aeac853
Compare
Brand glyphs (fab fa-*) live in fa-brands-400.woff2, which the preload list was missing. The font still loaded via @font-face in all.min.css, but only after stylesheet parse, leaving brand icons in fallback (or visibly thinner) on first paint. Adding the preload puts brands on the same critical path as solid and regular faces.
hakula139
force-pushed
the
feat/profile-socials
branch
4 times, most recently
from
May 10, 2026 07:40
0de01ae to
7589369
Compare
… SVGs The icon string in [[menu.*]] entries used to be a Font Awesome class string rendered inline as <i class="...">. The dispatcher accepts a second form, "svg:<slug>", which inlines a theme-bundled SVG from _partials/icons/<slug>.svg. SVGs may originate from Simple Icons (brand-only set, used for most entries here), other project repositories (NeoDB ships fediverse.svg, MetaBrainz ships listenbrainz_logo_icon.svg), or hand-authored sources. Falls back to the existing FA path for everything else, so existing fab/fas/far configs keep working. A shared CSS rule sizes both <i> and inline <svg> children of .header-link / .header-mobile-link to the fa-fw 1.25em footprint, and .profile-social svg matches the surrounding glyph at 1em with fill=currentColor — so a row mixing FA and inline SVGs aligns and recolors uniformly.
Default Tailwind defaults left the row visually loose: 12px x-gap, 18px glyphs, 36px-wide centering boxes. Drops the gap to 4px, shrinks the container to 32px, and bumps glyphs to 24px so the row matches the visual weight of a typical social-icon strip rather than scattering into separate badges.
hakula139
force-pushed
the
feat/profile-socials
branch
from
May 10, 2026 08:53
7589369 to
4a7a885
Compare
Use :is(i, svg) to consolidate the menu-icon selector across header-link and header-mobile-link, switch align-[-0.125em] to align-middle (FA's literal magic number was tuned for FA font metrics; align-middle keys off x-height and is robust to font-size changes), and replace h-[1em] w-[1em] on .profile-social svg with the v4 size-[1em] shorthand. No visual change to FA-only menu rows. Inline SVG glyphs sit fractionally lower against the text baseline in the menu, matching x-height middle rather than FA's pre-rendered offset.
The bundled icon registry is now upstream-only: Simple Icons brands (bilibili, douban, github, linkedin, mastodon, qq, steam, telegram, zhihu) plus two project-repo SVGs (fediverse from neodb-social/neodb, listenbrainz from MetaBrainz). Bangumi was the only hand-authored glyph and is fundamentally site-flavor — sites that link to Bangumi profiles should ship their own SVG under templates/_partials/icons/ and reference it as svg:bangumi (the dispatcher resolves through the site's template directory before falling back to the theme). Sites consuming this commit must add a bangumi.svg locally if their [[menu.social]] previously relied on the theme-bundled one.
…urfaces Three call sites now share one source of truth for the tappable icon hover treatment (background tint, link color, dark-mode swap): .header-link, .header-icon, and .profile-social. The matching surface also lands on .profile-social for the first time, fixing a regression against the legacy site row where each icon got an individual roundel on hover. Header desktop nav and icon buttons collapse the 95% duplicate base into a comma-listed shared rule with per-variant deltas (border-b-0 to kill anchor underline; cursor-pointer because <button> doesn't inherit it). All CSS-tokens live in a new _src/components/shared/ directory imported once near the top of main.css.
Add a docs/ directory mirroring kiln's audience-organized layout: docs/customization.md (how-to guide for visual tokens, template overrides, social icons, comments providers, fonts, static assets), docs/parameters.md ([params] schema reference with defaults and rendering context), and docs/i18n.md (translatable-key reference with override pattern). README sheds the verbose per-section [params] examples in favor of a single Quick Start config and a Documentation table linking to docs/. The detailed examples for [params.background], [params.comments], [params.footer], etc. now live exclusively in docs/parameters.md. CLAUDE.md trims three sections that were duplicating user-facing material: the design-token namespace list (now points at customization.md), the i18n override-pattern paragraph (now points at i18n.md), and the body-background user config (now points at parameters.md). The file stays contributor-focused — file-tree map, build pipeline, SRI flow, coding conventions — with a top-of-file pointer making the divide explicit. The svg:<slug> icon dispatcher (added in this branch's earlier commits) is documented in docs/customization.md with the bundled registry table and the site-override pattern. cspell dictionary picks up bangumi, bilibili, fediverse, listenbrainz, metabrainz, and neodb to cover docs/customization.md examples.
The token is --color-card, so the Tailwind utility is bg-card; bg-card-bg silently no-ops, leaving the back-to-home button without its surface fill.
Every other rule in the codebase puts @apply first, then raw declarations; .highlight was the lone outlier.
Sibling-rule form duplicated the :where() selector and contradicted the nested-inside convention used in apple-music.css and icon-button.css.
Bump top padding so the panel sits visually centered below the header instead of crowding it; modest extra below to balance.
Matches the rationale comment convention established by prose.css and mermaid.css for intentional layer bypasses.
Trailing-! important keeps it winning during the toggle window, so the out-of-layer placement was unnecessary; co-locating with the other prefers-reduced-motion: no-preference rule keeps related concerns together.
--radius-sm, --shadow-sm, and --shadow-lg have no consumers in CSS or templates; their auto-generated rounded-sm / shadow-sm / shadow-lg utilities aren't used anywhere either.
Three sites (callout-title, code/callout/toc chevrons, toc list icon) all repeated the same shrink-0 + Font Awesome family + weight setup before applying their content / size deltas. Folding into a shared utility couples the family + weight (which must agree) and lets each site keep its own content / sizing as the natural seam.
The border:1px var(--surface-glass-border) declaration was paired with glass-surface in five places (.glass-panel, .header-mobile, .skip-link focus, .OwO-body, .pf-modal). Coupling the border with the surface matches the same argument that justified glass-surface itself. .header-mobile keeps its bottom-only border via border-x-0 border-t-0; .header-nav was already overriding via border-0 border-b. The Pagefind modal keeps its !important border-color override since raw declarations inside @Utility blocks don't inherit the @apply ! modifier.
Replaces the raw border-color !important declaration with the equivalent border-(color:--surface-glass-border)! utility, keeping all overrides in the @apply chain.
The free-floating comment under the section divider read as orphaned; moving it next to .apple-music-light makes its scope explicit.
glass-surface! now propagates !important to its border-color raw declaration, so the explicit border-(color:...)! addition added zero new information.
The token table in docs/customization.md still listed --radius-sm and left shadow scales unenumerated; refresh to match the post-cleanup set (radii: md/lg/xl/card; shadows: md/card + drop-shadow-text). CLAUDE.md's CSS file tree was missing components/shared/, which now holds fa-icon.css and icon-button.css.
The previous attempt bumped the wrapper padding, which pushed the whole panel down. The right shape is to keep the panel anchored near the top (y-6 like other layouts) and bump the panel's *inner* padding so the 404 content sits visually centered within the surface. The back-home link also dropped its filled bg-card surface and now matches the icon-button language used by .header-link / .profile-social (transparent until hover, where it picks up the shared icon-tap-hover tinted background).
The previous attempt bumped wrapper padding, pushing the whole panel down. Right shape is to keep the panel anchored near top (py-6 like other layouts) and bump the panel's *inner* padding so the 404 content sits visually centered within the surface. The back-home link drops its filled bg-card surface and now matches the icon-button language used by .header-link / .profile-social — extracted as .back-home-link in a new layout/error-page.css since the chain exceeded the inline-utility threshold.
Previously h-8 w-8 with text-2xl gave a 24/32 = 75% icon-to-container ratio, leaving only 4px around the glyph and the hover circle barely visible. Switch to aspect-square + p-2 (matching the .header-link idiom) so the container scales with the icon and the tinted hover area reads as a deliberate surface. Bump gap from 1 to 2 for the same reason — buttons no longer touch.
hakula139
added a commit
to hakula139/hakula.xyz-kiln
that referenced
this pull request
May 10, 2026
## Summary - Port the legacy hakula.xyz social-link row to kiln. 12 `[[menu.social]]` entries with `weight` ordering, surfacing higher-priority contact channels (QQ, Telegram, email) above passive discovery links (GitHub, LinkedIn, Bilibili, Bangumi, Zhihu, NeoDB, Steam, ListenBrainz) and trailing the row with RSS. - `i18n/zh-Hans.toml` adds the `menu_social_*` block. Labels resolve via `t(item.name)` in IgnIt's home template, so `aria-label` / `title` render in zh-Hans (`知乎`, `豆瓣`, `邮箱`, ...). - QQ icon points at `/images/social/qq.webp` (the QR-code image, copied over from the legacy site at `static/images/social/qq.webp`); other external entries open in a new tab via the theme's `rel="me noopener noreferrer"` handling. - Email omits `external = true` so `mailto:` stays in the same tab. - All brand entries use IgnIt's `svg:<slug>` dispatcher to inline a theme-bundled SVG (Simple Icons for most; NeoDB renders the `fediverse` glyph since the official NeoDB logo doesn't reduce cleanly to monochrome). Non-brand entries (Email = `fas fa-envelope`, RSS = `fas fa-rss`) stay on Font Awesome — they're protocols, not brands. - **Bangumi icon owned by the site**: the theme intentionally doesn't bundle a bangumi glyph (no usable upstream SVG that reduces to a clean monochrome silhouette). This site ships a hand-authored `templates/_partials/icons/bangumi.svg` (a stylized retro TV) which IgnIt's icon dispatcher resolves through kiln's path loader (site shadows theme). Sites that want bangumi own their own glyph; sites that don't reference `svg:bangumi` are unaffected. - IgnIt submodule bumped to the icon-dispatcher tip from hakula139/IgnIt#55, including the theme-side cleanup folded into that PR (404 fix, `glass-surface` border fold, `@utility fa-icon`, dead-token cleanup, doc split). - `cspell` dictionary picks up `bangumi`, `bilibili`, `fediverse`, `listenbrainz`, `metabrainz`, `neodb`. - `CLAUDE.md` documents the `templates/_partials/icons/<slug>.svg` site-side override path so future contributors know where to land new bundled glyphs. ## Test plan - [x] `kiln build` succeeds against the bumped IgnIt submodule - [x] `pnpm build` (regenerated `static/css/style.css` to pick up the theme's new `@utility icon-tap-hover` and `@utility fa-icon` definitions) - [x] `pnpm format`, `pnpm lint`, `pnpm spellcheck` clean - [x] Visual smoke: home page shows the social icon row in `weight` order; tooltips and `aria-label`s resolve to the zh-Hans labels; external links open in a new tab with `rel="me noopener noreferrer"`; QQ link opens the QR image; mailto link opens in the same tab; bangumi renders the site-bundled SVG; brand glyphs render at the same visual weight as the FA placeholders alongside them; hover state matches `.header-icon` circular tinted background. Pairs with hakula139/IgnIt#55 and hakula139/kiln#59.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
[[menu.social]], mirroring the legacy LoveIt social-link row but driven by kiln's typed menu groups (nosocial.ymlpreset list, no shorthand syntax — themes treat the group as opaqueMenuItemrecords).<a>with an icon,aria-labelandtitlefromt(item.name)(so site authors can write either an i18n key or a literal label), andrel="me noopener noreferrer" target="_blank"whenexternal = true.rel="me"follows the IndieAuth / verified-profile convention for outbound social links._partials/macros/icon.html) that accepts either a Font Awesome class string ("fab fa-github") or"svg:<slug>", inlining a theme-bundled SVG from_partials/icons/<slug>.svg. SVGs may originate from Simple Icons, project repositories (NeoDB shipsfediverse.svg, MetaBrainz shipslistenbrainz_logo_icon.svg), or hand-authored sources — the prefix names what the macro does, not the source.<title>androle="img"markers are stripped — the parent<a>carries thearia-label, so the SVG isaria-hidden. Bangumi is intentionally not bundled (no usable SVG available upstream that reduces to a clean monochrome glyph); sites that want it ship a hand-authored SVG at the same path.<i>and inline<svg>children of.header-link/.header-mobile-linkget a 1.25em footprint (the FAfa-fwequivalent), and.profile-social svgmatches surrounding glyphs at 1em withfill=currentColor— so a row mixing FA and inline SVGs aligns and recolors uniformly.@utility icon-tap-hover(50% bg in light mode, 10% white in dark).fa-brands-400.woff2joins the head preload list. The brand face was loading lazily viaall.min.css, leaving brand glyphs in fallback (visibly thinner) on first paint..profile-socials/.profile-socialTailwind v4 utilities under the existing── Profile ──block inhome-card.css. Compiledstyle.cssregenerated viapnpm build.min_kiln_versionbumps to0.3.0-rc.1— the kiln release that ships feat!: named menu groups + literal-friendly t() kiln#59. Merge gating: kiln must release0.3.0-rc.1before this PR merges.Theme cleanup folded into this PR
Once the icon dispatcher landed, an audit pass surfaced unrelated CSS hygiene wins worth shipping in the same merge unit:
bg-card-bgreferenced a non-existent token (--color-card→bg-card); the back-to-home button silently rendered with no surface fill. The 404 panel also got asymmetric vertical padding (pt-16 pb-8 sm:pt-24 sm:pb-12) so it sits visually centered below the header instead of crowding it.@utility fa-icon: extracted theFont Awesome 6 Freefamily + weight +shrink-0setup repeated in three pseudo-element rules (.callout-title::before, the chevron pseudos incollapse.css,.toc-trigger::before).glass-surfaceutility folds the border: theborder: 1px solid var(--surface-glass-border)declaration paired withglass-surfacein five places (.glass-panel,.header-mobile,.skip-link:focus,.OwO-body,.pf-modal). Coupling the border with the surface matches the same argument that justifiedglass-surfaceitself; consumers that don't want the border (.header-nav,.header-mobile) explicitly override.--radius-sm,--shadow-sm,--shadow-lghad zero consumers in CSS or templates.theme-transitionblock folded into@layer base;@variant darknested inside.glass-glowrule (vs. sibling form);@applyordering in.highlightreordered to match the rest of the codebase;comments.cssunlayered status now has a rationale comment matching the precedent inprose.cssandmermaid.css.README.mdandCLAUDE.mdintodocs/{customization,parameters,i18n}.md(mirroring kiln's docs layout). Token tables refreshed to match the post-cleanup token set; CSS file tree updated to include the newcomponents/shared/directory.Test plan
pnpm build(Tailwind v4 compile)pnpm formatpnpm lint(markdownlint + ESLint)pnpm spellcheckhakula.xyz-kiln: icon row appears centered under subtitle, hover transitions to the same circular tinted background as.header-icon/.header-link, keyboard tab order walks through links inweightorder,aria-labelmatches resolved i18n strings (知乎,豆瓣, ...), external links open in a new tab withrel="me noopener noreferrer", local QQ entry opens the embedded image.svg:<slug>entry inlines its SVG at the same visual weight / color as the FA glyphs alongside it; FA brand row paints solid on first load (no fallback flash).Pairs with hakula139/kiln#59.