Files
travelplanning/LAYOUT_FIX_NEW.md
T

5.1 KiB

To AI Agent: Refactor Itinerary Timeline into an Exclusive File Tree Directory System (Single Expansion Mode)

1. Context & Architectural Analogy

We are refactoring the ItineraryTimeline component on the mobile view (yotrip.labz.io.vn) using a File Tree Directory System analogy:

  • Parent Folders ("Thư mục mẹ"): Represented by the Stages ("Chặng 1", "Chặng 2"...).
  • Child Nodes ("Thư mục con"): Represented by the Locations/Destinations inside that stage (Trần Cao Vân, Đồng Khởi...).

CRITICAL LOGIC CONSTRAINT (Exclusive Accordion):

  • When a Parent Folder (Stage) is collapsed, all of its Child Nodes (Locations) must immediately hide cleanly inside it.
  • Single Expansion Rule: The system must enforce an exclusive single-expansion mode. On the entire timeline screen, MAXIMUM ONE Parent Folder can be expanded at any given time.
  • Opening/Expanding a new Stage folder must automatically collapse whichever Stage folder was previously open.

2. State Management Specification (For Script/Logic Implementation)

To enforce the "Maximum 1 Expanded Folder" rule, do NOT use isolated individual boolean flags for each stage. Instead, implement a centralized single-active-state variable:

// Example React State Hook Blueprint:
// Track the ID or index of the single active expanded stage folder. 
// If null, all stages are collapsed.
const [expandedStageId, setExpandedStageId] = useState(initialStageId);

const handleStageToggle = (stageId) => {
  // If clicking the already open folder, close it. Otherwise, open the new one and shut the rest.
  setExpandedStageId(prevId => prevId === stageId ? null : stageId);
};

## 3. Component DOM Tree & CSS Blueprint
### A. Component Layout Structure

<div class="file-tree-itinerary-container">
  
  <div class="fixed-top-header-block">
    <header class="main-tour-header">...</header>
    <nav class="sub-navigation-tabs">...</nav>
  </div>

  <main class="directory-scroll-viewport">
    
    <section class="folder-node-wrapper collapsed">
      <div class="folder-header-row" onclick="handleStageToggle('stage_1')">
        <span class="folder-badge-index">1</span>
        <h3 class="folder-title">Chặng khởi đầu</h3>
        </div>
      <div class="folder-child-content-box">
         </div>
    </section>

    <section class="folder-node-wrapper expanded">
      <div class="folder-header-row" onclick="handleStageToggle('stage_2')">
        <span class="folder-badge-index">2</span>
        <h3 class="folder-title">Chặng 2</h3>
      </div>
      
      <div class="folder-child-content-box">
        <div class="child-nodes-list">
          <div class="location-child-card">Trần Cao Vân</div>
          <div class="location-child-card">Đồng Khởi</div>
        </div>
      </div>
    </section>

  </main>
</div>

### B. Core CSS Layout Styles

.file-tree-itinerary-container {
  display: flex !important;
  flex-direction: column !important;
  height: 100dvh !important;
  width: 100vw !important;
  overflow: hidden !important;
}

.directory-scroll-viewport {
  flex: 1 1 0% !important;
  overflow-y: auto !important;
  padding: 0 !important;
  margin: 0 !important;
  background-color: #f8fafc;
}

/* Base style for folder blocks stacked flush against each other */
.folder-node-wrapper {
  width: 100% !important;
  background-color: #ffffff;
  margin-bottom: 1px !important; /* Micro hair-line divider between folders */
  display: flex;
  flex-direction: column;
}

.folder-header-row {
  width: 100%;
  padding: 12px 16px !important;
  display: flex;
  align-items: center;
  background-color: #ffffff;
  cursor: pointer;
  /* Sticky behavior remains active when scrolling within an open directory */
  position: sticky !important;
  top: 0px; 
  z-index: 30;
}

/* CSS Grid Transition Engine for smooth directory expansions */
.folder-child-content-box {
  display: grid !important;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
  width: 100%;
}

.child-nodes-list {
  overflow: hidden;
  min-height: 0px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* --- MUTUALLY EXCLUSIVE STATE STYLES --- */

/* Collapsed Folder: Sub-files shrink immediately to 0 height */
.folder-node-wrapper.collapsed .folder-child-content-box {
  grid-template-rows: 0fr !important;
}

/* Expanded Folder: Opens dynamically to accommodate dynamic content height */
.folder-node-wrapper.expanded .folder-child-content-box {
  grid-template-rows: 1fr !important;
}

## 4. Acceptance Criteria for AI Agent Verification
[ ] Mutually Exclusive Test: Clicking an inactive Stage header while another stage is open must trigger a simultaneous transition: the old stage collapses back into a tight header row, and the clicked stage expands its location cards.

[ ] Zero-Gap Validation: All collapsed folder components must sit completely flush against the top tab block and one another, eliminating all gray margin bleeding.

[ ] Under-Clip Containment: When scrolling a long open folder, the list items must slide behind their sticky active parent folder row and disappear without visual overlapping artifacts.