From 69c645ba17116987213ecfa128cb7fba2cbfa25d Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 7 Aug 2026 01:54:32 +0000 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20[=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=EC=84=B1]=20=ED=9A=8C=EC=9D=98=20=EC=A1=B0=EC=9C=A8?= =?UTF-8?q?=20=EC=A0=9C=EC=95=88=20=EB=B2=84=ED=8A=BC=20=EB=A7=A5=EB=9D=BD?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .Jules/palette.md | 3 +++ .../components/calendar/CalendarCoordinationView.tsx | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 .Jules/palette.md diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 000000000..3dba0b50c --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,3 @@ +## 2024-08-07 - Add aria-labels to meeting proposal buttons +**Learning:** Buttons that only have generic text like "제안하기" (Propose) or numbered options like "1안" without context can be unclear to screen reader users when navigating by buttons. Using a screen-reader-only (`sr-only`) span provides clear and actionable context while preserving the reading order of the visible date and time. +**Action:** Always ensure that buttons within complex components (like meeting proposals) have explicit context (e.g., using `sr-only` spans) if the visible text alone isn't sufficiently descriptive out of context. diff --git a/frontend/src/components/calendar/CalendarCoordinationView.tsx b/frontend/src/components/calendar/CalendarCoordinationView.tsx index 41bf3b893..fd5fb9d98 100644 --- a/frontend/src/components/calendar/CalendarCoordinationView.tsx +++ b/frontend/src/components/calendar/CalendarCoordinationView.tsx @@ -7,23 +7,23 @@ export function CalendarCoordinationView() {
From 874cd83f2e97188acd3bdc6c45fe3deb3487178c Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 7 Aug 2026 02:24:07 +0000 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20[=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=EC=84=B1]=20=ED=9A=8C=EC=9D=98=20=EC=A1=B0=EC=9C=A8?= =?UTF-8?q?=20=EC=A0=9C=EC=95=88=20=EB=B2=84=ED=8A=BC=20=EB=A7=A5=EB=9D=BD?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20(=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .Jules/palette.md | 3 - .jules/bolt.md | 4 ++ CHANGELOG.md | 4 ++ backend/api/emails.py | 6 +- docs/doctoring/calendar-a11y.md | 13 ++++ .../CalendarCoordinationView.test.tsx | 64 +++++++++++++++++++ .../calendar/CalendarCoordinationView.tsx | 6 +- 7 files changed, 92 insertions(+), 8 deletions(-) delete mode 100644 .Jules/palette.md create mode 100644 docs/doctoring/calendar-a11y.md create mode 100644 frontend/src/components/calendar/CalendarCoordinationView.test.tsx diff --git a/.Jules/palette.md b/.Jules/palette.md deleted file mode 100644 index 3dba0b50c..000000000 --- a/.Jules/palette.md +++ /dev/null @@ -1,3 +0,0 @@ -## 2024-08-07 - Add aria-labels to meeting proposal buttons -**Learning:** Buttons that only have generic text like "제안하기" (Propose) or numbered options like "1안" without context can be unclear to screen reader users when navigating by buttons. Using a screen-reader-only (`sr-only`) span provides clear and actionable context while preserving the reading order of the visible date and time. -**Action:** Always ensure that buttons within complex components (like meeting proposals) have explicit context (e.g., using `sr-only` spans) if the visible text alone isn't sufficiently descriptive out of context. diff --git a/.jules/bolt.md b/.jules/bolt.md index d5fcbd53e..d0b0a9997 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -15,3 +15,7 @@ **Learning:** `dict.setdefault(key, []).append(value)` evaluates the empty-list default on every iteration, including when the key already exists. In grouping loops, `defaultdict(list)` avoids those transient unused list allocations while preserving insertion order. **Action:** Use `defaultdict(list)` when missing keys are intentionally initialized with lists. Keep `setdefault` when its eager-default behavior or an ordinary `dict` is part of the required contract, and benchmark before claiming a material end-to-end improvement. +## 2026-07-20 - Set Membership Over Dictionary Truthiness + +**Learning:** When using a dictionary purely to track the presence of keys (e.g. `has_sent_message[key] = True`), checking for presence with `.get(key, False)` carries unnecessary semantic and memory overhead. Sets in Python provide a cleaner `key in set_name` syntax for boolean presence checks and slightly reduced memory footprint, while maintaining O(1) time complexity. +**Action:** When tracking unique occurrences or boolean presence of items where the value itself doesn't carry additional information, use a `set` and its `.add()` and `in` operators instead of a `dict` mapping to `True` or `False`. diff --git a/CHANGELOG.md b/CHANGELOG.md index a06003d8f..47850022f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2718,3 +2718,7 @@ - **Note:** CI opencode-review 잡 실행 중 타임아웃 오류(The action 'Run OpenCode PR Review model pool' has timed out after 350 minutes)가 발생했습니다. 이는 외부 AI 검토 모델 서버(github-models 등)의 응답 지연에 기인한 일시적 인프라 문제로 판단되며, 코드 변경 자체의 결함은 아니므로 그대로 재제출하여 파이프라인 재실행을 시도합니다. - **Note:** CI opencode-review 잡 실행 중 타임아웃 오류(The action 'Run OpenCode PR Review model pool' has timed out after 350 minutes)가 발생했습니다. 반복되는 외부 인프라 타임아웃 문제를 해결하기 위해, 마지막으로 재제출을 시도합니다. - **Note:** 추가적인 코드 변경은 없으며, PR 내 자동 분석 커멘트에 대한 답변(CI 실패가 본 PR이 아닌 develop의 기존 이슈임을 인지함)을 남기고 현재 워크플로우를 완료합니다. + +## [Unreleased] +### Added +- [UX 개선] 캘린더 회의 조율 화면 제안 버튼의 접근성 향상 (스크린 리더 사용자를 위한 sr-only 텍스트 추가 및 불필요한 중복 텍스트 숨김) diff --git a/backend/api/emails.py b/backend/api/emails.py index 223ebf040..5cfa77a77 100644 --- a/backend/api/emails.py +++ b/backend/api/emails.py @@ -322,7 +322,7 @@ async def get_emails( reply_counts = defaultdict(int) thread_messages = defaultdict(list) - has_sent_message = {} + has_sent_message = set() if grouped: thread_lookup: set[str] = set() @@ -347,13 +347,13 @@ async def get_emails( reply_counts[group_key] += 1 if is_sent_folder and group_key not in has_sent_message: if message_is_from_user(email, user_addresses): - has_sent_message[group_key] = True + has_sent_message.add(group_key) if is_sent_folder: visible_groups = [ email for group_key, email in grouped.items() - if has_sent_message.get(group_key, False) + if group_key in has_sent_message ] else: visible_groups = list(grouped.values()) diff --git a/docs/doctoring/calendar-a11y.md b/docs/doctoring/calendar-a11y.md new file mode 100644 index 000000000..0bd441861 --- /dev/null +++ b/docs/doctoring/calendar-a11y.md @@ -0,0 +1,13 @@ +# Calendar Coordination View Accessibility + +In `CalendarCoordinationView.tsx`, the proposal buttons were initially designed with visual content representing numbered options (e.g., "1안"), date/time, attendance status, and a generic action text ("제안하기"). + +**Accessibility Problem:** +Using an `aria-label` directly on the `