Skip to content

Migrating from ghl-ui InputOtp to HighRise InputOtp

This guide will help you migrate from the ghl-ui InputOtp component to the new HighRise InputOtp component.

Component Implementation Changes

Import Changes

diff
- import { UIInputOtp } from '@gohighlevel/ghl-ui'
+ import { HLInputOtp } from '@platform-ui/highrise'

Basic Usage Changes

diff
- <UIInputOtp
-   :fields="6"
-   :disabled="false"
-   placeholder="0"
-   :size="'md'"
-   :status="'default'"
-   :separatorPosition="3"
-   @onComplete="handleComplete"
-   @onChange="handleChange"
- />
-
+ <HLInputOtp
+   id="otp-input"
+   :fields="6"
+   :separator-position="3"
+   :size="'md'"
+   @on-complete="handleComplete"
+   @on-change="handleChange"
+ />

HighRise InputOtp is event-driven: it manages its own internal state and emits on-change and on-complete. There is no v-model; persist the OTP in your state from these events.

Props Changes

ghl-ui PropHighRise PropNotes
fieldsfieldsSame meaning; default 6
disableddisabledSame
placeholderplaceholderSame; default "0"
sizesizeInherits form size if not set
statusstatusAdds CSS class (e.g., error, default)
separatorPositionseparator-positionSame behavior; renders a separator after the position
ididOptional; auto-generated when omitted
-(no v-model)Capture values from events instead of two-way binding

Examples

Basic OTP Input

vue
<template>
  <HLInputOtp id="basic-otp" :fields="6" :separator-position="3" size="md" @on-change="handleChange" />
</template>

<script setup>
import { ref } from 'vue'
import { HLInputOtp } from '@platform-ui/highrise'

const otpValue = ref('')

const handleChange = value => {
  otpValue.value = value
}
</script>

OTP Input with Completion Handling

vue
<template>
  <HLInputOtp
    id="otp-input"
    :fields="6"
    size="md"
    :separator-position="3"
    @on-change="value => (otpValue = value)"
    @on-complete="handleComplete"
  />
</template>

<script setup>
import { ref } from 'vue'
import { HLInputOtp } from '@platform-ui/highrise'

const otpValue = ref('')

const handleComplete = payload => {
  // payload.otp contains the concatenated value
  otpValue.value = payload.otp
  // Submit or validate here
}
</script>

Resetting the OTP Fields

vue
<template>
  <HLInputOtp :key="resetKey" id="resettable-otp" :fields="6" :separator-position="3" @on-change="value => (otpValue = value)" />
  <HLButton size="sm" @click="resetOtp">Reset</HLButton>
</template>

<script setup>
import { ref } from 'vue'
import { HLButton, HLInputOtp } from '@platform-ui/highrise'

const otpValue = ref('')
const resetKey = ref(0)

const resetOtp = () => {
  otpValue.value = ''
  resetKey.value += 1 // forces a fresh instance
}
</script>

Best Practices

  1. Persist the OTP via @on-change or @on-complete; there is no v-model.
  2. Use :key to reset the input after failed attempts or resend flows.
  3. Apply status="error" (or similar) for visual feedback when validation fails.
  4. Keep fields consistent with backend expectations; default is 6.
  5. Provide a separator position only when you need visual grouping (e.g., after the third digit).
  6. Supply id when you need deterministic selectors for testing; otherwise let it auto-generate.

Additional Notes

  1. Events: on-change emits the current string; on-complete emits { otp, state: 'completed' } once the length matches fields.
  2. Pasting rejects non-numeric characters; invalid paste returns without mutating the value.
  3. Size defaults to the surrounding form size when used inside HLFormItem.
  4. All additional attributes are dropped; only the documented props are applied.