frontend
Technical notes on web development, DevOps, and AI integration.
115 articles
- 22:43frontend
The Nav Accent That Moved on Its Own Turned Out to Be Modulo
The AI entry in my navbar changed color after a menu reorder. A lesson in modulo index color assignment and fixing it with data identity.
TL;DR: Styling nav entries with a modulo index ties colors to render position, so reordering the menu silently reshuffles accents. Pinning the special "Ask AI" entry to its href identity keeps its color stable. Adding an idle pill also satisfies WCAG 1.4.1, since shape reinforces hue for users who can't distinguish colors.
#tailwind#react#css - 20:27frontend
My WhatsApp Header Button Became an Ask AI Nav Entry
Removing the WhatsApp consultation pill and promoting Ask AI into the segmented nav: placement contracts for external CTAs versus internal features.
TL;DR: The WhatsApp consultation button was removed from the header, not just restyled. Ask AI moved into the main nav as a permanent entry, with the mobile consultation slot reassigned to it. The takeaway: features belong in navigation, while one-shot external actions like WhatsApp links belong on pages where they matter.
#ux#accessibility#next-intl - 18:21frontend
Slimmer Desktop Chat Composer with Tailwind sm: Variants
Shrinking the desktop chat input field and buttons with four responsive Tailwind classes, no separate component and no JavaScript required.
TL;DR: The chunky mobile-sized chat composer was wasting desktop space, but a separate component felt like overkill. Four responsive Tailwind classes fixed it: base sizes stay touch-friendly for phones, sm: variants tighten padding and shrink buttons on desktop. Trade-off is width-based, not pointer-based, so wide touchscreen laptops get small buttons too.
#tailwind#css#ux - 14:17frontend
Fullscreen Mobile Chat Under a Fixed 66px Header
Fullscreen mobile wrapper under a 66px fixed header using mt-66px plus calc 100dvh-66px, uncapped transcript, and a compact messaging header.
#css#tailwind#frontend - 12:43frontend
A Separate Mobile Chat Component With One Answer Logic
My mobile chat needed its own messaging-app-style frame, but the answer logic stays single-sourced by reusing the exported TurnBody.
TL;DR: A desktop three-column chat layout doesn't survive shrinking to phones, so the author built a separate mobile thread component using the familiar messaging-app pattern. Sticky header, chat bubbles, composer, all done with CSS sticky and backdrop-filter. Only the frame is duplicated; shared TurnBody logic keeps desktop and mobile in sync.
#react#frontend#ux - 12:40frontend
Duplicate Order 1: When My History Sidebar Vanished at lg
My chat history sidebar vanished at the lg breakpoint: a CSS order tie-break and a details element forced into flex duty, two roots in one commit.
TL;DR: A missing sidebar at lg breakpoints came down to two bugs from a mobile accordion refactor. Equal flex order values let the center wrapper win the source-order tie-break, fixed with an explicit lg:order-2. A details element can't flex-size children in Chromium, so it became state-driven with aria-expanded instead.
#css#react#tailwind - 12:35frontend
44px Buttons, 16px Fonts: Standard Numbers in Mobile Chat
A responsive pass on my AI chat panel: 44px send targets per WCAG, 16px input fonts against iOS zoom, and a 65vh transcript with overscroll containment.
TL;DR: A desktop-tidy chat panel broke on mobile in three unrelated ways, each fixed by a standardized number. Buttons grew to 44px per WCAG target-size guidance, and the textarea got a 16px font to stop Safari's forced zoom. A 65vh transcript with overscroll containment stops scroll chaining and pull-to-refresh.
#css#tailwind#react - 16:57frontend
Badge [2] in the Sidebar Isn't the Second Card You See
Citation badges in the sidebar list are computed with indexOf from the original array, not the filtered iteration position, so numbers stay truthful.
TL;DR: While refactoring a chat sources sidebar, badge numbers were computed over a filtered array, so dropping knowledge entries shifted every web source's number and broke reference links. The fix: compute numbers with indexOf on the original turn.sources, so badges always match answer references. Lesson: reference numbers must come from original data, not filtered display order.
#react#frontend#ux - 16:41frontend
It's Never Just a Re-Render
Knowledge cards now render inline below the chat answer; reusing the card component takes a named export, unique per-panel ids, and its own expand state.
TL;DR: Moving knowledge cards inline into the chat answer panel sounded trivial but broke two hidden contracts. SourceCard became a named export, and card ids got a prefix to avoid duplicate ids across the document. Expanded state now lives locally per panel, keyed by turn and slug, so opening a card in one panel doesn't leak into the other.
#react#frontend#ux