- Popover API เข้ามาแทนที่ JavaScript event listener, การจัดการสถานะ และการซิงก์แอตทริบิวต์ ARIA แบบแมนนวลที่เคยจำเป็นสำหรับการทำทูลทิป
- แค่มีแอตทริบิวต์
popover และ popovertarget ก็เปิด/ปิดได้ พร้อมรองรับปุ่ม Esc และ การนำทางด้วยคีย์บอร์ด โดยอัตโนมัติ
- ทำให้การทำงานร่วมกับ screen reader คาดเดาได้มากขึ้น, ซิงก์
aria-expanded อัตโนมัติ และ กู้คืนโฟกัส ได้ จนบั๊กด้านการเข้าถึงทั้งบางหมวดหายไปเลย
- แม้บางส่วนอย่างการควบคุมจังหวะเวลาและการตรวจจับ hover intent ยังต้องใช้ JavaScript แต่โมเดลปฏิสัมพันธ์หลักถูกย้ายให้เบราว์เซอร์ดูแล
- ถ้าเป็นดีไซน์ซิสเต็มขนาดใหญ่หรือกรณีที่ต้องการการจัดวางตำแหน่งซับซ้อน ไลบรารียังมีประโยชน์อยู่ แต่ ค่าเริ่มต้นกำลังเปลี่ยนไปเป็น Native API
ปัญหาของทูลทิปแบบเดิม
- ก่อนมี Popover API เบราว์เซอร์ยังไม่มีแนวคิดเรื่อง ทูลทิปแบบเนทีฟ ที่ทำงานได้ครอบคลุมทั้งเมาส์ คีย์บอร์ด และเทคโนโลยีช่วยการเข้าถึง
- รูปแบบเดิมถูกทำซ้ำอยู่เสมอ: องค์ประกอบตัวกระตุ้น, องค์ประกอบทูลทิปที่ซ่อนอยู่ และ JavaScript ที่คอยประสานทั้งสองส่วน
- แม้ดูเหมือนเรียบง่าย แต่พอใช้งานจริงกลับเจอปัญหาหลากหลาย
- ผู้ใช้คีย์บอร์ดกด
Tab เข้าไปที่ trigger แล้วทูลทิปไม่แสดง
- screen reader อ่านซ้ำสองรอบ หรือไม่อ่านเลย
- เมื่อเลื่อนเมาส์เร็ว ๆ จะเกิด การกะพริบ (flicker)
- เนื้อหาซ้อนทับกันบนหน้าจอขนาดเล็ก
- ปิดด้วยปุ่ม
Esc ไม่ได้ หรือโฟกัสหาย
- เมื่อเวลาผ่านไป โค้ดจะพองขึ้นจากการสะสม event listener, การแยกจัดการ hover/focus, เคสพิเศษของการคลิกภายนอก และการซิงก์แอตทริบิวต์ ARIA แบบแมนนวล
เหตุผลที่ต้องใช้ไลบรารี
- ไลบรารีช่วยทำงานจริงอย่าง การจัดตำแหน่ง, การพลิกตำแหน่งเมื่อชนขอบ viewport, การประสาน event ตามชนิดอินพุต และการรับรู้การเลื่อนในเลย์เอาต์ที่ซับซ้อน
- แค่เรื่องการจัดตำแหน่งอย่างเดียวก็ซับซ้อนพอจะทำให้การพึ่งพาไลบรารีดูสมเหตุสมผล เพราะต้องรับมือกับ scroll container, transform และ responsive layout
- แต่ปัญหาจริงอยู่ที่ พฤติกรรมด้านการเข้าถึง
- ทูลทิปแสดงช้า หรือไม่แสดงเลย
- ตอนกดแท็บเร็ว ๆ ทูลทิปถูกข้ามไป
- การปิดด้วย
Esc ไม่เสถียร
- ผู้ใช้เมาส์คาดหวัง ความทันทีทันใด ขณะที่ผู้ใช้คีย์บอร์ดคาดหวัง ความคาดเดาได้ และเมื่อพยายามรองรับทั้งสองแบบ ก็เกิดทั้งความหน่วงและ edge case
- บน screen reader ทูลทิปอาจถูกอ่าน, ไม่ถูกอ่าน หรือถูกอ่านซ้ำสองครั้ง เป็น พฤติกรรมที่ไม่สม่ำเสมอ
- ถ้าพลาดอัปเดตแอตทริบิวต์ ARIA ไปแม้เพียงตัวเดียว ก็อาจทำให้ accessibility tree สับสนหรือกลายเป็นสถานะที่มองไม่เห็น
ไม่ใช่ปัญหาที่ตัวโค้ด แต่เป็นข้อจำกัดของแพลตฟอร์ม
- แม้อิมพลีเมนเทชันจะผ่านการทดสอบและไลบรารีก็แข็งแรง แต่ปัญหาแกนกลางคือ เว็บแพลตฟอร์มไม่มี affordance ที่เหมาะสม
- เบราว์เซอร์ไม่มีวิธีรู้เลยว่าองค์ประกอบนั้นคือทูลทิป ทุกอย่างจึงอาศัยองค์ประกอบทั่วไป, event listener, ARIA แบบแมนนวล และตรรกะปิดเองตาม ข้อตกลงร่วม (convention)
- เมื่อเวลาผ่านไป การเปลี่ยนแปลงเล็ก ๆ ก็มีความเสี่ยง และการแก้ไขเล็กน้อยก็อาจทำให้เกิด regression ได้ เป็น โครงสร้างที่เปราะบาง
- ทุกครั้งที่เพิ่มทูลทิปใหม่ ก็รับช่วงความซับซ้อนเดิมเข้ามาทั้งหมด
เริ่มใช้ Popover API ครั้งแรก
- แรงจูงใจไม่ใช่เพราะอยากลองของใหม่ แต่เป็นเพราะ เหนื่อยกับการดูแลพฤติกรรมทูลทิปที่เบราว์เซอร์ควรเข้าใจเองอยู่แล้ว
- เริ่มจากรูปแบบที่เล็กที่สุด:
<button popovertarget="tip-1"> + <div id="tip-1" popover="manual" role="tooltip">
- ไม่มี event listener, ไม่มีการติดตามสถานะ, ไม่มีการอัปเดต ARIA จาก JavaScript
- เมื่อโฟกัสที่ปุ่ม ทูลทิปจะแสดง และเมื่อกด
Esc ก็หายไป
ความแตกต่างที่รู้สึกได้ทันที
- เปิด/ปิดได้โดยไม่ต้องใช้ JavaScript: เบราว์เซอร์จัดการการเรียกใช้งานจาก HTML โดยตรง และความสัมพันธ์ระหว่าง trigger กับทูลทิปถูกระบุอย่างชัดเจน
- ปุ่ม
Esc ทำงานอัตโนมัติ: ไม่ต้องเพิ่ม key listener เพราะเบราว์เซอร์เข้าใจเองว่าสามารถยกเลิก popover ได้
- ซิงก์สถานะ ARIA อัตโนมัติ: แอตทริบิวต์
aria-expanded จะอัปเดตอัตโนมัติเมื่อ popover เปิด/ปิด ไม่ต้องจัดการเอง และไม่มีความเสี่ยงจากสถานะค้างเก่า
- สิ่งที่สำคัญยิ่งกว่าการลดโค้ดคือ การย้ายความรับผิดชอบ: เดิม JavaScript เป็นผู้ “ทำให้ทูลทิปมีอยู่” แต่ตอนนี้เบราว์เซอร์เข้าใจบทบาทของมันจาก markup และให้มันเข้าไปมีส่วนใน โมเดลโฟกัส, accessibility tree และกฎการปิดแบบเนทีฟ
ทำความเข้าใจ Invoker Commands
popovertarget="id" ใช้เชื่อมปุ่มเข้ากับองค์ประกอบ popover
popovertargetaction ใช้กำหนดพฤติกรรม
show: เปิดอย่างเดียว
hide: ปิดอย่างเดียว
toggle (ค่าเริ่มต้น): ถ้าเปิดอยู่ให้ปิด ถ้าปิดอยู่ให้เปิด
- ทูลทิปเดียวกันสามารถมี หลาย trigger ได้ และปฏิสัมพันธ์พื้นฐานก็ไม่ต้องใช้ JavaScript
ของแถมด้านการเข้าถึงที่ได้ฟรี
-
คีย์บอร์ดที่ “ใช้งานได้เลย”
- ก่อนหน้านี้ต้องมีโครงสร้างหลายชั้น: ให้โฟกัสเป็นตัว trigger, ให้ blur เป็นตัวซ่อน, ผูก
Esc เอง และยังต้องจัดจังหวะเวลาให้ถูกด้วย
- เมื่อกำหนดแอตทริบิวต์
popover (auto หรือ manual) เบราว์เซอร์จะจัดการพื้นฐานให้: Tab/Shift+Tab ทำงานปกติ และ Esc ปิดได้แน่นอนทุกครั้ง
- ส่งผลให้ ตัด global keydown handler, ตรรกะ cleanup เฉพาะ
Esc และการตรวจสถานะระหว่างการนำทางด้วยคีย์บอร์ดออกจากโค้ดเบสได้
-
ความคาดเดาได้ของ screen reader
- นี่คือส่วนที่ดีขึ้นมากที่สุด เพราะก่อนหน้านี้แม้จะทำ ARIA อย่างระมัดระวังแล้ว พฤติกรรมก็ยังเปลี่ยนได้ และการแก้เล็กน้อยก็มีความเสี่ยง
- เมื่อใช้
popover="manual" role="tooltip" จะได้ พฤติกรรมที่เสถียรและคาดเดาได้มากขึ้น
- หลังเปลี่ยนมาใช้แล้ว Lighthouse ก็ไม่แสดงคำเตือนเรื่องสถานะ ARIA ที่ผิดพลาดอีก — เพราะไม่มีสถานะ ARIA แบบคัสตอมให้ทำพลาดแล้ว
-
การจัดการโฟกัส
- เดิมทีต้องมีกฎซับซ้อน เช่น ให้โฟกัส trigger แล้วแสดง, ถ้าโฟกัสย้ายเข้าไปในทูลทิปก็อย่าปิด, จัดการ blur และกู้คืนโฟกัสเอง
- ใน Popover API โฟกัสจะย้ายเข้าไปยัง popover อย่างเป็นธรรมชาติ และเมื่อปิดก็จะ คืนโฟกัสกลับไปที่ trigger โดยอัตโนมัติ
- ไม่ใช่เพิ่มโค้ดกู้คืนโฟกัส แต่เป็นการ ลบ โค้ดนั้นออก
ส่วนที่ Popover API ยังไปไม่ถึง
-
จังหวะเวลาของทูลทิป
- popover แบบเนทีฟเปิดและปิดทันที ทำให้เมื่อเลื่อนเมาส์เร็วไปนิดเดียวหรือแค่เฉี่ยว trigger ทูลทิปอาจกะพริบและ ให้ความรู้สึกไม่เสถียร
- จึงยังต้องมี การควบคุม delay ระหว่าง hover/focus กับการเปิด
- พฤติกรรมเปิด/ปิดพื้นฐานให้เบราว์เซอร์และ HTML invoker commands จัดการไป ส่วน JavaScript ใช้เฉพาะเพื่อ ปรับปรุงพฤติกรรมแบบมีเจตนา เช่น ยกเลิกการซ่อนเมื่อ pointer กำลังย้ายเข้าสู่ทูลทิป
- ทาง CSS ก็มีการสำรวจเรื่องนี้อยู่เช่นกัน โดย งานด้าน interest/invoker กำลังมุ่งไปสู่การเขียน delay ตอนเข้า/ออกด้วย CSS โดยตรง
-
Hover intent และ Invoker Commands
- เบราว์เซอร์ไม่สามารถรู้ได้ว่าทำไมใครบางคนถึง hover อยู่บนองค์ประกอบ — ตั้งใจหรือแค่ pointer ผ่านมา ตัดสินไม่ได้
- เมื่อ invoker commands จัดการการเปิด/ปิดแกนหลักแล้ว JavaScript ก็ไม่ต้องเป็นเจ้าของ interaction model อีกต่อไป แต่เพียง เพิ่มเรื่อง intent ทับลงไปข้างบน
- ใช้ JavaScript เฉพาะกับพฤติกรรมที่เบราว์เซอร์อนุมานเองไม่ได้ เช่น delay สั้น ๆ ก่อนซ่อน หรือยกเลิกการปิดเมื่อ pointer กำลังเคลื่อนไปยังทูลทิป
-
Manual Popover และโฟกัส
- ใน
popover="manual" เบราว์เซอร์จะ ไม่กู้คืนโฟกัสให้อัตโนมัติ ต่างจาก auto popover
- ถ้าทูลทิปเปิดด้วยโฟกัสและปิดด้วย blur ก็ต้องคืนโฟกัสกลับไปที่ trigger อย่างชัดเจนเอง
- นี่คือ เส้นแบ่งที่ชัดเจน ระหว่างพฤติกรรมของแพลตฟอร์มกับความตั้งใจของผู้ใช้
-
ประเมินกันแบบตรงไปตรงมา
- Popover API ไม่ได้แก้ปัญหาทูลทิปแบบมหัศจรรย์ แต่ช่วย หยุดการต้องสร้างโครงสร้างพื้นฐานที่เปราะบางขึ้นมาใหม่ซ้ำ ๆ
- ยังต้องใช้ JavaScript และยังต้องคิดถึง edge case อยู่ แต่ตอนนี้สามารถโฟกัสที่ การแก้ปัญหาของผลิตภัณฑ์ แทนการสร้าง UI primitive เดิมซ้ำได้
กรณีที่ยังต้องใช้ไลบรารีทูลทิป
-
ดีไซน์ซิสเต็มขนาดใหญ่หรือมีความเป็นผู้ใหญ่สูง
- ในดีไซน์ซิสเต็มขนาดใหญ่ที่หลายทีมใช้งานร่วมกัน ไลบรารีเป็นทางเลือกที่สมเหตุสมผลเพื่อให้ได้ พฤติกรรมแบบรวมศูนย์, แพตเทิร์นที่มีเอกสาร, และค่าเริ่มต้นที่สม่ำเสมอ
- การเปลี่ยน interaction model ที่อยู่ข้างใต้ไม่ใช่แค่การตัดสินใจทางเทคนิค แต่ยังเป็น การตัดสินใจระดับองค์กร
- ช่วยทำหน้าที่เป็น guardrail ให้กับสมาชิกทีมที่ยังไม่คุ้นกับรายละเอียดด้านการเข้าถึง
-
ความต้องการด้านการจัดตำแหน่งที่ซับซ้อน
- หากต้องตรวจจับการชนกันระหว่าง nested scroll container, มีตรรกะการพลิกตำแหน่งแบบคัสตอม หรืออยากควบคุม offset/ขอบเขตอย่างละเอียด ไลบรารีอย่าง Floating UI ก็ยังได้เปรียบ
- CSS anchor positioning เริ่มครอบคลุมปัญหาส่วนใหญ่ในด้านนี้แล้ว — สามารถวางตำแหน่งสัมพันธ์กับ trigger, รับรู้ viewport และพลิกตำแหน่งที่ขอบได้ด้วย CSS ล้วน
- แม้ยังเป็นฟีเจอร์ใหม่และมี known issue อยู่ แต่ก็ถูกรวมใน Interop แล้ว จึงมีแนวโน้มจะได้การรองรับจากเบราว์เซอร์ที่ครบและสม่ำเสมอ
- หากตอนนี้ยังต้องการพฤติกรรมข้ามเบราว์เซอร์ที่สม่ำเสมอ ไลบรารียังเป็นตัวเลือกที่ใช้งานได้จริง
-
ทีมที่ยังมีประสบการณ์ด้านการเข้าถึงไม่มาก
- สำหรับทีมที่ความรู้ด้านการเข้าถึงยังไม่มาก ไลบรารีที่ดีทำหน้าที่เป็น ตาข่ายนิรภัย — ไม่ได้การันตีการเข้าถึงที่สมบูรณ์แบบ แต่ช่วยป้องกันความผิดพลาดที่พบบ่อย
- แม้ Popover API จะให้ค่าเริ่มต้นที่ดีกว่า แต่ก็ยังต้องรู้ ว่าเมื่อไรควรเพิ่ม role, label, การจัดการโฟกัส และการทดสอบ
- ถ้าไม่มีความเข้าใจ แม้แต่เครื่องมือแบบเนทีฟก็ยังถูกใช้งานผิดได้
บทสรุป
- ด้วย Popover API ทูลทิปไม่ใช่สิ่งที่ต้องจำลองขึ้นมาอีกต่อไป แต่กลายเป็น องค์ประกอบที่เบราว์เซอร์เข้าใจ
- การเปิด ปิด พฤติกรรมคีย์บอร์ด การจัดการ
Esc และการเข้าถึงส่วนใหญ่ ถูกแพลตฟอร์มจัดการให้เอง
- สำหรับดีไซน์ซิสเต็มที่ซับซ้อน, การคัสตอมระดับสูง หรือข้อจำกัดจากระบบเก่า ไลบรารียังมีบทบาท แต่ ค่าเริ่มต้นกำลังเปลี่ยน
- นี่อาจเป็นครั้งแรกที่ทูลทิปที่เรียบง่ายที่สุด กลับเป็นทูลทิปที่ถูกต้องที่สุดได้พร้อมกัน
- แค่ลองเปลี่ยนทูลทิปในผลิตภัณฑ์สักตัวมาใช้ Popover API ก็จะเห็นได้ว่าอะไรบ้างที่หายไปจากโค้ด
ยังไม่มีความคิดเห็น