Files
inter-hub/specs/TailwindForInteractionHubs_v0.2.md
tegwick 8b6ce5bbc8 docs: add specification, reference docs, workplan, and agent guidance
Adds all Phase 0 content that was created but never committed:
- CLAUDE.md and SCOPE.md — agent and developer orientation
- specs/TailwindForInteractionHubs_v0.2.md — IHF Tailwind coding guide
- docs/ — five IHP v1.5 reference guides (overview, data, controllers, realtime, ihf-mapping)
- workplans/IHUB-WP-0001 — Phase 1 implementation plan (12 tasks, state-hub synced)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 02:07:13 +01:00

9.3 KiB
Raw Blame History

Tailwind for Interaction Hubs

Agentic Coding Best-Practice Guide
For building governed, observable, antifragile hub interfaces with Tailwind + IHP

Version: 0.2 (Agent-Optimized)
Status: Production-Ready Reference
Audience: Human developers and coding agents (LLMs)
Framework: IHP (Integrated Haskell Platform) + Interaction Hub Framework (IHF) layer
Date: March 2026


0. Quick-Start for Coding Agents (READ THIS FIRST)

When you receive a UI task for an Interaction Hub:

  1. Semantic first — Never start with classes. Ask: “What IHF primitive/widget does this map to?”
  2. Import hierarchy — Always import Web.View.IHF.Primitives, Web.View.IHF.Widgets, Web.View.IHF.Classes.
  3. Use wrappers — Render via widgetFrame, signalBadge, hubActionButton, etc.
  4. Token roles only — Reference surfaceBase, signalSuccess, focusRing (defined in Theme.hs).
  5. No raw soup — If you see >8 utility classes in one element, extract to a helper.
  6. Document for reproducibility — Every new primitive gets Haddock + example HSX.

This guide is your single source of truth. Follow it → zero drift.


1. Purpose

This guide makes Tailwind the shared visual grammar for all Interaction Hubs built on IHP + IHF, while keeping the IHF semantic model (Widget, Panel, SignalBadge, etc.) as the architectural control point.

It guarantees:

  • Perfect visual coherence across hubs
  • Zero CSS entropy
  • Agent-reproducible styling (no folklore)
  • Governed evolution via semantic contracts
  • Full compatibility with IHPs server-rendered HSX, partial updates, and future islands

Tailwind is the substrate. IHF widgets are the product.


2. Core Principle (Agent Rule #1)

-- ALWAYS do this
widgetFrame widget content

-- NEVER do this
<div class="rounded-xl border border-slate-700 bg-slate-900/80 px-4 py-3 shadow-sm ...">

Architecture layers (enforced order):

  1. IHF Semantic Model (Widget, HubPanel, CommentThread…)
  2. Visual Primitive Contracts (Primitives.hs)
  3. Tailwind Token Application (centralized in Classes.hs + tailwind.config.js)
  4. Screen Composition

3. IHP + Tailwind Setup (Mandatory Baseline)

Follow the official IHP Tailwind guide, then apply these IHF extensions:

Required Files (exact locations)

Project Root
├── tailwind/
│   ├── tailwind.config.js          ← extend with IHF tokens
│   └── app.css
├── Web/View/IHF/
│   ├── Theme.hs                    ← semantic roles
│   ├── Tokens.hs                   ← spacing/radius/shadow maps
│   ├── Classes.hs                  ← reusable class builders
│   ├── Primitives.hs               ← surface, panel, badge, button…
│   ├── Widgets.hs                  ← widgetFrame, inspectorPanel…
│   ├── Patterns.hs                 ← triageDashboard, decisionBoard…
│   ├── AnnotationUI.hs
│   └── GovernanceUI.hs
├── Web/View/CustomCSSFramework.hs  ← IHP component override (required for JIT)
└── Config/Config.hs                ← option customTailwind

Key tailwind.config.js snippet (add to IHF theme):

theme: {
  extend: {
    colors: {
      surfaceBase: "hsl(var(--surface-base))",
      signalSuccess: "hsl(var(--signal-success))",
      // … all roles from Theme.hs
    },
    spacing: { /* baseline rhythm */ },
  }
}

CustomCSSFramework.hs must expose customTailwind with Tailwind classes for all IHP form/button/flash helpers.


Layer Name Lives In Example Functions Purpose
A Semantic Interaction Widgets.hs / Types widgetFrame, commentRail What it is
B Visual Primitive Primitives.hs panel, signalBadge, actionButton Reusable building blocks
C Tailwind Utility Application Classes.hs panelClasses, badgeVariant Actual classes
D Screen Composition Patterns.hs triageDashboard Workflow views

5. Golden Rules for Agents

  • Rule 1: Every visual element must have a named Haskell wrapper (no raw <div class="…"> longer than one line).
  • Rule 2: All color/spacing decisions go through Theme.hs roles.
  • Rule 3: Variant logic must be exhaustive and named (primary | ghost | danger).
  • Rule 4: Commentability is first-class — every widget primitive exposes commentable :: Bool.
  • Rule 5: Before writing any new class string, check Classes.hs. If missing, add it there with documentation.

6. Visual Language & Tokens (Copy-Paste Ready)

6.1 Color Roles (Theme.hs)

surfaceBase, surfaceRaised, surfaceMuted,
borderSubtle, borderStrong,
textPrimary, textSecondary, textMuted,
signalInfo, signalSuccess, signalWarning, signalDanger,
focusRing, commentAccent, policyAccent, outcomeAccent

Map these to CSS variables in tailwind/app.css @layer base.

6.2 Spacing Rhythm (Tokens.hs)

space1, space2, space3, space4, space6, space8, space12, space16

Use only these. Arbitrary values are forbidden.

6.3 Radius & Shadow

roundedPanel = "rounded-xl"
roundedBadge = "rounded-lg"
shadowLight = "shadow-sm"

7. Core Primitives (Primitives.hs — Starter Template)

-- Example: panel
panel :: [Attribute] -> Html -> Html
panel attrs content = div!
    ( [ class_ (panelClasses <> " " <> unwords (map renderAttr attrs))
      , role_ "region"
      ] )
    content

panelClasses :: Text
panelClasses = "bg-surfaceBase border border-borderSubtle rounded-xl shadow-sm px-4 py-3"

-- Example: signalBadge
signalBadge :: SignalStatus -> Html
signalBadge status = span!
    [ class_ (badgeVariant status) ]
    [ text (statusLabel status) ]

All primitives follow this exact signature pattern.


8. Widget-Centered Rules (IHF Core)

Every Widget must render via widgetFrame:

widgetFrame :: Widget -> (Widget -> Html) -> Html
widgetFrame w inner = div!
    [ class_ widgetFrameClasses
    , dataAttribute "widget-id" (widgetId w)
    , dataAttribute "commentable" (show $ isCommentable w)
    ] $ do
        widgetHeader w
        inner w
        widgetFooter w

State cues (inspectable, commentable, in-flight) use one consistent visual language (header accent + badge + subtle background shift).


9. Agent-Friendly Practices

9.1 Component Creation Protocol (Mandatory)

When creating a new primitive:

  1. Add to Primitives.hs with full Haddock:
    {-# LANGUAGE OverloadedStrings #-}
    -- | A governed action button. Variants map to IHF policy levels.
    actionButton :: ActionVariant -> Text -> Html
    
  2. Define variant type in Types.hs.
  3. Implement class builder in Classes.hs.
  4. Add example usage in docs/Examples.hs.
  5. Update Short Operational Checklist (section 26).

9.2 Prompt Template for Future Agents

“Generate an IHF widget for X using only primitives from Web.View.IHF. Use semantic roles from Theme.hs. No raw Tailwind soup. Include comment affordance.”


10. Anti-Patterns (Hard-Coded Agent Rejection Rules)

  • Utility soup longer than 6 classes
  • Screen-local button/panel/badge reinvention
  • Literal color names in component signatures
  • Mixed density without system-level justification
  • Styling logic inside business controllers
  • Any custom CSS outside tailwind/app.css @layer components

11. Forms, Tables, Annotations, Governance (IHF-Specific)

  • Forms: Use styledFormGroupClass from CustomCSSFramework.hs + fieldWithPolicyNote.
  • Tables: Standardized sortableTable in Patterns.hs with actor/timestamp/state columns.
  • Annotations: First-class annotationThread + triage variants (open | reviewed | policySensitive).
  • Governance: decisionBanner, policyScopeBadge, traceabilityChain — all with built-in comment hooks.

12. File & Module Organization (Exact)

See section 3. All IHF UI lives under Web/View/IHF/.
Import graph is strict: Patterns.hsWidgets.hsPrimitives.hsClasses.hsTheme.hs.


13. Rollout Phases & Minimum Standard

Phase 1 (MVP): Theme + Tokens + Primitives (panel, button, badge, widgetFrame)
Phase 2: AnnotationUI + GovernanceUI
Phase 3: Hub-specific accents + adaptive patterns

Every new component must ship with:

  • Purpose
  • Type signature
  • Allowed variants
  • Accessibility notes
  • Commentability behavior
  • Example HSX

14. Short Operational Checklist (Agent + Human Merge Gate)

Before any PR/merge:

  • Semantic name used
  • Imported only from IHF modules
  • Classes composed via Classes.hs
  • State signaling matches existing system
  • Focus + contrast + color+icon rule satisfied
  • Comment affordance present where applicable
  • No custom CSS added
  • Agent reproduction test passed (copy-paste into new context works)

15. Motto

“Use Tailwind for expression. Let IHF widgets define meaning.”

This guide is the contract between humans and agents. Follow it and Interaction Hubs stay coherent, evolvable, and antifragile forever.