Aller au contenu

Apparence

Donnez au devis intégré l’apparence d’un composant conçu par votre propre équipe produit.

L’API Appearance

Un seul objet appearance contrôle l’aspect du devis intégré et des composants natifs. Il se compose de cinq éléments : theme, variables, rules, layout et fonts.

Le même objet, deux mécanismes. Pour l’iframe (embed.js, <cord-quote>, <CordCotizador>), l’objet est transmis au serveur de Cord, qui le valide et génère le CSS dans sa propre origine : votre page n’écrit jamais de styles à l’intérieur de l’iframe. Pour les composants natifs (<CordBuilder> via <CordProvider appearance={...}>), le SDK applique les variables sous forme de CSS sur votre page. rules et layout ne s’appliquent qu’à l’iframe ; elements et baseTheme, qu’aux composants natifs.

<script src="https://cordhq.app/embed.js" async></script>
<div
  data-cord-token="a1b2c3d4e5f60718"
  data-cord-appearance='{
    "theme": "flat",
    "variables": {
      "colorPrimary": "#0f766e",
      "colorText": "#0b1220",
      "borderRadius": "10px",
      "borderRadiusButton": "999px"
    },
    "rules": {
      "Button": { "text-transform": "uppercase", "letter-spacing": "0.04em" },
      "Total": { "font-weight": "700" }
    },
    "layout": { "compact": true, "hideChat": true },
    "fonts": [{ "cssSrc": "https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" }]
  }'>
</div>

Avec le Web Component, le même JSON se place dans l’attribut appearance ou dans la propriété element.appearance ; en React, dans la prop appearance de <CordCotizador>.

Thèmes (theme)

Thème Effet
light Par défaut.
dark Palette sombre complète : fond, surfaces, texte, bordures et champs. night en est un alias.
auto Suit le prefers-color-scheme du visiteur.
flat Sans ombre et avec des bordures visibles, pour les sites qui n’utilisent pas l’élévation.

Le thème s’applique en premier, et vos variables l’emportent toujours sur lui.

Variables (variables)

Elles s’écrivent en camelCase. Chacune agit sur une surface réelle du devis ; une variable que vous ne définissez pas conserve la valeur de Cord.

Variable Type Où elle s’affiche
colorPrimary couleur Bouton principal, accents, vos propres bulles de discussion
colorOnPrimary couleur Texte sur la couleur principale
colorBackground couleur Fond de la carte
colorSurface couleur Panneaux internes : notes, total, discussion, avis
colorText couleur Texte principal et montants
colorTextSecondary couleur Libellés, identifiant fiscal, notes
colorTextPlaceholder couleur En-têtes de tableau, aides, textes indicatifs
colorBorder couleur Séparateurs et bordures
colorDanger couleur Refus et erreurs
colorSuccess couleur Confirmations
colorInput couleur Fond des champs
colorInputText couleur Texte des champs
colorInputBorder couleur Bordure des champs
colorFocus couleur Bordure du champ actif
fontFamily famille Toute la carte
fontSize longueur Lignes
fontWeightBold graisse Boutons
borderRadius longueur Carte
borderRadiusButton longueur Boutons
borderRadiusInput longueur Champs
spacingCard espacement Marge intérieure de la carte (2rem ou 1.5rem 2rem)
shadowCard none ou default Ombre de la carte

Une couleur accepte l’hexadécimal, rgb(), hsl(), oklch(), oklab(), lab(), lch() ou un nom. Une longueur accepte px, rem, em ou %.

Règles par composant (rules)

Lorsque les variables ne suffisent pas, rules applique des propriétés à des composants dotés d’un nom public. Ce ne sont pas des sélecteurs CSS : ce sont des noms stables que Cord fait correspondre à son markup, de sorte qu’ils ne cassent pas lorsque le markup change.

"rules": {
  "Button": { "text-transform": "uppercase" },
  "Button:hover": { "opacity": "0.9" },
  "Input:focus": { "border-color": "#0f766e" },
  "Bubble--mine": { "background-color": "#0f766e" }
}

Composants : Card, Header, Total, Table, Row, SummaryRow, Notes, Button, Button:hover, ButtonSecondary, ButtonSecondary:hover, Input, Input:focus, Chat, Bubble, Bubble--mine.

Propriétés : color, background-color, border-color, border-width, border-style, border-radius, font-size, font-weight, letter-spacing, text-transform, padding, box-shadow (none ou default) et opacity.

Mise en page (layout)

Option Effet
compact: true Moins d’espace dans la carte, pour les colonnes étroites.
hideChat: true Masque la discussion et les commentaires par ligne.
hideNotes: true Masque le bloc de notes du devis.

Masquer ne relève que de la présentation : le devis et ses actions restent les mêmes sur le lien public.

Polices (fonts)

Jusqu’à quatre feuilles de style de fonts.googleapis.com ou fonts.bunny.net en https. Si vous ne déclarez pas fontFamily, Cord utilise la première famille de la première feuille.

Ce que Cord valide et pourquoi

Toute valeur qui aboutit dans le CSS passe par un validateur doté de listes fermées de clés, de composants et de propriétés, et d’une grammaire par type de valeur. url(), expression(), @, !important, ;, les accolades et < sont écartés, et l’objet entier est ignoré s’il dépasse 8 Ko. Ce qui est écarté ne casse pas le reste : c’est ignoré, le SDK le signale dans la console pendant le développement et cela apparaît dans la barre de débogage avec une clé de test.

Cela empêche d’utiliser l’apparence pour masquer des boutons, cacher le total ou charger des ressources tierces dans l’iframe : le design vous appartient, l’intégrité du devis relève de Cord.

Composants natifs

Mode headless (baseTheme: 'none')

Avec <CordBuilder> ou useQuoteBuilder et votre propre interface, appearance={{ baseTheme: 'none' }} sur <CordProvider> désactive la feuille de style de base. Les classes .cord-* restent dans le markup et l’aspect est entre vos mains (Tailwind, CSS Modules ou ce que vous utilisez).

Surcharges par élément (elements)

Chaque nœud de <CordBuilder> porte une classe stable .cord-<key> (builderRoot, formField, itemRow, summaryRoot, submitButton…). appearance.elements y ajoute votre className et votre style :

<CordProvider
  publishableKey={pk}
  appearance={{
    variables: { colorPrimary: '#0f766e', borderRadiusInput: '6px' },
    elements: {
      submitButton: 'my-button',
      itemRow: { style: { gap: '18px' } },
    },
  }}
>
  <CordBuilder />
</CordProvider>

La classe de base .cord-<key> n’est jamais remplacée ; la vôtre s’ajoute par-dessus.