Problem
PR #201 adds a padding prop to Carousel.Root that accepts number | string and converts numbers (and numeric strings) to px. The conversion is inlined in CarouselRoot.vue:
padding: toRef(() => {
if (isNullOrUndefined(padding)) return undefined
if (isNumber(padding)) return `${padding}px`
return /^-?\d+(\.\d+)?$/.test(padding) ? `${padding}px` : padding
}),
This is the first CSS-length prop in v0. The next one (Dialog width, Popover offset, Slider thumbSize, Image size, etc.) will copy-paste and drift on edge cases (empty string, whitespace, scientific notation, NaN).
Proposal
Add toUnit(value, unit = 'px') to #v0/utilities when a second caller lands. Signature and semantics roughly matching Vuetify 3's convertToUnit, named toUnit to match the to* prefix convention (PHILOSOPHY §3.3):
export function toUnit (value: number | string | null | undefined, unit = 'px'): string | undefined {
if (isNullOrUndefined(value) || value === '') return undefined
if (isNumber(value)) return `${value}${unit}`
return /^-?\d+(\.\d+)?$/.test(value) ? `${value}${unit}` : value
}
Tree-shakeable, #__NO_SIDE_EFFECTS__, fits alongside clamp / range.
Open questions
Decide before promoting:
"" → undefined or ""?
"0" → "0px" or passthrough?
" 10 " (whitespace) — trim or fail?
"1e3" — convert or passthrough?
- Separate
toUnit vs. generic toCssValue — does a consumer ever need units other than px?
Pick semantics explicitly; don't inherit by accident.
Acceptance
- Helper lives at
packages/0/src/utilities/helpers.ts with tests covering every edge case listed above.
CarouselRoot.vue padding: block replaced with toUnit(padding).
- At least one additional caller wired up in the same PR (otherwise the "2+ callers" bar isn't met and this stays inline).
Context
Problem
PR #201 adds a
paddingprop toCarousel.Rootthat acceptsnumber | stringand converts numbers (and numeric strings) topx. The conversion is inlined inCarouselRoot.vue:This is the first CSS-length prop in v0. The next one (Dialog
width, Popoveroffset, SliderthumbSize, Imagesize, etc.) will copy-paste and drift on edge cases (empty string, whitespace, scientific notation,NaN).Proposal
Add
toUnit(value, unit = 'px')to#v0/utilitieswhen a second caller lands. Signature and semantics roughly matching Vuetify 3'sconvertToUnit, namedtoUnitto match theto*prefix convention (PHILOSOPHY §3.3):Tree-shakeable,
#__NO_SIDE_EFFECTS__, fits alongsideclamp/range.Open questions
Decide before promoting:
""→undefinedor""?"0"→"0px"or passthrough?" 10 "(whitespace) — trim or fail?"1e3"— convert or passthrough?toUnitvs. generictoCssValue— does a consumer ever need units other thanpx?Pick semantics explicitly; don't inherit by accident.
Acceptance
packages/0/src/utilities/helpers.tswith tests covering every edge case listed above.CarouselRoot.vuepadding:block replaced withtoUnit(padding).Context
TODO(utilities): promote to \toUnit`inpackages/0/src/components/Carousel/CarouselRoot.vue`.