Custom date range picker component for PBA Hotel Apps
npm install @archpublicwebsite/rangepickerCustom, lightweight date range picker component for Vue 3 with Tailwind CSS prefix support.
- ðĻ Vue 3 Composition API - Built with modern Vue 3 and TypeScript
- ðĶ CSS Prefix Support - All Tailwind classes prefixed with arch- to prevent conflicts with Vuetify/Bootstrap
- ð
Dayjs Integration - Powerful date manipulation without moment.js bloat
- ðĻ Themeable - Easy color customization via props (HEX colors)
- ðą Mobile Responsive - Touch-friendly with bottom sheet on mobile
- ðŊ Smart Positioning - Auto-adjusts based on available viewport space
- âŋ Accessible - Keyboard navigation and screen reader support
- ð SSR Compatible - Works perfectly with Nuxt 3
- ðŠķ Lightweight - ~49KB CSS (gzipped: 5.3KB), ~40KB JS (gzipped: 9.4KB)
``bash`
npm install @archpublicwebsite/rangepickeror
pnpm add @archpublicwebsite/rangepickeror
yarn add @archpublicwebsite/rangepicker
Important: You must import both the component AND the CSS file.
`vue
primary-color="#3b82f6"
placeholder="Check in / Check out"
/>
`
Full TypeScript support with exported types for type-safe development:
`vue
v-bind="pickerOptions"
primary-color="#3b82f6"
placeholder="Check in / Check out"
/>
`
Why separate CSS import?
- Better performance (CSS cached independently)
- Smaller JS bundle
- No Flash of Unstyled Content (FOUC)
- Industry standard (like Vuetify, Element Plus, etc.)
Tailwind CSS Prefix:
All Tailwind utility classes are prefixed with arch- to prevent conflicts with other CSS frameworks like Vuetify or Bootstrap. Your existing styles won't be affected!
Customize colors easily by passing HEX color values as props. Each rangepicker instance can have its own color scheme:
`vue
primary-color="#3b82f6"
secondary-color="#60a5fa"
placeholder="Blue theme"
/>
primary-color="#8b5cf6"
secondary-color="#a78bfa"
placeholder="Purple theme"
/>
primary-color="#ef4444"
secondary-color="#f87171"
placeholder="Red theme"
/>
`
Use custom fonts to match your brand typography:
`vue
font-family="'Roboto', sans-serif"
primary-color="#3b82f6"
placeholder="With Roboto"
/>
font-family="'Poppins', sans-serif"
primary-color="#8b5cf6"
placeholder="With Poppins"
/>
placeholder="Inherits parent font"
/>
`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| primary-color | string | - | Main color for selected dates and buttons (HEX format, e.g., #3b82f6) |secondary-color
| | string | - | Color for hover states and secondary elements (HEX format, optional) |font-family
| | string | inherit | Custom font family (e.g., 'Roboto', sans-serif, 'Poppins', sans-serif) |
Features:
- â
Scoped per instance - Multiple pickers can have different colors simultaneously
- â
No global state - Colors don't conflict between instances
- â
HEX format - Standard 3 or 6 digit HEX colors (e.g., #3b82f6, #fff)
- â
Auto-conversion - Automatically converts HEX to RGB for CSS variables
- â
Optional - Falls back to default theme if not provided
- â
Custom fonts - Use any font family, inherits from parent by default
This package is designed to work seamlessly with any Vue 3 framework:
- â
Vuetify - No CSS conflicts thanks to arch- prefix
- â
Bootstrap - Works alongside Bootstrap utilities
- â
Element Plus - Fully compatible
- â
Quasar - No issues
- â
Plain Vue 3 - Works great standalone
- â
Nuxt 3 - SSR compatible
The arch- prefix on all Tailwind classes ensures zero conflicts with other CSS frameworks.
`vue
:options="options"
primary-color="#1976d2"
placeholder="Check in / Check out"
class="my-custom-input"
/>
`
`vue
ref="triggerRef"
type="text"
:value="dateRangeText"
placeholder="Select dates"
readonly
@click="isOpen = true"
/>
v-model:is-open="isOpen"
:trigger-element="triggerRef"
:value-of-months="2"
format="DD MMM YYYY"
/>
`
`vue
v-model:is-open="isOpen"
:trigger-element="triggerRef"
v-bind="options"
/>
`Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| modelValue | { startDate?: string \| Date \| Dayjs, endDate?: string \| Date \| Dayjs } | {} | Selected date range |isOpen
| | boolean | false | Controls picker visibility |variant
| | 'desktop' \| 'mobile' | 'desktop' | Display variant |primaryColor
| | string | - | Primary color in HEX format (e.g., #3b82f6) |secondaryColor
| | string | - | Secondary color in HEX format (e.g., #60a5fa) |minDate
| | string \| Date \| Dayjs | - | Minimum selectable date |maxDate
| | string \| Date \| Dayjs | - | Maximum selectable date |minDays
| | number | - | Minimum number of days in range |maxDays
| | number | - | Maximum number of days in range |valueOfMonths
| | number | 2 | Number of months to display |valueOfColumns
| | number | 2 | Grid columns for months |disabledDates
| | (string \| Date)[] | [] | Array of disabled dates |holidays
| | (string \| Date)[] | [] | Array of holiday dates |format
| | string | 'YYYY-MM-DD' | Date format |delimiter
| | string | ' - ' | Delimiter between dates |placeholder
| | string | 'Select dates' | Placeholder text |label
| | string | - | Label for the picker |showTooltip
| | boolean | true | Show night count tooltip |autoApply
| | boolean | false | Auto-apply selection |position
| | 'auto' \| 'top' \| 'bottom' | 'auto' | Positioning strategy |triggerElement
| | HTMLElement \| null | - | Trigger element for positioning |
| Event | Payload | Description |
|-------|---------|-------------|
| update:modelValue | { startDate: string, endDate: string } | Emitted when date range changes |update:isOpen
| | boolean | Emitted when picker opens/closes |dateSelected
| | Dayjs | Emitted when a date is clicked |rangeSelected
| | { start: Dayjs, end: Dayjs } | Emitted when range is complete |
This package is built with TypeScript and provides full type definitions. All types are automatically exported for your convenience.
`typescript`
import type {
RangepickerProps, // Component props interface
RangepickerEmits, // Event emitter interface
DateRange, // Date range object type
CalendarDay, // Internal calendar day type
CalendarMonth // Internal calendar month type
} from '@archpublicwebsite/rangepicker'
#### RangepickerProps
Complete props interface with JSDoc documentation. All props are optional with sensible defaults:
`typescript`
interface RangepickerProps {
modelValue?: { startDate?: string | Date | Dayjs; endDate?: string | Date | Dayjs }
isOpen?: boolean
variant?: 'desktop' | 'mobile'
minDate?: string | Date | Dayjs
maxDate?: string | Date | Dayjs
minDays?: number
maxDays?: number
close?: boolean
valueOfMonths?: number // default: 2
valueOfColumns?: number // default: 2
disabledDates?: (string | Date)[]
holidays?: (string | Date)[]
format?: string // default: 'YYYY-MM-DD'
delimiter?: string // default: ' - '
placeholder?: string
label?: string
showTooltip?: boolean // default: true
autoApply?: boolean // default: false
position?: 'auto' | 'top' | 'bottom'
triggerElement?: HTMLElement | null
colorStyles?: Record
}
#### DateRange
Type for the v-model binding:
`typescript`
interface DateRange {
startDate: string
endDate: string
}
#### RangepickerEmits
Event emitter types for type-safe event handling:
`typescript`
interface RangepickerEmits {
'update:modelValue': [value: { startDate: string; endDate: string }]
'update:isOpen': [value: boolean]
'dateSelected': [date: Dayjs]
'rangeSelected': [start: Dayjs, end: Dayjs]
}
#### Type-Safe Component Props
`typescript
import type { RangepickerProps } from '@archpublicwebsite/rangepicker'
// Define props with autocomplete support
const config: Partial
format: 'DD/MM/YYYY',
minDays: 2,
maxDays: 30,
autoApply: true,
showTooltip: true
}
`
#### Type-Safe Event Handlers
`typescript
import type { Dayjs } from 'dayjs'
function handleDateSelected(date: Dayjs) {
console.log('Selected:', date.format('YYYY-MM-DD'))
}
function handleRangeSelected(start: Dayjs, end: Dayjs) {
const nights = end.diff(start, 'day')
console.log(Booking: ${nights} nights)`
}
#### Type-Safe Refs
`typescript
import { ref } from 'vue'
import type { DateRange } from '@archpublicwebsite/rangepicker'
const dateRange = ref
const holidays = ref
const disabledDates = ref
`
With the exported types, you'll get:
- â
Autocomplete - IntelliSense for all props and events
- â
Type Checking - Compile-time error detection
- â
Documentation - Hover tooltips with prop descriptions and default values
- â
Refactoring - Safe rename and refactor operations
- â
Error Prevention - Catch typos and incorrect prop usage before runtime
`bashInstall dependencies
pnpm install
CSS Architecture
The component uses Tailwind CSS with
arch- prefix to prevent conflicts with other frameworks:$3
- â
Zero conflicts with Vuetify, Bootstrap, Element Plus, etc.
- â
Safe to use alongside any CSS framework
- â
All utilities prefixed: .arch-flex, .arch-text-sm, .arch-bg-white, etc.
- â
Custom classes untouched: .rangepicker-* classes remain unprefixed$3
1. Color Props (Easiest):
`vue
primary-color="#3b82f6"
secondary-color="#60a5fa"
/>
`2. CSS Variables (Global):
`css
:root {
--color-primary: 59 130 246; / RGB format /
--color-secondary: 148 163 184;
}
`3. Custom CSS Overrides:
`css
/ Override component styles /
.rangepicker-day-selected {
background-color: purple !important;
}
`Troubleshooting
$3
Make sure you imported the CSS:
`js
import '@archpublicwebsite/rangepicker/style.css'
`$3
This should NOT happen thanks to the arch- prefix. If you see conflicts, please open an issue.$3
Ensure vue` is installed as a dependency in your project.- Chrome/Edge (latest 2 versions)
- Firefox (latest 2 versions)
- Safari (latest 2 versions)
- Mobile Safari (iOS 14+)
- Chrome for Android (latest)
See the main repository README for contribution guidelines.
MIT ÂĐ Archipelago International