Design system · @bebshai/ui

Components

The monitoring kit in @bebshai/ui. Import from @bebshai/ui/components/…; each demo is the real component.

Status badges

status-badge.tsx. Icon plus label, never colour alone. Op badges are mono letters with the full word as their accessible name.

DebugInfoWarnErrorFatal
SuccessFailureBlockedIUDGETPOST200404503RunningSucceededFailed

Filter bar

filter-bar.tsx. Search, the single most-used facet inline (dashed until set), time range (≥1024px), and Filters with a count. Filters is a popover on desktop and a bottom sheet on phones; edits apply on Apply.

Level: Error

State: {"q":"","level":["error"],"time":{"preset":"24h"}}

DoKeep exactly one facet inline; everything else lives behind Filters.

Dense table with keyset paging

data-table.tsx with dense, keyset, onRowClick, activeRowId and stackOnMobile. Rows are keyboard reachable: Tab to a row, j/k to move, Enter to open. Below 768px rows become stacked cards.

LevelErrorTime12:03:07CodeinternalMessageinternal errorRoute/v1/admin/tenants
LevelErrorTime11:42:07Codejob.realtime.sweepMessagejob failedRoute—
LevelErrorTime11:17:07Codedb.deniedMessagedb access deniedRoute/v1/workspaces/{slug}/members
LevelTimeCodeMessageRoute
Error12:03:07internalinternal error/v1/admin/tenants
Error11:42:07job.realtime.sweepjob failed—
Error11:17:07db.denieddb access denied/v1/workspaces/{slug}/members

Pager

pager.tsx. The one pager: DataTable's pagination and keyset footers, the orders and customers lists and the order history all render it. The summary sits left; the Rows select, then the buttons, sit right. One control height (control-sm) for every piece.

Numbered: outline ‹ ›, ghost numbers, the current page outline. Below 640px it folds to ‹ 5 / 9 ›.
Next only (keyset, or the total is unknown): Newest from page 2 on, then Newer / Older or Next.
DoUse the kit Pager (or DataTable's pagination / keyset) for every list footer; pass labels and digits in the reader's language.
Don'tHand-roll page buttons, fill the current page with the primary colour, or hide ‹ › at the ends (disable them).

Stat tiles and panels

stat-tile.tsx. The sparkline runs to the card's left, right and bottom edges, with no end dot.

5xx rate+0.12 pt
0.42%
+0.12 pt
p95 latency−38 ms
312 ms
−38 ms
Failed sign-ins+19
37
+19
Failed jobs−2
1
−2

Log volume by severity

13:0001:0012:00 UTC
Peak 104 · gridline 100
InfoWarnErrorFatal

Report charts

headline-figure.tsx, trend-chart.tsx, waterfall.tsx, segment-bar-list.tsx (and bar-list.tsx's tones): the Reports page's pieces. Colour means something (profit, loss, warning); volumes stay neutral; every chart has its numbers as text or an sr-only table.

Profit৳61,700↑ 12% ↑ 12% compared with September৳55,100 before
  • Sales
  • Costs & expenses
  • Profit
Sales, costs and profitSalesCosts & expensesProfit
1 Oct৳16,000৳21,000−৳5,000
2 Oct৳9,000৳6,500৳2,500
3 Oct৳17,000৳11,000৳6,000
4 Oct৳18,000৳12,500৳5,500
  1. Net sales৳3,45,600
  2. Goods−৳1,82,400
  3. Courier & returns−৳34,400
  4. Expenses−৳67,100
  5. Profit৳61,700
  • 0–3 days
  • 4–7 days
  • 8–15 days
  • Over 15 days
  • Steadfast৳1,31,300
  • Pathao৳47,000
  • Silk saree19 sold · 23.9% margin৳19,495
  • Phone stand23 sold · −4% margin−৳316

Detail sheet pieces

key-value-list.tsx, code-block.tsx and json-diff.tsx: the sections of a detail sheet.

Summary

Level
Fatal
Code
panic
Route
/v1/uploads
Request
01a0e7e8-83bf-7b62-9dd4-1e5281c377a7
Tenant
—

Stack trace

goroutine 1558 [running]:
runtime/debug.Stack()
	/usr/local/go/src/runtime/debug/stack.go:26 +0x67
github.com/stackrover/bebshai/apps/api/internal/server.recoverer.func1.1()
	/app/internal/server/middleware.go:305 +0xac
panic({0x1b521e0?, 0xc000235dd0?})
	/usr/local/go/src/runtime/panic.go:859 +0x125
github.com/stackrover/bebshai/apps/api/internal/server.(*Server).handleCreateUpload(...)
	/app/internal/server/uploads.go:41 +0x1d3

Metadata

{
"slug": "acme-bd",
"plan": "pro",
"status": "trial",
"limits": {
"members": 25,
"storageGb": 50
},
"tags": [
"dhaka",
"wholesale"
],
"trialEndsAt": null
}

Changes

- name: "Acme BD"
+ name: "Acme Bangladesh"
password_hash: "[redacted]"
- plan: "free"
+ plan: "pro"
status: "trial"

Request timeline

request-timeline.tsx. Every stream for one request id, merged oldest first.

  1. 12:04:07.301
    POST /v1/admin/tenants 20138 ms · 198.51.100.23
  2. 12:04:07.318
    I tenants · acme-bdRow change by [email protected]
  3. 12:04:07.319
  4. 12:04:07.330
    Warn slow query231 ms

Radio cards

radio-card.tsx. A real radio group of cards (role pickers, plan choices): arrow keys move the selection, the selected card is the tab stop, Space or Enter selects. The indicator dot shows the choice, so it never rests on colour alone. A disabled card can say why.

Image upload

image-upload.tsx. A square preview tile with Upload, or Replace and Remove, beside it (the business profile logo). Type and size are checked before upload and fail inline; while uploading the tile shows a local preview, a progress bar (indeterminate until the first progress report) and disabled buttons; a failed upload restores the previous image. Drop a file on the tile or use the buttons. uploadWithProgress PUTs to a presigned URL with progress. Here a file whose name starts with “fail” fails.

Shop logo
Logo

PNG, JPG or WebP, up to 2 MB

Invoice header

PNG, JPG or WebP, up to 200 KB

Favicon
Favicon

Only owners can change this

Catalog inputs

money-input.tsx (MoneyInput, QuantityInput), chips-input.tsx, image-grid.tsx, category-picker.tsx, media-thumb.tsx and bulk-bar.tsx: the product editor's pieces (docs/design/catalog-stock.md § 4). Amounts and quantities parse with the same rules as the Go API (packages/contracts/test/money-cases.json).

Type Latin or Bangla digits. The value is base units: whole taka, grams, inches. Blur shows lakh grouping in Bangla. Try 850.50 or 1.5 pcs.
লালনীলসবুজ
Enter or a comma adds; a pasted “S, M, L” adds three; Backspace in the empty field removes the last. Duplicates (any case) are skipped.
Cover
4:5 shape. Drag to reorder, or focus a tile and use Alt + ← / →; Delete removes. The first photo is the cover (2×2).
No photos: the whole card is one drop zone.
CategoryPicker: roots first; → or Enter drills in, ← goes back; typing searches every level with paths (Bangla or English). + Create adds under the current level.
3 selected
MediaThumb (sm, default 32px, lg, xl; a muted icon without a photo, a CSS crop until the cropped copies exist) and BulkBar (Esc clears; narrow it and the last actions fold into ⋯).
NameOnline
  • Women
  • Saree
  • Jamdani
  • Taant
  • Three-piece
  • Men
  • Panjabi

Drag a row by its handle, or focus one and press Alt+↑ / Alt+↓.

TreeList: a tree as a clean list. Drag onto the middle of a row to nest (three levels at most), onto its top or bottom quarter to place before or after; ← → close and open.
DoKeep amounts in whole taka and quantities in base units; the inputs only parse and display.
Don'tShow a toast for a typing error: put the onError reason under the field.

Rich text

rich-text/rich-text-editor.tsx and rich-text-view.tsx (Tiptap v3, MIT extensions). The product description: exactly the blocks and marks the API accepts (docs/api/phase-1a.md § Rich text), stored as JSON, images by media id. Toolbar, bubble menu, floating +, slash menu with Bangla keywords, block handle (drag, or click for Turn into, Duplicate, Move, Delete; ⌘⇧↑ / ⌘⇧↓, ⌘D), markdown shortcuts. Input rules and the slash menu wait for IME composition to end.

RichTextEditor: type / for blocks (/শিরোনাম, /table), select text for the bubble, hover a block for its handle. Paste or drop an image to see the upload placeholder.

কেন এই জামদানি শাড়ি

নারায়ণগঞ্জের তাঁতিদের হাতে বোনা, খাঁটি সুতি। হালকা, নরম, আর সারাদিন আরামদায়ক।

  • দৈর্ঘ্য ১২ হাত, সাথে ব্লাউজ পিস

  • রং না ওঠার নিশ্চয়তা

প্রথম ধোয়া ঠান্ডা পানিতে, আলাদা করে।

ফেরত দেওয়া যাবে?

হ্যাঁ, ৭ দিনের মধ্যে, না পরা অবস্থায়।

RichTextView of the same document. The API check passes (242 characters, 0 images).
DoValidate with validateRichText (@bebshai/contracts) before saving; it is the Go validator's rules.
Don'tStore or render HTML, or offer colours, fonts or alignment: the storefront theme owns them.

Language switch

language-switch.tsx. বাংলা / English, the same pill as the theme switcher. Each label carries its own lang; never uppercase or tracked. Used in the user menu's Language row and top-right on pre-auth pages (size sm).

Shell pieces

theme-switcher.tsx, user-menu.tsx, live-indicator.tsx and command-menu.tsx (⌘K). The second avatar is the tenant menu: Your account, Switch workspace, the Language row above Theme, and labels fed from the locale (switch it above).

LiveConnectingPaused

Search

Search orders, customers, products or pages…

Search

Search pages and commands…