@citizenplane/pimp
v24.2.6
Published
<div align="center"> <a href="https://pimp.citizenplane.com" target="_blank"> <img alt="orbit-components" src="https://i.imgur.com/ZgJ9Sfq.png" width="100px" /> </a> </div>
Maintainers
Keywords
Readme
Pimp mission
Pimp aims to bring order and consistency to all of our products and processes. We elevate user experience and increase the speed and efficiency of how we design and build products.
Installation
pimp components are served as an npm package.
Add them to your project by running:
// with npm
npm install @citizenplane/pimp
// with yarn
yarn add @citizenplane/pimpUsage
In a nuxt project
- Add this line to your
nuxt-config.js:
// nuxt-config.js
...
css: [
{ src: '@citizenplane/pimp/dist/pimp.css' },
],
...- Include any of our components in your project and use it:
<template>
<cp-button appearance="primary" color="purple" />
</template>
<script>
import CpButton from '@citizenplane/pimp'
export default {
components: {
CpButton,
},
}
</script>If you want to use any component without having to import them manually, you can create a plugin:
- Create a plugin called
citizenplane-pimp.js:
// ~/plugins/citizenplane-pimp.js
import Vue from 'vue'
import Pimp from '@citizenplane/pimp'
Vue.use(Pimp)- Add this line to your
nuxt-config.js:
// nuxt-config.js
...
plugins: [
{ src: '~plugins/citizenplane-pimp.js' },
]
...- Use components directly in your project without having to import nor declaring them:
<template>
<cp-button appearance="primary" color="purple" />
</template>Breaking changes in 23.0.0
CpCalendarandCpCoreDatepickerare no longer exported.CpDatepickercovers both the field and the inline calendar (is-inline).CpDatepicker'slocaleprop no longer changes the calendar language. It only formats the dates shown in the field; the calendar followsapplyPimpLocale(see Calendar locale).
Datepicker
CpDatepicker is a read-only field that opens a calendar: in a popover anchored to the field on desktop, two months side by side (one with single-month), and in a bottom sheet with one month under the mobile breakpoint (552px). is-inline renders the calendar alone, without the field. It emits dates, a list of ISO dates (YYYY-MM-DD), after every pick: one entry in single mode, the start then the start and the end in range mode:
<cp-datepicker
init-date-one="2026-10-01"
init-date-two="2026-10-08"
label="Travel dates"
min-date="2026-09-24"
mode="range"
@dates="onDates"
/>min-date defaults to today (allow-past-dates drops it) and, like max-date, accepts an ISO date or a Date. init-date-one / init-date-two stay in sync with the field. close-after-select (default true) closes the calendar after the date, or after the end date in range mode. The field shows the dates formatted with locale (Wed Oct 1, 2026); the calendar's month and weekday names come from applyPimpLocale. Keyboard: Enter, Space or ArrowDown on the field opens the calendar on the selected day (or today), arrows move between days, Enter picks, Escape closes and focuses the field back.
Calendar locale
CpDateInput's and CpDatepicker's calendars read its month names, weekday names and first day of the week from PrimeVue's global locale, which pimp sets to en-US on install. Call applyPimpLocale with the app's culture at boot and again whenever the app language changes:
// ~/plugins/citizenplane-pimp.js
import Pimp, { applyPimpLocale } from '@citizenplane/pimp'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Pimp)
applyPimpLocale(nuxtApp.vueApp, nuxtApp.$i18n.locale.value)
})The labels come from Intl for any BCP 47 culture (fr-FR, es-ES, pt-PT…); an invalid tag falls back to en-US. The locale is global: one locale per app instance.
The first day of the week follows the culture (en-US starts on Sunday, fr-FR on Monday). Pass firstDayOfWeek to override it, using PrimeVue's convention (0 = Sunday, 1 = Monday … 6 = Saturday); month names, weekday names and date formats still follow the culture:
applyPimpLocale(nuxtApp.vueApp, nuxtApp.$i18n.locale.value, { firstDayOfWeek: 1 })Migrating from CoreDatepicker, which always started the week on Monday: pass { firstDayOfWeek: 1 } to keep that behaviour, instead of switching the culture (en-GB for en-US) or adding a -u-fw-mon extension to the tag.
Switch box
CpSwitchBox is a box whose header shows an illustration, a title, a description and a switch. Turning the switch on expands the default slot below the header. The box only provides the content container, so style what you put inside yourself. The title is the switch's accessible name. With is-always-expanded, the switch is hidden, the content is always shown and v-model is ignored:
<cp-switch-box
v-model="hasFrequentFlyerProgram"
description="Add your membership number to earn miles on this trip."
illustration="frequent-flyer"
title="Frequent flyer program"
>
<cp-input v-model="membershipNumber" label="Membership number" />
</cp-switch-box>Components
Now that you're all set up, you can retrieve components documentation on pimp.citizenplane.com.

Reduced motion
Under prefers-reduced-motion: reduce, pimp's shipped CSS flattens every transition's duration to near-zero and every animation's duration/iteration-count to a single near-instant pass — including your app's own transitions and animations, not just pimp's. Only an element entering or leaving (a Vue <Transition>'s -enter-active/-leave-active classes) keeps a short, real opacity fade; everything else, including plain opacity/color hover transitions, becomes instant. This is a behaviour change apps should be aware of if they rely on their own transition timing.
Mark an animation that conveys real state (e.g. a loading spinner) as exempt with data-motion="essential" on the element or an ancestor — its animation-* timing is left untouched.
In script, useReducedMotion (exported from @citizenplane/pimp) reflects the OS preference reactively, for JS-driven cases CSS can't express.
🧑💻 Contributing to Pimp
We are working on making this project a fully open source. We appreciate any contributions you might make.
🍴 Step 1. Fork this repository
In order to contribute to Pimp, you need to fork this repo, and develop on your own local clone.
If you don't know how to do so, follow this guide!
📖 Step 2. Get playground up and running
First, move into your local cloned repository with the help of cd, after that install your node_modules with:
// with npm
npm installTo actually start seeing the components you have to run the project with the command:
npm run devNow go to http://localhost:8080 in your browser.
🛠 Step 3. Make your changes
Now you can start developing!
All the components are under the src/components/ directory and associated code changes will automatically be reflected in the playground.
In order to run the documentation page locally, run these commands in your terminal:
cd docs
npm install
npm run devNow you can visit http://localhost:8080/ in your browser.
🔀 Step 5. Before pushing
Run the checks used in CI:
npm run lint
npm run types📝 Commit Guidelines
This project follows Conventional Commits specification. All commit messages are automatically validated.
Using Interactive Commit Tool
For an interactive commit experience that guides you through creating a proper commit message:
git add .
npm run commit or git czManual Commit Format
If you prefer to write commit messages manually, follow this format:
<type>: <description>Available types:
feat: A new featurefix: A bug fixdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoringperf: Performance improvementstest: Adding or updating testschore: Maintenance tasksci: CI/CD changesbuild: Build system changesrevert: Revert a previous commit
Rules:
- Keep the description under 48 characters
- Use lowercase for the description
- Don't end with a period
Examples:
git commit -m "feat: add new button component"
git commit -m "fix: resolve input validation issue"
git commit -m "docs: update installation guide"The commit message will be automatically validated before the commit is accepted.
🏆 Step 6. Making your pull request
To be done
🥂 Step 7. Pat yourself on the back
Congrats, you're officially a Pimp contributor!
Feedback
We want to provide only components of the highest quality. We can’t do that without your feedback. If you have any suggestions about what we can do to improve components, please report it directly as an issue or drop us a line at [email protected].
👏 Respect earns Respect
Please respect our Code of Conduct, in short:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
License
Pimp is released under the MIT license.
Copyright © 2021 CitizenPlane, Inc.
