Skip to content

Tabsย #2

@hsskey

Description

@hsskey

๐Ÿ“‹ ์ปดํฌ๋„ŒํŠธ ์ •๋ณด

  • ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„: Tab
  • ์ปดํฌ๋„ŒํŠธ ์„ค๋ช…: ํƒญ์€ ํ•˜๋‚˜์˜ UI ๋‚ด์—์„œ ์—ฌ๋Ÿฌ ์„น์…˜์˜ ๋‚ด์šฉ์„ ๊ณ„์ธต์ ์œผ๋กœ ์ œ๊ณตํ•˜๋ฉฐ, ๊ฐ ํƒญ์„ ์„ ํƒํ•˜์—ฌ ํŠน์ • ์ฝ˜ํ…์ธ ๋ฅผ ํ™œ์„ฑํ™”์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ
  • ์‚ฌ์šฉ ์‚ฌ๋ก€: ๋™์ผํ•œ ์นดํ…Œ๊ณ ๋ฆฌ๋‚˜ ์ฃผ์ œ๋ฅผ ํฌํ•จํ•˜๋Š” ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋‚˜ ์„น์…˜์„ ํ•œ ํ™”๋ฉด์—์„œ ์ œ๊ณตํ•  ๋•Œ ์‚ฌ์šฉ. ์˜ˆ๋ฅผ ๋“ค์–ด, ์„ค์ • ํŽ˜์ด์ง€, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ •๋ณด ์˜์—ญ ๋“ฑ์„ ํ•˜๋‚˜์˜ ํ™”๋ฉด์—์„œ ๊ฐ„๋‹จํžˆ ์ „ํ™˜ํ•˜๋ฉฐ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ์ง€์›

๐Ÿ“š ์ฐธ์กฐ ๋ฐ ๋ ˆํผ๋Ÿฐ์Šค

  • ARIA Authoring Practices: W3C ARIA Patterns
    • ๊ด€๋ จ ํŒจํ„ด ๋ฐ ์ ์šฉ๋œ ์ ‘๊ทผ์„ฑ ๊ธฐ์ค€ ํ™•์ธ
  • ๊ธฐํƒ€ ๋ ˆํผ๋Ÿฐ์Šค: MUI, Ant Design, Web.dev ๋“ฑ์˜ ๋ฌธ์„œ์™€ ๋น„๊ตํ•˜์—ฌ ํŒจํ„ด ๋ถ„์„

๐Ÿ“ ์ ‘๊ทผ์„ฑ ๋ฐ ARIA ์ ์šฉ ์—ฌ๋ถ€

  • ARIA Pattern ์ ์šฉ: ARIA Pattern ๋งํฌ
    • ์‚ฌ์šฉ๋œ ARIA ์†์„ฑ: role="tablist", role="tab", aria-selected, aria-controls, role="tabpanel" ๋“ฑ์ด ์‚ฌ์šฉ๋จ. role="tablist"๋Š” ํƒญ์˜ ๋ฆฌ์ŠคํŠธ์ž„์„ ๋ช…์‹œํ•˜๋ฉฐ, ๊ฐ๊ฐ์˜ ํƒญ์€ role="tab"์„ ๊ฐ–๊ณ  ํ•ด๋‹น ์ฝ˜ํ…์ธ  ์˜์—ญ๊ณผ ์—ฐ๊ฒฐ๋จ. aria-selected ์†์„ฑ์„ ํ†ตํ•ด ํ˜„์žฌ ์„ ํƒ๋œ ํƒญ์„ ๋ช…์‹œํ•˜๊ณ , aria-controls๋กœ ํƒญ๊ณผ ์ฝ˜ํ…์ธ  ์˜์—ญ์„ ์—ฐ๊ฒฐํ•จ
  • ์ ‘๊ทผ์„ฑ ๊ด€๋ จ ๊ณ ๋ ค์‚ฌํ•ญ: ํƒญ์˜ ์ „ํ™˜ ์‹œ ํ‚ค๋ณด๋“œ ์‚ฌ์šฉ ๋ฐ ํฌ์ปค์Šค ์ด๋™์„ ๊ณ ๋ คํ•ด์•ผ ํ•˜๋ฉฐ, ๊ฐ ํƒญ ํŒจ๋„์ด ์‰ฝ๊ฒŒ ํƒ์ƒ‰ ๊ฐ€๋Šฅํ•˜๋„๋ก aria-labelledby์™€ ๊ฐ™์€ ์†์„ฑ์„ ํ™œ์šฉ
  • ์ ‘๊ทผ์„ฑ ๊ธฐ๋Šฅ ์š”์•ฝ: ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํƒญ์€ aria-selected="true"๋กœ ์„ค์ •ํ•˜๊ณ , ํ•ด๋‹น ํŒจ๋„์ด ๋ช…ํ™•ํžˆ ์ธ์‹๋  ์ˆ˜ ์žˆ๋„๋ก role="tabpanel"์„ ํ†ตํ•ด ์ ‘๊ทผ์„ฑ ๊ฐ•ํ™”

๐Ÿ—๏ธ ๋งˆํฌ์—… ๊ตฌ์กฐ ๋ถ„์„

  • HTML ์‹œ๋งจํ‹ฑ ํƒœ๊ทธ ์‚ฌ์šฉ: <div> ๋‚ด์— role="tablist", role="tab", role="tabpanel" ๋“ฑ์œผ๋กœ ์‹œ๋งจํ‹ฑํ•œ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณต. ๊ฐ ํƒญ์€ aria-controls ์†์„ฑ์„ ํ†ตํ•ด ํŠน์ • ํŒจ๋„๊ณผ ์—ฐ๊ฒฐ๋˜๊ณ , ํ™œ์„ฑํ™” ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด aria-selected ์†์„ฑ์„ ์‚ฌ์šฉ
  • ๋งˆํฌ์—… ๊ตฌ์กฐ ๋น„๊ต:
// W3C ์˜ˆ์‹œ
<div role="tablist" aria-labelledby="tablist-1">
  <button role="tab" aria-controls="tabpanel-1"></button>
</div>
<div role="tabpanel" id="tabpanel-1"></div>

// MUI ์˜ˆ์‹œ
<div role="tablist">
  <button role="tab" aria-controls="tabpanel-id"></button>
</div>
<div role="tabpanel" id="tabpanel-id"></div>

// Web.dev
<snap-tabs>
  <header>
    <nav><a href="#tab1"></a></nav>
  </header>
  <section><article id="tab1"></article></section>
</snap-tabs>

// Ant Design
<div role="tablist">
  <div role="tab" aria-controls="tabpanel-id"></div>
</div>
<div role="tabpanel" id="tabpanel-id"></div>
  • ๊ตฌ์กฐ์  ์„ ํƒ ์ด์œ :
    • MUI ๋ฐ Ant Design: ์‹œ๋งจํ‹ฑ ์›น ์ ‘๊ทผ์„ฑ์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด role="tablist", role="tab", role="tabpanel"์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…ํ™•ํ•œ ๊ตฌ์กฐ ์ œ๊ณต. ์ด๋กœ์จ ์Šคํฌ๋ฆฐ ๋ฆฌ๋” ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ฐ ํƒญ๊ณผ ํŒจ๋„ ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๋ช…ํ™•ํžˆ ์ „๋‹ฌํ•˜๊ณ , ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ๋ฐ ์ ‘๊ทผ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ด
    • Web.dev: <snap-tabs>๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํƒญ ๊ฐ„ ์ „ํ™˜ ์‹œ ์Šคํฌ๋กค๊ณผ ๊ฐ™์€ ์ธํ„ฐ๋ž™์…˜์„ ๊ฐ•์กฐ. ์Šคํฌ๋กค๋กœ ์ „ํ™˜ํ•˜๋Š” ๋ฐฉ์‹์€ ๋ชจ๋ฐ”์ผ ๋“ฑ์—์„œ ๋ณด๋‹ค ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ

๐Ÿ’ก UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋น„๊ต ๋ถ„์„

  • MUI: <button>์„ ์‚ฌ์šฉํ•ด ๊ฐ ํƒญ์„ ์ •์˜ํ•˜๋ฉฐ, ์‹œ๋งจํ‹ฑํ•˜๊ณ  ์ ‘๊ทผ์„ฑ ๋†’์€ ๊ตฌ์กฐ ์œ ์ง€. aria-selected์™€ aria-controls ์†์„ฑ์„ ์‚ฌ์šฉํ•ด ํƒญ๊ณผ ์ฝ˜ํ…์ธ  ์˜์—ญ์„ ๋ช…ํ™•ํžˆ ์—ฐ๊ฒฐ
  • Ant Design: ๋น„์Šทํ•˜๊ฒŒ ์‹œ๋งจํ‹ฑํ•œ ์ ‘๊ทผ์„ฑ์„ ์ค‘์‹œํ•˜๋ฉฐ, ๊ฐ ํƒญ์€ role="tab" ์†์„ฑ์„ ํ†ตํ•ด ํŒจ๋„๊ณผ ์—ฐ๊ฒฐ๋˜๊ณ  aria-labelledby์™€ ๊ฐ™์€ ์†์„ฑ์œผ๋กœ ์ ‘๊ทผ์„ฑ ๊ฐ•ํ™”
  • Web.dev: <snap-tabs>๋ฅผ ์‚ฌ์šฉํ•ด ํƒญ ์ „ํ™˜ ์‹œ ์Šคํฌ๋กค๊ณผ ๊ฐ™์€ ์ž์—ฐ์Šค๋Ÿฌ์šด UX๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, HTML ํƒœ๊ทธ์™€ CSS ์Šคํฌ๋กค ๊ธฐ๋Šฅ์„ ๊ฒฐํ•ฉํ•˜์—ฌ ๋ณด๋‹ค ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณต

โš™๏ธ ๊ตฌํ˜„ ๋ฐ ์„ค๊ณ„ ๊ณ ๋ ค์‚ฌํ•ญ

  • ์ฃผ์š” ์„ค๊ณ„ ๊ณ ๋ ค์‚ฌํ•ญ: ํƒญ ์ปดํฌ๋„ŒํŠธ๋Š” ์‹œ๋งจํ‹ฑ HTML ํƒœ๊ทธ ๋ฐ ์ ์ ˆํ•œ ARIA ์†์„ฑ ์‚ฌ์šฉ์„ ํ†ตํ•ด ์ ‘๊ทผ์„ฑ์„ ๊ฐ•ํ™”ํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์‰ฝ๊ฒŒ ํ˜„์žฌ ํƒญ๊ณผ ํŒจ๋„์˜ ๋‚ด์šฉ์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•จ. ํƒญ ์ „ํ™˜ ์‹œ ์Šคํฌ๋กค์ด๋‚˜ ํด๋ฆญ ์ด๋ฒคํŠธ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ์ฝ˜ํ…์ธ ๊ฐ€ ํ‘œ์‹œ๋˜๋„๋ก ์„ค๊ณ„
  • ์ฝ”๋“œ ์˜ˆ์‹œ:
<div role="tablist">
  <button role="tab" aria-controls="panel-1" aria-selected="true" id="tab-1">Tab 1</button>
  <button role="tab" aria-controls="panel-2" aria-selected="false" id="tab-2">Tab 2</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">Content of Tab 1</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>Content of Tab 2</div>

๐Ÿ” ํ…Œ์ŠคํŠธ ๋ฐ ๊ฒ€ํ† 

  • ์ ‘๊ทผ์„ฑ ํ…Œ์ŠคํŠธ: ์Šคํฌ๋ฆฐ ๋ฆฌ๋”์™€ ํ‚ค๋ณด๋“œ ๋‚ด๋น„๊ฒŒ์ด์…˜ ์‚ฌ์šฉ์„ฑ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ๊ฐ ํƒญ์ด ์ ์ ˆํžˆ ์ธ์‹๋˜๊ณ  ์ „ํ™˜๋˜๋Š”์ง€ ํ™•์ธ. aria-selected ์†์„ฑ์˜ ๋™์ž‘์„ ํ†ตํ•ด ํ™œ์„ฑํ™”๋œ ํƒญ์ด ์ œ๋Œ€๋กœ ์•ˆ๋‚ด๋˜๋Š”์ง€ ๊ฒ€ํ† 
  • ๋ธŒ๋ผ์šฐ์ € ํ˜ธํ™˜์„ฑ ํ…Œ์ŠคํŠธ: ์ฃผ์š” ๋ธŒ๋ผ์šฐ์ €(Chrome, Firefox, Safari, Edge)์—์„œ ํƒญ ์ „ํ™˜์ด ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธ
  • ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ: ์‚ฌ์šฉ์ž ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ํƒญ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•œ ์ „ํ™˜์ด ์ง๊ด€์ ์ด๊ณ  ํŽธ๋ฆฌํ•œ์ง€ ํ™•์ธํ•˜๊ณ  ๊ฐœ์„  ์‚ฌํ•ญ ๋ฐ˜์˜

๐Ÿ“Œ ์ถ”๊ฐ€ ์ฐธ๊ณ  ์‚ฌํ•ญ

  • ๊ด€๋ จ ๋ฌธ์„œ: W3C ARIA Authoring Practices, Web.dev Tabs Example
  • ์˜๊ฒฌ ๋ฐ ์ œ์•ˆ: ํƒญ ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ์˜๊ฒฌ์ด๋‚˜ ๊ฐœ์„  ์‚ฌํ•ญ ์ถ”๊ฐ€

๐ŸŽฏ ์—ญํ• , ์†์„ฑ, ์ƒํƒœ ๋ฐ ํƒœ๊ทธ ์†์„ฑ

  • Role, Attribute, State
    • Role: role="tablist", role="tab", role="tabpanel"์„ ํ†ตํ•ด ๊ฐ ์—ญํ• ์„ ๋ช…์‹œ
    • Attribute: aria-controls, aria-labelledby๋ฅผ ์‚ฌ์šฉํ•ด ํƒญ๊ณผ ํŒจ๋„ ๊ฐ„์˜ ๊ด€๊ณ„ ๋ช…ํ™•ํžˆ ์„ค์ •
    • State: ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ํƒญ์—๋Š” aria-selected="true"๋ฅผ ์„ค์ •ํ•ด ์‹œ๊ฐ์  ๋ฐ ํ”„๋กœ๊ทธ๋žจ์ ์œผ๋กœ ํ˜„์žฌ ์œ„์น˜ ํ‘œ์‹œ
  • JavaScript ๋ฐ CSS ์‚ฌ์šฉ ์—ฌ๋ถ€
    • JavaScript ์‚ฌ์šฉ ์—ฌ๋ถ€: ํƒญ ์ „ํ™˜ ์‹œ ์ฝ˜ํ…์ธ ์˜ ํ‘œ์‹œ ๋ฐ ์ˆจ๊น€์„ JavaScript๋กœ ์ œ์–ดํ•˜๋ฉฐ, ํ‚ค๋ณด๋“œ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ์ ‘๊ทผ์„ฑ ํ–ฅ์ƒ
    • CSS ์ ์šฉ ์‚ฌํ•ญ: ์Šคํฌ๋กค ์ „ํ™˜ ๋“ฑ ์‹œ๊ฐ์  ํšจ๊ณผ๋ฅผ ์œ„ํ•ด CSS ์Šคํฌ๋กค ์Šค๋ƒ…(snap)์„ ์‚ฌ์šฉํ•ด ์ž์—ฐ์Šค๋Ÿฌ์šด UX ์ œ๊ณต

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions