feat(TimeRangeField): Implement TimeRangeField Component#2206
feat(TimeRangeField): Implement TimeRangeField Component#2206
Conversation
commit: |
56f5cdb to
777084c
Compare
777084c to
cdf8ffe
Compare
cdf8ffe to
cf88efc
Compare
|
@epr3 will merge this to the next minor release, alongside with another possible component 🤞🏻 |
|
Sounds good! 👍 |
|
This would be a really cool feature to publish @zernonia ;) |
|
@epr3 can you please update code to update the pkg-pr-new package |
cf88efc to
6e7c671
Compare
📝 WalkthroughWalkthroughA TimeRangeField feature is added: Root and Input components with locale-aware formatting, granularity, keyboard navigation, validation, context API, tests, stories, demos, documentation, and public exports/types. Changes
Sequence DiagramsequenceDiagram
participant User as User
participant Input as TimeRangeFieldInput
participant Root as TimeRangeFieldRoot
participant Formatter as DateFormatter
participant Context as RootContext
User->>Input: focus / click segment
Input->>Root: request focus / emit segment interaction
Root->>Context: update focused element / segment state
Root->>Formatter: format segment value (locale, hourCycle)
Formatter-->>Root: formatted segment parts
Root->>Input: provide segment display & attributes
Input-->>User: render segment (aria, value)
User->>Input: type value / press Arrow
Input->>Root: emit update/modelValue or navigation event
Root->>Root: validate (min/max/unavailable, order)
Root-->>Input: update segment state or move focus
Input-->>User: update UI and focus
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 16
🤖 Fix all issues with AI agents
In `@docs/components/demo/TimeRangeField/css/styles.css`:
- Around line 17-28: Remove the redundant border-width declaration in the
.TimeField rule: the existing border-width: 1px; is immediately overridden by
the border: 1px solid var(--gray-9); shorthand, so delete the border-width line
from the .TimeField CSS (locate the .TimeField selector in styles.css).
- Around line 54-55: The selector `.TimeFieldSegment:[aria-valuetext='Empty']`
is invalid CSS; remove the extraneous colon so the class and attribute selector
are combined (i.e., place the attribute selector immediately after
`.TimeFieldSegment`) to target elements with class TimeFieldSegment that have
aria-valuetext="Empty". Update the rule for `.TimeFieldSegment` +
`[aria-valuetext='Empty']` accordingly so the color declaration applies
correctly.
In `@docs/components/demo/TimeRangeField/tailwind/index.vue`:
- Around line 20-22: The v-for loops over segments.start and segments.end use
:key="item.part" which can collide for multiple 'literal' parts; change both
loops (the one iterating over segments.start and the one over segments.end) to
include the loop index (e.g., (item, idx) in segments.start / segments.end) and
build a stable unique key combining item.part and the index (such as
`${item.part}-${idx}`) so each rendered fragment has a unique key and Vue
warnings are eliminated.
In `@docs/content/docs/components/time-range-field.md`:
- Around line 675-700: The example uses Vue's watch but doesn't import it;
update the <script setup> imports to include watch (alongside ref) so the
watcher on timeRange works—locate the import line that brings in ref (and
possibly Time) and add watch to that import list to ensure the watch(timeRange,
...) call is defined.
- Around line 161-169: The examples use the Time constructor but do not import
it; add an import for Time from 'reka-ui' alongside TimeRangeFieldInput and
TimeRangeFieldRoot in the <script setup> blocks (e.g., import { Time,
TimeRangeFieldInput, TimeRangeFieldRoot } from 'reka-ui') so new Time(9, 0) and
other occurrences resolve; apply the same import addition to all subsequent
examples in this file that call new Time(...).
In `@docs/content/meta/TimeRangeFieldInput.md`:
- Around line 18-21: Update the 'part' field's description to refer to "time"
instead of "date" in the TimeRangeFieldInput metadata: change the description
string for 'part' (currently "<p>The part of the date to render</p>\n") to use
"time" ("<p>The part of the time to render</p>\n"); if this file is generated,
update the source template that produces the 'part' description so future
regenerations use "time" not "date".
In `@docs/content/meta/TimeRangeFieldRoot.md`:
- Around line 18-105: The docs for TimeRangeFieldRoot contain date/calendar
wording and a redundant granularity sentence; update the generator templates
(source templates/generator) that produce the descriptions for properties like
defaultPlaceholder, defaultValue, granularity, placeholder (and any other
TimeValue/TimeRange fields) to use time-specific wording (e.g., "time" instead
of "date/calendar") and rewrite the granularity description to a single clear
sentence explaining that it controls the displayed time segments up to the
specified unit (hour|minute|second) and the default behavior; ensure the
generator emits the corrected descriptions for 'defaultPlaceholder',
'defaultValue', 'granularity', and 'placeholder'.
In `@packages/core/src/DateRangeField/DateRangeFieldRoot.vue`:
- Around line 114-123: Update the JSDoc in the defineSlots call for
DateRangeFieldRoot to replace references to "time" with "date" or "date range"
so the slot description correctly reflects the component; specifically update
the comment for modelValue (currently "The current time of the field") to "The
current date or date range of the field" and adjust the segments comment
(currently "The time field segment contents") to "The date field segment
contents" while keeping the existing props names (modelValue, segments,
isInvalid) and types unchanged.
In `@packages/core/src/TimeRangeField/story/_DummyTimeRangeField.vue`:
- Around line 17-20: The v-for over segments.start uses item.part as the key
which can repeat (e.g., multiple "literal" segments); update the keying in both
the start and end loops (the template iterating segments.start and the
corresponding template for segments.end around lines 38-41) to use a stable
unique key such as the loop index or a composite key combining item.part with
the index (e.g., `${item.part}-${index}`) to avoid duplicate keys and render
instability.
In `@packages/core/src/TimeRangeField/story/_TimeRangeField.vue`:
- Around line 42-46: Remove the invalid disabled attribute from the <span>
element (the element with data-testid="value" that renders {{ modelValue }});
keep tabindex="-1" to prevent focus and, if you need to convey
non-interactive/disabled semantics, add aria-disabled="true" to that same span
instead of disabled.
- Around line 23-27: The v-for uses non-unique keys (item.part) in
TimeRangeFieldInput which can repeat (e.g., multiple 'literal' segments); update
the v-for to include the iteration index (e.g., v-for="(item, idx) in
segments.start") and change the :key to a composite value using the part and
index (e.g., `${item.part}-${idx}`) to guarantee uniqueness; apply the same
change for the corresponding segments.end v-for loop so both TimeRangeFieldInput
lists use unique keys.
In `@packages/core/src/TimeRangeField/story/TimeRangeFieldDefault.story.vue`:
- Around line 13-16: The v-for templates use :key="item.part" which can
duplicate for repeated literal segments; update both v-for blocks (the template
iterating over segments.start and the template iterating over segments.end) to
use a unique key such as the loop index or a composite key (e.g.,
`${item.part}-${index}`) instead of item.part so each rendered segment has a
stable, unique key.
In `@packages/core/src/TimeRangeField/TimeRangeField.test.ts`:
- Line 49: The describe block for 'timeField' is incorrectly declared async;
remove the async modifier from the describe callback (the describe('timeField',
async () => { ... }) declaration) so that only the individual it/test callbacks
handle async operations—update the declaration to describe('timeField', () => {
... }) and ensure no awaits remain in that describe body.
- Around line 70-82: The test for ZonedDateTime is flaky due to locale-dependent
formatting; update the setup call in this spec to pin the locale and hour cycle
by passing locale: 'en-US' and hourCycle: 'h12' in the props (e.g., include
locale: 'en-US' and hourCycle: 'h12' alongside timeRangeFieldProps: {
modelValue: zonedDateTime }) so the AM/PM and EST expectations (and the 12-hour
end.hour calculation) are stable across environments.
In `@packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue`:
- Around line 419-437: The hourCycle is passed into
provideTimeRangeFieldRootContext as a static value (props.hourCycle) and won't
react to parent updates; change the argument to pass a reactive ref/computed
instead (e.g., computed(() => props.hourCycle) or ref(props.hourCycle)) or
update the context type to accept Ref<HourCycle|undefined> and provide
props.hourCycle as a ref so children consuming hourCycle from
provideTimeRangeFieldRootContext will update when the prop changes.
In `@time-range-field.md`:
- Around line 304-318: The helper function isTimeRangeValid is defined but never
used; either remove the unused function or wire it into the example validation
flow by invoking isTimeRangeValid wherever time-range checks occur (e.g., in the
validation handler or function that validates timeRange objects) and ensure it
relies on isTimeUnavailable for business-hours checks; update any callers or
docs to reference isTimeRangeValid (or delete the function and remove any
related references to avoid dead code).
🧹 Nitpick comments (5)
packages/core/src/TimeRangeField/story/_TimeRangeField.vue (1)
2-7: AlignonUpdate:modelValuetype with range value
update:modelValuefor a range should use the range type, not a singleTimeValue. This keeps story/test typing aligned with the component API.✅ Suggested fix
-import type { TimeValue } from '@/shared/date' ... -const props = defineProps<{ timeRangeFieldProps?: TimeRangeFieldRootProps, emits?: { 'onUpdate:modelValue'?: (data: TimeValue) => void } }>() +const props = defineProps<{ timeRangeFieldProps?: TimeRangeFieldRootProps, emits?: { 'onUpdate:modelValue'?: (data: TimeRangeFieldRootProps['modelValue']) => void } }>()packages/core/src/TimeRangeField/story/TimeRangeFieldChromatic.story.vue (1)
53-55: Timezone example variant doesn't demonstrate timezone functionality.This variant is identical to the "Placeholder" variant and doesn't actually showcase timezone handling. Consider either removing it or adding a
ZonedDateTimevalue to properly demonstrate timezone behavior.packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue (3)
463-473: VisuallyHidden input value may display "undefined - undefined".When both
startandendare undefined, the hidden input's value will be the string"undefined - undefined". Consider providing a fallback empty string for better form handling.Proposed fix
<VisuallyHidden :id="id" as="input" feature="focusable" tabindex="-1" - :value="`${modelValue?.start?.toString()} - ${modelValue?.end?.toString()}`" + :value="modelValue?.start && modelValue?.end ? `${modelValue.start.toString()} - ${modelValue.end.toString()}` : ''" :name="name" :disabled="disabled" :required="required"
234-242: Computed setters return values unnecessarily.The
return newValuestatements in the computed setters forconvertedStartValue,convertedEndValue, andconvertedPlaceholderare unnecessary. Vue computed setters don't use return values.Proposed fix for convertedStartValue (apply same pattern to others)
set(newValue) { if (newValue) { startValue.value = startValue.value && 'day' in startValue.value ? newValue : new Time(newValue.hour, newValue.minute, newValue.second, startValue.value?.millisecond) } else { startValue.value = newValue } - return newValue },Also applies to: 251-259, 278-282
326-340: Duplicate watchers onconvertedModelValue.There are two separate
watchcalls onconvertedModelValue(lines 326-340 and 364-367). These could be consolidated into a single watcher for clarity and to avoid potential ordering issues.Proposed consolidation
watch(convertedModelValue, (_modelValue) => { const isStartChanged = _modelValue?.start && convertedStartValue.value ? _modelValue.start.compare(convertedStartValue.value) !== 0 : _modelValue?.start !== convertedStartValue.value if (isStartChanged) { convertedStartValue.value = _modelValue?.start?.copy() } const isEndChanged = _modelValue?.end && convertedEndValue.value ? _modelValue.end.compare(convertedEndValue.value) !== 0 : _modelValue?.end !== convertedEndValue.value if (isEndChanged) { convertedEndValue.value = _modelValue?.end?.copy() } + + // Sync placeholder with start value + if (_modelValue && _modelValue.start !== undefined && placeholder.value.compare(_modelValue.start) !== 0) + placeholder.value = _modelValue.start.copy() }) - -watch(convertedModelValue, (_modelValue) => { - if (_modelValue && _modelValue.start !== undefined && placeholder.value.compare(_modelValue.start) !== 0) - placeholder.value = _modelValue.start.copy() -})Also applies to: 364-367
| .TimeField { | ||
| display: flex; | ||
| padding: 0.5rem; | ||
| align-items: center; | ||
| border-radius: 0.25rem; | ||
| border-width: 1px; | ||
| text-align: center; | ||
| background-color: #ffffff; | ||
| user-select: none; | ||
| color: var(--green-10); | ||
| border: 1px solid var(--gray-9); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -type f -name "styles.css" | grep -i timerangeRepository: unovue/reka-ui
Length of output: 110
🏁 Script executed:
cat -n ./docs/components/demo/TimeRangeField/css/styles.cssRepository: unovue/reka-ui
Length of output: 1405
Remove redundant border-width property that is overridden by the border shorthand.
The border-width: 1px; on line 22 is immediately overridden by the border: 1px solid var(--gray-9); shorthand on line 27. This creates a CSS redundancy that linters like Biome flag as an error. Remove the redundant border-width declaration.
🔧 Suggested fix
.TimeField {
display: flex;
padding: 0.5rem;
align-items: center;
border-radius: 0.25rem;
- border-width: 1px;
text-align: center;
background-color: `#ffffff`;
user-select: none;
color: var(--green-10);
border: 1px solid var(--gray-9);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .TimeField { | |
| display: flex; | |
| padding: 0.5rem; | |
| align-items: center; | |
| border-radius: 0.25rem; | |
| border-width: 1px; | |
| text-align: center; | |
| background-color: #ffffff; | |
| user-select: none; | |
| color: var(--green-10); | |
| border: 1px solid var(--gray-9); | |
| } | |
| .TimeField { | |
| display: flex; | |
| padding: 0.5rem; | |
| align-items: center; | |
| border-radius: 0.25rem; | |
| text-align: center; | |
| background-color: `#ffffff`; | |
| user-select: none; | |
| color: var(--green-10); | |
| border: 1px solid var(--gray-9); | |
| } |
🧰 Tools
🪛 Biome (2.1.2)
[error] 27-27: Unexpected shorthand property border after border-width
(lint/suspicious/noShorthandPropertyOverrides)
🤖 Prompt for AI Agents
In `@docs/components/demo/TimeRangeField/css/styles.css` around lines 17 - 28,
Remove the redundant border-width declaration in the .TimeField rule: the
existing border-width: 1px; is immediately overridden by the border: 1px solid
var(--gray-9); shorthand, so delete the border-width line from the .TimeField
CSS (locate the .TimeField selector in styles.css).
| .TimeFieldSegment:[aria-valuetext='Empty'] { | ||
| color: var(--grass-6); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's find and read the file
cat -n "docs/components/demo/TimeRangeField/css/styles.css" | sed -n '50,60p'Repository: unovue/reka-ui
Length of output: 243
🌐 Web query:
CSS attribute selector syntax with class selector invalid colon
💡 Result:
If you write a selector like .foo:bar, the : is parsed as the start of a pseudo-class (:bar), so it looks “invalid” unless :bar is a real pseudo-class. To match an actual class name that contains a colon (e.g. class="foo:bar"), you have two common options:
- Escape the colon in the class selector
.foo\:bar { /* styles */ }MDN notes class selector names must be valid CSS identifiers, and non-identifier characters must be escaped before use. [2]
- Use an attribute selector instead
[class~="foo:bar"] { /* styles */ }This matches when the element’s class attribute (a whitespace-separated list) contains the word foo:bar. Attribute selector syntax and [attr~=value] behavior are documented on MDN. [1][2]
If you’re generating selectors in JS, you can safely escape arbitrary class strings with:
const sel = "." + CSS.escape("foo:bar");MDN documents CSS.escape() for building safe selectors. [3]
Sources: [1] [2] [3]
Fix invalid CSS selector syntax.
.TimeFieldSegment:[aria-valuetext='Empty'] is invalid CSS. The colon (:) is used for pseudo-classes or pseudo-elements, but [aria-valuetext='Empty'] is an attribute selector. Remove the colon to properly combine the class and attribute selectors.
🔧 Suggested fix
-.TimeFieldSegment:[aria-valuetext='Empty'] {
+.TimeFieldSegment[aria-valuetext='Empty'] {
color: var(--grass-6);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .TimeFieldSegment:[aria-valuetext='Empty'] { | |
| color: var(--grass-6); | |
| .TimeFieldSegment[aria-valuetext='Empty'] { | |
| color: var(--grass-6); | |
| } |
🧰 Tools
🪛 Biome (2.1.2)
[error] 54-54: Unexpected value or character.
Expected one of:
(parse)
🤖 Prompt for AI Agents
In `@docs/components/demo/TimeRangeField/css/styles.css` around lines 54 - 55, The
selector `.TimeFieldSegment:[aria-valuetext='Empty']` is invalid CSS; remove the
extraneous colon so the class and attribute selector are combined (i.e., place
the attribute selector immediately after `.TimeFieldSegment`) to target elements
with class TimeFieldSegment that have aria-valuetext="Empty". Update the rule
for `.TimeFieldSegment` + `[aria-valuetext='Empty']` accordingly so the color
declaration applies correctly.
| v-for="item in segments.start" | ||
| :key="item.part" | ||
| > |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n docs/components/demo/TimeRangeField/tailwind/index.vueRepository: unovue/reka-ui
Length of output: 2261
🏁 Script executed:
# Search for similar v-for patterns in other TimeRangeField demos
find docs/components/demo/TimeRangeField -name "*.vue" -type f | head -5Repository: unovue/reka-ui
Length of output: 162
🏁 Script executed:
cat -n docs/components/demo/TimeRangeField/css/index.vueRepository: unovue/reka-ui
Length of output: 2009
🏁 Script executed:
# Check for TimeRangeField component implementation to understand segment structure
find . -type f -name "*.vue" -o -name "*.ts" -o -name "*.js" | xargs grep -l "TimeRangeFieldRoot" | grep -E "^\./(src|components)" | head -3Repository: unovue/reka-ui
Length of output: 40
🏁 Script executed:
# Find TimeRangeField component definition
find . -type f \( -name "*.vue" -o -name "*.ts" \) | xargs grep -l "TimeRangeField" | head -10Repository: unovue/reka-ui
Length of output: 646
🏁 Script executed:
# Check the TimeRangeFieldRoot component to understand segment structure
head -100 ./packages/core/src/TimeRangeField/TimeRangeFieldRoot.vueRepository: unovue/reka-ui
Length of output: 4069
🏁 Script executed:
# Check for segment creation to understand typical segment structure
grep -A 20 "segmentContents" ./packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue | head -40Repository: unovue/reka-ui
Length of output: 2100
🏁 Script executed:
# Look for where segments are created to understand if multiple items can have same part
grep -A 30 "createContent\|getTimeFieldSegmentElements" ./packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue | head -50Repository: unovue/reka-ui
Length of output: 1468
🏁 Script executed:
# Find the createContent function implementation
rg -A 30 "function createContent|export.*createContent" --type ts --type js packages/core/src/shared/date/ | head -80Repository: unovue/reka-ui
Length of output: 5758
🏁 Script executed:
# Check story files to see what segments actually contain
grep -A 10 "segments\." ./packages/core/src/TimeRangeField/story/TimeRangeFieldDefault.story.vue | head -30Repository: unovue/reka-ui
Length of output: 680
Use unique keys combining part and index to avoid collisions.
Multiple segments can have part: 'literal' (e.g., time separators), creating duplicate keys with :key="item.part". This causes Vue warnings and potential rendering issues.
🔧 Suggested fix
<template
- v-for="item in segments.start"
- :key="item.part"
+ v-for="(item, index) in segments.start"
+ :key="item.part + '-' + index"
>Also applies to lines 44-46 for segments.end.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| v-for="item in segments.start" | |
| :key="item.part" | |
| > | |
| v-for="(item, index) in segments.start" | |
| :key="item.part + '-' + index" | |
| > |
🤖 Prompt for AI Agents
In `@docs/components/demo/TimeRangeField/tailwind/index.vue` around lines 20 - 22,
The v-for loops over segments.start and segments.end use :key="item.part" which
can collide for multiple 'literal' parts; change both loops (the one iterating
over segments.start and the one over segments.end) to include the loop index
(e.g., (item, idx) in segments.start / segments.end) and build a stable unique
key combining item.part and the index (such as `${item.part}-${idx}`) so each
rendered fragment has a unique key and Vue warnings are eliminated.
| ```vue | ||
| <script setup> | ||
| import { TimeRangeFieldInput, TimeRangeFieldRoot } from 'reka-ui' | ||
|
|
||
| const timeRange = ref({ | ||
| start: new Time(9, 0), | ||
| end: new Time(17, 0) | ||
| }) | ||
|
|
||
| const errors = ref([]) | ||
|
|
||
| watch(timeRange, (newRange) => { | ||
| errors.value = [] | ||
| if (newRange.start && newRange.end) { | ||
| if (newRange.start.compare(newRange.end) >= 0) { | ||
| errors.value.push('End time must be after start time') | ||
| } | ||
| if (newRange.start.hour < 8 || newRange.start.hour > 18) { | ||
| errors.value.push('Start time must be between 8 AM and 6 PM') | ||
| } | ||
| if (newRange.end.hour < 8 || newRange.end.hour > 18) { | ||
| errors.value.push('End time must be between 8 AM and 6 PM') | ||
| } | ||
| } | ||
| }, { deep: true }) | ||
| </script> |
There was a problem hiding this comment.
Missing watch import in Advanced Validation example.
The example uses Vue's watch function but doesn't include it in the imports.
Proposed fix
<script setup>
+import { Time } from '@internationalized/date'
+import { ref, watch } from 'vue'
import { TimeRangeFieldInput, TimeRangeFieldRoot } from 'reka-ui'
const timeRange = ref({🤖 Prompt for AI Agents
In `@docs/content/docs/components/time-range-field.md` around lines 675 - 700, The
example uses Vue's watch but doesn't import it; update the <script setup>
imports to include watch (alongside ref) so the watcher on timeRange
works—locate the import line that brings in ref (and possibly Time) and add
watch to that import list to ensure the watch(timeRange, ...) call is defined.
| <template | ||
| v-for="item in segments.start" | ||
| :key="item.part" | ||
| > |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n packages/core/src/TimeRangeField/story/TimeRangeFieldDefault.story.vueRepository: unovue/reka-ui
Length of output: 2264
🏁 Script executed:
find packages/core/src/TimeRangeField -name "*.ts" -o -name "*.tsx" -o -name "*.vue" | grep -v story | head -20Repository: unovue/reka-ui
Length of output: 268
🏁 Script executed:
cat -n packages/core/src/TimeRangeField/TimeRangeFieldRoot.vueRepository: unovue/reka-ui
Length of output: 19491
🏁 Script executed:
rg "type SegmentPart" --type tsRepository: unovue/reka-ui
Length of output: 353
🏁 Script executed:
cat -n packages/core/src/shared/date/types.ts | head -100Repository: unovue/reka-ui
Length of output: 2222
🏁 Script executed:
rg "const.*SEGMENT_PARTS" packages/core/src/shared/date/parts.ts -A 20Repository: unovue/reka-ui
Length of output: 1229
🏁 Script executed:
rg "function createContent" packages/core/src/shared/date/ -A 50Repository: unovue/reka-ui
Length of output: 7829
🏁 Script executed:
rg "segments\." packages/core/src/TimeRangeField/ -A 2 -B 2Repository: unovue/reka-ui
Length of output: 2635
Use unique keys for repeated segments
item.part can repeat (e.g., multiple literal segments for separators like : and /), which creates duplicate keys and causes Vue rendering instability. Use an index or unique identifier for the key.
✅ Suggested fix
- <template
- v-for="item in segments.start"
- :key="item.part"
- >
+ <template
+ v-for="(item, idx) in segments.start"
+ :key="`${item.part}-${idx}`"
+ >Also applies to segments.end (lines 34-37)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <template | |
| v-for="item in segments.start" | |
| :key="item.part" | |
| > | |
| <template | |
| v-for="(item, idx) in segments.start" | |
| :key="`${item.part}-${idx}`" | |
| > |
🤖 Prompt for AI Agents
In `@packages/core/src/TimeRangeField/story/TimeRangeFieldDefault.story.vue`
around lines 13 - 16, The v-for templates use :key="item.part" which can
duplicate for repeated literal segments; update both v-for blocks (the template
iterating over segments.start and the template iterating over segments.end) to
use a unique key such as the loop index or a composite key (e.g.,
`${item.part}-${index}`) instead of item.part so each rendered segment has a
stable, unique key.
| expect(await axe(container)).toHaveNoViolations() | ||
| }) | ||
|
|
||
| describe('timeField', async () => { |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Read the specific test file around line 49
sed -n '45,60p' packages/core/src/TimeRangeField/TimeRangeField.test.ts | cat -nRepository: unovue/reka-ui
Length of output: 737
🏁 Script executed:
# Check the full describe block to see if async operations exist
sed -n '49,150p' packages/core/src/TimeRangeField/TimeRangeField.test.ts | head -100Repository: unovue/reka-ui
Length of output: 3637
🏁 Script executed:
# Search for other async describe blocks in test files to identify patterns
rg "describe\(['\"].*['\"],\s*async\s*\(\)" --type ts --type tsx -c | head -20Repository: unovue/reka-ui
Length of output: 85
Remove unnecessary async from describe callback
The describe block is marked as async but contains no async operations—all async logic is properly isolated within individual it blocks. This violates testing best practices and can mask errors.
Suggested fix
-describe('timeField', async () => {
+describe('timeField', () => {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| describe('timeField', async () => { | |
| describe('timeField', () => { |
🤖 Prompt for AI Agents
In `@packages/core/src/TimeRangeField/TimeRangeField.test.ts` at line 49, The
describe block for 'timeField' is incorrectly declared async; remove the async
modifier from the describe callback (the describe('timeField', async () => { ...
}) declaration) so that only the individual it/test callbacks handle async
operations—update the declaration to describe('timeField', () => { ... }) and
ensure no awaits remain in that describe body.
| it('populates segment with value - `ZonedDateTime`', async () => { | ||
| const { start, end, getByTestId } = setup({ | ||
| timeRangeFieldProps: { modelValue: zonedDateTime }, | ||
| }) | ||
|
|
||
| expect(start.hour).toHaveTextContent(String(zonedDateTime.start.hour)) | ||
| expect(start.minute).toHaveTextContent(String(zonedDateTime.start.minute)) | ||
| expect(end.hour).toHaveTextContent(String(zonedDateTime.end.hour - 12)) | ||
| expect(end.minute).toHaveTextContent(String(zonedDateTime.end.minute)) | ||
| expect(getByTestId('start-dayPeriod')).toHaveTextContent('AM') | ||
| expect(getByTestId('start-timeZoneName')).toHaveTextContent('EST') | ||
| expect(getByTestId('end-dayPeriod')).toHaveTextContent('PM') | ||
| expect(getByTestId('end-timeZoneName')).toHaveTextContent('EST') |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cd packages/core/src/TimeRangeField && find . -type f -name "*.test.ts" | head -5Repository: unovue/reka-ui
Length of output: 82
🏁 Script executed:
cat -n packages/core/src/TimeRangeField/TimeRangeField.test.ts | head -100Repository: unovue/reka-ui
Length of output: 4653
🏁 Script executed:
wc -l packages/core/src/TimeRangeField/TimeRangeField.test.tsRepository: unovue/reka-ui
Length of output: 117
🏁 Script executed:
find packages/core/src/TimeRangeField -type f \( -name "*.vue" -o -name "*.ts" \) | grep -v test | grep -v storyRepository: unovue/reka-ui
Length of output: 212
🏁 Script executed:
cat -n packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue | head -150Repository: unovue/reka-ui
Length of output: 6899
🏁 Script executed:
cat -n packages/core/src/TimeRangeField/story/_TimeRangeField.vueRepository: unovue/reka-ui
Length of output: 1728
🏁 Script executed:
cat -n packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue | sed -n '130,200p'Repository: unovue/reka-ui
Length of output: 2777
🏁 Script executed:
cd packages/core && grep -r "useLocale\|useDateFormatter" --include="*.ts" --include="*.vue" -A 3 | head -40Repository: unovue/reka-ui
Length of output: 2485
🏁 Script executed:
cd packages/core/src && grep -r "timeZoneName" --include="*.ts" --include="*.vue" -B 3 -A 3 | head -60Repository: unovue/reka-ui
Length of output: 3338
🏁 Script executed:
cd packages/core/src && grep -r "dayPeriod" --include="*.ts" --include="*.vue" -B 3 -A 3 | head -60Repository: unovue/reka-ui
Length of output: 3387
🏁 Script executed:
cd packages/core/src && grep -r "zonedDateTime" --include="*.test.ts" -B 5 -A 10 | head -100Repository: unovue/reka-ui
Length of output: 6470
🏁 Script executed:
cd packages/core/src/DateField && grep -n "zonedDateTime" DateField.test.ts -A 8 | head -40Repository: unovue/reka-ui
Length of output: 1554
🏁 Script executed:
cd packages/core && find . -type f \( -name "vitest.config.*" -o -name "setup.ts" -o -name "setup.js" \) | xargs cat 2>/dev/null | head -80Repository: unovue/reka-ui
Length of output: 40
🏁 Script executed:
cd packages/core && find . -type f -name "*.ts" -path "*/test/*" -o -name "*setup*" | grep -i test | head -20Repository: unovue/reka-ui
Length of output: 115
🏁 Script executed:
cat packages/core/vitest.config.tsRepository: unovue/reka-ui
Length of output: 120
🏁 Script executed:
cat packages/core/vitest.setup.tsRepository: unovue/reka-ui
Length of output: 475
🏁 Script executed:
cat packages/core/src/test/utils.tsRepository: unovue/reka-ui
Length of output: 338
🏁 Script executed:
cd packages/core/src/DateField && cat -n DateField.test.ts | sed -n '75,100p'Repository: unovue/reka-ui
Length of output: 1423
🏁 Script executed:
cd packages/core && rg "locale.*en-US|hourCycle.*h12" --type ts --type vue -B 2 -A 2 | head -50Repository: unovue/reka-ui
Length of output: 85
🏁 Script executed:
cd packages/core && rg "locale.*en-US|hourCycle.*h12" -B 2 -A 2 | head -50Repository: unovue/reka-ui
Length of output: 1028
🏁 Script executed:
cd packages/core/src/DateField && cat -n DateField.test.ts | sed -n '83,95p'Repository: unovue/reka-ui
Length of output: 812
🏁 Script executed:
cd packages/core && grep -r "beforeAll\|beforeEach\|setLocale\|useLocale" src/test/ -A 3Repository: unovue/reka-ui
Length of output: 40
🏁 Script executed:
cd packages && cat -n core/src/TimeRangeField/TimeRangeField.test.ts | sed -n '1,25p'Repository: unovue/reka-ui
Length of output: 1288
🏁 Script executed:
cd packages/core && grep -r "vi.useFakeTimers\|vi.setConfig\|process.env.TZ\|Intl" vitest.setup.ts -A 3 -B 3Repository: unovue/reka-ui
Length of output: 40
🏁 Script executed:
cd packages/core && find . -type f -name "*.ts" -o -name "*.js" | xargs grep -l "export.*useLocale" | head -3Repository: unovue/reka-ui
Length of output: 105
🏁 Script executed:
cd packages/core && grep -r "export.*useLocale\|function useLocale" src/shared --include="*.ts" -A 10 | head -40Repository: unovue/reka-ui
Length of output: 816
🏁 Script executed:
cd packages/core/src && grep -r "useDateFormatter" src/shared/date --include="*.ts" -A 15 | head -60Repository: unovue/reka-ui
Length of output: 106
🏁 Script executed:
cd packages/core && python3 << 'EOF'
from datetime import datetime
import json
# Check timezone abbreviation for January 1, 2022 in America/New_York
# and how it formats with different locales
test_date = "2022-01-01T09:15:00-05:00" # EST (winter time)
# This is just to verify the concept - the actual formatting
# happens in JavaScript/Node.js context via Intl API
print("Timezone info for 2022-01-01 in America/New_York:")
print("- Winter (January) = EST (UTC-5)")
print("- Test date hour: 9 AM (should be 'AM')")
print("- End date hour: 5 PM (17:00 - 12 = 5, should be 'PM')")
print("\nFormatting depends on:")
print("1. Locale: 'en-US' vs 'en' (generic) vs others")
print("2. HourCycle: 'h12' for 12-hour format with AM/PM")
EOFRepository: unovue/reka-ui
Length of output: 144
🏁 Script executed:
cd packages/core/src && grep -r "segmentContents\|formatSegment" TimeRangeField --include="*.ts" --include="*.vue" -B 2 -A 5 | head -80Repository: unovue/reka-ui
Length of output: 2741
Stabilize ZonedDateTime test with explicit locale and hour cycle
This test expects locale-specific formatting (AM/PM, EST) but doesn't pin the locale. Unlike the Time and CalendarDateTime tests in the same suite, this should explicitly specify locale: 'en-US' and hourCycle: 'h12' to avoid flakiness from environment or system defaults.
Suggested fix
const { start, end, getByTestId } = setup({
- timeRangeFieldProps: { modelValue: zonedDateTime },
+ timeRangeFieldProps: { modelValue: zonedDateTime, locale: 'en-US', hourCycle: 'h12' },
})🤖 Prompt for AI Agents
In `@packages/core/src/TimeRangeField/TimeRangeField.test.ts` around lines 70 -
82, The test for ZonedDateTime is flaky due to locale-dependent formatting;
update the setup call in this spec to pin the locale and hour cycle by passing
locale: 'en-US' and hourCycle: 'h12' in the props (e.g., include locale: 'en-US'
and hourCycle: 'h12' alongside timeRangeFieldProps: { modelValue: zonedDateTime
}) so the AM/PM and EST expectations (and the 12-hour end.hour calculation) are
stable across environments.
| provideTimeRangeFieldRootContext({ | ||
| locale, | ||
| startValue: convertedStartValue, | ||
| endValue: convertedEndValue, | ||
| placeholder: convertedPlaceholder, | ||
| disabled, | ||
| formatter, | ||
| hourCycle: props.hourCycle, | ||
| step, | ||
| readonly, | ||
| isInvalid, | ||
| segmentValues: { start: startSegmentValues, end: endSegmentValues }, | ||
| segmentContents: editableSegmentContents, | ||
| elements: segmentElements, | ||
| setFocusedElement, | ||
| focusNext() { | ||
| nextFocusableSegment.value?.focus() | ||
| }, | ||
| }) |
There was a problem hiding this comment.
hourCycle in context is not reactive.
The hourCycle property is passed directly as props.hourCycle rather than as a ref/computed. If the parent changes the hourCycle prop dynamically, child components won't react to the change.
Proposed fix
+const hourCycle = computed(() => props.hourCycle)
+
provideTimeRangeFieldRootContext({
locale,
startValue: convertedStartValue,
endValue: convertedEndValue,
placeholder: convertedPlaceholder,
disabled,
formatter,
- hourCycle: props.hourCycle,
+ hourCycle: hourCycle.value,
step,
readonly,Alternatively, update the context type to accept Ref<HourCycle | undefined> and pass it as a ref for full reactivity.
🤖 Prompt for AI Agents
In `@packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue` around lines 419 -
437, The hourCycle is passed into provideTimeRangeFieldRootContext as a static
value (props.hourCycle) and won't react to parent updates; change the argument
to pass a reactive ref/computed instead (e.g., computed(() => props.hourCycle)
or ref(props.hourCycle)) or update the context type to accept
Ref<HourCycle|undefined> and provide props.hourCycle as a ref so children
consuming hourCycle from provideTimeRangeFieldRootContext will update when the
prop changes.
| // Only allow time ranges within business hours | ||
| function isTimeRangeValid(timeRange) { | ||
| if (!timeRange.start || !timeRange.end) | ||
| return true | ||
|
|
||
| // Start time must be before end time | ||
| if (timeRange.start.compare(timeRange.end) >= 0) | ||
| return false | ||
|
|
||
| // Both times must be within business hours | ||
| if (isTimeUnavailable(timeRange.start) || isTimeUnavailable(timeRange.end)) | ||
| return false | ||
|
|
||
| return true | ||
| } |
There was a problem hiding this comment.
Unused isTimeRangeValid in validation example
The helper is defined but never used. Either wire it into the example (if supported) or remove it to avoid confusion.
✅ Suggested fix (remove unused helper)
-// Only allow time ranges within business hours
-function isTimeRangeValid(timeRange) {
- if (!timeRange.start || !timeRange.end)
- return true
-
- // Start time must be before end time
- if (timeRange.start.compare(timeRange.end) >= 0)
- return false
-
- // Both times must be within business hours
- if (isTimeUnavailable(timeRange.start) || isTimeUnavailable(timeRange.end))
- return false
-
- return true
-}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Only allow time ranges within business hours | |
| function isTimeRangeValid(timeRange) { | |
| if (!timeRange.start || !timeRange.end) | |
| return true | |
| // Start time must be before end time | |
| if (timeRange.start.compare(timeRange.end) >= 0) | |
| return false | |
| // Both times must be within business hours | |
| if (isTimeUnavailable(timeRange.start) || isTimeUnavailable(timeRange.end)) | |
| return false | |
| return true | |
| } |
🤖 Prompt for AI Agents
In `@time-range-field.md` around lines 304 - 318, The helper function
isTimeRangeValid is defined but never used; either remove the unused function or
wire it into the example validation flow by invoking isTimeRangeValid wherever
time-range checks occur (e.g., in the validation handler or function that
validates timeRange objects) and ensure it relies on isTimeUnavailable for
business-hours checks; update any callers or docs to reference isTimeRangeValid
(or delete the function and remove any related references to avoid dead code).
6e7c671 to
03775c4
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@docs/components/demo/TimeRangeField/css/styles.css`:
- Line 24: Replace the long hex color in the background-color declaration in
styles.css (the background-color: `#ffffff`; line) with the shorthand form `#fff` to
satisfy the color-hex-length lint rule; update the background-color property
value to use `#fff` wherever that exact declaration appears in TimeRangeField's
styles.
In `@packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue`:
- Around line 148-150: The locale-change watcher is calling getSegmentElements
(which selects [data-reka-date-field-segment]) but the mounted code and
TimeRangeField expect time-field segments; update the watcher to call
getTimeFieldSegmentElements instead so it repopulates segmentElements with the
correct [data-reka-time-field-segment] nodes. Locate the locale watcher that
currently uses getSegmentElements and replace that call with
getTimeFieldSegmentElements, ensuring it still iterates and adds items into the
segmentElements Set the same way as the onMounted block.
In `@time-range-field.md`:
- Line 172: The v-for in the template iterates over segments.start using
:key="item.part" which can produce duplicate keys (e.g., repeated "literal"
parts); update the template's v-for to capture the index (template v-for="(item,
index) in segments.start") and make the key unique by combining part and index
(use a template string like `${item.part}-${index}`) so each rendered segment
(in the template with v-for, segments.start, and item.part) has a stable unique
key.
- Line 62: The prop description in TimeRangeField for the granularity prop is
redundant (it currently says "Defaults to minute if a Time is provided,
otherwise defaults to minute"); update the granularity description in
time-range-field.md (the TimeRangeField prop docs) to a single clear default
statement such as "Defaults to minute." so it no longer repeats the same branch;
ensure the prop name "granularity" and the component name "TimeRangeField"
remain referenced correctly in the updated text.
🧹 Nitpick comments (3)
packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue (3)
326-340: Two separate watchers onconvertedModelValue— consider merging.There are two
watch(convertedModelValue, ...)callbacks (lines 326 and 364). This splits related synchronization logic across two watchers on the same source, making the execution order harder to reason about. Consider merging them into a single watcher.Also applies to: 364-367
292-292:initialSegmentsis not reactive to granularity changes.
initialSegmentsis computed once frominferredGranularity.valueat initialization time. Ifgranularityprop changes dynamically, the reset logic in the watchers (lines 348 and 375) will use stale segment shapes. Consider making it acomputed.Suggested fix
-const initialSegments = initializeTimeSegmentValues(inferredGranularity.value) +const initialSegments = computed(() => initializeTimeSegmentValues(inferredGranularity.value))Then update usages to
initialSegments.value:- startSegmentValues.value = { ...initialSegments } + startSegmentValues.value = { ...initialSegments.value }
136-138: Formatter created with non-reactive locale.
useDateFormatter(locale.value, ...)receives the unwrapped string, so the formatter's internalhourCycleoption is fixed at creation time. While the locale watcher (line 352) manually callsformatter.setLocale(value), thehourCyclenormalization passed during construction won't be refreshed ifhourCycleprop changes. This is consistent with the non-reactivehourCycleissue already flagged but worth noting the formatter is also affected.
| border-radius: 0.25rem; | ||
| border-width: 1px; | ||
| text-align: center; | ||
| background-color: #ffffff; |
There was a problem hiding this comment.
Use shorthand hex color.
#ffffff should be #fff per the color-hex-length stylelint rule.
Suggested fix
- background-color: `#ffffff`;
+ background-color: `#fff`;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| background-color: #ffffff; | |
| background-color: `#fff`; |
🧰 Tools
🪛 Stylelint (17.2.0)
[error] 24-24: Expected "#ffffff" to be "#fff" (color-hex-length)
(color-hex-length)
🤖 Prompt for AI Agents
In `@docs/components/demo/TimeRangeField/css/styles.css` at line 24, Replace the
long hex color in the background-color declaration in styles.css (the
background-color: `#ffffff`; line) with the shorthand form `#fff` to satisfy the
color-hex-length lint rule; update the background-color property value to use
`#fff` wherever that exact declaration appears in TimeRangeField's styles.
| onMounted(() => { | ||
| getTimeFieldSegmentElements(parentElement.value).forEach(item => segmentElements.value.add(item as HTMLElement)) | ||
| }) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, let's look at the file structure and find the functions
echo "=== Looking for getTimeFieldSegmentElements function ==="
rg -n "function getTimeFieldSegmentElements|const getTimeFieldSegmentElements" packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue -A 5
echo -e "\n=== Looking for getSegmentElements function ==="
rg -n "function getSegmentElements|const getSegmentElements" packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue -A 5
echo -e "\n=== Checking if these functions are imported ==="
head -50 packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue | grep -E "import|from"Repository: unovue/reka-ui
Length of output: 1024
🏁 Script executed:
#!/bin/bash
# Let's check the entire file to understand the context better
wc -l packages/core/src/TimeRangeField/TimeRangeFieldRoot.vueRepository: unovue/reka-ui
Length of output: 117
🏁 Script executed:
#!/bin/bash
# Get the relevant sections of the file
echo "=== Lines 148-155 (onMounted hook) ==="
sed -n '148,155p' packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue
echo -e "\n=== Lines 352-365 (locale-change watcher) ==="
sed -n '352,365p' packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue
echo -e "\n=== Search for function definitions ==="
rg -n "getTimeFieldSegmentElements|getSegmentElements" packages/core/src/TimeRangeField/TimeRangeFieldRoot.vueRepository: unovue/reka-ui
Length of output: 1413
🏁 Script executed:
#!/bin/bash
# Find where these functions are imported from
echo "=== Finding imports for getSegmentElements and getTimeFieldSegmentElements ==="
sed -n '1,30p' packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue | grep -n "getSegmentElements\|getTimeFieldSegmentElements"
echo -e "\n=== Full import statements ==="
sed -n '1,30p' packages/core/src/TimeRangeField/TimeRangeFieldRoot.vueRepository: unovue/reka-ui
Length of output: 1296
🏁 Script executed:
#!/bin/bash
# Find where these functions are defined
echo "=== Searching for getSegmentElements definition ==="
rg -n "export.*getSegmentElements|function getSegmentElements|const getSegmentElements" packages/core/src/TimeRangeField/ -A 3
echo -e "\n=== Searching for getTimeFieldSegmentElements definition ==="
rg -n "export.*getTimeFieldSegmentElements|function getTimeFieldSegmentElements|const getTimeFieldSegmentElements" packages/core/src/TimeRangeField/ -A 3Repository: unovue/reka-ui
Length of output: 171
🏁 Script executed:
#!/bin/bash
# Find the shared/date directory and search for these functions
echo "=== Directory structure of shared/date ==="
find packages/core/src/shared/date -type f -name "*.ts" -o -name "*.js"
echo -e "\n=== Searching for getSegmentElements ==="
rg -n "getSegmentElements" packages/core/src/shared/date/ -A 5
echo -e "\n=== Searching for getTimeFieldSegmentElements ==="
rg -n "getTimeFieldSegmentElements" packages/core/src/shared/date/ -A 5Repository: unovue/reka-ui
Length of output: 1712
🏁 Script executed:
#!/bin/bash
# Verify the context once more to make sure this is in TimeRangeFieldRoot.vue
echo "=== Verify the file and context ==="
echo "File: packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue"
echo "Line 149 context:"
sed -n '148,150p' packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue
echo ""
echo "Line 359 context:"
sed -n '358,360p' packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue
echo ""
echo "=== Confirm these are the only two places where these functions are used ==="
rg -n "getSegmentElements\|getTimeFieldSegmentElements" packages/core/src/TimeRangeField/TimeRangeFieldRoot.vueRepository: unovue/reka-ui
Length of output: 559
Replace getSegmentElements with getTimeFieldSegmentElements in the locale-change watcher.
The locale watcher at line 359 uses getSegmentElements which queries [data-reka-date-field-segment] selectors, while onMounted at line 149 correctly uses getTimeFieldSegmentElements which queries [data-reka-time-field-segment] selectors. After a locale change, this causes the segment elements set to be repopulated with date-field segments instead of time-field segments, breaking TimeRangeField functionality. Update line 359 to use getTimeFieldSegmentElements for consistency.
🤖 Prompt for AI Agents
In `@packages/core/src/TimeRangeField/TimeRangeFieldRoot.vue` around lines 148 -
150, The locale-change watcher is calling getSegmentElements (which selects
[data-reka-date-field-segment]) but the mounted code and TimeRangeField expect
time-field segments; update the watcher to call getTimeFieldSegmentElements
instead so it repopulates segmentElements with the correct
[data-reka-time-field-segment] nodes. Locate the locale watcher that currently
uses getSegmentElements and replace that call with getTimeFieldSegmentElements,
ensuring it still iterates and adds items into the segmentElements Set the same
way as the onMounted block.
| <TimeRangeFieldInput part="minute" type="end" /> | ||
| </TimeRangeFieldRoot> | ||
| </template> | ||
| ``` |
There was a problem hiding this comment.
Redundant granularity description.
The prop description reads "Defaults to minute if a Time is provided, otherwise defaults to minute" — both branches say the same thing. This appears to be a copy-paste artifact from DateField where the fallback granularity differs depending on value type. Update to simply state the default.
🤖 Prompt for AI Agents
In `@time-range-field.md` at line 62, The prop description in TimeRangeField for
the granularity prop is redundant (it currently says "Defaults to minute if a
Time is provided, otherwise defaults to minute"); update the granularity
description in time-range-field.md (the TimeRangeField prop docs) to a single
clear default statement such as "Defaults to minute." so it no longer repeats
the same branch; ensure the prop name "granularity" and the component name
"TimeRangeField" remain referenced correctly in the updated text.
| v-slot="{ segments, isInvalid }" | ||
| class="flex select-none bg-white items-center rounded text-center border border-gray-300 p-2 data-[invalid]:border-red-500" | ||
| > | ||
| <template v-for="item in segments.start" :key="item.part"> |
There was a problem hiding this comment.
Duplicate v-for keys across all doc examples.
Every code example uses :key="item.part" for the segment loops, but item.part can repeat (e.g., multiple literal separators). Since these examples are copy-pasted by users, consider using (item, index) with :key="\${item.part}-${index}`"` to teach the correct pattern from the start.
🤖 Prompt for AI Agents
In `@time-range-field.md` at line 172, The v-for in the template iterates over
segments.start using :key="item.part" which can produce duplicate keys (e.g.,
repeated "literal" parts); update the template's v-for to capture the index
(template v-for="(item, index) in segments.start") and make the key unique by
combining part and index (use a template string like `${item.part}-${index}`) so
each rendered segment (in the template with v-for, segments.start, and
item.part) has a stable unique key.
Closes #2182
Summary by CodeRabbit
New Features
Documentation