@ceed/ads 1.29.0 → 1.30.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/components/CurrencyInput/CurrencyInput.d.ts +1 -1
  2. package/dist/components/CurrencyInput/hooks/use-currency-setting.d.ts +2 -2
  3. package/dist/components/DataTable/hooks.d.ts +2 -1
  4. package/dist/components/DataTable/utils.d.ts +1 -0
  5. package/dist/components/ProfileMenu/ProfileMenu.d.ts +1 -1
  6. package/dist/components/SearchBar/SearchBar.d.ts +21 -0
  7. package/dist/components/SearchBar/index.d.ts +3 -0
  8. package/dist/components/data-display/Badge.md +39 -71
  9. package/dist/components/data-display/DataTable.md +1 -1
  10. package/dist/components/data-display/InfoSign.md +98 -74
  11. package/dist/components/data-display/Typography.md +97 -363
  12. package/dist/components/feedback/Dialog.md +62 -76
  13. package/dist/components/feedback/Modal.md +44 -259
  14. package/dist/components/feedback/llms.txt +0 -2
  15. package/dist/components/index.d.ts +2 -0
  16. package/dist/components/inputs/Autocomplete.md +107 -356
  17. package/dist/components/inputs/ButtonGroup.md +106 -115
  18. package/dist/components/inputs/Calendar.md +459 -98
  19. package/dist/components/inputs/CurrencyInput.md +5 -183
  20. package/dist/components/inputs/DatePicker.md +431 -108
  21. package/dist/components/inputs/DateRangePicker.md +492 -131
  22. package/dist/components/inputs/FilterMenu.md +19 -169
  23. package/dist/components/inputs/FilterableCheckboxGroup.md +23 -123
  24. package/dist/components/inputs/IconButton.md +88 -137
  25. package/dist/components/inputs/Input.md +0 -5
  26. package/dist/components/inputs/MonthPicker.md +422 -95
  27. package/dist/components/inputs/MonthRangePicker.md +466 -89
  28. package/dist/components/inputs/PercentageInput.md +16 -185
  29. package/dist/components/inputs/RadioButton.md +35 -163
  30. package/dist/components/inputs/RadioTileGroup.md +61 -150
  31. package/dist/components/inputs/SearchBar.md +44 -0
  32. package/dist/components/inputs/Select.md +326 -222
  33. package/dist/components/inputs/Switch.md +376 -136
  34. package/dist/components/inputs/Textarea.md +10 -213
  35. package/dist/components/inputs/Uploader/Uploader.md +66 -145
  36. package/dist/components/inputs/llms.txt +1 -3
  37. package/dist/components/navigation/Breadcrumbs.md +322 -80
  38. package/dist/components/navigation/Dropdown.md +221 -92
  39. package/dist/components/navigation/IconMenuButton.md +502 -40
  40. package/dist/components/navigation/InsetDrawer.md +738 -68
  41. package/dist/components/navigation/Link.md +298 -39
  42. package/dist/components/navigation/Menu.md +285 -92
  43. package/dist/components/navigation/MenuButton.md +448 -55
  44. package/dist/components/navigation/Pagination.md +338 -47
  45. package/dist/components/navigation/ProfileMenu.md +268 -45
  46. package/dist/components/navigation/Stepper.md +28 -160
  47. package/dist/components/navigation/Tabs.md +316 -57
  48. package/dist/components/surfaces/Sheet.md +334 -151
  49. package/dist/index.browser.js +15 -13
  50. package/dist/index.browser.js.map +4 -4
  51. package/dist/index.cjs +313 -291
  52. package/dist/index.d.ts +1 -1
  53. package/dist/index.js +450 -372
  54. package/dist/llms.txt +1 -8
  55. package/framer/index.js +1 -1
  56. package/package.json +16 -15
  57. package/dist/chunks/rehype-accent-FZRUD7VI.js +0 -39
  58. package/dist/components/feedback/CircularProgress.md +0 -257
  59. package/dist/components/feedback/Skeleton.md +0 -280
  60. package/dist/components/inputs/FormControl.md +0 -361
  61. package/dist/components/inputs/RadioList.md +0 -241
  62. package/dist/components/inputs/Slider.md +0 -334
  63. package/dist/guides/ThemeProvider.md +0 -116
  64. package/dist/guides/llms.txt +0 -9
@@ -1,8 +1,8 @@
1
1
  # Menu
2
2
 
3
- Menu and MenuItem are the content layer of a dropdown menu system. Menu renders the floating panel that contains a list of selectable items, while MenuItem represents each individual option. Together with Dropdown (the state container) and a trigger component (MenuButton or IconMenuButton), they form a complete menu composition.
3
+ ## Introduction
4
4
 
5
- Menu is built on Joy UI's Menu component and supports sizes, placements, custom styling, and rich content inside menu items such as icons, links, and nested layouts.
5
+ Menu MenuItem 컴포넌트는 드롭다운 메뉴의 콘텐츠를 구성하는 컴포넌트입니다. Joy UI Menu MenuItem을 기반으로 합니다.. Dropdown 컴포넌트와 함께 사용하여 사용자에게 선택 가능한 옵션들을 제공합니다. 네비게이션, 액션 메뉴, 컨텍스트 메뉴 다양한 용도로 활용할 수 있습니다.
6
6
 
7
7
  ```tsx
8
8
  <Box sx={{
@@ -26,42 +26,27 @@ Menu is built on Joy UI's Menu component and supports sizes, placements, custom
26
26
  ## Usage
27
27
 
28
28
  ```tsx
29
- import { Dropdown, Menu, MenuItem } from '@ceed/ads';
30
- import { MenuButton } from '@ceed/ads';
29
+ import { Dropdown, MenuButton, Menu, MenuItem } from '@ceed/ads';
31
30
 
32
31
  function MyComponent() {
33
32
  return (
34
33
  <Dropdown>
35
- <MenuButton>Open Menu</MenuButton>
34
+ <MenuButton>메뉴 열기</MenuButton>
36
35
  <Menu>
37
- <MenuItem>Option 1</MenuItem>
38
- <MenuItem>Option 2</MenuItem>
39
- <MenuItem>Option 3</MenuItem>
36
+ <MenuItem>옵션 1</MenuItem>
37
+ <MenuItem>옵션 2</MenuItem>
38
+ <MenuItem>옵션 3</MenuItem>
40
39
  </Menu>
41
40
  </Dropdown>
42
41
  );
43
42
  }
44
43
  ```
45
44
 
46
- ## Composition Pattern
47
-
48
- Menu is always used inside a Dropdown together with a trigger element. The full composition looks like this:
49
-
50
- ```
51
- Dropdown -- state container (open/close)
52
- MenuButton -- trigger element (or IconMenuButton)
53
- Menu -- floating panel
54
- MenuItem -- individual option
55
- ListDivider -- visual separator between groups
56
- ```
57
-
58
- See the [Dropdown](?path=/docs/components-navigation-dropdown--docs) documentation for guidance on when to use the composition pattern versus the standalone MenuButton/IconMenuButton components.
59
-
60
- ## Features
45
+ ## Examples
61
46
 
62
47
  ### Basic Menu
63
48
 
64
- A standard menu with simple text items, optionally separated by dividers.
49
+ 가장 기본적인 Menu 사용법입니다.
65
50
 
66
51
  ```tsx
67
52
  <Stack direction="row" spacing={3}>
@@ -92,7 +77,7 @@ A standard menu with simple text items, optionally separated by dividers.
92
77
 
93
78
  ### Menu Sizes
94
79
 
95
- Menu supports `sm`, `md`, and `lg` sizes that affect the padding and font size of all items.
80
+ 다양한 크기의 메뉴를 사용할 있습니다.
96
81
 
97
82
  ```tsx
98
83
  <Stack direction="row" spacing={3}>
@@ -133,7 +118,7 @@ Menu supports `sm`, `md`, and `lg` sizes that affect the padding and font size o
133
118
 
134
119
  ### MenuItem States
135
120
 
136
- MenuItems can be `selected`, `disabled`, or colored with semantic colors like `primary`, `danger`, `success`, and `warning`.
121
+ MenuItem의 다양한 상태를 표현할 있습니다.
137
122
 
138
123
  ```tsx
139
124
  <Dropdown>
@@ -152,7 +137,7 @@ MenuItems can be `selected`, `disabled`, or colored with semantic colors like `p
152
137
 
153
138
  ### MenuItem with Icons
154
139
 
155
- Add icons before item text to improve scannability. Use consistent icon sizing with `sx={{ mr: 1.5, fontSize: 'lg' }}`.
140
+ 메뉴 아이템에 아이콘을 추가할 있습니다.
156
141
 
157
142
  ```tsx
158
143
  <Dropdown>
@@ -195,7 +180,7 @@ Add icons before item text to improve scannability. Use consistent icon sizing w
195
180
 
196
181
  ### Actions Menu
197
182
 
198
- Build action menus for CRUD operations. Use `color="danger"` to highlight destructive actions.
183
+ 편집, 삭제 등의 액션 메뉴로 활용할 있습니다.
199
184
 
200
185
  ```tsx
201
186
  <Dropdown>
@@ -238,7 +223,7 @@ Build action menus for CRUD operations. Use `color="danger"` to highlight destru
238
223
 
239
224
  ### Clickable Menu Items
240
225
 
241
- Attach `onClick` handlers to menu items to respond to user selections.
226
+ 메뉴 아이템에 클릭 이벤트를 연결할 있습니다.
242
227
 
243
228
  ```tsx
244
229
  <Stack spacing={2}>
@@ -257,7 +242,7 @@ Attach `onClick` handlers to menu items to respond to user selections.
257
242
 
258
243
  ### Menu as Links
259
244
 
260
- Use the `component="a"` prop on MenuItem to render items as anchor links for navigation.
245
+ 메뉴 아이템을 링크로 사용할 있습니다.
261
246
 
262
247
  ```tsx
263
248
  <Dropdown>
@@ -281,7 +266,7 @@ Use the `component="a"` prop on MenuItem to render items as anchor links for nav
281
266
 
282
267
  ### Profile Menu
283
268
 
284
- Combine custom Box content (user info header) with standard MenuItem entries for rich profile menus.
269
+ 사용자 프로필 메뉴의 완성된 예제입니다.
285
270
 
286
271
  ```tsx
287
272
  <Dropdown>
@@ -351,7 +336,7 @@ Combine custom Box content (user info header) with standard MenuItem entries for
351
336
 
352
337
  ### Menu Placements
353
338
 
354
- Control the position of the menu panel relative to the trigger using the `placement` prop. Supported values include `top-start`, `top`, `top-end`, `bottom-start`, `bottom`, and `bottom-end`.
339
+ 메뉴가 나타나는 위치를 다양하게 설정할 있습니다.
355
340
 
356
341
  ```tsx
357
342
  <Stack spacing={4} alignItems="center" sx={{
@@ -420,7 +405,7 @@ Control the position of the menu panel relative to the trigger using the `placem
420
405
 
421
406
  ### Long Scrollable Menu
422
407
 
423
- For menus with many items, apply `maxHeight` and `overflow: 'auto'` through the `sx` prop.
408
+ 많은 옵션이 있는 메뉴는 스크롤을 적용할 있습니다.
424
409
 
425
410
  ```tsx
426
411
  <Dropdown>
@@ -438,7 +423,7 @@ For menus with many items, apply `maxHeight` and `overflow: 'auto'` through the
438
423
 
439
424
  ### Custom Styled Menu
440
425
 
441
- Customize the menu panel appearance with border-radius, shadows, borders, and custom item spacing.
426
+ CSS 스타일을 이용해 메뉴를 커스터마이징할 있습니다.
442
427
 
443
428
  ```tsx
444
429
  <Stack direction="row" spacing={3}>
@@ -502,7 +487,7 @@ Customize the menu panel appearance with border-radius, shadows, borders, and cu
502
487
 
503
488
  ### Menu in Card
504
489
 
505
- Embed a Dropdown menu inside cards or other container components for contextual actions.
490
+ 카드나 다른 컴포넌트 내에서 메뉴를 사용할 있습니다.
506
491
 
507
492
  ```tsx
508
493
  <Sheet variant="outlined" sx={{
@@ -562,7 +547,7 @@ Embed a Dropdown menu inside cards or other container components for contextual
562
547
 
563
548
  ### Nested Content
564
549
 
565
- Menu can contain non-MenuItem elements like Box, Typography, and progress indicators alongside standard items.
550
+ 메뉴 내에 복잡한 콘텐츠를 구성할 있습니다.
566
551
 
567
552
  ```tsx
568
553
  <Dropdown>
@@ -646,42 +631,93 @@ Menu can contain non-MenuItem elements like Box, Typography, and progress indica
646
631
  </Dropdown>
647
632
  ```
648
633
 
634
+ ## Component Structure
635
+
636
+ Menu는 다음과 같은 구조로 구성됩니다:
637
+
638
+ ```tsx
639
+ <Dropdown>
640
+ <MenuButton>트리거</MenuButton>
641
+ <Menu>
642
+ {/* 기본 메뉴 아이템 */}
643
+ <MenuItem>기본 아이템</MenuItem>
644
+
645
+ {/* 아이콘이 있는 메뉴 아이템 */}
646
+ <MenuItem>
647
+ <Icon sx={{ mr: 1 }} />
648
+ 아이콘 아이템
649
+ </MenuItem>
650
+
651
+ {/* 구분선 */}
652
+ <ListDivider />
653
+
654
+ {/* 색상이 있는 메뉴 아이템 */}
655
+ <MenuItem color="danger">위험한 작업</MenuItem>
656
+
657
+ {/* 비활성 메뉴 아이템 */}
658
+ <MenuItem disabled>비활성 아이템</MenuItem>
659
+
660
+ {/* 링크 메뉴 아이템 */}
661
+ <MenuItem component="a" href="/link">
662
+ 링크 아이템
663
+ </MenuItem>
664
+
665
+ {/* 클릭 핸들러가 있는 메뉴 아이템 */}
666
+ <MenuItem onClick={handleClick}>클릭 가능한 아이템</MenuItem>
667
+ </Menu>
668
+ </Dropdown>
669
+ ```
670
+
649
671
  ## Common Use Cases
650
672
 
651
- ### Action Menu with Icons
673
+ ### Navigation Menu
652
674
 
653
675
  ```tsx
654
676
  <Dropdown>
655
- <MenuButton variant="plain" size="sm">Actions</MenuButton>
677
+ <MenuButton>네비게이션</MenuButton>
656
678
  <Menu>
657
- <MenuItem onClick={handleEdit}>
658
- <EditIcon sx={{ mr: 1 }} />
659
- Edit
679
+ <MenuItem component="a" href="/home">
680
+
660
681
  </MenuItem>
661
- <MenuItem onClick={handleCopy}>
662
- <CopyIcon sx={{ mr: 1 }} />
663
- Copy
682
+ <MenuItem component="a" href="/products">
683
+ 제품
684
+ </MenuItem>
685
+ <MenuItem component="a" href="/services">
686
+ 서비스
664
687
  </MenuItem>
665
688
  <ListDivider />
666
- <MenuItem color="danger" onClick={handleDelete}>
667
- <DeleteIcon sx={{ mr: 1 }} />
668
- Delete
689
+ <MenuItem component="a" href="/contact">
690
+ 문의하기
669
691
  </MenuItem>
670
692
  </Menu>
671
693
  </Dropdown>
672
694
  ```
673
695
 
674
- ### Navigation Menu
696
+ ### Action Menu with Icons
675
697
 
676
698
  ```tsx
677
699
  <Dropdown>
678
- <MenuButton>Navigate</MenuButton>
700
+ <MenuButton variant="plain" size="sm">
701
+ 작업
702
+ </MenuButton>
679
703
  <Menu>
680
- <MenuItem component="a" href="/home">Home</MenuItem>
681
- <MenuItem component="a" href="/products">Products</MenuItem>
682
- <MenuItem component="a" href="/services">Services</MenuItem>
704
+ <MenuItem onClick={handleEdit}>
705
+ <EditIcon sx={{ mr: 1 }} />
706
+ 편집
707
+ </MenuItem>
708
+ <MenuItem onClick={handleCopy}>
709
+ <CopyIcon sx={{ mr: 1 }} />
710
+ 복사
711
+ </MenuItem>
712
+ <MenuItem onClick={handleShare}>
713
+ <ShareIcon sx={{ mr: 1 }} />
714
+ 공유
715
+ </MenuItem>
683
716
  <ListDivider />
684
- <MenuItem component="a" href="/contact">Contact</MenuItem>
717
+ <MenuItem color="danger" onClick={handleDelete}>
718
+ <DeleteIcon sx={{ mr: 1 }} />
719
+ 삭제
720
+ </MenuItem>
685
721
  </Menu>
686
722
  </Dropdown>
687
723
  ```
@@ -690,75 +726,232 @@ Menu can contain non-MenuItem elements like Box, Typography, and progress indica
690
726
 
691
727
  ```tsx
692
728
  <Dropdown>
693
- <MenuButton
694
- startDecorator={<Avatar size="sm" src="/avatar.jpg" />}
695
- endDecorator={<ExpandMoreIcon />}
696
- >
697
- Username
729
+ <MenuButton startDecorator={<Avatar size="sm" src="/avatar.jpg" />} endDecorator={<ExpandMoreIcon />}>
730
+ 사용자명
698
731
  </MenuButton>
699
732
  <Menu>
733
+ {/* 프로필 헤더 */}
700
734
  <Box sx={{ px: 2, py: 1.5 }}>
701
- <Typography level="title-sm">Username</Typography>
702
- <Typography level="body-xs" color="neutral">user@example.com</Typography>
735
+ <Typography level="title-sm">사용자명</Typography>
736
+ <Typography level="body-xs" color="neutral">
737
+ user@example.com
738
+ </Typography>
703
739
  </Box>
740
+
704
741
  <ListDivider />
742
+
705
743
  <MenuItem>
706
744
  <PersonIcon sx={{ mr: 1 }} />
707
- Profile
745
+ 프로필 보기
708
746
  </MenuItem>
709
747
  <MenuItem>
710
748
  <SettingsIcon sx={{ mr: 1 }} />
711
- Settings
749
+ 설정
712
750
  </MenuItem>
751
+
713
752
  <ListDivider />
753
+
714
754
  <MenuItem>
715
755
  <LogoutIcon sx={{ mr: 1 }} />
716
- Logout
756
+ 로그아웃
717
757
  </MenuItem>
718
758
  </Menu>
719
759
  </Dropdown>
720
760
  ```
721
761
 
722
- ## Best Practices
762
+ ### Filter Menu
723
763
 
724
- - **Use ListDivider to group related items.** Logical grouping helps users scan the menu faster. Place destructive actions (like Delete) in their own group at the bottom.
764
+ ```tsx
765
+ const [filter, setFilter] = useState('전체');
725
766
 
726
- ```tsx
727
- {/* Good: Grouped actions with divider */}
767
+ <Dropdown>
768
+ <MenuButton startDecorator={<FilterListIcon />} endDecorator={<ExpandMoreIcon />}>
769
+ 필터: {filter}
770
+ </MenuButton>
728
771
  <Menu>
729
- <MenuItem>Edit</MenuItem>
730
- <MenuItem>Duplicate</MenuItem>
731
- <ListDivider />
732
- <MenuItem color="danger">Delete</MenuItem>
772
+ <MenuItem selected={filter === '전체'} onClick={() => setFilter('전체')}>
773
+ 전체
774
+ </MenuItem>
775
+ <MenuItem selected={filter === '활성'} onClick={() => setFilter('활성')}>
776
+ 활성
777
+ </MenuItem>
778
+ <MenuItem selected={filter === '비활성'} onClick={() => setFilter('비활성')}>
779
+ 비활성
780
+ </MenuItem>
733
781
  </Menu>
734
- ```
782
+ </Dropdown>;
783
+ ```
735
784
 
736
- - **Keep icon sizing consistent.** When using icons in menu items, apply the same `fontSize` and `mr` (margin-right) to all icons so items align cleanly.
785
+ ### Context Menu (Right-click Menu)
737
786
 
738
- ```tsx
739
- {/* Good: Consistent icon styling */}
740
- <MenuItem><EditIcon sx={{ mr: 1.5, fontSize: 'lg' }} />Edit</MenuItem>
741
- <MenuItem><DeleteIcon sx={{ mr: 1.5, fontSize: 'lg' }} />Delete</MenuItem>
787
+ ```tsx
788
+ const [contextMenu, setContextMenu] = useState(null);
789
+
790
+ const handleContextMenu = (event) => {
791
+ event.preventDefault();
792
+ setContextMenu({
793
+ mouseX: event.clientX - 2,
794
+ mouseY: event.clientY - 4,
795
+ });
796
+ };
797
+
798
+ <div onContextMenu={handleContextMenu}>
799
+ 우클릭 가능한 영역
800
+ {contextMenu && (
801
+ <Menu
802
+ open
803
+ anchorReference="anchorPosition"
804
+ anchorPosition={{
805
+ top: contextMenu.mouseY,
806
+ left: contextMenu.mouseX,
807
+ }}
808
+ onClose={() => setContextMenu(null)}
809
+ >
810
+ <MenuItem>복사</MenuItem>
811
+ <MenuItem>붙여넣기</MenuItem>
812
+ <MenuItem>삭제</MenuItem>
813
+ </Menu>
814
+ )}
815
+ </div>;
816
+ ```
742
817
 
743
- {/* Avoid: Inconsistent icon sizes */}
744
- <MenuItem><EditIcon sx={{ mr: 1 }} />Edit</MenuItem>
745
- <MenuItem><DeleteIcon sx={{ mr: 2, fontSize: 'xl' }} />Delete</MenuItem>
746
- ```
818
+ ### Submenu Pattern
747
819
 
748
- - **Limit menu length.** Aim for 3-7 visible items. For longer lists, set `maxHeight` on Menu to enable scrolling, or reconsider the UI pattern.
820
+ ```tsx
821
+ <Dropdown>
822
+ <MenuButton>파일</MenuButton>
823
+ <Menu>
824
+ <MenuItem>새 파일</MenuItem>
825
+ <MenuItem>열기</MenuItem>
749
826
 
750
- ```tsx
751
- {/* ✅ Good: Scrollable long menu */}
752
- <Menu sx={{ maxHeight: 300, overflow: 'auto' }}>
753
- ```
827
+ {/* 서브메뉴는 별도 Dropdown으로 구현 */}
828
+ <MenuItem>
829
+ 최근 파일
830
+ <Dropdown>
831
+ <MenuButton variant="plain" size="sm" sx={{ ml: 'auto' }}>
832
+
833
+ </MenuButton>
834
+ <Menu placement="right-start">
835
+ <MenuItem>파일1.txt</MenuItem>
836
+ <MenuItem>파일2.txt</MenuItem>
837
+ <MenuItem>파일3.txt</MenuItem>
838
+ </Menu>
839
+ </Dropdown>
840
+ </MenuItem>
841
+
842
+ <ListDivider />
843
+ <MenuItem>저장</MenuItem>
844
+ <MenuItem>종료</MenuItem>
845
+ </Menu>
846
+ </Dropdown>
847
+ ```
754
848
 
755
- - **Use semantic colors intentionally.** Reserve `color="danger"` for destructive actions. Do not use multiple colors in the same menu unless each color carries a distinct meaning.
849
+ ## Menu Placement
756
850
 
757
- - **Provide clear labels.** Every MenuItem should have a concise, action-oriented label that makes its purpose obvious without needing additional context.
851
+ 메뉴의 위치는 `placement` prop으로 조정할 있습니다:
852
+
853
+ ```tsx
854
+ <Menu placement="top-start"> {/* 위쪽 왼쪽 정렬 */}
855
+ <Menu placement="top"> {/* 위쪽 중앙 정렬 */}
856
+ <Menu placement="top-end"> {/* 위쪽 오른쪽 정렬 */}
857
+ <Menu placement="bottom-start"> {/* 아래쪽 왼쪽 정렬 (기본값) */}
858
+ <Menu placement="bottom"> {/* 아래쪽 중앙 정렬 */}
859
+ <Menu placement="bottom-end"> {/* 아래쪽 오른쪽 정렬 */}
860
+ ```
758
861
 
759
862
  ## Accessibility
760
863
 
761
- - **ARIA roles**: Menu automatically receives `role="menu"` and each MenuItem receives `role="menuitem"`. These roles help assistive technologies announce the menu structure correctly.
762
- - **Keyboard navigation**: When the menu is open, Arrow Up/Down moves between items, Enter selects the focused item, and Escape closes the menu and returns focus to the trigger.
763
- - **Disabled items**: Use the `disabled` prop on MenuItem to prevent interaction. Disabled items remain in the tab order but cannot be activated, allowing screen readers to announce them as unavailable.
764
- - **Icon-only items**: If a MenuItem contains only an icon without visible text, add an `aria-label` to provide an accessible name.
864
+ Menu 컴포넌트는 다음과 같은 접근성 기능을 제공합니다:
865
+
866
+ ### 키보드 탐색
867
+
868
+ - **Tab**: 메뉴 버튼으로 포커스 이동
869
+ - **Enter/Space**: 메뉴 열기/닫기
870
+ - **↑/↓**: 메뉴 아이템 간 이동
871
+ - **Escape**: 메뉴 닫기
872
+ - **Enter**: 메뉴 아이템 선택
873
+
874
+ ### ARIA 속성
875
+
876
+ - `role="menu"`: 메뉴 역할 정의
877
+ - `role="menuitem"`: 메뉴 아이템 역할 정의
878
+ - `aria-expanded`: 메뉴 열림/닫힘 상태
879
+ - `aria-haspopup`: 팝업 메뉴 존재 표시
880
+
881
+ ### 추가 접근성 고려사항
882
+
883
+ ```tsx
884
+ <MenuItem aria-label="사용자 프로필 편집">
885
+ <EditIcon />
886
+ 편집
887
+ </MenuItem>
888
+
889
+ <MenuItem disabled aria-label="현재 사용할 수 없는 기능">
890
+ 사용 불가
891
+ </MenuItem>
892
+ ```
893
+
894
+ ## Best Practices
895
+
896
+ 1. **명확한 라벨링**: 메뉴 아이템은 명확하고 이해하기 쉬운 텍스트를 사용하세요.
897
+
898
+ 2. **아이콘 일관성**: 아이콘을 사용할 때는 일관된 크기와 스타일을 유지하세요.
899
+
900
+ ```tsx
901
+ <MenuItem>
902
+ <EditIcon sx={{ mr: 1.5, fontSize: 'lg' }} />
903
+ 편집
904
+ </MenuItem>
905
+ ```
906
+
907
+ 3. **논리적 그룹화**: 관련된 메뉴 아이템들은 ListDivider로 구분하세요.
908
+
909
+ 4. **위험한 작업 구분**: 삭제와 같은 위험한 작업은 색상으로 구분하세요.
910
+
911
+ ```tsx
912
+ <MenuItem color="danger">
913
+ <DeleteIcon sx={{ mr: 1 }} />
914
+ 삭제
915
+ </MenuItem>
916
+ ```
917
+
918
+ 5. **적절한 메뉴 크기**: 너무 긴 메뉴는 스크롤을 적용하거나 서브메뉴로 나누세요.
919
+
920
+ ```tsx
921
+ <Menu sx={{ maxHeight: 300, overflow: 'auto' }}>
922
+ ```
923
+
924
+ 6. **상태 피드백**: 선택된 아이템이나 현재 상태를 명확히 표시하세요.
925
+
926
+ 7. **모바일 고려**: 터치 기기에서 사용하기 쉽도록 충분한 터치 영역을 제공하세요.
927
+
928
+ ## Performance Considerations
929
+
930
+ 1. **메뉴 지연 로딩**: 복잡한 메뉴는 필요할 때만 렌더링하세요.
931
+
932
+ 2. **가상화**: 매우 긴 메뉴 목록에는 가상화를 고려하세요.
933
+
934
+ 3. **메모이제이션**: 정적인 메뉴 아이템들은 메모이제이션을 활용하세요.
935
+
936
+ ## Troubleshooting
937
+
938
+ ### 흔한 문제들
939
+
940
+ 1. **메뉴가 화면을 벗어남**
941
+
942
+ ```tsx
943
+ <Menu placement="top-end"> {/* placement 조정 */}
944
+ ```
945
+
946
+ 2. **긴 메뉴 스크롤 문제**
947
+
948
+ ```tsx
949
+ <Menu sx={{ maxHeight: 400, overflow: 'auto' }}>
950
+ ```
951
+
952
+ 3. **모바일에서 터치 영역 부족**
953
+ ```tsx
954
+ <MenuItem sx={{ minHeight: 44 }}> {/* 최소 터치 영역 보장 */}
955
+ ```
956
+
957
+ Menu와 MenuItem은 사용자 친화적이고 접근성이 뛰어난 메뉴 시스템을 구축하는 핵심 컴포넌트입니다. 적절히 활용하면 직관적이고 효율적인 사용자 인터페이스를 만들 수 있습니다.