@super-ic/web-patterns
v0.1.9
Published
Shared marketing patterns for SuperIC: the case-study card contract, surface-radius helpers, and the candidate NeighborhoodLanding recipe.
Readme
@super-ic/web-patterns
Marketing web patterns built on the SuperIC foundation token layer:
CaseStudyCard(aliased asCaseStudyCardShell): the structural case-study card: one whole-card control, a full-bleed 16:10 product-proof band, an identity-first body, and an open/locked access contract.SURFACE_RADIUS_TOKENS,SURFACE_RADIUS_CLASSES,nestedSurfaceRadius: the shared surface-radius scale used to keep nested surfaces concentric.CaseStudyCardProvenance,CaseStudyCardProductAccess: the shape of the presentation metadata a consumer passes in.
The package ships no card records. There is no roster, no slug list and no copy in this package: every card's destination, identity mark, product proof, headline and result is consumer-owned and passed as props. That is deliberate, and it is why the type is exported but the data is not.
Install
npm install @super-ic/web-patterns @super-ic/foundation @super-ic/primitives react react-dom@super-ic/foundation (^0.2.0) and react (>=19) are peer
dependencies. Install them yourself; this package will not pull them in.
@super-ic/icon-contracts is a hard dependency and comes along automatically;
the card renders its forward chevron through it.
Three mandatory setup steps
The existing case-study card ships JSX and Tailwind class strings. Its layout
requires the token and Tailwind steps below. NeighborhoodLanding additionally
ships its own exported recipe stylesheet, documented below. Skip the
nucleo bind and Icon throws IconGlyphsNotBoundError at render.
1. Import the token stylesheet once
import "@super-ic/foundation/tokens.css";Import it once at the application root, before anything renders. It defines the
:root layer the card's classes resolve against, including --radius-card,
--radius-card-frame, --elev-card, --elev-pill, --motion-hover-duration
and --motion-ease-quiet. Without it the card has square corners, no
elevation, and no hover transition.
2. Import the package Tailwind bridge
Tailwind v4 does not scan node_modules, so the utility classes this package
emits generate no CSS unless the package's built output is scanned. Import
Tailwind once, then import the public bridge. The bridge scans this package's
distributed JavaScript and includes the public primitives bridge:
@import "tailwindcss";
@import "@super-ic/web-patterns/tailwind.css";Omit the owning bridge and the card renders as unstyled markup with correct semantics.
3. Bind Nucleo glyphs once at the application root
The card draws its control chevron through @super-ic/icon-contracts Icon.
That component throws IconGlyphsNotBoundError unless the consumer evaluates
the nucleo subpath before the first render:
import "@super-ic/icon-contracts/nucleo";Import it once in a module that runs on both the server and the client. A server-only import leaves the client unbound after hydration. The package contract test binds this subpath before it renders a card. Product tests should do the same, or they will mask a production outage.
Access contract: locked requires onUnlock
access defaults to "open", which renders an anchor to href. Setting
access="locked" renders a single role="button" control with
aria-haspopup="dialog" and no href, so the consumer's own gate decides
what happens.
That control has to do something, so the component fails closed rather than rendering a dead card:
/* Throws: Locked case-study cards require an unlock handler */
<CaseStudyCard href="/case-studies/example" access="locked" {...rest} />/* Correct */
<CaseStudyCard
href="/case-studies/example"
access="locked"
onUnlock={() => setGateOpen(true)}
lockedControlRef={gateReturnFocusRef}
{...rest}
/>The throw happens during render, in development and production alike. Pass
lockedControlRef so focus can return to the card after your dialog closes.
Framework-native navigation
An open card renders a plain <a> by default. To route through a framework
link, supply renderOpenControl. It receives the full set of control props
(href, className, the data-* slots, aria-label, aria-describedby) and
must spread all of them onto whatever it renders:
<CaseStudyCard
href="/case-studies/example"
renderOpenControl={({ children, ...props }) => <Link {...props}>{children}</Link>}
{...rest}
/>Known gap
One token family the card's class names is not in
@super-ic/foundation/tokens.css today:
--enterprise-bg/--enterprise-fg(viabg-enterprise-bgandtext-enterprise-fg) are excluded from the generated layer on purpose. In the source they are a site-local plate bound to the dark ramp, so emitting them would ship a permanently dark card. See the@super-ic/foundationREADME. The public Tailwind bridge supplies the foundation mappings forborder-border,ring-ringandring-offset-background. Until the enterprise plate is closed in a consumer's own stylesheet, its surface inherits the page background. Everything else (geometry, hierarchy, radii, elevation, motion and the whole accessibility contract) resolves from the token layer and public bridge.
NeighborhoodLanding (candidate)
Sharing-tab foreground, background and borders change together without a color transition. This preserves readable inactive and selected labels during theme initialization as well as keyboard selection. Verify both themes at natural phone size; a difference between background colors alone does not prove legibility.
NeighborhoodLanding is an object-led public community landing recipe. It pairs
a tangible illustrative example with two ways to participate, a residency and
joining section, practical disclosures, and legal/help destinations. Its CSS
belongs to the package; product consumers must not recreate this composition.
This is a review candidate, not an accepted product or release claim.
import { NeighborhoodLanding, type NeighborhoodLandingProps } from "@super-ic/web-patterns";
import "@super-ic/foundation/tokens.css";
import "@super-ic/web-patterns/neighborhood-landing.css";
// Bind the approved semantic glyph provider at server and client roots.
import "@super-ic/icon-contracts/nucleo";
const page: NeighborhoodLandingProps = /* product-owned content and routes */;
<NeighborhoodLanding {...page} />;The consuming Tailwind v4 entry must compile the public primitive bridge:
@import "tailwindcss";
@import "@super-ic/web-patterns/tailwind.css";The package bridge scans web-patterns and the primitives' built output and
provides foundation utility mappings and Accordion animations. Recipe layout comes from
neighborhood-landing.css; do not scan a private DS source path. The recipe uses
public buttonVariants on real anchors so navigation retains link semantics,
plus public Tabs, Accordion and semantic icons. It does not use a button role on
an anchor or implement replacement keyboard behavior. The recipe's module has a
client directive because its disclosures and tabs are interactive.
The product supplies brand, media, copy, eligibility, join availability, routes,
and each claim. membership.join is a required discriminated union:
available: one destination withlabeland realhref, plus a truthful note.unavailable: reason/title, explanation and a real help destination. No disabled fake submit button or implicit waitlist is rendered.
hero.availability is also required. Keep it consistent with the product's
actual activation state. An unfinished DS build does not determine production
membership availability. This component never creates accounts, verifies
residency, collects email, sends support messages, or claims backend readiness.
renderLink may adapt external page destinations to a framework link. Forward
all received anchor properties, including href, className, children and focus
behavior. Internal skip, how-it-works and join anchors remain native document
navigation. The calling application supplies its route implementation and
back/forward behavior. Do not replace real destinations with # or silently
swallow links. The specimen's dialog destinations are explicitly labeled local
previews and are not part of this package.
Contract and proof
- Two participation examples are required, each with a stable unique ID and three real explanatory steps. These are examples, not fabricated posts. Asking/offering copy belongs to the tenant. Keyboard Left/Right selects tabs; Enter/Space operates disclosure triggers. The underlying public primitives own these semantics.
- Every link has visible text or the brand's accessible name. The main, sharing and membership sections have stable per-instance IDs and programmatic focus targets for native anchor navigation. FAQ questions name their own buttons.
- Hero media requires src, nonempty alt, intrinsic dimensions and a visible
caption. Optional possibility and example media use the public
NeighborhoodLandingMediashape. Possibility IDs must be unique. Test failures both before hydration and after handlers attach; neither path may leave a broken image or hide the associated copy and action. These images are informative only, lazy-load outside the hero, use contain presentation, and disappear independently on error; their surrounding copy and actions remain. A newsrcresets that failure state. Media never establishes runtime availability, membership or authority. The consumer retains the rights/provenance record. No supplied media or participation example may imply existing inventory or real demand without evidence. The package contains no photos or tenant records. - Layout uses the foundation's type, spacing, surface, action, border, radius and focus roles. The optional tenant accent-quiet role falls back to surface-2 for a brand without that role. Width responds to the actual recipe container, not only the viewport. Reduced motion preserves all content and actions.
- Allowed composition: a page-level landing, with a brand mark, short copy, illustrative photo, two participation explanations and plain-text/linked FAQ answers. Keep links and small paragraphs inside answers, not nested modals, primary actions or another page recipe.
- Anti-patterns: fake member counts, listings, testimonials or trust scores; blanket safety/insurance claims; public addresses or residency evidence; inactive paid/service modes presented as available; repeated feature-card walls; an application form that the consumer cannot actually submit.
- Limits: one landing/main landmark per page; exactly two examples and three steps per example; unique IDs within each repeated collection; no invented density modes or loading states. Text can grow without clipping, but long hero copy weakens the first-viewport composition and needs editorial review.
- Ownership: shared recipe and its browser contract belong to SuperIC DS; resident policy, routes, activation, claims and support belong to the consuming product. The candidate has no automatic promotion path.
- Migration: replace page-local marketing shells with the public recipe and exported CSS after review. Existing marketing exports remain unchanged; this addition does not retroactively accept their legacy behavior.
Executable requirements in contracts/neighborhood-landing.json bind to the
candidate stories and the actual neighborhood-landing.browser.test.ts titles.
Those bindings are an input to the coordinator's canonical catalog integration,
not a fabricated accepted-registry record. A file being present is not proof of
execution. Record the executed report and exact source/package hashes when this
candidate is integrated; repeat installed-consumer checks on the final graph.
Public help and documents
Import PublicSiteFrame, PublicArticle, HelpDirectory and PublicAvailability
from @super-ic/web-patterns, with @super-ic/web-patterns/public-content.css.
These are candidate recipes. Compile the public foundation/primitives Tailwind
bridge and load the tenant's public font sheets at the consumer root.
PublicSiteFrame owns the public header, one main landmark, skip link and footer.
Compose exactly one h1-owning article, help directory or availability boundary.
Pass real links and preserve normal browser modifier-key behavior in onNavigate.
Navigation IDs must be unique and at most one item is current. Marks use their
natural aspect ratio at a 100px width; the consumer supplies the actual tenant mark.
PublicArticle receives a title, introduction, optional factual date/version label,
optional notice, stable section slugs, trusted React prose and related routes. Use
paragraphs, lists, description lists, links and h3 subheadings in section bodies.
Do not inject raw HTML or another page/main/h1. Section IDs must be unique lowercase
slugs. The table of contents uses native fragment links and a native disclosure so
document navigation and all prose remain usable without JavaScript. This native
document disclosure is intentional; it does not replace application dialogs or
shadcn form controls. Supplied metadata is not a legal-readiness or acceptance claim.
Set anchorId to a stable lowercase slug when a document needs stable deep links.
The consumer must keep each supplied anchorId unique within the rendered document;
omitting it retains instance-safe fragment IDs. Article prose supports semantic tables
with a muted, left-aligned caption and token-bound reading rows.
HelpDirectory uses public Input and Button controls. The consumer supplies query,
search commands and mutually exclusive ready, empty, loading or failed results.
Ready groups need unique IDs and useful topic links. Keep the query on failure,
invalidate old results after a newer query/route and never interpret a successful
search as a support submission. The separate contact action is a real supplied route.
Set search.action for a native GET fallback before hydration, and optionally set
search.queryName when the query parameter is not q. Hydrated submission prevents
the native navigation and calls the controlled search callback.
PublicAvailability displays a public-safe closed, restricted, sign-in, unavailable
or loading projection. The product supplies the reason, permitted recovery links
and retained intent. Do not infer authorization from query parameters or render an
old private action during loading. No waitlist, membership or legal document exists
merely because the recipe renders.
The nine historical marketing.tsx values are removed from this candidate public
API. Their original examples remain privately under stories/legacy-support/.
NeighborhoodLanding replaces MarketingHero/ValueHypothesisBlock/HowItWorksSteps;
PublicArticle replaces DocumentPage/DocumentSection/DocumentVersionNotice and can
show a supplied notice; the controlled app-patterns SupportIntake replaces the
inert SupportIntakeForm/SupportReceivedState. The removal manifest is
design-system/retired-web-exports.json in the authoring repository. Retirement
does not close the complete product responsibilities or confer acceptance.
PublicDocumentDialog is the controlled document reader for policy, privacy and other
reference content opened from a form. Import @super-ic/web-patterns/public-content.css.
Supply open, onOpenChange, title, description, contentLabel, returnLabel and
trusted React prose as children. Put h3 headings inside its sections. The viewport
layout keeps the heading and return action visible while the prose scrolls. It uses
the public Sheet focus behavior and restores the opener; allow Base UI's scheduled
focus-guard handoff before asserting the resulting target. Place the consumer's public
PortalContainerProvider inside the active tenant/theme scope. Opening or closing the
reader must not accept any consent or submit/clear the form. Document validity,
publication status and authorization remain product responsibilities.
Powered by SuperIC
Import PoweredBySuperIC from @super-ic/web-patterns or its /powered-by-superic subpath. The normal @super-ic/web-patterns/tailwind.css aggregate includes its styling automatically; the dedicated @super-ic/web-patterns/powered-by-superic.css subpath remains available with the shared foundation stylesheet. The exact approved outlined wordmark is provided by the peer package @super-ic/brand-contracts/superic-logo.
The neutral attribution preserves href, variant (auto, light, dark), size (sm, md), label, source, and className. Auto uses the nearest inherited semantic theme without client state or SVG swapping. Sizes preserve 14px/18px logos with 11px/12px labels. The small label is supplementary attribution, not an instruction or form label. Explicit variant secondary text uses the existing readable semantic role. HTTP(S) and root-relative destinations are accepted; referral parameters preserve existing query fields and hashes. External-link target behavior is _blank with noopener noreferrer.
