Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libs/ui/agent-plugin/skills/component-usage-ux/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Tree widget with arrow-key selection -> tree-view-usage
Loading placeholder -> skeleton-usage
Catalog search navigation -> search-suggestions-usage
Catalog facet filtering -> facet-filter-panel-usage
Cart/order product row -> line-item-usage
Prepared amount breakdown and total -> totals-summary-usage
Quantity with unit/help/error/pending -> quantity-field-usage
Bare numeric draft or stepper -> numeric-input-usage
Shortcut hint or keyboard registration -> hotkeys-usage
Expand Down
96 changes: 96 additions & 0 deletions libs/ui/agent-plugin/skills/line-item-usage/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
name: line-item-usage
description: >
Use after component-usage-ux when an app needs @techsio/ui-kit LineItem
compound composition for editable cart rows, compact previews or read-only recaps.
metadata:
component_version: "1.0.2"
type: "core"
library: "@techsio/ui-kit"
library_version: "0.3.2"
requires: "component-usage-ux quantity-field-usage price-block-usage app-token-overrides ux-guidelines"
sources: "libs/ui/src/organisms/line-item.tsx libs/ui/src/tokens/components/organisms/_line-item.css libs/ui/stories/organisms/line-item.stories.tsx libs/ui/docs/cart-presentation-figma-handoff.md"
---

# @techsio/ui-kit LineItem usage

LineItem is a compound presentation organism. Applications own DTO mapping,
formatting, routing, inventory, validation, saving and removal requests.

LineItem uses React context and is a client module. In Next.js, compose the root
and its compound parts inside a wrapper with `"use client"`, including read-only
order recaps. A Server Component can render that wrapper with serializable data;
do not access `LineItem.Body` or other compound properties in a Server Component.

## Setup

```tsx
import { LineItem } from "@techsio/ui-kit/organisms/line-item"
import { PriceBlock } from "@techsio/ui-kit/molecules/price-block"
import { QuantityField } from "@techsio/ui-kit/molecules/quantity-field"

<LineItem title="Montážní sada M8" readOnly={readOnly}>
<LineItem.Body>
<LineItem.Heading>
<LineItem.Title />
<LineItem.Price><PriceBlock state="known" amountLabel="498 Kč" /></LineItem.Price>
</LineItem.Heading>
<LineItem.Options>100 ks · pozink</LineItem.Options>
<LineItem.Controls>
<LineItem.Quantity readOnlyLabel="2 balení">
<QuantityField label="Množství: Montážní sada M8" unitLabel="balení"
value={draft} onValueChange={({ value }) => setDraft(value)} />
</LineItem.Quantity>
<LineItem.Actions><LineItem.Remove label="Odebrat" onClick={removeItem} /></LineItem.Actions>
</LineItem.Controls>
</LineItem.Body>
</LineItem>
```

## Compound contract

- Root requires plain product `title` and `children`. `layout="compact"` reduces
image size and spacing. Root shares layout, readOnly and pending through context.
- Parts must render inside LineItem; otherwise they throw a descriptive error.
- `Image` wraps Image or the app's image adapter. It is optional; omit the whole
part if no image is available. The default grid uses two columns for a direct
Image child and one column without it.
- `Body`, `Heading`, `Title`, `Price`, `Options` and `Controls` arrange content.
`Title` defaults to the root title, or accepts a Link containing the same name.
`Price` accepts PriceBlock or an already formatted line amount.
- Supply AvailabilityStatus and StatusText directly where the composition needs
availability and item-level error feedback. No new engine is added for either.
- `Quantity` requires `readOnlyLabel` even in an editable composition. In readOnly
it renders that text and does not mount its editable children. In pending it
makes the editable children inert. Prefer QuantityField and pass pending to it
as well for its visual and native input state.
- Put custom mutation actions inside `Actions`. In readOnly the whole part is
omitted; pending makes its children inert. App-owned actions should also use
disabled for visual feedback. Navigation links may remain outside Actions.
- `Remove` renders the kit Button with a required visible localized `label`, adds
the root product title to its accessible name and forwards Button props/ref.
It is omitted in readOnly and disabled in pending even outside Actions.
Callers cannot override its accessible name via aria-label/aria-labelledby.
- `pending` requires localized `pendingLabel`. Root renders and associates the
feedback automatically below the composed content; no implicit live region.
- The root cannot inspect arbitrary child components. Use Quantity, Actions and
Remove for editable controls so the shared state guards apply.

## UX/UI guidelines

- Keep product name, options, price and quantity recognizable across contexts.
- Use compact presentation for a preview and ordinary spacing for the main cart.
- Unavailable items may remain removable. The app decides quantity restrictions.
- Keep a rejected draft visible and place its error near the relevant item.
- Preserve the supplied amounts while updating; never calculate totals here.
- Read-only recaps show quantity text and omit mutation actions.

## Tokens and stories

Override LineItem tokens for local presentation needs. Brand-wide changes belong
in semantic tokens. Styles use `src/tokens/components/organisms/_line-item.css`.

Organisms/LineItem covers editable, read-only, pending, unavailable, item error,
compact/long content and CustomComposition. The custom story demonstrates an
omitted image, a relocated price and extra actions with the same shared guards.
Figma handoff follows component-to-figma after API stabilization.
69 changes: 69 additions & 0 deletions libs/ui/agent-plugin/skills/totals-summary-usage/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
name: totals-summary-usage
description: >
Use after component-usage-ux when an app needs @techsio/ui-kit TotalsSummary
to present prepared cart or checkout rows, unresolved fees, discounts,
a labeled total and actions blocked while updating.
metadata:
component_version: "1.0.0"
type: "core"
library: "@techsio/ui-kit"
library_version: "0.3.2"
requires: "component-usage-ux app-token-overrides ux-guidelines"
sources: "libs/ui/src/molecules/totals-summary.tsx libs/ui/src/tokens/components/molecules/_totals-summary.css libs/ui/stories/molecules/totals-summary.stories.tsx libs/ui/docs/cart-presentation-figma-handoff.md"
---

# @techsio/ui-kit TotalsSummary Usage

Use TotalsSummary for a cart or checkout breakdown of already prepared labels
and values. Applications own calculations, currency formatting, tax rules,
transport/payment selection, requests and order submission.

## Setup

```tsx
import { TotalsSummary } from "@techsio/ui-kit/molecules/totals-summary"

<TotalsSummary
rows={[
{ id: "goods", label: "Goods", value: "€50.00" },
{ id: "shipping", label: "Shipping", value: "Choose shipping" },
]}
totalLabel="Subtotal including tax"
totalValue="€50.00"
footer="The final total follows shipping and payment selection."
/>
```

## Contract

- rows is a readonly array with stable unique id, label and value strings.
- Each row may have note and emphasis (default or discount).
- totalLabel and totalValue are required strings supplied by the application.
- footer and actions accept consumer content.
- Native div attributes and a div ref are supported.
- pending: true requires a localized pendingLabel. The last supplied values
remain visible, aria-busy describes the update, and the actions wrapper is inert.
Add disabled to action buttons when a disabled appearance is desired.
- The component does not create a live region. The application owns announcements
of completed requests or errors outside the busy summary.

## UX/UI guidelines

Load ux-guidelines and app-token-overrides for composition and appearance.
Do not represent an unselected fee as zero. Supply a clear unresolved label
and call the total a subtotal when final fees are missing. Include the tax
convention in the total label or footer. Show a discount as a separate negative
value; emphasis does not change its amount or sign.

Use PriceBlock for one product's price. Use TotalsSummary for a labeled breakdown.
Do not pass Medusa DTOs, calculation functions or mutation hooks into the summary.
Do not use row notes or footer for mutable order controls: only the actions slot
is blocked while pending.

## Stories

Playground exposes labels, rows, total and pending controls. Partial preserves
unselected fees, Complete shows final fees and an action, Discounted shows a
negative discount, Pending retains amounts and blocks the checkout action,
and CustomRows demonstrates tax and deposit rows without a fixed schema.
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ Each `<component>-usage` skill repeats its own rows in its UX/UI section.
| Product image with thumbnails / zoom | `Gallery` | `Carousel` |
| Horizontally browsable slides (banners, related products) | `Carousel` | `Gallery` |
| Product in a listing | `ProductCard` | custom card divs |
| Product row in cart or order recap | `LineItem` | `ProductCard`, app-owned repeated row markup |
| Prepared amount breakdown and total | `TotalsSummary` | component-owned fee calculations |
| Catalog facets | `FacetFilterPanel` | hand-built accordions of checkboxes |
| Images with fixed ratio / framework optimisation | `Image` (`as={NextImage}`) | `<img>` |
| Decorative or adjacent icon | `Icon` | emoji, inline SVG |
44 changes: 44 additions & 0 deletions libs/ui/docs/cart-presentation-figma-handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# PR10 cart presentation: Figma handoff

LineItem and TotalsSummary implement audit C01/C02. Both are presentational; application formatting, shipping selection, inventory, totals and mutations remain application-owned.

## Component ownership

LineItem is a client module because its compound parts share React context.
Next.js consumers compose the whole row inside a `"use client"` wrapper, even
for read-only recaps. Server Components pass serializable data to that wrapper.

- LineItem is a compound organism. Root shares title, layout, pending and readOnly. Image, Body, Heading, Title, Price, Options and Controls arrange application-provided content. Quantity requires readOnlyLabel and replaces editable children with text in readOnly. Actions omits mutation controls in readOnly and blocks them while pending. Remove uses a localized label containing the root product name, is omitted in readOnly and disabled while pending. Root pending feedback is automatic. AvailabilityStatus and StatusText can be inserted directly; image, price and actions can be omitted or rearranged.
- TotalsSummary is a molecule. It renders supplied label/value rows and notes in a definition list, a separately labeled total, optional footer and actions. Pending preserves the supplied values and blocks actions. An unresolved fee must be supplied as text such as `Choose delivery`, not assumed to be zero.

## Figma component pages

Created through direct Figma MCP using `component-to-figma`:

- [LineItem review page](https://www.figma.com/design/gi5GUSWwAeXknaKEeLqK5w/New-Design-System?node-id=3901-173), page `3898:2`, set `3900:594`, eight layout/readOnly/pending variants.
- [TotalsSummary review page](https://www.figma.com/design/gi5GUSWwAeXknaKEeLqK5w/New-Design-System?node-id=3902-34), page `3898:3`, set `3899:92`, two pending variants. Private row set `3899:25` represents supplied data, not another React component API.

Both pages carry red review markers. Existing pages, component masters, variable values and modes were preserved. Nested PriceBlock, QuantityField, Button, AvailabilityStatus and StatusText are instances. QuantityField instances clear their inherited forced Light mode. Local button paint overrides avoid stale remote bindings inside these new components.

LineItem examples: editable, read-only, compact, pending, unavailable, item error, long product title and custom composition with extra actions. TotalsSummary examples: partial, complete, discounted, pending and custom rows. The cart composition story demonstrates reuse; it does not define another shared component.

## Token binding

Bind component token aliases to existing semantic variables. Preserve the two-layer chain in each component stylesheet. Gap variables use the current Figma conventions and skill workflow. New LineItem image dimensions, title/detail typography and spacing come from existing scale tokens. TotalsSummary content/muted/discount foregrounds, divider, total weight and row/section spacing alias existing tokens. Supporting text uses the primary foreground for readable light/dark defaults; size provides its hierarchy. The existing secondary foreground has insufficient dark-mode contrast and is unchanged.

Source of truth:

- `src/tokens/components/organisms/_line-item.css`
- `src/tokens/components/molecules/_totals-summary.css`
- `src/organisms/line-item.tsx`
- `src/molecules/totals-summary.tsx`

New `line-item` and `totals-summary` collections contain aliases, including reference-to-derived chains. Two missing computed success foreground primitives live in a new `core` collection and are aliased by `semantic/color/success/fg` in Light/Dark. Preview panels switch this semantic collection together with the existing Theme. No existing token collections were reorganized. Figma uses the existing library Inter font; browser system-ui can wrap differently. Fluid image/title/quantity dimensions use 96/120/240 px design references while code retains its clamp expressions.

## Verification and Code Connect

Full review sheets were visually inspected against Storybook. Row notes grow their containers, pending feedback does not overlap, and review sections have no overlap or horizontal overflow. The custom composition moves price below options and supplies an additional outlined action. The item error follows controls. These two composition presets are private static documentation components; the public configurable set remains LineItem.

Local parserless templates are `src/organisms/line-item.figma.ts` and `src/molecules/totals-summary.figma.ts`. `pnpm --dir libs/ui figma:connect:parse` passed with both templates included. This validates parsing, not live template execution in Figma. TotalsSummary converts configurable row helpers to the `rows` data prop; footer/actions remain slots. LineItem maps its root variants and composition slots to the public compound API.

Figma rejected both registration attempts: "Published component not found. Please make sure component/component set is published before mapping." Code Connect remains unregistered. Publish the component sets to the Figma team library, then register the templates. Library publication is independent of a GitHub merge. Nested dependency mappings must also be available for their slot snippets to resolve fully.
3 changes: 2 additions & 1 deletion libs/ui/skills/_artifacts/domain_map.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,8 @@ skills:
toast-usage, breadcrumb-usage, tree-view-usage, skeleton-usage, and
hotkeys-usage for shortcut hints and explicit-store registration,
command-usage for searchable action panels, quantity-field-usage for
controlled quantity drafts with units and pending feedback, and additional entries
controlled quantity drafts with units and pending feedback, line-item-usage for
cart/order rows, totals-summary-usage for prepared amount breakdowns, and additional entries
generated from libs/ui/src inventory.
failure_modes:
- id: "monolithic-usage-guidance"
Expand Down
2 changes: 1 addition & 1 deletion libs/ui/skills/_artifacts/skill_spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Total: 14 skills, 52 failure modes.

| Skill | Subsystems | Reference candidates |
| --- | --- | --- |
| `component-usage-ux` | per-component usage layer | `button-usage`, `input-usage`, `link-button-usage`, `dialog-usage`, `toast-usage`, `breadcrumb-usage`, `tree-view-usage`, `skeleton-usage`, `quantity-field-usage` for units/drafts/pending, plus additional usage skills generated from `libs/ui/src` inventory |
| `component-usage-ux` | per-component usage layer | `button-usage`, `input-usage`, `link-button-usage`, `dialog-usage`, `toast-usage`, `breadcrumb-usage`, `tree-view-usage`, `skeleton-usage`, `quantity-field-usage` for units/drafts/pending, `line-item-usage` for cart/order rows, `totals-summary-usage` for prepared amount breakdowns, plus additional usage skills generated from `libs/ui/src` inventory |
| `framework-consumer-integration` | Next.js adapter usage | NextLink/NextImage adapter props and prop forwarding |
| `hotkeys-usage`, `command-usage` | shortcuts and searchable actions | independent hints/registrations, compound Command, existing Dialog and shared application callbacks |
| `zag-compound-components` | Zag-backed components | machine/connect patterns and component-specific parts |
Expand Down
36 changes: 36 additions & 0 deletions libs/ui/skills/_artifacts/skill_tree.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1407,3 +1407,39 @@ skills:
- src/tokens/components/organisms/_table.css
- stories/organisms/table.stories.tsx
- skills/_artifacts/consumer_app_usage_rules.md

- name: line-item-usage
slug: line-item-usage
type: sub-skill
domain: consumer-app-adoption
path: skills/line-item-usage/SKILL.md
package: libs/ui
description: Compound cart and order rows with shared editable/read-only and pending guards.
requires:
- component-usage-ux
- quantity-field-usage
- price-block-usage
- app-token-overrides
- ux-guidelines
sources:
- src/organisms/line-item.tsx
- src/tokens/components/organisms/_line-item.css
- stories/organisms/line-item.stories.tsx
- docs/cart-presentation-figma-handoff.md

- name: totals-summary-usage
slug: totals-summary-usage
type: sub-skill
domain: consumer-app-adoption
path: skills/totals-summary-usage/SKILL.md
package: libs/ui
description: Prepared amount breakdowns, unresolved fees and explicit totals without calculations.
requires:
- component-usage-ux
- app-token-overrides
- ux-guidelines
sources:
- src/molecules/totals-summary.tsx
- src/tokens/components/molecules/_totals-summary.css
- stories/molecules/totals-summary.stories.tsx
- docs/cart-presentation-figma-handoff.md
2 changes: 2 additions & 0 deletions libs/ui/skills/component-usage-ux/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Tree widget with arrow-key selection -> tree-view-usage
Loading placeholder -> skeleton-usage
Catalog search navigation -> search-suggestions-usage
Catalog facet filtering -> facet-filter-panel-usage
Cart/order product row -> line-item-usage
Prepared amount breakdown and total -> totals-summary-usage
Quantity with unit/help/error/pending -> quantity-field-usage
Bare numeric draft or stepper -> numeric-input-usage
Shortcut hint or keyboard registration -> hotkeys-usage
Expand Down
Loading
Loading