Shadcn Vue Phone Input is a phone input component built as part of the Shadcn design system. It offers a blend of customization and out-of-the-box styling, adhering to Shadcn's sleek and modern design principles.
I needed a phone input component for a project. I looked around for any phone input components that used Shadcn's design system, but I found only Shadcn Phone Input. So, I decided to do this for vue myself, granted access from creator, created base-vue-phone-input for customizable vue phone inputs. Hope you find it useful!
<template> <PhoneInput noUseBrowserLocale fetchCountry class="flex" country-locale="en-EN" :ignored-countries="['AC']"> <template #selector="{ inputValue, updateInputValue, countries }"> <Popover v-model:open="open"> <PopoverTrigger> <Button variant="outline" class="flex gap-1 rounded-e-none rounded-s-lg px-3"> <FlagComponent :country="inputValue" /> <ChevronsUpDown class="-mr-2 h-4 w-4 opacity-50" /> </Button> </PopoverTrigger> <PopoverContent class="w-[300px] p-0"> <Command> <CommandInput placeholder="Search country..." /> <CommandEmpty>No country found.</CommandEmpty> <CommandList> <CommandGroup> <CommandItem v-for="option in countries" :key="option.iso2" :value="option.name" class="gap-2" @select=" () => { updateInputValue(option.iso2) open = false focused = true } "> <FlagComponent :country="option?.iso2" /> <span class="flex-1 text-sm">{{ option.name }}</span> <span class="text-foreground/50 text-sm">{{ option.dialCode }}</span> </CommandItem> </CommandGroup> </CommandList> </Command> </PopoverContent> </Popover> </template> <template #input="{ inputValue, updateInputValue, placeholder }"> <Input ref="phoneInput" class="rounded-e-lg rounded-s-none" type="text" :model-value="inputValue" @input="updateInputValue" :placeholder="placeholder" /> </template> </PhoneInput> </template> <script lang="ts" setup> import PhoneInput from 'base-vue-phone-input' import { useFocus } from '@vueuse/core' import { ChevronsUpDown } from 'lucide-vue-next' import { FlagComponent } from '../../.nuxt/components' const open = ref(false) const phoneInput = ref(null) const { focused } = useFocus(phoneInput) </script>
<template> <span class="bg-foreground/20 flex h-4 w-6 overflow-hidden rounded-sm"> <img v-if="country" :src="flagUrl" :alt="countryName" :title="countryName" /> </span> </template> <script setup> import { computed, defineProps } from 'vue' const props = defineProps({ country: { required: true, }, countryName: { type: String, required: false, }, }) const flagUrl = computed(() => { return `https://flagcdn.com/w40/${props.country.toLowerCase()}.png` }) </script>
You can find out more about the API and implementation in the base-vue-phone-input documentation.