# KView components

> Every component and helper Kustomer gives KView templates, with live previews, a map of where each one fits, a playground, and the props for each.

Source: https://developer.kustomer.com/docs/apps/kview-components

[KView](https://developer.kustomer.com/docs/apps/kviews) templates build their UI from components Kustomer provides. They match the agent desktop, follow the agent's light or dark theme, and handle masked data for you. This page shows where each one fits, lets you try them, and lists every prop.

Components and helpers are global in a template: write `<Field … />` or `_.get(…)` without importing anything.

## Where components go

Each KView renders in one context, and some components are built for a specific one: `Row` edits attributes in the insights panel, `Field` lays out a KObject's body in the timeline, and `CreateFormRow` belongs in create forms.

_A mock agent desktop with four outlined regions: the expanded KObject in the timeline (expanded-timeline), a create form (create-form), the details panel at the top of the insights panel (smartbar-details) and an app card in the insights panel (smartbar-card). Selecting a region lists the components built for it, such as Grid, Column, Field, Images and Pill for the timeline; Row, RowPriority, RowAssignmentUser and RowAssignmentTeam for details; BasicRow, Button, ButtonGroup and DynamicCard for cards; and CreateFormRow for create forms._

## Browse the components

Pick a component to see it render, change its props, and copy the template.

_A filterable grid of every KView component and helper, each with a live preview: layout (Container, Segment, Grid, Column), timeline fields (Field, BasicField, Images), detail rows (Row, BasicRow, CreateFormRow, RowAssignmentUser, RowAssignmentTeam, RowPriority, the deprecated CollapsedRows), relationship cards (Customer, Company, Conversation, Kobject and their Field variants), buttons and pills, embedding (DynamicCard, Card), data (WithUser) and helpers (lodash, moment, KustomerRequest, runCommand, renderHandlebars, internationalizeStandardAttribute, renderSnippet). Selecting one shows its preview, prop controls, the template and its props table._

## Try it

Write a template and see it render in any context. The **Data** tab holds the variables your template reads, as in the Data tab of Kustomer's KView editor; edit them to test missing or unusual values. Turn on **Mask** to see what an agent who can't view the customer's email and phone gets, and switch the preview to dark mode to check your colors.

_A KView editor beside a live preview. Choose a starter (an order in the timeline, a customer card, buttons that call APIs, conversation details, masked data, theme variables, a create form, or state with hooks) and a context. The Code tab holds the template and the Data tab the JSON it reads. The preview renders in the matching part of the agent desktop, in light or dark mode, with masking on or off; errors point to the line in the template. Buttons that call KustomerRequest or runCommand are logged in a Requests panel instead of being sent._

The playground follows Kustomer's rules: context variables are global, the template's last JSX expression is what renders, and syntax errors show the line and column. API calls, commands, links and edits are logged instead of sent, and relationship cards only find the records in the sample data.

## Show rows only when they apply

In the insights panel and in create forms, a row can depend on other attributes: show **Return reason** only when the conversation's **Contact reason** is `return`, for example. Set this in the KView editor's **Conditions** tab, or in the visual builder with **Only show this attribute if…**. Conditions aren't available for `expanded-timeline` views.

_A condition builder. Pick a view (conversation details, customer details, an order create form, or an order in the timeline) and the row to show or hide, then add up to three conditions joined by OR, each with an attribute, an operator (Equals, Has any value, and Starts with or Is within where the attribute allows it) and a value, plus an option to require the row before the conversation is marked done. Beside it, the Conditions JSON updates as you build, with a breakdown of each key into resource, custom marker, klass and attribute, and the 400 errors Kustomer returns for a missing value or a timeline view. Below, a preview of the insights panel lets you change the sample record and see each condition pass or fail, and the row show, hide, or become required._

The Conditions tab holds a JSON object with a key for each row that has conditions:

```json title="Conditions"
{
  "conversation_custom_returnReasonStr": {
    "condition": {
      "op": "or",
      "values": [
        { "op": "eq", "property": "conversation_custom_contactReasonStr", "values": ["return"], "dependentFieldRequired": true },
        { "op": "exists", "property": "conversation_custom_trackingNumberStr", "values": [] }
      ]
    }
  }
}
```

| Key                               | Meaning                                                                                                                                                                                                                                                                                       |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Attribute keys                    | `<resource>_<attribute>` for standard attributes, such as `conversation_brand`; `<resource>_custom_<attribute>` for custom ones, such as `customer_custom_loyaltyTierStr`; and `kobject_custom_<klass>_<attribute>` for KObjects, such as `kobject_custom_order_giftBool`.                    |
| `condition.op`                    | Always `or`: the row shows when any condition matches.                                                                                                                                                                                                                                        |
| `values[].op`                     | `eq` (equals the value; text ignores case), `exists` (has any value) or `startsWith`. The editor offers `startsWith` for free-text custom attributes and conversation and company names, where it's case-sensitive, and for tree attributes, where it matches the value or anything under it. |
| `values[].property`               | The attribute to test, in the same key format: one of the view's own custom attributes, or a standard conversation, customer or company attribute.                                                                                                                                            |
| `values[].values`                 | Required. One value, such as `["return"]` or `[true]`: Kustomer only checks the first, so add a condition for each value you want to match. Use `[]` with `exists`.                                                                                                                           |
| `values[].dependentFieldRequired` | Requires the row before the conversation is marked done, once that condition matches. Only for custom conversation attributes in `smartbar-details` views, and not on conditions that test `conversation_status` or `conversation_subStatus`.                                                 |

When a row's conditions stop matching, Kustomer hides it and clears its value if the agent can edit the record, so a stale answer doesn't stay behind. List attributes such as `conversation_channels` match `eq` when they include the value, and `exists` when they aren't empty.

## Masked data and dark mode

`Field`, `BasicField`, `Row`, `BasicRow` and the other field components show masked values the way the agent is allowed to see them, and Kustomer turns a masked value placed directly inside an element, such as `<div>{email}</div>`, into its masked text. Anywhere else, such as inside a template string or a URL, you get the masked object itself. See [Handle masked data](https://developer.kustomer.com/docs/apps/kviews#handle-masked-data).

Every component follows the agent's theme. For your own markup, use the [theme variables](https://developer.kustomer.com/docs/apps/kviews#support-dark-mode) instead of fixed colors.

## Layout

### `Container`

An outer wrapper that can add Kustomer's standard padding. Works in every context.

| Prop         | Type    | Default | Description                                                 |
| ------------ | ------- | ------- | ----------------------------------------------------------- |
| `usePadding` | boolean |         | Adds 8px of padding on every side. Ignored in create forms. |
| `children`   | JSX     |         | The content.                                                |

```jsx
<Container usePadding>
  <BasicField label="Order" value={object.title} />
</Container>
```

### `Segment`

Groups related content and leaves 28px of space below it. Works in every context.

| Prop       | Type   | Default | Description                                                                            |
| ---------- | ------ | ------- | -------------------------------------------------------------------------------------- |
| `style`    | object |         | Inline styles as an object, such as `style={{ padding: 8 }}`. A CSS string is ignored. |
| `children` | JSX    |         | The content.                                                                           |

```jsx
<div>
  <Segment>
    <BasicField label="Status" value={object.custom.statusStr} />
  </Segment>
  <Segment>
    <BasicField label="Notes" value={object.custom.notesTxt} />
  </Segment>
</div>
```

### `Grid`

Lays out `Column`s in a row 16 units wide. Columns past 16 wrap to the next line; nothing checks the sum. Designed for `expanded-timeline` and `smartbar-card`.

| Prop       | Type   | Default | Description                                                                            |
| ---------- | ------ | ------- | -------------------------------------------------------------------------------------- |
| `style`    | object |         | Inline styles as an object, such as `style={{ padding: 8 }}`. A CSS string is ignored. |
| `children` | JSX    |         | One or more `Column`s.                                                                 |

```jsx
<Grid>
  <Column size="ten">
    <Field type="kobject.order" field="orderNumberStr" value={object.custom.orderNumberStr} />
    <Field type="kobject.order" field="placedAt" value={object.custom.placedAt} />
  </Column>
  <Column size="six">
    <Field type="kobject.order" field="totalNum" value={object.custom.totalNum} />
  </Column>
</Grid>
```

### `Column`

One column of a `Grid`, sized in sixteenths of the row. Designed for `expanded-timeline` and `smartbar-card`.

| Prop       | Type              | Default   | Description                                                                            |
| ---------- | ----------------- | --------- | -------------------------------------------------------------------------------------- |
| `size`     | `one` … `sixteen` | `sixteen` | The width in sixteenths, as a word. A number, such as `size={8}`, has no effect.       |
| `style`    | object            |           | Inline styles as an object, such as `style={{ padding: 8 }}`. A CSS string is ignored. |
| `children` | JSX               |           | The content.                                                                           |

```jsx
<Grid>
  <Column size="eight" style={{ background: 'var(--background-secondary)' }}>
    <BasicField label="Size" value="eight" />
  </Column>
</Grid>
```

## Timeline fields

### `Field`

A labeled value, formatted from the attribute's metadata, so dates, numbers, booleans and links look the way they do elsewhere in Kustomer. Designed for `expanded-timeline` and `smartbar-card`.

| Prop    | Type   | Default | Description                                                                                                         |
| ------- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------- |
| `field` | string |         | **Required.** The attribute name, such as `totalNum`. A name ending in `Rel` renders the related KObject as a card. |
| `type`  | string |         | **Required.** The record type the attribute belongs to: `customer`, `company`, `conversation` or `kobject.<klass>`. |
| `value` | any    |         | The value, usually read with `_.get(object, 'custom.totalNum')`.                                                    |
| `label` | string |         | Replaces the attribute's display name.                                                                              |

```jsx
<Field type="kobject.order" field="placedAt" value={_.get(object, 'custom.placedAt')} />
```

### `BasicField`

A label and a value as you pass them, in the field layout. It doesn't read metadata or format values. Designed for `expanded-timeline` and `smartbar-card`.

| Prop    | Type   | Default | Description |
| ------- | ------ | ------- | ----------- |
| `label` | string |         | The label.  |
| `value` | any    |         | The value.  |

```jsx
<BasicField label="Carrier" value="UPS Ground" />
```

### `Images`

An image carousel with a dot for each image, up to 450px tall. Renders nothing for an empty array. Designed for `expanded-timeline` and `smartbar-card`.

| Prop     | Type      | Default | Description                                                                            |
| -------- | --------- | ------- | -------------------------------------------------------------------------------------- |
| `images` | string\[] |         | **Required.** Image URLs.                                                              |
| `style`  | object    |         | Inline styles as an object, such as `style={{ padding: 8 }}`. A CSS string is ignored. |

```jsx
<Images images={object.images} />
```

## Detail rows

### `Row`

An attribute row for the insights panel. Agents click the value to edit it, and Kustomer saves it to the record. Designed for `smartbar-card` and `smartbar-details`.

| Prop                  | Type    | Default | Description                                                                                                   |
| --------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| `field`               | string  |         | **Required.** The attribute name, such as `returnReasonStr`.                                                  |
| `object`              | string  |         | **Required.** `conversation`, `customer`, `company` or `kobject`: the record the row belongs to and saves to. |
| `value`               | any     |         | The current value, such as `_.get(conversation, 'custom.returnReasonStr')`.                                   |
| `label`               | string  |         | Replaces the attribute's display name.                                                                        |
| `readOnly`            | boolean |         | Shows the value without letting agents edit it.                                                               |
| `editable`            | boolean |         | Lets agents edit a KObject attribute. Conversation, customer and company rows are editable unless `readOnly`. |
| `componentAttributes` | object  |         | `{ readOnly, fullWidth, displayName }`. `fullWidth: true` puts the value under the label.                     |
| `placeholder`         | string  | `—`     | Shown when there's no value.                                                                                  |
| `context`             | string  |         | `create-form` renders a `CreateFormRow` instead.                                                              |

```jsx
<Row
  object="conversation"
  field="returnReasonStr"
  value={_.get(conversation, 'custom.returnReasonStr')}
/>
```

### `BasicRow`

A label and a value in the row layout. It isn't editable and doesn't read metadata. Designed for `smartbar-card` and `smartbar-details`.

| Prop    | Type   | Default | Description |
| ------- | ------ | ------- | ----------- |
| `label` | string |         | The label.  |
| `value` | any    |         | The value.  |

```jsx
<BasicRow label="Loyalty tier" value={_.get(customer, 'custom.loyaltyTierStr', 'none')} />
```

### `CreateFormRow`

One field of a KObject create form, with the input for its type. Designed for `create-form`.

| Prop    | Type   | Default | Description                                                     |
| ------- | ------ | ------- | --------------------------------------------------------------- |
| `field` | string |         | **Required.** The attribute name.                               |
| `klass` | string |         | **Required.** The Klass being created, such as `kobject.order`. |

```jsx
<div>
  <CreateFormRow klass="kobject.order" field="orderNumberStr" />
  <CreateFormRow klass="kobject.order" field="placedAt" />
</div>
```

### `RowAssignmentUser`

The conversation's assignee, with Kustomer's picker for changing it. Designed for `smartbar-details`.

```jsx
<RowAssignmentUser />
```

### `RowAssignmentTeam`

The conversation's team. Renders nothing when the org has no teams. Designed for `smartbar-details`.

```jsx
<RowAssignmentTeam />
```

### `RowPriority`

The conversation's priority, 1 to 5. Agents click to change it. Designed for `smartbar-details`.

```jsx
<RowPriority />
```

### `CollapsedRows`

A wrapper that older generated layouts put around rows. It no longer collapses anything. Designed for `smartbar-details`.

> **Deprecated:** Renders its children unchanged. Leave it out of new templates, or use `Segment` to group rows.

| Prop       | Type | Default | Description  |
| ---------- | ---- | ------- | ------------ |
| `children` | JSX  |         | The content. |

```jsx
<CollapsedRows>
  <RowPriority />
  <RowAssignmentUser />
</CollapsedRows>
```

## Relationship cards

### `Customer`

A link to a customer: avatar and name. Renders nothing until the customer loads. Works in every context.

| Prop | Type   | Default | Description                      |
| ---- | ------ | ------- | -------------------------------- |
| `id` | string |         | **Required.** The customer's ID. |

```jsx
<Customer id={customer.id} />
```

### `CustomerField`

`Customer` with a label, in the field layout. Designed for `expanded-timeline` and `smartbar-card`.

| Prop    | Type   | Default | Description                              |
| ------- | ------ | ------- | ---------------------------------------- |
| `id`    | string |         | **Required.** The customer's ID.         |
| `label` | string |         | **Required.** The label beside the card. |

```jsx
<CustomerField id={customer.id} label="Customer" />
```

### `Company`

A link to a company. Renders nothing until the company loads. Works in every context.

| Prop | Type   | Default | Description                     |
| ---- | ------ | ------- | ------------------------------- |
| `id` | string |         | **Required.** The company's ID. |

```jsx
<Company id={company.id} />
```

### `CompanyField`

`Company` with a label, in the field layout. Designed for `expanded-timeline` and `smartbar-card`.

| Prop    | Type   | Default | Description                              |
| ------- | ------ | ------- | ---------------------------------------- |
| `id`    | string |         | **Required.** The company's ID.          |
| `label` | string |         | **Required.** The label beside the card. |

```jsx
<CompanyField id={company.id} label="Company" />
```

### `Conversation`

A link to a conversation, with its channel's icon. Works in every context.

| Prop | Type   | Default | Description                          |
| ---- | ------ | ------- | ------------------------------------ |
| `id` | string |         | **Required.** The conversation's ID. |

```jsx
<Conversation id={'64f0c1a2e7b9d1001f3a3001'} />
```

### `ConversationField`

`Conversation` with a label, in the field layout. Designed for `expanded-timeline` and `smartbar-card`.

| Prop    | Type   | Default | Description                              |
| ------- | ------ | ------- | ---------------------------------------- |
| `id`    | string |         | **Required.** The conversation's ID.     |
| `label` | string |         | **Required.** The label beside the card. |

```jsx
<ConversationField id={'64f0c1a2e7b9d1001f3a3001'} label="Conversation" />
```

### `Kobject`

A link to a KObject, with its title. Works in every context.

| Prop   | Type   | Default | Description                                       |
| ------ | ------ | ------- | ------------------------------------------------- |
| `id`   | string |         | **Required.** The KObject's ID.                   |
| `type` | string |         | **Required.** The Klass, such as `kobject.order`. |

```jsx
<Kobject id={'64f0c1a2e7b9d1001f3a4002'} type="kobject.order" />
```

### `KobjectField`

`Kobject` with a label, in the field layout. Designed for `expanded-timeline` and `smartbar-card`.

| Prop    | Type   | Default | Description                                       |
| ------- | ------ | ------- | ------------------------------------------------- |
| `id`    | string |         | **Required.** The KObject's ID.                   |
| `type`  | string |         | **Required.** The Klass, such as `kobject.order`. |
| `label` | string |         | **Required.** The label beside the card.          |

```jsx
<KobjectField id={'64f0c1a2e7b9d1001f3a4002'} type="kobject.order" label="Kobject" />
```

## Buttons and pills

### `Button`

The primary action in a view. Works in every context.

| Prop         | Type                                                              | Default   | Description                                                                                                       |
| ------------ | ----------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------- |
| `children`   | string                                                            |           | **Required.** The label.                                                                                          |
| `onClick`    | function                                                          |           | Runs when the agent clicks. Call `KustomerRequest` or `runCommand` here.                                          |
| `link`       | string                                                            |           | A URL to open in a new tab instead. The button renders as a link.                                                 |
| `icon`       | string                                                            |           | A [Material Design Icons](https://pictogrammers.com/library/mdi/) name shown before the label, such as `refresh`. |
| `size`       | `xSmall` \| `small`                                               | `small`   | 26px or 30px tall. `medium` is deprecated and renders as `small`.                                                 |
| `grow`       | `auto` \| `fill`                                                  | `auto`    | `fill` stretches the button to the width of its container.                                                        |
| `marginSize` | `none` \| `small` \| `medium` \| `large` \| `xlarge` \| `xxlarge` | `medium`  | Space above and below. `medium` is 8px.                                                                           |
| `theme`      | `default` \| `ai`                                                 | `default` | `ai` uses the gradient Kustomer gives AI actions.                                                                 |
| `disabled`   | boolean                                                           |           | Grays the button out; clicks don't run.                                                                           |
| `loading`    | boolean                                                           |           | Shows a spinner in place of the icon and disables the button.                                                     |

```jsx
<Button icon="refresh"
  onClick={() => KustomerRequest({ url: `/v1/customers/${customer.id}` }, (err) => (err ? 'Refresh failed' : 'Customer refreshed'))}
>
  Refresh
</Button>
```

### `ButtonSecondary`

An outlined button for actions beside a primary one. Works in every context.

| Prop         | Type                                                              | Default   | Description                                                                                                       |
| ------------ | ----------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------- |
| `children`   | string                                                            |           | **Required.** The label.                                                                                          |
| `onClick`    | function                                                          |           | Runs when the agent clicks. Call `KustomerRequest` or `runCommand` here.                                          |
| `link`       | string                                                            |           | A URL to open in a new tab instead. The button renders as a link.                                                 |
| `icon`       | string                                                            |           | A [Material Design Icons](https://pictogrammers.com/library/mdi/) name shown before the label, such as `refresh`. |
| `size`       | `xSmall` \| `small`                                               | `small`   | 26px or 30px tall. `medium` is deprecated and renders as `small`.                                                 |
| `grow`       | `auto` \| `fill`                                                  | `auto`    | `fill` stretches the button to the width of its container.                                                        |
| `marginSize` | `none` \| `small` \| `medium` \| `large` \| `xlarge` \| `xxlarge` | `medium`  | Space above and below. `medium` is 8px.                                                                           |
| `theme`      | `default` \| `ai`                                                 | `default` | `ai` uses the gradient Kustomer gives AI actions.                                                                 |
| `disabled`   | boolean                                                           |           | Grays the button out; clicks don't run.                                                                           |
| `loading`    | boolean                                                           |           | Shows a spinner in place of the icon and disables the button.                                                     |

```jsx
<ButtonSecondary icon="refresh"
  onClick={() => KustomerRequest({ url: `/v1/customers/${customer.id}` }, (err) => (err ? 'Refresh failed' : 'Customer refreshed'))}
>
  Refresh
</ButtonSecondary>
```

### `ButtonDanger`

An outlined red button for destructive actions, such as cancelling an order. Works in every context.

| Prop         | Type                                                              | Default  | Description                                                                                                       |
| ------------ | ----------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `children`   | string                                                            |          | **Required.** The label.                                                                                          |
| `onClick`    | function                                                          |          | Runs when the agent clicks. Call `KustomerRequest` or `runCommand` here.                                          |
| `link`       | string                                                            |          | A URL to open in a new tab instead. The button renders as a link.                                                 |
| `icon`       | string                                                            |          | A [Material Design Icons](https://pictogrammers.com/library/mdi/) name shown before the label, such as `refresh`. |
| `size`       | `xSmall` \| `small`                                               | `small`  | 26px or 30px tall. `medium` is deprecated and renders as `small`.                                                 |
| `grow`       | `auto` \| `fill`                                                  | `auto`   | `fill` stretches the button to the width of its container.                                                        |
| `marginSize` | `none` \| `small` \| `medium` \| `large` \| `xlarge` \| `xxlarge` | `medium` | Space above and below. `medium` is 8px.                                                                           |
| `disabled`   | boolean                                                           |          | Grays the button out; clicks don't run.                                                                           |
| `loading`    | boolean                                                           |          | Shows a spinner in place of the icon and disables the button.                                                     |

```jsx
<ButtonDanger icon="refresh"
  onClick={() => KustomerRequest({ url: `/v1/customers/${customer.id}` }, (err) => (err ? 'Refresh failed' : 'Customer refreshed'))}
>
  Refresh
</ButtonDanger>
```

### `ButtonText`

A button without a border, for low-emphasis actions. Works in every context.

| Prop         | Type                                                              | Default   | Description                                                                                                       |
| ------------ | ----------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------- |
| `children`   | string                                                            |           | **Required.** The label.                                                                                          |
| `onClick`    | function                                                          |           | Runs when the agent clicks. Call `KustomerRequest` or `runCommand` here.                                          |
| `link`       | string                                                            |           | A URL to open in a new tab instead. The button renders as a link.                                                 |
| `icon`       | string                                                            |           | A [Material Design Icons](https://pictogrammers.com/library/mdi/) name shown before the label, such as `refresh`. |
| `endIcon`    | string                                                            |           | An icon name shown after the label.                                                                               |
| `size`       | `xSmall` \| `small`                                               | `small`   | 26px or 30px tall. `medium` is deprecated and renders as `small`.                                                 |
| `grow`       | `auto` \| `fill`                                                  | `auto`    | `fill` stretches the button to the width of its container.                                                        |
| `marginSize` | `none` \| `small` \| `medium` \| `large` \| `xlarge` \| `xxlarge` | `medium`  | Space above and below. `medium` is 8px.                                                                           |
| `theme`      | `default` \| `danger` \| `subtle` \| `white` \| `ai`              | `default` | The text color. `ai` uses the AI gradient.                                                                        |
| `disabled`   | boolean                                                           |           | Grays the button out; clicks don't run.                                                                           |
| `loading`    | boolean                                                           |           | Shows a spinner in place of the icon and disables the button.                                                     |

```jsx
<ButtonText
  onClick={() => KustomerRequest({ url: `/v1/customers/${customer.id}` }, (err) => (err ? 'Refresh failed' : 'Customer refreshed'))}
>
  Refresh
</ButtonText>
```

### `ButtonGroup`

A row of buttons with 8px between them. Works in every context.

| Prop       | Type             | Default | Description                                       |
| ---------- | ---------------- | ------- | ------------------------------------------------- |
| `grow`     | `auto` \| `fill` | `auto`  | `fill` shares the full width between the buttons. |
| `children` | JSX              |         | The buttons.                                      |

```jsx
<ButtonGroup>
  <Button onClick={() => runCommand('acme_orders.app.resend-receipt', { args: { orderId: '4417' } }, (err) => (err ? 'Not sent' : 'Receipt sent'))}>Resend receipt</Button>
  <ButtonSecondary link="https://shop.acme.example/orders/4417">Open in Acme</ButtonSecondary>
</ButtonGroup>
```

### `Pill`

A small rounded status label. Each `type` has its own colors, and some add an icon. Works in every context.

| Prop              | Type                                                                                                                                                                                           | Default | Description                                                                                                                             |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `message`         | string                                                                                                                                                                                         |         | **Required.** The text. Pill takes `message`, not children.                                                                             |
| `type`            | `info` \| `infoSecondary` \| `success` \| `alert` \| `danger` \| `active` \| `inactive` \| `complete` \| `activeComplete` \| `ai` \| `neutralLight` \| `neutralMedium` \| `warning` \| `error` |         | **Required.** `warning` looks like `alert`, `error` like `danger`, `neutralLight` like `info` and `neutralMedium` like `infoSecondary`. |
| `icon`            | string                                                                                                                                                                                         |         | Replaces the type's icon.                                                                                                               |
| `removeIcon`      | boolean                                                                                                                                                                                        |         | Hides the type's icon.                                                                                                                  |
| `tooltip`         | string                                                                                                                                                                                         |         | Shown on hover.                                                                                                                         |
| `tooltipPosition` | string                                                                                                                                                                                         | `top`   | Where the tooltip opens: `top`, `bottom`, `left` or `right`.                                                                            |

```jsx
<Pill type="success" message={_.startCase(object.custom.statusStr)} />
```

## Embedding

### `DynamicCard`

An iframe of a page you host, sized to fit as the page calls `Kustomer.resize()` from the Cards SDK. Works in every context.

| Prop          | Type    | Default | Description                                                                                         |
| ------------- | ------- | ------- | --------------------------------------------------------------------------------------------------- |
| `src`         | string  |         | **Required.** Your page, over HTTPS.                                                                |
| `context`     | object  |         | Sent to your page when it initializes and whenever the agent moves. Defaults to the view's context. |
| `fillToWidth` | boolean |         | Stretches to the width of the panel.                                                                |
| `noPadding`   | boolean |         | Removes the 10px of padding around the iframe.                                                      |

```jsx
<DynamicCard src={`https://kustomer.acme.example/card?customer=${customer.id}`} context={context} fillToWidth />
```

### `Card`

An iframe of a page you host, at a fixed size. Works in every context.

| Prop                | Type             | Default | Description                                                                                  |
| ------------------- | ---------------- | ------- | -------------------------------------------------------------------------------------------- |
| `src`               | string           |         | **Required.** Your page, over HTTPS.                                                         |
| `height`            | number \| string |         | The height, such as `320` or `"320px"`.                                                      |
| `width`             | number \| string | `300`   | The width.                                                                                   |
| `context`           | object           |         | Sent to your page, as with `DynamicCard`.                                                    |
| `fillToWidth`       | boolean          |         | Stretches to the width of the panel.                                                         |
| `noPadding`         | boolean          |         | Removes the 10px of padding.                                                                 |
| `modalHeight`       | number           | `300`   | The height of modals the page opens.                                                         |
| `modalWidth`        | number           | `500`   | The width of modals the page opens.                                                          |
| `iframePermissions` | string           |         | The iframe's `allow` attribute. Defaults to `clipboard-read; clipboard-write; microphone *`. |

```jsx
<Card src="https://kustomer.acme.example/returns" height={200} fillToWidth />
```

## Data

### `WithUser`

Loads a Kustomer user and passes it to a function you write. Renders nothing until the user loads. Works in every context.

| Prop       | Type            | Default | Description                                                                                                   |
| ---------- | --------------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| `id`       | string          |         | **Required.** The user's ID, such as `conversation.assignedUsers[0]`.                                         |
| `children` | `(user) => JSX` |         | **Required.** Called with the user, flattened: `id`, `name`, `displayName`, `email` and its other attributes. |

```jsx
<WithUser id={conversation.assignedUsers[0]}>
  {(user) => <BasicRow label="Assigned to" value={user.displayName} />}
</WithUser>
```

## Helpers

### `_`

[Lodash](https://lodash.com/docs/4.17.15). `_.get` reads nested values without throwing when a parent is missing. Works in every context.

```jsx
<BasicRow label="Lifetime value" value={_.get(customer, 'custom.lifetimeValueNum', 0).toFixed(2)} />
```

### `moment`

[Moment.js](https://momentjs.com/docs/), for formatting and comparing dates. Works in every context.

```jsx
<BasicField label="Placed" value={moment(object.custom.placedAt).format('MMM D, YYYY')} />
```

### `KustomerRequest`

Calls the Kustomer API as the agent, with the agent's permissions. Returns a promise that resolves to the response, or to the error: it never rejects. Works in every context.

| Parameter               | Type                          | Default | Description                                                                                                                     |
| ----------------------- | ----------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `request`               | `{ url, method, body }`       |         | **Required.** A relative API path, such as `/v1/customers/{id}`; the HTTP method (default `GET`); and a body, sent as JSON.     |
| `formatResponseMessage` | `(err, attributes) => string` |         | Called with `(undefined, response.data.attributes)` on success and `(error)` on failure. Return a string to show it as a toast. |

```jsx
<Button
  onClick={() =>
    KustomerRequest(
      { url: `/v1/customers/${customer.id}`, method: 'PATCH', body: { custom: { loyaltyTierStr: 'platinum' } } },
      (err, attributes) => (err ? 'Update failed' : `Tier set to ${attributes.custom.loyaltyTierStr}`),
    )
  }
>
  Upgrade to platinum
</Button>
```

### `runCommand`

Runs one of your app's commands, so Kustomer's servers call your API with the app's secrets. Works in every context.

| Parameter               | Type                          | Default | Description                                                                                                                              |
| ----------------------- | ----------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                  | string                        |         | **Required.** The command name, such as `acme_orders.app.lookup-order`.                                                                  |
| `body`                  | `{ args, headers, body }`     |         | The same body as the [run endpoint](https://developer.kustomer.com/docs/apps/kviews#run-a-command).                                      |
| `formatResponseMessage` | `(err, attributes) => string` |         | Called with the run's attributes, including `statusCode`. A string becomes a toast: a success toast below 400, an error toast otherwise. |

```jsx
<Button
  onClick={() =>
    runCommand('acme_orders.app.lookup-order', { args: { orderId: object.externalId } }, (err, run) =>
      err ? 'Acme is unreachable' : `Acme answered ${run.statusCode}`,
    )
  }
>
  Check with Acme
</Button>
```

### `renderHandlebars`

Fills in merge fields, such as `{{customer.email}}`, from the view's data. Returns the fallback when any of them is empty. Works in every context.

| Parameter      | Type   | Default | Description                                                                                                             |
| -------------- | ------ | ------- | ----------------------------------------------------------------------------------------------------------------------- |
| `value`        | string |         | **Required.** Text with merge fields. Each record also has `email` and `phone` shortcuts for its first email and phone. |
| `fallbackLink` | string |         | **Required.** Returned when a merge field has no value.                                                                 |
| `data`         | object |         | **Required.** The values to merge, usually `data`, the template's whole context.                                        |

```jsx
<ButtonSecondary link={renderHandlebars('https://shop.acme.example/admin?email={{customer.email}}', 'https://shop.acme.example/admin', data)}>
  Find in Acme
</ButtonSecondary>
```

### `internationalizeStandardAttribute`

Returns a standard attribute's display name in the agent's language, or the attribute name if it isn't a standard attribute. Works in every context.

| Parameter   | Type   | Default | Description                                                             |
| ----------- | ------ | ------- | ----------------------------------------------------------------------- |
| `attribute` | string |         | **Required.** The attribute name, such as `createdAt`.                  |
| `klass`     | string |         | **Required.** `customer`, `company`, `conversation` or a KObject Klass. |

```jsx
<BasicRow label={internationalizeStandardAttribute('createdAt', 'customer')} value={moment(customer.createdAt).format('LL')} />
```

### `renderSnippet`

Renders one of the org's snippets in the agent's language, or the key if there's no such snippet. Works in every context.

| Parameter    | Type   | Default | Description                    |
| ------------ | ------ | ------- | ------------------------------ |
| `snippetKey` | string |         | **Required.** The snippet key. |

```jsx
<BasicRow label="Returns" value={renderSnippet('returns_policy')} />
```
