We use cookies to understand how this site is used. You can accept or reject them — see our Cookie Policy for details.

API Reference

TreatmentConsultant props

PropTypeDefaultDescription
configDeepPartial<TreatmentConsultantConfig>{}Overrides merged with the defaults — see Configuration
styleClassPassthroughstring | string[][]Extra classes added to the widget's root element
licenseKeystringundefinedOverrides the plugin's key for this instance — see Licensing

TreatmentConsultant emits

EventPayloadFires when
changeConsultationSelectionsAny selection changes
completeConsultationSelectionsThe client reaches the Results step

createHairTreatments()

A Vue plugin factory. Installing it provides a default config to every TreatmentConsultant in the app — instance-level config props are merged on top of this.

ts
function createHairTreatments(
  config?: DeepPartial<TreatmentConsultantConfig> & { licenseKey?: string }
): Plugin

pages.docs.apiReference.createHairTreatments.licenseKeyField

TextConfig

Every user-facing string, grouped by where it's shown.

ts
interface TextConfig {
  header: {
    /** Brand/salon name shown in the built-in header. Empty string hides it. */
    brand: string
    title: string
  }
  navigation: {
    steps: string[]
    back: string
    next: string
    viewResults: string
    backToResults: string
  }
  progress: {
    /** Format string for the step counter. Use {step}, {total}, {label} as placeholders. */
    stepFormat: string
  }
  steps: {
    hairType: string
    naturalColour: string
    greyCoverage: string
    greyCoverageSubtitle: string
    desiredColour: string
    desiredColourSkipSublabel: string
    treatments: string
    treatmentsSubtitle: string
    applicationType: string
    applicationTypeSubtitle: string
    cut: string
    cutSubtitle: string
  }
  /** Title/body (and optional per-step `image`) for the hero area shown above each
   *  selection step. Keyed the same as `steps`. */
  explainers: Record<string, { title: string; body: string; image?: string }>
  results: {
    title: string
    colourSection: string
    treatmentsSection: string
    processesRequired: string
    noColour: { label: string; note: string }
    noTreatment: { label: string; note: string }
    compatOk: string
    compatWarning: string
    suitability: Record<Suitability, { icon: string; label: string }>
  }
  summary: {
    hairType: string
    naturalColour: string
    dreamColour: string
    treatments: string
    noTreatment: string
    applicationType: string
    cut: string
  }
  cta: {
    disclaimer: string
    bookLabel: string
    bookHref: string
    resetLabel: string
  }
}

Option types

The shapes behind each option array in TreatmentConsultantConfig.

ts
type HairTypeId = "straight" | "wavy" | "curly" | "coily"

interface HairTypeOption {
  id: HairTypeId
  label: string
  pattern: string
  image?: string
}

type NaturalColourId =
  | "light-blonde" | "dark-blonde" | "light-brown" | "dark-brown"
  | "red" | "black" | "grey-white"

interface ColourOption {
  id: NaturalColourId
  label: string
  colour: string
  image?: string
  textDark?: boolean
}

type DesiredColourId =
  | "none" | "blonde" | "brown" | "red" | "black" | "grey-silver" | "vivid" | "balayage"

interface DesiredColourOption {
  id: DesiredColourId
  label: string
  colour?: string
  image?: string
  textDark?: boolean
}

type ApplicationTypeId = "all-over" | "balayage" | "highlights" | "lowlights" | "t-section"

interface ApplicationTypeOption {
  id: ApplicationTypeId
  label: string
  description?: string
  icon: string
}

interface GreyCoverageOption {
  id: string
  label: string
}

/** Individual named shade within a broad category — Premium-only "granular" catalog mode. */
interface DesiredShadeOption {
  id: string
  label: string
  desiredColourId: DesiredColourId
  colour?: string
  image?: string
  image2x?: string
}

interface NaturalShadeOption {
  id: string
  label: string
  naturalColourId: NaturalColourId
  colour?: string
  image?: string
  image2x?: string
}

type CutId = "none" | "trim" | "restyle" | "layers" | "fringe"

interface CutOption {
  id: CutId
  label: string
  description?: string
  icon: string
  excludedByHairTypes?: HairTypeId[]
  warnForHairTypes?: HairTypeId[]
  warnings?: Partial<Record<HairTypeId, { note: string; detail: string }>>
}

type TreatmentId =
  | "none" | "keratin-smoothing" | "brazilian-blowout" | "perm" | "relaxer"
  | "japanese-straightening" | "deep-conditioning" | "bond-repair" | "gloss"
  | "scalp-treatment" | "blowdry"

interface Treatment {
  id: TreatmentId
  label: string
  icon: string
  description?: string
  notes: string[]
  /** Show a colour-compatibility badge on the results screen */
  compatibility?: boolean
  /** "ok" = compatible same-day; "warning" = not same-day as colour */
  colourCompatibility?: "ok" | "warning"
  excludes?: TreatmentId[]
  /** Set to false to hide this treatment from the treatments step */
  display?: boolean
}

ConsultationSelections

The payload shape for both the change and complete events.

ts
interface ConsultationSelections {
  hairType: HairTypeId | null
  naturalColour: NaturalColourId | null
  /** Picked shade id in "granular" naturalColourMode; null in basic mode or before picking */
  naturalShade: string | null
  greyCoverage: string | null
  desiredColour: DesiredColourId | null
  /** Picked shade id in "granular" dreamColourMode; null in basic mode or before picking */
  desiredShade: string | null
  applicationType: ApplicationTypeId | null
  cut: CutId | null
  treatments: TreatmentId[]
}

Suitability

ts
type Suitability = "great" | "possible" | "difficult" | "not-recommended"

Slots

header

Renders above the step content, inside the widget's root. By default this shows the built-in header (text.header.brand / .title plus a live progress label) — provide this slot to replace it with your own markup entirely. It's a scoped slot, so a custom step counter stays in sync automatically:

Slot propTypeDescription
displayStepnumberCurrent step, 1-indexed, adjusted for skipped/hidden steps
totalStepsnumberTotal step count (6 or 7, depending on behaviour.showTreatmentsStep)
displayStepLabelstringCurrent step's label from text.navigation.steps
progressLabelstringThe formatted string driving the built-in progress text (text.progress.stepFormat)
vue
<TreatmentConsultant>
  <template #header="{ displayStep, totalSteps, displayStepLabel }">
    <header class="my-consultation-header">
      <img class="my-logo" src="/my-logo.svg" alt="My Salon" />
      <span>Step {{ displayStep }} of {{ totalSteps }} — {{ displayStepLabel }}</span>
    </header>
  </template>
</TreatmentConsultant>