> ## Documentation Index
> Fetch the complete documentation index at: https://www.twicecommerce.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Design Patterns

> The handful of structural UI patterns TWICE repeats everywhere — tables, tabs, attributes, relationships, and permissions.

<Snippet file="definitions/design-patterns-definition.mdx" />

A small set of design patterns repeat across every part of TWICE. Once you know how a stock item's detail page works, you already know how an order, a customer, and a listing work. This page is the map.

## Data tables

The default view for every resource in TWICE is a data table. Inventory, Catalog, Orders, Customers, Collections — all the same component, with the same toolbar.

<Tabs>
  <Tab title="Core features" icon="table">
    | Feature             | Behavior                                                                                  |
    | :------------------ | :---------------------------------------------------------------------------------------- |
    | **Search**          | Full-text search across all values, visible columns and hidden ones                       |
    | **Filter**          | Multiple filter conditions combined with AND; operators match what the backend can answer |
    | **Sort**            | Click any column header to sort ascending or descending                                   |
    | **Group**           | Collapse rows by any compatible column (booleans, selects, dates)                         |
    | **Column controls** | Show, hide, reorder, pin, and resize columns                                              |
    | **Density**         | Three row heights — compact, standard, comfortable                                        |
    | **Export**          | Export the current view to CSV — respects filters and visible columns                     |
  </Tab>

  <Tab title="Saved views" icon="bookmark">
    Any combination of filters, sorts, groups, and column settings can be saved as a **table view**.

    * Save views for personal use or share with the team
    * Switch between views via the view selector at the top of the table
    * Set a default view per table
    * Duplicate or rename existing views

    Views are stored per user and per table; sharing a view exposes it to your team without forcing them onto it.
  </Tab>

  <Tab title="Time-aware features" icon="clock">
    Inventory tables include a date picker in the toolbar. Picking a date or date range re-renders the table to show inventory state at that moment in time — past or future.

    * **Availability checks** — what's free over a specific rental window
    * **Historical reporting** — what was committed on a given day
    * **Forecasting** — projected utilization
  </Tab>
</Tabs>

<Note>
  The table pattern is consistent across inventory, catalog, orders, customers, and collections. Learning it once applies everywhere.
</Note>

Read more: [Tables](/docs/admin/tables) · [Usage patterns](/docs/concepts/repeating-patterns/usage-patterns)

## Detail pages with tabs

Click a row in any table and you land on its detail page. Detail pages follow a consistent layout: a header with the entity's identifying fields and primary actions, then a horizontal tab strip for everything else.

The tab set varies by entity type but follows a predictable rhythm:

| Entity     | Tabs                                                                                                                   |
| :--------- | :--------------------------------------------------------------------------------------------------------------------- |
| Stock Item | General · Attributes · Income & Expenses · Fulfilment · Documents · Events · Activity log                              |
| SKU        | General · Attributes · Stock Items · Documents · Activity log                                                          |
| Listing    | General · Attributes · Pricing · Marketing · Variants · Documents · Publishing · Activity log                          |
| Customer   | General · Attributes · Orders · Stock Items · Documents · Activity log                                                 |
| Order      | Summary · Line Items · Customers · Stock Items · Fulfillment & Return · Payments · Comments · Documents · Activity log |
| Location   | Contact · Time zone · Fulfillment · Sales channels · Opening hours · Emails · Documents                                |

Two tabs appear almost everywhere:

* **Attributes** — custom fields organised by [Attribute Group](/docs/concepts/admin/attribute-groups)
* **Activity log** — the request-level audit trail scoped to this entity

Tab order, badges, and visibility all respect the user's permission grants — tabs the user can't access are hidden, not greyed out.

## Drawer vs. full page

For lightweight create/edit flows TWICE uses a **drawer** that slides in from the right. The drawer keeps you on the current list, so you don't lose context. Heavier flows — adding a Location, configuring a Listing — open a **full-page editor** because they need more screen and break into their own tab structure.

Rules of thumb:

| Pattern          | When                                                                    |
| :--------------- | :---------------------------------------------------------------------- |
| **Drawer**       | Single-form edits, quick creates, configuring an Attribute              |
| **Modal dialog** | Confirmations, deletes, simple two-field forms                          |
| **Full page**    | Multi-tab editors (Location, Listing), workflows with multiple sections |

## Attribute system

Every entity can carry custom fields via [Attributes](/docs/concepts/admin/attributes). The format set is fixed — text, number, boolean, date, datetime, select, multiselect, and formula — but you can define as many Attributes as you need per resource.

### Where Attributes surface

| Context      | Behavior                                                          |
| :----------- | :---------------------------------------------------------------- |
| Data tables  | Appear as filterable, sortable columns                            |
| Detail pages | Editable fields in the Attributes tab, grouped by Attribute Group |
| Exports      | Visible Attribute columns included in CSV                         |
| Workflows    | Available as trigger conditions and action targets                |
| API          | Returned in the `attributes` map on each record                   |

Read more: [Attributes](/docs/concepts/admin/attributes) · [Attribute Groups](/docs/concepts/admin/attribute-groups)

## Relationship models

TWICE organises commerce data into four connected asset types. Each one references others — there are no silos.

```mermaid theme={null}
%%{init: {'flowchart': {'nodeSpacing': 30, 'rankSpacing': 50}}}%%
flowchart LR
    subgraph Inventory["Inventory"]
        SKU["SKU"]
        StockItem["Stock Item"]
    end

    subgraph Catalog["Catalog"]
        Listing["Listing"]
        Collection["Collection"]
    end

    subgraph Orders["Orders"]
        Order["Order"]
        LineItem["Line Item"]
    end

    subgraph Customers["Customers"]
        Customer["Customer"]
    end

    SKU -->|"tracked by"| StockItem
    SKU -->|"presented as"| Listing
    Listing -->|"grouped into"| Collection
    Customer -->|"places"| Order
    Order -->|"contains"| LineItem
    LineItem -->|"reserves"| StockItem
    LineItem -->|"references"| Listing

    style Inventory fill:#3b82f633,stroke:#3b82f6,stroke-width:2px
    style Catalog fill:#10b98133,stroke:#10b981,stroke-width:2px
    style Orders fill:#f59e0b1a,stroke:#f59e0b,stroke-width:2px
    style Customers fill:#a855f71a,stroke:#a855f7,stroke-width:2px
    style SKU fill:#3b82f61a,stroke:#3b82f6,stroke-width:1px
    style StockItem fill:#3b82f61a,stroke:#3b82f6,stroke-width:1px
    style Listing fill:#10b9811a,stroke:#10b981,stroke-width:1px
    style Collection fill:#10b9811a,stroke:#10b981,stroke-width:1px
    style Order fill:#f59e0b1a,stroke:#f59e0b,stroke-width:1px
    style LineItem fill:#f59e0b1a,stroke:#f59e0b,stroke-width:1px
    style Customer fill:#a855f71a,stroke:#a855f7,stroke-width:1px
```

| Relationship           | Direction    | Description                                                 |
| :--------------------- | :----------- | :---------------------------------------------------------- |
| SKU > Stock Item       | One-to-many  | A SKU defines a product; Stock Items are the physical units |
| SKU > Listing          | One-to-one   | A Listing presents a SKU to customers                       |
| Listing > Collection   | Many-to-many | Listings grouped into Collections for merchandising         |
| Customer > Order       | One-to-many  | A Customer places Orders over time                          |
| Order > Line Item      | One-to-many  | An Order contains Line Items                                |
| Line Item > Stock Item | One-to-one   | A Line Item reserves a specific Stock Item                  |
| Line Item > Listing    | Many-to-one  | A Line Item references the Listing the customer selected    |

These relationships mean you can navigate from any entity to its related records — a Stock Item shows the SKU it belongs to, the Listing presenting it, and every Order that has reserved it.

## Status and State

Every primary entity carries a **Status** (lifecycle stage) and most also carry a **State** (operational condition). The values are entity-specific, not universal:

| Entity     | Status values                              | State values                         |
| :--------- | :----------------------------------------- | :----------------------------------- |
| Stock Item | In use / Out of use / Lost / Sold          | In / Out                             |
| Order      | Pending / Draft / Open / Active / Archived | Payment & Fulfillment states (chips) |
| Listing    | Draft / Published / Archived               | —                                    |

Read more: [Status vs State](/docs/concepts/repeating-patterns/status-vs-state)

## Bulk actions

Most tables support row selection via the leftmost checkbox column. Selecting one or more rows reveals a bulk toolbar:

* **Edit** — apply the same attribute change to every selected row
* **Tag / Untag** — apply or remove tags in bulk
* **Archive** — change status to Archived where applicable
* **Delete** — permanent delete (where the entity allows it)
* **Export** — export selected rows as CSV

Bulk actions respect permissions — users without the corresponding scope don't see the bulk toolbar.

## Permission layers

Access control combines three independent layers:

| Layer            | Controls                                     | Values                                     |
| :--------------- | :------------------------------------------- | :----------------------------------------- |
| **Role**         | Base permission level                        | Owner, Admin, Manager, Member              |
| **Visibility**   | Which sections, tables, and tabs are visible | Per-section toggles                        |
| **Access level** | What operations are allowed on visible data  | Manage (full CRUD) or Edit (read + update) |

A user's effective permissions are the intersection of all three. The pattern applies uniformly — inventory, catalog, orders, customers, settings all use the same model.

<Note>
  Tabs and bulk actions hide automatically rather than render as disabled. If a feature isn't visible, check the user's role and visibility settings before assuming the feature is missing.
</Note>

## Example: how the patterns combine

A standard Stock Item API response shows the patterns above in one payload — data-table identity, custom attributes, related references, lifecycle status, and the user's permission to mutate it.

```json theme={null}
{
  "id": "stk_abc123",
  "skuId": "sku_xyz789",
  "status": "active",
  "binLocation": "A-12",
  "serviceLocationId": "loc_def456",
  "attributes": {
    "attr_color": "Navy",
    "attr_condition": "good",
    "attr_serialNumber": "BK-2024-0011"
  },
  "sku": {
    "id": "sku_xyz789",
    "name": "Classic Jacket",
    "code": "JCK-CLS"
  },
  "tags": [{ "id": "tag_winter", "name": "Winter pool" }],
  "createdAt": "2026-01-15T09:22:00.000Z"
}
```

The response carries everything you saw in the UI — the entity's identity, its [Attributes](/docs/concepts/admin/attributes), its relationships to a SKU and a Location, its lifecycle [status](/docs/concepts/inventory/stock-item-status), and the tags applied to it.

## Related

<CardGroup cols={2}>
  <Card title="Tables" icon="table" href="/docs/admin/tables">
    Data table features and operations
  </Card>

  <Card title="Attributes" icon="tags" href="/docs/concepts/admin/attributes">
    Custom fields that extend the data model
  </Card>

  <Card title="Status vs State" icon="arrows-rotate" href="/docs/concepts/repeating-patterns/status-vs-state">
    Per-entity status and state matrices
  </Card>

  <Card title="Usage Patterns" icon="hand-pointer" href="/docs/concepts/repeating-patterns/usage-patterns">
    Day-to-day interaction patterns
  </Card>

  <Card title="OS Approach" icon="microchip" href="/docs/concepts/os-approach">
    The platform philosophy behind these patterns
  </Card>

  <Card title="Activity Logs" icon="clock-rotate-left" href="/docs/concepts/admin/activity-logs">
    The audit trail on every detail page
  </Card>
</CardGroup>
