fix(portal): review display, hover overlay, and drag ghost for complex field types
- Extract formatFieldValue helper for shared use between review step
and confirmation page — one source of truth for TAG_PICKER,
AVAILABILITY_PICKER, and SECTION_PRIORITY display, so the raw-ID
and [object Object] leaks from two parallel stringifiers can't
regress on either side.
- TAG_PICKER: lookup via field.available_tags (server-inlined).
- AVAILABILITY_PICKER: lookup via usePublicFormTimeSlots, strip
seconds. "Laden…" while the cache warms.
- SECTION_PRIORITY: defensive shape-guard prevents [object Object]
leaks, sorted priority-prefixed rendering ("1. Bar, 2. Hospitality").
- Subtle primary-tinted hover (4% primary, primary border) replacing
the near-black Vuetify default overlay on unranked section cards.
- Explicit ghost-class / drag-class / chosen-class on vuedraggable
with solid drag-clone + elevation shadow and a 30%-opacity silhouette
at the origin, so mid-drag text no longer overlaps.
- 17 new formatFieldValue unit assertions + 2 new FieldSectionPriority
assertions locking in the draggable classes and the disabled-card
toggle at max.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -187,7 +187,10 @@ function sectionNameFor(id: string): string {
|
||||
v-model="ranked"
|
||||
item-key="section_id"
|
||||
handle=".section-priority-handle"
|
||||
:animation="180"
|
||||
ghost-class="section-priority-ghost"
|
||||
chosen-class="section-priority-chosen"
|
||||
drag-class="section-priority-drag"
|
||||
:animation="150"
|
||||
:delay="100"
|
||||
:delay-on-touch-only="true"
|
||||
class="section-priority-ranked mb-4"
|
||||
@@ -318,12 +321,13 @@ function sectionNameFor(id: string): string {
|
||||
assistive tech, which Vuetify's :disabled would do. */
|
||||
.section-priority-unranked-card {
|
||||
cursor: pointer;
|
||||
transition: background-color 120ms;
|
||||
transition: background-color 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.section-priority-unranked-card:hover,
|
||||
.section-priority-unranked-card:focus-visible {
|
||||
background-color: rgb(var(--v-theme-surface-variant));
|
||||
.section-priority-unranked-card:hover:not(.section-priority-unranked-disabled),
|
||||
.section-priority-unranked-card:focus-visible:not(.section-priority-unranked-disabled) {
|
||||
background-color: rgb(var(--v-theme-primary) / 0.04);
|
||||
border-color: rgb(var(--v-theme-primary));
|
||||
}
|
||||
|
||||
.section-priority-unranked-disabled {
|
||||
@@ -331,13 +335,29 @@ function sectionNameFor(id: string): string {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.section-priority-unranked-disabled:hover,
|
||||
.section-priority-unranked-disabled:focus-visible {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.section-priority-rank {
|
||||
min-inline-size: 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* vuedraggable drag states — SortableJS applies these classes. The
|
||||
defaults leave the drag-clone semi-transparent while the ghost
|
||||
stays solid at the origin, which produces text overlap mid-drag. */
|
||||
.section-priority-ghost {
|
||||
opacity: 0.3;
|
||||
background: rgb(var(--v-theme-surface-bright));
|
||||
}
|
||||
|
||||
.section-priority-drag {
|
||||
/* !important overrides SortableJS's inline opacity: 0.8 default so
|
||||
the drag-clone reads as solid + elevated. */
|
||||
opacity: 1 !important;
|
||||
background: rgb(var(--v-theme-surface));
|
||||
box-shadow: 0 8px 24px rgb(0 0 0 / 0.15);
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.section-priority-chosen {
|
||||
cursor: grabbing;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user