From c17b055c2e844fde24097a3bbd54793cab057187 Mon Sep 17 00:00:00 2001
From: Wang Ng
Date: Sat, 18 Jul 2026 19:31:45 -0500
Subject: [PATCH 1/3] fix(ui): modify dropdown to match component UI
replace default dropdown UI from mac/windows to a custom designed one
---
.../components/address/CSVUploadOverlay.tsx | 269 ++++++++++++++----
app/ui/src/app/edit/formStyles.v2.ts | 12 +-
2 files changed, 224 insertions(+), 57 deletions(-)
diff --git a/app/ui/src/app/edit/components/address/CSVUploadOverlay.tsx b/app/ui/src/app/edit/components/address/CSVUploadOverlay.tsx
index 519bbafc..3b5153f1 100644
--- a/app/ui/src/app/edit/components/address/CSVUploadOverlay.tsx
+++ b/app/ui/src/app/edit/components/address/CSVUploadOverlay.tsx
@@ -1,6 +1,14 @@
"use client";
-import { useRef, useState, useCallback, useMemo, useEffect } from "react";
+import {
+ useRef,
+ useState,
+ useCallback,
+ useMemo,
+ useEffect,
+ useLayoutEffect,
+ type CSSProperties,
+} from "react";
import {
OVERLAY_BACKDROP,
OVERLAY_HEADER,
@@ -10,6 +18,7 @@ import {
OVERLAY_CANCEL_BTN,
OVERLAY_PRIMARY_BTN,
CSV_UPLOAD_OVERLAY_PANEL,
+ CSV_UPLOAD_OVERLAY_PANEL_TALL,
CSV_UPLOAD_OVERLAY_INNER,
CSV_UPLOAD_OVERLAY_CONTENT,
CSV_UPLOAD_OVERLAY_TOP,
@@ -26,6 +35,14 @@ import {
CSV_UPLOAD_FILE_CHIP_RIGHT,
CSV_UPLOAD_FILE_CHIP_SIZE,
CSV_UPLOAD_FILE_CHIP_REMOVE,
+ OVERLAY_SELECT_WRAPPER,
+ OVERLAY_SELECT_VALUE,
+ OVERLAY_SELECT_ICON,
+ CSV_UPLOAD_SELECT_PLACEHOLDER,
+ OVERLAY_AUTOCOMPLETE_DROPDOWN,
+ OVERLAY_AUTOCOMPLETE_ITEM,
+ OVERLAY_AUTOCOMPLETE_ITEM_ACTIVE,
+ OVERLAY_AUTOCOMPLETE_ITEM_TEXT,
} from "@/app/edit/formStyles.v2";
import ErrorOverlay from "@/app/edit/components/shared/ErrorOverlay";
import type { AddressCard } from "@/app/edit/types/delivery";
@@ -58,6 +75,22 @@ type CSVUploadOverlayProps = {
initialFile?: File;
};
+const CHEVRON_DOWN_ICON = (
+
+);
+
const MAX_CSV_BYTES = 10 * 1024 * 1024;
function formatFileSize(bytes: number): string {
@@ -106,6 +139,175 @@ function buildAddressCards(
});
}
+// ─── Custom mapping dropdown (matches overlay design instead of native
-
+
-
- {headers.map((header, idx) => (
+
+ {headers.map((header) => (
-
+
{header.charAt(0).toUpperCase() + header.slice(1)}
-
-
-
- {mapping[header]
- ? FIELD_LABELS[
- mapping[header] as Exclude
- ]
- : "Select"}
-
-
-
+ onMappingChange(header, field)}
+ />
{previewRows.map((row, i) => {
@@ -350,7 +511,7 @@ function StepRowSelector({
Review and select information to import
-
+
e.stopPropagation()}
role="dialog"
aria-modal="true"
diff --git a/app/ui/src/app/edit/formStyles.v2.ts b/app/ui/src/app/edit/formStyles.v2.ts
index c0892095..20c0ebae 100644
--- a/app/ui/src/app/edit/formStyles.v2.ts
+++ b/app/ui/src/app/edit/formStyles.v2.ts
@@ -792,14 +792,17 @@ export const ERROR_OVERLAY_FOOTER = "flex items-center justify-end";
export const CSV_UPLOAD_OVERLAY_PANEL =
"bg-[var(--edit-bg-primary)] flex flex-col gap-[14px] items-end overflow-hidden p-4 lg:p-6 rounded-[6px] w-full lg:max-w-[800px] mx-2 lg:mx-4 shadow-lg max-h-[90dvh]";
+export const CSV_UPLOAD_OVERLAY_PANEL_TALL =
+ "bg-[var(--edit-bg-primary)] flex flex-col gap-[14px] items-end overflow-hidden p-4 lg:p-6 rounded-[6px] w-full lg:max-w-[800px] mx-2 lg:mx-4 shadow-lg h-[90dvh]";
+
export const CSV_UPLOAD_OVERLAY_INNER =
- "flex flex-col gap-[16px] items-end w-full";
+ "flex flex-col gap-[16px] items-end w-full flex-1 min-h-0";
export const CSV_UPLOAD_OVERLAY_CONTENT =
- "flex flex-col gap-[16px] items-center w-full";
+ "flex flex-col gap-[16px] items-center w-full flex-1 min-h-0";
export const CSV_UPLOAD_OVERLAY_TOP =
- "flex flex-col gap-[24px] items-start w-full";
+ "flex flex-col gap-[24px] items-start w-full flex-1 min-h-0";
export const CSV_UPLOAD_DROP_ZONE =
"bg-[var(--edit-stone-50)] border border-[var(--edit-stone-200)] border-dashed flex flex-col h-[200px] items-center justify-center overflow-clip pt-[24px] pb-[16px] rounded-[6px] w-full";
@@ -841,6 +844,9 @@ export const CSV_UPLOAD_FILE_CHIP_SIZE =
export const CSV_UPLOAD_FILE_CHIP_REMOVE =
"flex items-center justify-center size-4 text-[var(--edit-text-primary)] hover:opacity-70 transition-opacity cursor-pointer";
+export const CSV_UPLOAD_SELECT_PLACEHOLDER =
+ "font-normal text-[16px] leading-6 text-[var(--edit-stone-600)] pointer-events-none flex-1 truncate";
+
// ── SpinnerIcon ───────────────────────────────────────────────────────────────
export const SPINNER_ICON_WRAPPER = "relative size-[33px]";
From 7a07421d856a9f1b77e055b2a9653074a50d7ffc Mon Sep 17 00:00:00 2001
From: Wang Ng
Date: Sat, 18 Jul 2026 19:33:15 -0500
Subject: [PATCH 2/3] fix(ui): update 'upload file' to match updated design
---
app/ui/src/app/upload-route/page.tsx | 95 ++++++++++++-----------
app/ui/src/app/upload-save-point/page.tsx | 93 ++++++++++++----------
app/ui/src/app/welcome/page.tsx | 24 +++---
3 files changed, 114 insertions(+), 98 deletions(-)
diff --git a/app/ui/src/app/upload-route/page.tsx b/app/ui/src/app/upload-route/page.tsx
index 42ae6195..3436f311 100644
--- a/app/ui/src/app/upload-route/page.tsx
+++ b/app/ui/src/app/upload-route/page.tsx
@@ -119,48 +119,64 @@ export default function UploadRoutePage() {
.upload-dropzone {
width: 100%;
max-width: 580px;
- border: 1.5px dashed #ccc;
- border-radius: 12px;
- padding: 52px 24px;
+ height: 200px;
+ border: 1px dashed #dcdbd8;
+ border-radius: 6px;
+ padding: 24px 24px 16px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
- gap: 10px;
- cursor: pointer;
- background: #f9f9f8;
+ gap: 8px;
+ background: #f8f7f5;
transition: border-color 0.15s, background 0.15s;
- margin-bottom: 16px;
- min-height: 160px;
+ margin-bottom: 8px;
}
.upload-dropzone.dragging {
- border-color: #4a8c7a;
- background: #f0f7f5;
+ border-color: #57ac91;
+ background: #f0faf6;
}
- .upload-dropzone-icon { color: #555; margin-bottom: 4px; }
+ .upload-dropzone-icon { color: #3d3d3c; margin-bottom: 4px; display: flex; }
.upload-dropzone-text {
- font-size: 14px;
- color: #333;
+ font-size: 16px;
+ color: #272725;
text-align: center;
}
.upload-dropzone-browse {
font-size: 14px;
- color: #4a8c7a;
- font-weight: 500;
+ font-weight: 600;
+ color: #272725;
text-align: center;
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-family: inherit;
+ padding: 8px 16px;
+ border-radius: 4px;
+ transition: background 0.15s;
+ }
+
+ .upload-dropzone-browse:hover { background: #f6f5f2; }
+
+ .upload-dropzone-description {
+ width: 100%;
+ max-width: 580px;
+ font-size: 14px;
+ color: #464544;
+ margin-bottom: 24px;
}
.upload-file-row {
width: 100%;
max-width: 580px;
- background: #eef5f3;
- border: 1px solid #d0e5df;
- border-radius: 8px;
- padding: 10px 16px;
+ background: #d5f2e8;
+ border: none;
+ border-radius: 6px;
+ padding: 16px;
display: flex;
align-items: center;
gap: 10px;
@@ -306,7 +322,6 @@ export default function UploadRoutePage() {
{/* Drop zone — shows spinner while file is being read */}
!isProcessing && inputRef.current?.click()}
onDragEnter={handleDragEnter}
onDragOver={(e) => e.preventDefault()}
onDragLeave={handleDragLeave}
@@ -317,36 +332,23 @@ export default function UploadRoutePage() {
) : (
<>
Drag and drop .json files here, or
-
Browse files
+
>
)}
+
+ Import your route file to begin. Maximum file size of {MAX_FILE_MB}{" "}
+ MB.
+
+
{file && !isProcessing && (
+
+ Import a save point or CSV file to continue. Maximum file size of{" "}
+ {MAX_FILE_MB} MB.
+
+
{file && !isProcessing && (