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

# Bloco Cart items

> O bloco Cart items: a lista de itens do carrinho, a linha Product e o hospedeiro dos sub-blocos aninhados.

> O bloco **Cart items** é a lista de itens de linha do carrinho, renderizando cada produto que o comprador adicionou com sua imagem, título, variante, preço, seletor de quantidade e controle de remoção. É um bloco obrigatório, e é o contêiner que hospeda os sub-blocos do carrinho (a linha **Product**, [**Subscription upgrade**](/pt/aftersell/cart/subscription-upgrade-block) e [**Custom code**](/pt/aftersell/cart/custom-code-blocks)), fornecendo a estrutura à qual os sub-blocos por linha se anexam.

<Frame>
  <img src="https://mintcdn.com/aftersell/1Y3gBpUfxv16VGSW/images/aftersell/cart-items-block-line-product-title-variant.png?fit=max&auto=format&n=1Y3gBpUfxv16VGSW&q=85&s=3c9f088b55cfd8450dcb8670dfe0728a" alt="Bloco Cart items exibindo itens de linha com imagem do produto, título, variante, preço, seletor de quantidade e controle de remoção" width="1420" height="486" data-path="images/aftersell/cart-items-block-line-product-title-variant.png" />
</Frame>

<div id="the-product-row">
  ## A linha Product
</div>

Dentro de Cart items fica o sub-bloco **Product**: a própria linha do item. Ele é bloqueado e adicionado automaticamente, então todo bloco Cart items sempre tem exatamente uma linha Product que você não pode remover; você reposiciona os outros sub-blocos ao redor dela. Suas configurações controlam como o preço de cada linha é exibido:

| Configuração                               | O que controla                                                                                                                                                                                                                                                                                                                                               | Padrão                                          |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------- |
| **Strike-through price**                   | Qual preço é exibido riscado: **Compare-at or pre-discount, whichever is higher**, **Compare-at price**, **Pre-discount price** ou **No strike-through**.                                                                                                                                                                                                    | Compare-at or pre-discount, whichever is higher |
| **Strike-through price for subscriptions** | A mesma escolha para linhas de assinatura, com duas diferenças: uma opção extra **Subscription compare-at price**, e **Compare-at price** renomeado para **Product compare-at, then subscription compare-at**.                                                                                                                                               | Compare-at or pre-discount, whichever is higher |
| **Savings label**                          | Se a economia é exibida como **Amount**, **Percentage** ou fica **Hidden**.                                                                                                                                                                                                                                                                                  | Amount                                          |
| **Bundle price**                           | Como o preço exibido é calculado para linhas de bundle. **Automatic** mostra o total de todos os itens do bundle (ou o preço do item principal quando os demais são gratuitos). **Main item price only** mostra apenas o preço do item principal (âncora). Isso é apenas um rótulo de exibição — o total do carrinho da Shopify é sempre a fonte de verdade. | Automatic                                       |
| **Savings text**                           | O rótulo de economia. Suporta o token `{{value}}`.                                                                                                                                                                                                                                                                                                           | `Save {{value}}`                                |

A própria linha renderiza a imagem do produto (com link para a página do produto quando disponível), título, variante, preço e qualquer preço de comparação riscado, um seletor de quantidade e um botão de remover. Linhas de bundle mostram uma lista expansível dos seus componentes.

<div id="text-styling">
  ### Estilização de texto
</div>

A linha Product inclui uma seção **Text** nas suas configurações de Design. Use-a para controlar a tipografia de elementos de texto individuais em cada item de linha. Selecione um elemento de texto no seletor para ajustar suas configurações:

| Configuração       | O que controla                                                                                                                                                  |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Text color**     | Cor do elemento de texto selecionado.                                                                                                                           |
| **Font**           | **Theme font** (herda a fonte do seu tema) ou **Custom font** (insira o nome de uma fonte que o seu tema já carrega). Disponível apenas para **Product title**. |
| **Size**           | Tamanho da fonte em pixels.                                                                                                                                     |
| **Weight**         | Peso da fonte: Light, Regular, Medium, Semibold ou Bold.                                                                                                        |
| **Line height**    | Altura da linha como multiplicador do tamanho da fonte (por exemplo, `1.4`).                                                                                    |
| **Letter spacing** | Espaçamento entre letras em pixels. Valores negativos comprimem o texto.                                                                                        |

Os elementos de texto que você pode estilizar estão agrupados por categoria:

**Product**

* **Product title** — o nome do produto em cada linha. Também suporta uma família de fonte personalizada.
* **Variant** — o rótulo da variante (por exemplo, *Size: Medium*).
* **Subscription plan** — o rótulo somente leitura do plano exibido nas linhas de assinatura.

**Pricing**

* **Price** — o preço atual da linha.
* **Compare-at price** — o preço original riscado.
* **Savings** — o rótulo de economia (por exemplo, *Save \$5.00*). Apenas Size e Line height — negrito e cor são definidos no Rich Text Editor acima.

**Bundle**

* **Bundle toggle** — o cabeçalho expansível que abre a lista de componentes de um bundle.
* **Bundle item title** — o título de cada componente dentro de um bundle.
* **Bundle item variant** — o rótulo de variante de cada componente do bundle.

Deixar qualquer campo em branco mantém o valor padrão do elemento.

<Tip>
  Clicar em um elemento de texto diretamente na pré-visualização do carrinho o destaca e abre seus controles no painel automaticamente.
</Tip>

<div id="discount-tags-design">
  ### Design das tags de desconto
</div>

A linha Product inclui uma seção **Discount tags** nas suas configurações de Design. Use-a para estilizar as pílulas de tag de desconto que aparecem em cada item de linha:

| Configuração         | O que controla                                          | Padrão    |
| -------------------- | ------------------------------------------------------- | --------- |
| **Background color** | Cor de preenchimento da pílula da tag de desconto.      | `#F1F1F1` |
| **Text color**       | Cor do texto dentro da pílula da tag de desconto.       | `#585858` |
| **Border radius**    | Arredondamento dos cantos da pílula da tag de desconto. | `6px`     |

Essas configurações se aplicam apenas às tags de desconto de itens de linha no bloco Cart items. As tags de código de desconto no [bloco Summary](/pt/aftersell/cart/summary-block) são estilizadas separadamente.

<div id="sub-blocks-and-how-they-position">
  ## Sub-blocos e como eles se posicionam
</div>

Cart items é o único bloco que hospeda sub-blocos. **Os sub-blocos são renderizados uma vez por linha, dentro de cada linha de produto**, posicionados em relação à linha Product fixada:

* Sub-blocos ordenados **antes** da linha Product aparecem **acima** do conteúdo do produto em cada linha.
* Sub-blocos ordenados **depois** da linha Product aparecem **abaixo** do conteúdo do produto em cada linha.

Assim, um [Subscription upgrade](/pt/aftersell/cart/subscription-upgrade-block) colocado depois da linha Product aparece abaixo de cada linha elegível, e não uma única vez no final da lista inteira.

<div id="behavior">
  ## Comportamento
</div>

* Quando o carrinho não tem itens, o drawer muda para o estado vazio e este bloco não é exibido.
* **Apenas uma alteração no carrinho é executada por vez.** Enquanto uma atualização de quantidade ou remoção está em andamento, os controles da linha ficam desativados para manter o carrinho consistente, e são reativados quando a alteração é concluída.
* Reduzir a quantidade de uma linha abaixo de 1 a remove. Uma quantidade que a loja rejeita (por exemplo, acima do estoque disponível) é ressincronizada com o último valor válido.
* **Bundles mudam como uma unidade.** Ajustar a quantidade na linha âncora de um bundle escala o bundle inteiro em uma única operação — se um item filho está incluído a 3 por âncora, levar a âncora de 1 para 2 leva esse filho a 6. Remover a âncora remove todos os membros do bundle de uma vez.
* **Alguns bundles não podem ter a quantidade alterada.** Se qualquer filho de um bundle estiver incluído a uma taxa fracionária (1,5 por âncora, por exemplo), o seletor de quantidade desse bundle é bloqueado: os botões +/− e o campo de quantidade ficam desativados, e quantidades digitadas não são aceitas. O bundle ainda pode ser removido.
* **Linhas de assinatura mostram seu plano.** Quando uma linha tem um plano de venda e o sub-bloco [Subscription upgrade](/pt/aftersell/cart/subscription-upgrade-block) está desativado ou não foi adicionado, a linha Product mostra um rótulo de plano somente leitura abaixo da variante — por exemplo, *Delivers every month (save 30%)*. Quando esse sub-bloco está ativado, ele apresenta o plano no seu próprio seletor, então o rótulo somente leitura é suprimido em vez de duplicado.

<div id="placement-and-limits">
  ## Posicionamento e limites
</div>

* **Região:** corpo.
* **Máximo:** 1 por estado do carrinho.
* **Estado:** apenas carrinho cheio.
* **Bloqueado e adicionado por padrão.** Cart items não pode ser removido nem ocultado, apenas reposicionado.

<div id="custom-template">
  ## Template personalizado
</div>

Suporta um [template personalizado](/pt/aftersell/cart/custom-templates) pela sua aba Code, que substitui a marcação nativa deste bloco pelo seu JSX. Estas são as props que ele recebe.

O contêiner **Cart items** não tem template personalizado. A linha **Product** dentro dele tem, e é a superfície mais rica do carrinho: seu template é renderizado uma vez por linha.

<div id="line-content">
  ### Conteúdo da linha
</div>

| Prop               | Tipo                        | Para que serve                                                                                                                                                                                                                              |
| ------------------ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title`            | `string`                    | Título do produto, em texto simples.                                                                                                                                                                                                        |
| `variantTitle`     | `string \| null`            | Rótulo da variante. `null` para produtos de variante única e bundles nativos.                                                                                                                                                               |
| `url`              | `string \| null`            | URL da página do produto. `null` quando a linha não deve ter link.                                                                                                                                                                          |
| `imageUrl`         | `string \| null`            | Imagem da linha. `null` quando o produto não tem nenhuma.                                                                                                                                                                                   |
| `quantity`         | `number`                    | Quantidade atual na linha.                                                                                                                                                                                                                  |
| `price`            | `string`                    | Preço da linha, **já formatado**.                                                                                                                                                                                                           |
| `compareAtPrice`   | `string \| null`            | O preço "anterior" riscado, já formatado. `null` quando não há nada a riscar.                                                                                                                                                               |
| `savingsHtml`      | `string \| null`            | Rótulo de economia como HTML sanitizado. `null` quando oculto ou quando não há economia.                                                                                                                                                    |
| `discountTags`     | `string[]`                  | Títulos dos descontos nesta linha, por exemplo `['Spring Sale']`. `[]` quando não há nenhum.                                                                                                                                                |
| `sellingPlanLabel` | `string \| null`            | Nome do plano de assinatura somente leitura. `null` quando é uma linha de compra única, ou quando o sub-bloco [Subscription upgrade](/pt/aftersell/cart/subscription-upgrade-block#custom-template) está renderizando a interface do plano. |
| `bundle`           | `object \| null`            | View model do [bundle](/pt/aftersell/cart/sdk-cart-object#bundles) em uma linha âncora. `null` caso contrário.                                                                                                                              |
| `productId`        | `number`                    | ID do produto na Shopify.                                                                                                                                                                                                                   |
| `variantId`        | `number`                    | ID da variante na Shopify.                                                                                                                                                                                                                  |
| `line`             | `AftersellCartLine`         | A [linha do carrinho](/pt/aftersell/cart/sdk-cart-object#cart-lines) completa, para qualquer coisa que as props acima não cubram.                                                                                                           |
| `formatMoney`      | `(cents: number) => string` | Formata um valor em unidades menores. Use para preços que você lê de `line`.                                                                                                                                                                |

<Warning>
  **`price` e `compareAtPrice` são strings formatadas; tudo em `line` está em centavos.** Não faça aritmética com `price`. Calcule a partir de `line.finalLinePrice` e afins, e depois passe o resultado por `formatMoney`.
</Warning>

<div id="quantity-and-removal">
  ### Quantidade e remoção
</div>

| Prop                | Tipo                                             | Para que serve                                                                                                                                                                                                                                         |
| ------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `increment`         | `() => void`                                     | Adiciona um à linha.                                                                                                                                                                                                                                   |
| `decrement`         | `() => void`                                     | Remove um da linha.                                                                                                                                                                                                                                    |
| `remove`            | `() => void`                                     | Remove a linha por completo.                                                                                                                                                                                                                           |
| `quantityInput`     | `string`                                         | Valor atual para um `<input>` de quantidade controlado. Uma string, para que estados de digitação intermediários sobrevivam.                                                                                                                           |
| `onQuantityInput`   | `(event: Event) => void`                         | Handler `onInput` para esse campo.                                                                                                                                                                                                                     |
| `commitQuantity`    | `() => void`                                     | Aplica a quantidade digitada. Conecte ao `onBlur`.                                                                                                                                                                                                     |
| `onQuantityKeyDown` | `(event: KeyboardEvent) => void`                 | Handler `onKeyDown`, para que Enter confirme.                                                                                                                                                                                                          |
| `busy`              | `boolean`                                        | `true` enquanto qualquer mutação do carrinho está em andamento. Desative seus controles com base nisso.                                                                                                                                                |
| `pending`           | `'increment' \| 'decrement' \| 'remove' \| null` | Qual ação está atualmente em andamento, para um spinner direcionado.                                                                                                                                                                                   |
| `stepperLocked`     | `boolean`                                        | `true` quando a quantidade não pode ser alterada, porque a linha é uma âncora de bundle com um filho incluído a uma taxa fracionária por âncora. Oculte ou desative o seletor — os handlers nativos já rejeitam alterações enquanto ele está definido. |

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomTemplate(props) {
  return (
    <div className="cart-external-cart-items__row" style={{ display: 'flex', gap: '12px', opacity: props.busy ? 0.6 : 1 }}>
      {props.imageUrl && <img src={props.imageUrl} alt="" width={64} height={64} />}

      <div style={{ flex: 1 }}>
        {props.url ? <a href={props.url}>{props.title}</a> : <span>{props.title}</span>}
        {props.variantTitle && <div style={{ opacity: 0.6 }}>{props.variantTitle}</div>}
        {props.sellingPlanLabel && <div style={{ opacity: 0.6 }}>{props.sellingPlanLabel}</div>}

        {props.discountTags.map((tag) => (
          <span key={tag} style={{ fontSize: '11px', border: '1px solid', borderRadius: '4px', padding: '1px 5px' }}>
            {tag}
          </span>
        ))}

        {!props.stepperLocked && (
          <div style={{ display: 'flex', alignItems: 'center', gap: '6px', marginTop: '6px' }}>
            <button type="button" onClick={props.decrement} disabled={props.busy}>&minus;</button>
            <input
              value={props.quantityInput}
              onInput={props.onQuantityInput}
              onBlur={props.commitQuantity}
              onKeyDown={props.onQuantityKeyDown}
              size={2}
            />
            <button type="button" onClick={props.increment} disabled={props.busy}>+</button>
            <button type="button" onClick={props.remove} disabled={props.busy}>
              {props.pending === 'remove' ? 'Removing…' : 'Remove'}
            </button>
          </div>
        )}
      </div>

      <div style={{ textAlign: 'right' }}>
        <div>{props.price}</div>
        {props.compareAtPrice && <s style={{ opacity: 0.5 }}>{props.compareAtPrice}</s>}
        {props.savingsHtml && <div dangerouslySetInnerHTML={{ __html: props.savingsHtml }} />}
      </div>
    </div>
  );
}
```

<div id="rendering-a-bundle">
  ### Renderizando um bundle
</div>

Na linha âncora de um bundle, `bundle.children` contém seu conteúdo. Os filhos nunca aparecem como linhas próprias, então, se você não os renderizar, o comprador não verá o que há no bundle:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomTemplate(props) {
  return (
    <div>
      <div>{props.title} {props.price}</div>

      {props.bundle && (
        <ul style={{ margin: '4px 0 0 12px', fontSize: '12px', opacity: 0.7 }}>
          {props.bundle.children.map((child, i) => (
            <li key={child.key ?? i}>{child.quantity} × {child.title}</li>
          ))}
        </ul>
      )}
    </div>
  );
}
```

O `key` de um filho é `null` para um componente de bundle nativo da Shopify, então recorra ao índice, como acima.

<div id="design">
  ## Design
</div>

Estilize este bloco pela sua seção **Design** no painel de configurações. São substituições por bloco que se sobrepõem ao seu design global e recorrem a ele quando estão em branco.

O que são configurações de design? Saiba mais aqui: [Configurações de design](/pt/aftersell/cart/design-settings).
