feat(shell): config-driven topbar links (GitHub/social) with shipped brand marks#47
Merged
Conversation
…brand marks ## Summary Adds `c.topbar_links` — a per-site list of repo/social links rendered as icon-only ghost buttons in the topbar, next to the theme switcher. The headline case is a GitHub repo link with a real GitHub logo. lucide (the kit's synced icon set) ships NO brand logos — it dropped its brand icons, and rails_icons' brand library (simple_icons) is gone from the current `icons` gem; syncing tabler's brand glyphs would clone ~5,900 SVGs per site. So the kit ships its OWN small, curated set of developer/social marks as inline SVG (`DocsUI::BrandMark`), each an official Simple-Icons 24×24 single-path glyph: github, gitlab, discord, x, rubygems, bluesky, mastodon, slack, whatsapp, telegram, linkedin, youtube, reddit, stackoverflow. An `icon:` that isn't a shipped brand is treated as a lucide name and delegated to `DocsUI::Icon`; omitting `icon:` renders the label as text. External links open in a new tab with rel=noopener; site-relative links open in place. Defaults to `[]`, so a site that sets nothing has a byte-identical topbar. ## What changed - `DocsKit::Configuration#topbar_links` — new knob, default [], normalizes Hashes → `DocsKit::TopbarLink` value objects (symbol/string-keyed). - `DocsKit::TopbarLink` — value object (href/label/icon, #external?, .from). - `DocsUI::BrandMark` — inline brand SVG lookup, lucide fallthrough. Brand marks use fill=currentColor + role=img + <title> for accessibility. - `DocsUI::TopbarLinks` — renders the links; `DocsUI::Shell` composes it before the theme switcher (keeps Shell under the class-length limit). - Install: commented `c.topbar_links` example in the initializer template (so `docs-kit new` sites get it); README section + component table; dogfooded in the docs site (a GitHub link to mhenrixon/docs-kit). ## Test Coverage - config: default [], Hash normalization, order, nil→[], TopbarLink objects - TopbarLink: .from (Hash/object, string keys, icon coercion), #external? - BrandMark: .brand?, all 14 brands present + valid 24×24 single-path SVGs, brand render (viewBox/currentColor/role/title), String key, lucide fallthrough - TopbarLinks: brand mark, aria-label, external target/rel, relative link, icon-less text button, order, empty→nothing - Shell: links render before the switcher; unchanged when unset - Generator: initializer documents the commented knob No new CSS class emitted (btn/btn-square/btn-ghost/size-5/flex-none already scanned literals); brand paths verified byte-exact against simpleicons.org. ## Verification - [x] bundle exec rspec — 654 examples, 0 failures, 96% coverage - [x] bundle exec rubocop — 121 files, no offenses - [x] docs site CSS rebuilt (bin/build-css) Claude-Session: https://claude.ai/code/session_01FPQb6z3YwcKRMbvoJhdxnX
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
Adds
c.topbar_links— a per-site list of repo/social links rendered as icon-only ghost buttons in the topbar, next to the theme switcher. The headline case is a GitHub repo link with a real GitHub logo (this PR dogfoods it: the docs site now links tomhenrixon/docs-kit).Why ship our own brand marks
lucide (the kit's synced icon set) ships no brand logos — it dropped its brand icons, and rails_icons' brand library (
simple_icons) is gone from the currenticonsgem. Syncing tabler'sbrand-*glyphs would clone ~5,900 SVGs into every site. So the kit ships its own small, curated set of developer/social marks as inline SVG (DocsUI::BrandMark), each an official Simple-Icons 24×24 single-path glyph, verified byte-exact against simpleicons.org:An
icon:that isn't a shipped brand is treated as a lucide name and delegated toDocsUI::Icon; omittingicon:renders the label as a text button. External links open in a new tab withrel="noopener"; site-relative links open in place. Marks usefill: currentColor, so they recolor with the active daisyUI theme.Backwards compatible:
c.topbar_linksdefaults to[]— a site that sets nothing has a byte-identical topbar.What changed
DocsKit::Configuration#topbar_links(default[], normalizes Hashes → value objects)DocsKit::TopbarLink(href/label/icon,#external?,.from)DocsUI::BrandMark(inline brand SVG + lucide fallthrough)DocsUI::TopbarLinks(renders the links);DocsUI::Shellcomposes it before the theme switcherc.topbar_linksexample in the initializer template (sodocs-kit newsites get it)No new CSS class is emitted —
btn/btn-square/btn-ghost/size-5/flex-noneare already-scanned literals — so no@sourcechange is needed.Test plan
[], Hash normalization, declaration order,nil→[], acceptsTopbarLinkobjects.from(Hash/object, string keys, icon coercion),#external?.brand?; all 14 brands present + valid 24×24 single-path SVGs; brand render (viewBox / currentColor / role=img /<title>); String key; lucide fallthrougharia-label, externaltarget/rel, relative link, icon-less text button, order, empty → nothingVerification
bundle exec rspec— 654 examples, 0 failures, 96% line coveragebundle exec rubocop— 121 files, no offensesbin/build-css); all emitted classes presenthttps://claude.ai/code/session_01FPQb6z3YwcKRMbvoJhdxnX