Guided Journey · Trang nhiều journey và JourneyShell
Một phần của Guided Journey pattern (SRC-1253). Trang nhiều journey (unit, lesson) và bố cục trang learn JourneyShell: menu, thanh bước, thẻ trái và URL.
8. Trang nhiều journey (unit, lesson) (SRC-1259)
Khi một trang chứa nhiều chặng hơn một thanh nên gánh (unit AI Teen: 5 chặng cộng các lesson), chia thành 2-3 journey, mỗi journey 2-5 bước, và cho learner chọn journey bằng menu:
+---------------------------------------------------------------+
| <- Thoát UNIT 1 . PERSONAL WEBSITE |
| [ v Khởi động ][ 2 Học ][ (lock) Chứng minh ] <- menu (Tabs) |
| (1)--->(2)--->(3)--->(4) 2/4 <- (b) |
+---------------------------------------------------------------+
| nội dung của bước đang xem |- Menu là NavBar của JourneyShell (§9, SRC-1263; trước đó là shadcn
Tabs): mỗi journey một nút, journey đang xem mangaria-current="page", phím mũi tên chuyển focus giữa các journey, Enter mở. Mỗi mục mang số và trạng thái (số + dấu tick = xong, số = đang mở, số + khoá = chưa mở, kèm chữ cho máy đọc màn hình; SRC-1276). - Thanh bước (§2b, biến thể
labeled; từ SRC-1272 mỗi bước là một pill số + tên, xem §9) chỉ vẽ bước của journey đang chọn, có tên từng bước; cả khối NavBar + thanh dínhtop-0. Dòng tiêu đề "Unit 1 · ..." và bộ đếm "2/4" đã bỏ: breadcrumb hàng 1 nói unit/lesson (§9). - Mặc định mở journey chưa xong đầu tiên, ở bước chưa xong đầu tiên.
- URL nói journey và bước (
.../{journey}/{step}), bấm tab thì ghim bước vào URL; link không có hai đoạn ấy về mặc định. - Nhóm journey theo câu hỏi learner đang tự hỏi (khởi động, học, chứng minh), không theo loại component. Không tạo loại nội dung mới để lấp cho đủ số bước.
- Bản learn:
apps/learn/src/components/JourneyProgressBar.tsx(node là nút, có trạng thái khoá) vàapps/learn/src/aiTeen/JourneyMenu.tsx(dựng trênJourneyShell, §9). Ví dụ đang chạy: trang unit và lesson ởlearn.nemo12.com/ai-teen(SDD-043 §9.5).
8a. Chế độ tập trung cho LEARN (SRC-1261)
Trên trang có nhiều journey mà một journey là chỗ HỌC thật (trang khoá bố mẹ của Marlins: GOAL, WHERE AM I, UNDERSTAND, LEARN, TRY, REFLECT, DECIDE), bấm vào journey học không mở thêm một danh sách card dưới menu. Màn đổi hẳn sang chế độ tập trung:
+---------------------------------------------------------------+
| [x] LEARN . UNIT 1/3 (1)->(2)->(3) | <- thanh tối giản: thoát + chấm unit nhỏ
| [ v Unit Discovery ][ 2 Unit Learning ] <- menu |
| (1)--->(2)--->(3)--->(4) 1/4 <- (b) |
+---------------------------------------------------------------+
| nội dung của MỘT bước [ Đã đọc, tiếp ] |- Menu của trang (bảy journey) và thanh trên của khoá biến mất; nút thoát (
X, 44px) đưa về trang khoá hoặc bậc trên (unit → LEARN, chỗ học → unit). - Thanh tiến độ chỉ nói vị trí trong LEARN: các unit là chấm cam nhỏ (
compact, không nhãn) ngay trên thanh tối giản; trong một unit hay một chỗ học thì thêm menu §8 với 2 journey và chấm cam của journey đang chọn. - Mỗi màn hiện một bước, không phải danh sách card; nút cuối bước ("Đã đọc, tiếp") đánh dấu xong và sang bước kế, vượt sang journey kế khi hết.
- Chia journey theo course-design-standard: unit = Discovery (CD-9: câu hỏi, Big Idea, khái niệm, skill) và Learning (các lesson rồi Performance Task); lesson = Discovery (CD-8: mục tiêu, SCQA, ví dụ, hiểu lầm) và Assessment (Formative Task, thử ngoài đời, rút ra, bước tiếp).
- Bản marlins:
apps/marlins/src/courseJourneys/LearnFocus.tsx,JourneyMenu.tsx,apps/marlins/src/components/JourneyProgressBar.tsx(thêmcompact; vòng rỗng nền--card-deepvì marlins không có--backgroundsáng). Card trả lời của trang khoá:courseJourneys/StepCard.tsx, theo đúng bảng chế độ §2c; ô Sửa chỉ hiện khi đã có câu trả lời để card chưa trả lời giữ đủ bề ngang cho câu hỏi ở 375px. - Bẫy:
sticky top-0không dính nếu một tổ tiên cóoverflow: hidden(.od-rootcủa marlins có). Dùngoverflow-cliptrên khung ấy.
8b. Bố cục ba phần: NavBar, Progress Bar, Status Card (SRC-1261)
Luật bố cục của chủ dự án 06.10.2026 cho MỌI màn của khoá bố mẹ Marlins (trang khoá, LEARN, unit, chỗ học):
+---------------------------------------------------------------+
| <- The Student Portrait (PT) |
| [v GOAL][ WHERE AM I ][ UNDERSTAND ][ LEARN ]... <- NavBar | journey hiện tại: nền coral đặc
| (1)---->(2)---->((3))---->(4) 2/4 <- Progress | tên bước LUÔN hiện dưới chấm
| Hiện tại 1 Hiện tại 2 Hiện tại 3 Thời gian |
+---------------------------------------------------------------+
| card đánh số ... | TÌNH TRẠNG | |
| | Đang ở WHERE AM I | | <- Status Card, góc trên phải
| | Skill 3/3 | | 3 đến 5 dòng dữ liệu thật
| | 1→3 . 0→2 . ?→2 | |
| | Thời gian 20 giờ | |
+---------------------------------------------------------------+- NavBar = các journey. Mục menu là journey của trang (GOAL, WHERE AM I, UNDERSTAND, LEARN, TRY, REFLECT, DECIDE). Journey hiện tại nổi rõ: nền coral đặc (
bg-coral-deep, chữ trắng), không chỉ đậm hơn một chút. Ở 375px dải menu cuộn ngang trong chính nó và tự kéo mục hiện tại vào giữa (chỉ đổiscrollLeft, trang không nhảy). Trong chế độ tập trung LEARN (§8a) NavBar thu nhỏ thành một dải chip cùng bảy journey, LEARN nổi coral, kèm chấm unit nhỏ; menu Tabs của unit / chỗ học nằm ngay dưới với kiểu phụ (nền kính sáng + viền), để hai tầng không giành nhau màu. - Progress Bar = các bước của journey HIỆN TẠI, ngay dưới NavBar. Tên mỗi bước luôn hiện trên thanh (khác §2b, nơi 375px chỉ giữ nhãn bước hiện tại): desktop tên đầy đủ, 375px tên ngắn (
short, tối đa 10 ký tự, ví dụ "Bài 1", "Đích 1", "Task"), và nếu vẫn không vừa thì thanh cuộn ngang trong chính nó, không giấu tên. Bước hiện tại: vòng viền coral + quầng, tên đậm có gạch dưới coral. Ở LEARN thanh là các unit; vào unit hay chỗ học thì là các bước của journey đang chọn. - Status Card ở góc trên phải vùng nội dung (từ
lg: cột phải 17rem, dính dưới thanh; dướilg: đứng đầu vùng nội dung). 3 đến 5 dòng, chỉ dữ liệu đã lưu: đang ở journey / bước nào, số skill đã chọn, cặp level hiện tại → mục tiêu, giờ ước tính, % tiến độ và số chỗ học đã mở (ở chỗ học: điểm quiz, đã thử / đã rút ra). Trống thì nói trống và chỉ chỗ điền ("Chưa chọn, chọn ở GOAL"); thiếu một phần thì nói phần đã biết ("Ít nhất 10 giờ, còn thiếu level hiện tại"); chưa đăng nhập thì dòng cuối nói lựa chọn chưa được lưu. Hàm thuầnstatusLinestrongapps/marlins/src/courseJourneys/model.ts; componentStatusCard.tsx(+WithStatusbố cục hai cột).
9. Bố cục trang learn: JourneyShell (SRC-1263)
Luật bố cục của chủ dự án 06.10.2026, áp cho mọi trang AI Teen và mọi trang learn.nemo12.com/ielts. Cùng ba phần với §8b (trang khoá Marlins, SRC-1261); mục này là bản learn. Learner luôn biết mình đang ở mục menu nào và ở bước nào. Ngoại lệ từ SRC-1286: trang chi tiết LESSON không có Progress Bar; các bước nằm trong card cột trái (§12).
+---------------------------------------------------------------+
| NEMO IELTS [1 Set My Goal][2 Discover My Level]...[6 Get Unstuck] (?) (Account v) | <- NavBar
| (1)Target band -> (2)Test date -> (3)Gap -> (4)Next step | <- Progress Bar
+---------------------------------------------------------------+
| nội dung trang | YOUR STATUS |
| | Membership ... | <- Status Card
| | Target ... | 3-5 dòng thật
| | Test date ... |
+---------------------------------------------------------------+NavBar ở đầu mọi màn. Mục menu là các JOURNEY; journey của trang đang mở sáng rõ (
bg-ocean-900,aria-current="page"). Ở trang tổng (hub) và trang tài khoản, mục sáng là journey KẾ TIẾP và mangaria-current="step".Progress Bar ngay dưới NavBar = các bước của journey đang đứng (bước nhỏ của mục menu đang sáng). Tên mỗi bước LUÔN hiện trên thanh. Bước hiện tại có
aria-current="step", mọi nút cóaria-labelnói trạng thái bằng chữ. Pill (SRC-1272, chủ dự án 07.10.2026): mỗi bước là MỘT khối bo tròn chứa cả số lẫn tên ("② Câu hỏi" thành[ 2 Câu hỏi ]), không còn vòng tròn số với nhãn trôi bên cạnh và không còn mũi tên giữa các bước (khoảng cách giữa các pill đã nói thứ tự). Trạng thái:Trạng thái Pill Đang ở nền accent đặc, chữ trắng Xong chỉ số, nền accent nhạt, KHÔNG dấu tick (SRC-1300 thay dòng "tick cạnh số" của SRC-1276) Chưa tới viền, nền trong, chữ mờ, giữ số Khoá biểu tượng khoá đứng cạnh số, viền, mờ ( opacity),disabledthậtCả nút là pill NHỎ (SRC-1300, chủ dự án 08.10.2026, "nhỏ xíu"): cao 32px khi dùng chuột (
h-8,px-3,gap-1), chữ vẫn 14px theo sàn UI audit; trên màn cảm ứng (pointer: coarse) cao lại tối thiểu 40px để chạm trúng. Áp chung cho AI Teen và learn/ielts(một component). Không dấu tick trên hai hàng (SRC-1300, chủ dự án 08.10.2026): NavBar journey và hàng bước chỉ hiện SỐ, không còn dấu tick nào. Mục xong nói bằng màu dịu (mục NavBar chữmuted-foreground, pill nền accent nhạt) và bằng chữ cho máy đọc màn hình (" (done)" / "đã xong"), không bằng biểu tượng. Khoá vẫn giữ ổ khoá cạnh số (khoá là "không bấm được", không phải trạng thái xong). Luật này THAY phần "xong = số + tick" ngay dưới cho hai hàng ấy, ở mọi nơiJourneyNavBar/ProgressNodesvẽ (learn/ieltsvà AI Teen, một component). Ô tick bước trong card trái của AI Teen (§12,data-step-check) là NÚT để learner tick, không phải dấu trạng thái, nên giữ nguyên. Số luôn đứng đầu (SRC-1276, chủ dự án 07.10.2026): MỌI journey (mục NavBar, "1 Khởi động", "2 Học") và MỌI bước (pill, "1 Mục tiêu", "2 Mình đang ở đâu?") luôn hiện SỐ ở đầu; mục xong hiện số KÈM dấu tick, không bao giờ để tick thay số. Luật này thay dòng "dấu tick thay số" của bảng trên và của menu §8; mục khoá cũng giữ số, biểu tượng khoá đứng cạnh. Đã áp ở learn (SRC-1278):JourneyNavBarluôn vẽdata-journey-no(mặc định theo vị trí 1..N) vàdata-journey-iconcạnh nó; pill củaProgressNodesluôn vẽdata-step-no, tick hoặc khoá làdata-step-iconriêng. Một component, nên AI Teen và learn/ieltscùng có. Quy trình dựng journey: skill.claude/skills/journey-design.Status Card ở góc trên phải vùng nội dung: 3-5 dòng dữ liệu THẬT về learner. Nó thay mọi "cụm thông tin" trên đầu trang: hàng chip của IELTS (Free: N days left, Target 7.5, 437 days left, 0/60 min · 0%). Thiếu dữ liệu thì nói thiếu ("Not set yet", "Chưa chọn"), không bao giờ điền số mẫu. AI Teen không có Status Card (SRC-1272): breadcrumb nói em ở unit/lesson nào, menu nói journey, thanh nói bước; bỏ card thì nội dung dùng hết bề ngang (không còn cột phải 17rem). Trong
JourneyShellkhestatuslà tuỳ chọn: không truyền thì không có cột phải.
Hàng cấp: header ba hàng (SRC-1264). Khi một chương trình có nhiều CẤP lồng nhau (AI Teen: chương trình → course → unit → lesson), header có thêm một hàng ở trên cùng và thành ba hàng:
+---------------------------------------------------------------+
| (logo) AI Teen 2 · Unit 1 v (M) | <- 1. cấp: breadcrumb "em đang ở đâu"
| [1 Khởi động][2 Học][3 Chứng minh] | <- 2. các journey CỦA CẤP ẤY
| [1 Mục tiêu] [2 Mình đang ở đâu?] | <- 3. các bước của journey đang xem
+---------------------------------------------------------------+- Hàng cấp: logo bên trái, breadcrumb của cấp hiện tại ngay cạnh logo, tài khoản bên phải. Mỗi đoạn trước là một nút đổi sang cấp ấy; đoạn cuối là cấp hiện tại (
aria-current="page"). Ở 375px, từ ba đoạn trở lên, mọi đoạn trừ đoạn cuối gấp thành một nút biểu tượng đi lên một cấp (SRC-1272), cấp hiện tại luôn đọc trọn. - Hàng journey: NavBar ở trên, nay chỉ còn menu journey của cấp đang đứng. Ở cấp lesson, journey CHÍNH LÀ Learning Activity (SRC-1281), và từ SRC-1287 trang lesson không còn hàng 2, hàng 3: activity và bước nằm ở thẻ trái (§9a ngay dưới). Số activity do khuôn của course quy định, không phải cố định của mẫu: AI Teen 2-3 ba (1 Bắt đầu, 2 Tìm hiểu, 3 Đúc kết), AI Teen 1 năm (1 Bắt đầu, 2 Xem ví dụ, 3 Tìm hiểu sâu, 4 Kiểm tra, 5 Đúc kết; SDD-043 §12.6). Phần đọc có thể chia vào nhiều activity, nhưng số phần đánh liền cho cả lesson (
Phần 4vẫn là phần thứ tư dù nằm ở activity thứ hai), vì trạng thái đã qua lưu theo số phần. Activity kiểm tra kết thúc bằng một bước "Kết quả" nêu chỗ cần ôn (khác cổng đọc §10: cổng chỉ báo tổng). - Hàng bước: Progress Bar ở trên.
- Mục lục mở từ đoạn cuối breadcrumb (SRC-1272, chủ dự án 07.10.2026). Đoạn cấp hiện tại mang một chevron và là nút mở cây:
AI Teen 2 · Unit 1 · Lesson 1 v. Không còn nút "Mục lục" riêng ở bên phải. Các đoạn trước vẫn đổi cấp như cũ ("AI Teen 2" về trang course, "Unit 1" về unit) và không bao giờ mở cây. Luật SRC-1264 "bấm đoạn breadcrumb không bao giờ mở cây" vì thế hẹp lại đúng chỗ nó cần: nó bảo vệ các đoạn ĐỔI CẤP, còn đoạn cuối trước đây là chữ trơn không làm gì, nay mới có việc. Nút giữ chữ của cấp làm nội dung (Lesson 1),aria-current="page",aria-haspopup="dialog",aria-expanded; tên cho máy đọc màn hình là "Lesson 1, mở mục lục". Từsmcây nằm trong shadcn Popover neo vào đoạn ấy; dướismlà Sheet dưới đáy. - Phạm vi cây (SRC-1272): CHỈ các unit và lesson của course đang xem (unit ở gốc, lesson bên dưới), không liệt kê cả ba course, không có mục "Tổng quan". Course khác cách một cấp, ở trang chương trình. Cây theo WAI-ARIA
role="tree"(phím mũi tên), có từ cấp course trở xuống; cấp chương trình không có cây. - Không có link "Thoát" / "Về unit" riêng: breadcrumb là lối lên cấp trên.
- Công tắc VI/EN của header (SRC-1272, AI Teen). Ở hàng 1, ngay trước tài khoản, công tắc
LangSwitchcủa Design System (radiogroup, phím mũi tên, hai ô 40px) đổi chữ của cả ba hàng: đoạn breadcrumb, tên journey (hàng 2), tên bước (hàng 3, kể cảaria-labelvà chữ trạng thái cho máy đọc màn hình). Nội dung trang không đổi. Mặc định tiếng Việt, lựa chọn nhớ theo trình duyệt (localStorage, bọc try/catch). Nhãn hai thứ tiếng khai một chỗ: SDD-043 §9.8. - Không có nút Tổng quan (SRC-1272). Nút "Tổng quan" cố định ở hàng 1 (SRC-1269) đã bỏ cùng mục "Tổng quan" trong cây: Overview của lesson và của unit nay là phần đầu màn ĐẦU TIÊN của lesson (Bắt đầu · Câu hỏi) và của unit (Khởi động · Mục tiêu); outcomes của course nằm ngay trên trang course, và Course Overview (vòng Learning Cycle) cách trang course một link. Chi tiết: SDD-043 §12.2. Hàng 1 và hàng 2 vẫn mang được một nhãn nhỏ (
LevelCrumb.tag,JourneyMenuItem.tag, chỉ từsm), nhưng AI Teen thôi dùng từ SRC-1279: ba journey của lesson nay tên là "Bắt đầu", "Tìm hiểu", "Đúc kết", tự nói pha vòng trong bằng tiếng Việt, nên tag tiếng Anh trên tab, ở đầu bước và tag chặng cạnh breadcrumb Lesson đã bỏ (SDD-043 §12.5). Đừng dùng nhãn nhỏ để lặp điều tên mục đã nói. - Hiện thực: prop
levelscủaJourneyShell(LevelBreadcrumb; đoạn cuối thay bằng nút riêng quaLevelCrumb.node). Trang nào không truyền thì header giữ hai hàng như trên (learn/ieltshiện nay). AI Teen: SDD-043 §9.7.
§9a. Trang lesson: thẻ trái, một trang cuộn, scroll-spy (SRC-1287, chủ dự án 07.10.2026). Áp cho mọi lesson AI Teen (layout dùng chung). Chi tiết hiện thực: SDD-043 §12.7.
+---------------------------------------------------------------+
| (logo) AI Teen 1 · Unit 1 · Lesson 1 v VI|EN (M) | <- chỉ còn hàng cấp
+------------------+--------------------------------------------+
| 1 Bắt đầu v | LESSON 1/6 · <Guiding Question> |
| 1 Câu hỏi | 2 Xem ví dụ |
| 2 Thử hỏi v | ------------------------------------------|
| 2 Xem ví dụ | PHẦN 2/5 |
| 1 Đổi cách hỏi | Cùng chủ đề, hỏi khác đi <- tên đầy đủ |
| 2 So sánh * | ... nội dung, cổng đọc ... |
| 3 Tìm hiểu sâu # | PHẦN 3/5 |
| 1 Gọi tên # | ... (các bước CỦA activity đang chọn, |
| 4 Kiểm tra | nối tiếp nhau trên một trang cuộn) |
| 5 Đúc kết | |
+------------------+--------------------------------------------+
v = xong (số + tick) * = đang xem (scroll-spy) # = khoá (số + khoá)- Không thanh bước, không menu journey trên trang lesson: header chỉ là hàng cấp (breadcrumb + cây Mục lục, VI/EN, tài khoản).
JourneyShellnhậnhideNavvàstepstuỳ chọn cho ca này. - Thẻ trái (từ
lg, dính dưới header): mọi activity của lesson, mỗi activity các bước, tất cả có số. Tên activity và tên bước rất ngắn: tối đa 3 chữ (chữ = cụm tách bởi dấu cách), ưu tiên 1-2; tên đầy đủ của phần đọc vẫn là tiêu đề trong vùng chính. Dữ liệu:LessonPart.step. Xong = số kèm tick, khoá = số kèm khoá và nútdisabled(thấy được, không tới được), đang xem = nền accent. - Vùng chính chỉ hiện các bước của activity đang chọn, nối nhau trên một trang cuộn; chọn activity khác ở thẻ thì vùng chính đổi sang các bước của nó. Phần còn khoá hiện một ô giữ chỗ có biểu tượng khoá, không hiện nội dung.
- Scroll-spy: bước có mép trên đã qua vạch (đáy phần dính + 24px) là bước đang xem, sáng trong thẻ. Bấm một bước thì cuộn tới nó, mép trên cách đáy phần dính 12px (đo lúc chạy, như
stickyOffsetở §8 bẫy cuộn); vùng chính có đệm dưới 40vh để bước cuối cũng lên được tới vạch. - 375px: thẻ thành một thanh dính dưới header ghi "2 Xem ví dụ · 2 So sánh v"; bấm mở Sheet ở trên cùng với đúng nội dung thẻ; chọn xong thì Sheet đóng.
- Ô tick mỗi bước: mỗi dòng bước có sẵn một ô
data-step-checkcho việc learner tự tick hoàn thành bước (chủ dự án 07.10.2026, đặc tả ở một mục SDD riêng). Khi mục ấy chưa gộp, ô chỉ hiện tick SUY RA (bước đã xong theo luật cổng đọc và kết quả bài tập); việc tick tay và ghi lên server là việc sau.
Điện thoại (375px). NavBar hai hàng: logo + trợ giúp + tài khoản ở trên, menu journey ở hàng dưới (nhãn ngắn: Goal, Level, Plan, Practice...). Thanh bước dùng nhãn ngắn, cuộn ngang khi không vừa, và tự cuộn bước hiện tại vào tầm nhìn (tức thì nếu learner bật reduced motion). Status Card (chỉ IELTS) xuống dưới thanh, thu thành thẻ hai cột gọn. Trang không bao giờ cuộn ngang.
Bàn phím. Tab vào menu; mũi tên trái/phải, Home/End chuyển focus giữa các journey; journey khoá là disabled thật. Nút trên thanh bước là <button>, cao tối thiểu 44px.
learn là một cụm đóng: không link nào sang www (SRC-1290, chủ dự án 07.10.2026). Trên TOÀN BỘ learn.nemo12.com (mọi chương trình: /speak, /sat, /essay, /grammar, /ap, /math, /ai-teen, /walk, /ielts, trang chủ /, /programs, /schools, hồ sơ...) không a[href] nào trỏ tới nemo12.com hay www.nemo12.com. Mục nào learn có trang tương đương thì trỏ vào trang ấy; không có thì BỎ link hoặc bỏ mục. Menu chương trình (apps/learn/src/programNav.ts) chỉ còn tên chương trình (về Tổng quan) và những mục có đích THẬT trên learn (khai ở local): SAT có Lộ trình, Chương trình; ESSAY có Tài nguyên; SPEAK có Cách học; GRAMMAR, AP, MATH, AI TEEN chỉ còn tên. Mục Học phí không còn trên learn vì không chương trình nào có trang học phí trên learn ngoài /ielts/membership (nằm trong menu tài khoản của sân IELTS). Lưới chương trình vẫn ở, vì nó trỏ vào /programs của chính learn. Chân trang learn là © năm + tên và bốn icon mạng xã hội, bỏ link nemo12.com; màn Join và màn ra mắt có "← Về trang chủ" (/) thay cho "← Về Nemo12". Sub-domain khác www vẫn được link khi có lý do: marlins.nemo12.com (lối sang khu phụ huynh ở trang chủ và màn Join), tutors.nemo12.com (đích 301 của /tutors/** cũ). Link mạng xã hội, nhóm Zalo, phòng Zoom và nguồn nghiên cứu không phải www nên không thuộc luật này. Chữ thường nhắc tới nemo12.com (không phải link) và link chia sẻ hiện bằng chữ để chép (Learning Plan) vẫn được. Gác bằng e2e apps/learn/e2e/learnNoWwwLinks.spec.ts: một trang đại diện của mọi chương trình, so hostname của mọi a[href] với ^(www\.)?nemo12\.com$, và mọi sub-domain *.nemo12.com khác phải nằm trong danh sách cho phép.
Không có link thoát ra trong cụm chương trình (learn /ielts). Chặt hơn luật trên: bên trong learn.nemo12.com/ielts/** không có link nào nhảy ra ngoài cụm /ielts: không tab chương trình trỏ sang www, không lưới chương trình (/programs), không link sang chương trình khác hay trang chủ learn, không link mạng xã hội ở chân trang. Chỉ giữ menu tài khoản (đăng xuất) và popover trợ giúp. Nguồn tham khảo cần ghi thì ghi bằng chữ (tên công trình, nơi đăng), link chia sẻ cần đưa người khác thì hiện bằng chữ để chép. Gác bằng e2e apps/learn/e2e/ieltsJourneyShell.spec.ts: mọi a[href] trên hơn 40 trang /ielts phải nằm dưới /ielts.
Hiện thực.
| File | Vai trò |
|---|---|
apps/learn/src/components/JourneyShell.tsx | JourneyShell (hàng cấp tuỳ chọn + NavBar + thanh + khe Status Card tuỳ chọn), LevelBreadcrumb, JourneyNavBar, StatusCard |
apps/learn/src/components/JourneyProgressBar.tsx | ProgressNodes, biến thể labeled là thanh của shell (pill số + tên, SRC-1272) |
apps/learn/src/ielts/journeys/IeltsJourneyShell.tsx | shell của /ielts: journey theo đường dẫn (journeyOfPath), bước và Status Card từ model.ts |
apps/learn/src/aiTeen/ProgramJourney.tsx (ProgramShell), JourneyMenu.tsx, CourseTree.tsx (TreeCrumb) | shell của AI Teen: cấp chương trình, course, unit, lesson; hàng cấp và Mục lục; không Status Card |
Thêm một trang mới vào AI Teen hoặc /ielts: dùng shell có sẵn, không dựng thanh riêng. Tên bước và luật "xong" của một journey nằm ở MỘT chỗ (journeySteps cho IELTS, programSteps / journeys.ts cho AI Teen) để thanh và nội dung trang không nói hai điều khác nhau.
9x. learn /ielts: năm journey, menu thu gọn (SRC-1300, chủ dự án 08.10.2026; thu gọn đã đảo ở SRC-1321)
- Năm mục, tên ngắn: "1 Goal", "2 My Level", "3 Plan", "4 Learn", "5 Progress" (
JOURNEY_NAVtrongapps/learn/src/ielts/journeys/model.ts). Tiêu đề trang vẫn giữ tên đầy đủ (JOURNEYS[id].title). - Get Unstuck rời menu, thành bước cuối "5 Stuck?" của Progress (pill trên hàng bước dẫn thẳng tới
/ielts/unstuck, và một card "Stuck?" cuối trang Progress có nút "Tìm chỗ kẹt"). URL/ielts/unstuckgiữ nguyên; ở trang ấy menu sáng "5 Progress", hàng bước sáng "Stuck?". Hub còn hai tầng, năm chặng (tầng C "Get better" bỏ). Lý do: chặng kẹt là câu hỏi learner đặt ra KHI xem tiến bộ ("sao mình không lên?"), không phải một chặng đi lần lượt; để nó thành mục thứ sáu thì menu dài thêm cho một trang ít khi mở. - Menu thu gọn (
collapsiblecủaJourneyNavBar): mặc định chỉ hiện mục hiện tại, gọn, là một nút cóaria-expandedvà mũi tên nhỏ. Bấm thì cả menu trượt mở ngang (motion,width0 → auto, 240ms); chọn một mục, bấm ra ngoài hay Esc thì trượt gập lại (Esc trả focus về nút). Mở rồi thì mũi tên trái/phải, Home, End đi giữa các mục; khi đang gập, mũi tên trái/phải mở menu.prefers-reduced-motion= tức thì. Ở 375px menu mở cuộn ngang trong chính nó và tự cuộn để mục hiện tại còn trong tầm nhìn. - Hàng bước KHÔNG thu gọn, chỉ làm nhỏ lại: hàng bước là chỗ learner biết mình đang ở bước nào và bấm sang bước kế, giấu nó thì mất đúng chức năng "luôn biết mình ở đâu" của shell; còn hàng journey thì đổi hiếm, nên gập nó tiết kiệm chỗ mà không mất gì. AI Teen giữ menu mở như cũ (chủ dự án chỉ nói learn
/ielts). - Cổng: e2e
apps/learn/e2e/ieltsJourneyShell.spec.ts(5 mục luôn hiện, bàn phím, không dấu tick trên hai hàng, Stuck? tới được/ielts/unstuck, 375px, pill ≤33px với chuột và ≥40px trên cảm ứng). - Đã đảo phần thu gọn (SRC-1321, chủ dự án 10.10.2026): menu cấp 1 của learn
/ieltsnay LUÔN mở (bỏcollapsibleở đây; prop vẫn còn trongJourneyNavBar).featuredtô một mục cố định (Learn:bg-accent-deep, chữ trắng) trên mọi trang;tagsbiến các mục còn lại thành tag nhỏ có viền, vùng bấm 40px, tag hiện tại viền + chữ đậm. Menu xuống dòng ở màn hẹp. Hàng bước giữ nguyên; hàng bước của Learn là bốn kỹ năng (SDD-038 §167, đoạn SRC-1321).