Skip to content

feat(shell): config-driven topbar links (GitHub/social) with shipped brand marks#47

Merged
mhenrixon merged 1 commit into
mainfrom
feature/topbar-links
Jul 3, 2026
Merged

feat(shell): config-driven topbar links (GitHub/social) with shipped brand marks#47
mhenrixon merged 1 commit into
mainfrom
feature/topbar-links

Conversation

@mhenrixon

Copy link
Copy Markdown
Owner

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 to mhenrixon/docs-kit).

c.topbar_links = [
  { href: "https://github.com/you/repo", label: "GitHub",  icon: :github },
  { href: "https://discord.gg/invite",   label: "Discord", icon: :discord },
  { href: "/changelog",                  label: "Changelog", icon: "history" }, # a lucide icon
]

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 current icons gem. Syncing tabler's brand-* 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:

: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 a text button. External links open in a new tab with rel="noopener"; site-relative links open in place. Marks use fill: currentColor, so they recolor with the active daisyUI theme.

Backwards compatible: c.topbar_links defaults to [] — a site that sets nothing has a byte-identical topbar.

What changed

Layer Change
Config DocsKit::Configuration#topbar_links (default [], normalizes Hashes → value objects)
Value object DocsKit::TopbarLink (href/label/icon, #external?, .from)
Component DocsUI::BrandMark (inline brand SVG + lucide fallthrough)
Component DocsUI::TopbarLinks (renders the links); DocsUI::Shell composes it before the theme switcher
Install path commented c.topbar_links example in the initializer template (so docs-kit new sites get it)
Docs README section + component table; dogfooded in the docs site

No new CSS class is emitted — btn/btn-square/btn-ghost/size-5/flex-none are already-scanned literals — so no @source change is needed.

Test plan

  • config — default [], Hash normalization, declaration order, nil[], accepts 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=img / <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

Verification

  • bundle exec rspec654 examples, 0 failures, 96% line coverage
  • bundle exec rubocop — 121 files, no offenses
  • docs site CSS rebuilt (bin/build-css); all emitted classes present

https://claude.ai/code/session_01FPQb6z3YwcKRMbvoJhdxnX

…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
@mhenrixon mhenrixon self-assigned this Jul 3, 2026
@mhenrixon mhenrixon added the enhancement New feature or request label Jul 3, 2026
@mhenrixon mhenrixon merged commit 33b7e8e into main Jul 3, 2026
4 checks passed
@mhenrixon mhenrixon deleted the feature/topbar-links branch July 4, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant