Skip to content

feat(sirsoft-admin_basic): OneTimeSecretPanel + StatCardGrid composite components#27

Open
Tuwasduliebst wants to merge 1 commit into
gnuboard:mainfrom
Tuwasduliebst:feature/admin-onetime-secret-panel-statcard-grid
Open

feat(sirsoft-admin_basic): OneTimeSecretPanel + StatCardGrid composite components#27
Tuwasduliebst wants to merge 1 commit into
gnuboard:mainfrom
Tuwasduliebst:feature/admin-onetime-secret-panel-statcard-grid

Conversation

@Tuwasduliebst
Copy link
Copy Markdown

Summary

Adds two new composite components to sirsoft-admin_basic that JSON layouts can reference declaratively.

OneTimeSecretPanel

"Shown once, capture now" UX for plaintext secrets — the standard pattern for surfaces like API keys, webhook signing secrets, one-time access tokens. The component:

  • Hides the secret behind an explicit "Reveal" click (defends against shoulder-surfing)
  • Copies to clipboard via navigator.clipboard with a <textarea> + execCommand fallback for non-HTTPS dev contexts
  • Collapses on acknowledgement so the value disappears from the DOM
  • Optional afterAcknowledge: { redirect | dispatch } for post-capture navigation

StatCardGrid

Responsive grid wrapper around the existing StatCard component. Lets layouts express dashboard headers as a declarative stats[] array + column count + responsive breakpoints, instead of hand-rolling the Tailwind grid + iteration boilerplate per layout.

Why

These were originally built for gb7-restapi's admin UI:

  • OneTimeSecretPanel is referenced by admin_gb7_keys_form.json's success screen (showing the plaintext API key exactly once after issuance) and the parallel admin_gb7_webhooks_form.json (webhook signing secret, same UX).
  • StatCardGrid is referenced by admin_gb7_request_logs_index.json's 4-up dashboard header (Total / 2xx / 4xx / 429 traffic stats).

Both are generic enough to belong in core sirsoft-admin_basic — any module that mints secrets or summarises domain stats can reuse them without re-implementing the UX. Without these in core, layouts referencing them render broken on a fresh G7 install (the JSON contract is correct but the components.json registry doesn't know about them).

Conventions followed

  • Pure React + Tailwind, no external state
  • Translation via window.G7Core.t() with sensible English defaults (so missing translations degrade gracefully)
  • Defensive against undefined data while the layout engine loads (don't crash, render empty)
  • components.json manifest entries with full prop documentation (matches the StatCard / CardGrid pattern)
  • Bundled module's dist/ regen happens via the standard npm run build from templates/_bundled/sirsoft-admin_basic/ — no special build step

Compatibility

Purely additive. No changes to existing components, no API breakage, no schema changes.

Test plan

  • npm run build from templates/_bundled/sirsoft-admin_basic/ produces dist/ without TypeScript errors
  • OneTimeSecretPanel renders correctly with value="test-secret" in a sample layout — Reveal → Copy → Acknowledge sequence works
  • StatCardGrid renders 4 StatCards in a row at lg breakpoint, 1 column on mobile
  • Existing layouts (admin_user_list.json etc.) continue to render unchanged

🤖 Generated with Claude Code

…e components

Two new composite components for layouts that need them:

OneTimeSecretPanel
  "Shown once, capture now" UX for plaintext secrets. The secret is
  hidden behind an explicit "Reveal" click (so it doesn't sit on
  screen waiting to be shoulder-surfed), copyable to clipboard via
  navigator.clipboard with a textarea fallback for non-HTTPS
  contexts, and the panel collapses on acknowledgement so the value
  disappears from the DOM.

  Used by gb7-restapi (https://github.com/Tuwasduliebst/gb7-restapi)
  in admin_gb7_keys_form.json's success-screen panel and the parallel
  admin_gb7_webhooks_form.json. Generic enough for any module that
  mints API keys / signing secrets / one-time access tokens.

  Props: value, title, warning, copyButtonLabel, revealButtonLabel,
  acknowledgeLabel, afterAcknowledge ({redirect|dispatch}),
  initiallyHidden (defaults true).

StatCardGrid
  Responsive grid wrapper around the existing StatCard component.
  Lets layouts express dashboard headers declaratively (an array of
  StatCard props + a column count + responsive breakpoints) rather
  than hand-rolling the Tailwind grid + iteration boilerplate every
  time.

  Used by gb7-restapi's admin_gb7_request_logs_index.json for the
  4-up Total / 2xx / 4xx / 429 dashboard. The same pattern fits any
  admin landing page that summarises domain stats.

  Props: stats (StatCardProps[]), columns, gap, responsiveColumns
  ({sm, md, lg, xl}).

Both components follow the existing composite patterns:
  - Pure React + Tailwind, no external state
  - Translation via window.G7Core.t() with sensible English defaults
  - Defensive against undefined data while the layout engine loads
  - components.json manifest entries with full JSDoc-style props

No breaking changes — purely additive.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant