Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@
## 2024-07-10 - prefers-reduced-motion 지원 μΆ”κ°€
**Learning:** μ‹œμŠ€ν…œ λ ˆλ²¨μ—μ„œ μ• λ‹ˆλ©”μ΄μ…˜ 쀄이기(prefers-reduced-motion)λ₯Ό μ„€μ •ν•œ μ‚¬μš©μžλ₯Ό μœ„ν•΄ κ³Όλ„ν•œ μ• λ‹ˆλ©”μ΄μ…˜κ³Ό λΆ€λ“œλŸ¬μš΄ μŠ€ν¬λ‘€μ„ λΉ„ν™œμ„±ν™”ν•˜λŠ” 것이 ν•„μš”ν•©λ‹ˆλ‹€. μ΄λ•Œ `0s` λŒ€μ‹  `0.01ms`λ₯Ό μ‚¬μš©ν•˜μ—¬ `transitionend`와 같은 λΈŒλΌμš°μ € μ΄λ²€νŠΈκ°€ μ •μƒμ μœΌλ‘œ λ°œμƒν•˜λ„λ‘ ν•΄μ•Ό μžλ°”μŠ€ν¬λ¦½νŠΈ 콜백이 λ©ˆμΆ”λŠ”(hanging) 문제λ₯Ό λ°©μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
**Action:** 항상 `styles.css` ν•˜λ‹¨μ— `prefers-reduced-motion: reduce` λ―Έλ””μ–΄ 쿼리λ₯Ό μΆ”κ°€ν•˜μ—¬ λͺ¨λ“  μš”μ†Œμ˜ `animation-duration`κ³Ό `transition-duration`을 `0.01ms`둜 μ„€μ •ν•˜κ³  `scroll-behavior: auto`λ₯Ό μ μš©ν•©λ‹ˆλ‹€.
## 2025-01-15 - ν„°μΉ˜ ν”Όλ“œλ°±μ΄ μžˆλŠ” λ²„νŠΌ(Tactile Button Feedback)
**Learning:** μ‚¬μš©μžλŠ” 평면적인 μ›Ή λ²„νŠΌμ„ 클릭할 λ•Œ 물리적 ν”Όλ“œλ°±μ˜ λΆ€μž¬λ₯Ό λŠλ‚λ‹ˆλ‹€. `:hover` μƒνƒœκ°€ μ˜λ„λ₯Ό λ³΄μ—¬μ£ΌκΈ°λŠ” ν•˜μ§€λ§Œ, 클릭 μ¦‰μ‹œ μΌμ–΄λ‚˜λŠ” 물리적인 λ°˜μ‘(예: `transform: scale()`)은 μΈν„°νŽ˜μ΄μŠ€λ₯Ό 훨씬 더 λΉ λ¦ΏλΉ λ¦Ών•˜κ³  'μ•± 같은' λŠλ‚Œμ„ μ€λ‹ˆλ‹€. 적은 μ½”λ“œλ‘œλ„ 큰 효과λ₯Ό λ‚΄λŠ” 마이크둜 μΈν„°λž™μ…˜μž…λ‹ˆλ‹€.
**Action:** λ²„νŠΌμ˜ `:active` μƒνƒœμ— μ „μ—­μ μœΌλ‘œ `transform: scale()`을 μ μš©ν•˜μ—¬ μ‹œκ°μ  ν„°μΉ˜ ν”Όλ“œλ°±μ„ μ œκ³΅ν•©λ‹ˆλ‹€.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# CHANGELOG

## [Unreleased]
- **UX κ°œμ„ **: 평면적인 λ²„νŠΌμ— 클릭 μ‹œ 즉각적인 물리적 ν”Όλ“œλ°±(Transform μΆ•μ†Œ 효과)을 μ œκ³΅ν•˜μ—¬ 'μ•± 같은' λ°˜μ‘ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬μΆ•ν–ˆμŠ΅λ‹ˆλ‹€.
- **λ³΄μ•ˆ κ°œμ„ **: μ»΄ν¬λ„ŒνŠΈ 가러리의 인라인 μŠ€ν¬λ¦½νŠΈμ™€ μŠ€νƒ€μΌμ„ μ™ΈλΆ€ 파일둜 λΆ„λ¦¬ν•˜κ³ , μ—„κ²©ν•œ Content-Security-Policyλ₯Ό μ μš©ν•΄ XSS λ°©μ–΄λ₯Ό κ°•ν™”ν–ˆμŠ΅λ‹ˆλ‹€.
- **μ„±λŠ₯ νšŒκ·€ 볡원**: μ˜€ν”„μŠ€ν¬λ¦° `.section` λ Œλ”λ§μ„ `content-visibility: auto`둜 μ§€μ—°ν•˜κ³ , 일반 μ„Ήμ…˜μ€ 600pxΒ·μ½˜ν…μΈ κ°€ 큰 DIKW/projects μ„Ήμ…˜μ€ 1000px의 `contain-intrinsic-size` placeholderλ₯Ό μœ μ§€ν•΄ 초기 λ Œλ”λ§ λΉ„μš©κ³Ό μŠ€ν¬λ‘€λ°” 이동을 ν•¨κ»˜ μ€„μ˜€μŠ΅λ‹ˆλ‹€.
- **λ³΄μ•ˆ κ°œμ„ **: Trusted Types 기반 CSP κ°•ν™”: 잠재적인 DOM 기반 XSS 곡격을 λ°©μ§€ν•˜κΈ° μœ„ν•΄ `require-trusted-types-for 'script'` μ§€μ‹œμ–΄ μΆ”κ°€
Expand Down
13 changes: 11 additions & 2 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,18 @@ a {
min-width: 38px;
min-height: 32px;
border: 0;
border-radius: 4px;
background: transparent;
color: var(--muted);
font: inherit;
font-size: 13px;
font-weight: 850;
cursor: pointer;
transition: opacity 0.2s;
transition: opacity 0.2s, background-color 0.2s, color 0.2s, transform 0.1s ease-out;
}

.language-switch button:active {
transform: scale(0.94);
}

.language-switch button:not([aria-pressed="true"]):hover {
Expand Down Expand Up @@ -218,13 +223,17 @@ h1 {
text-decoration: none;
font-size: 15px;
font-weight: 800;
transition: opacity 0.2s;
transition: opacity 0.2s, transform 0.1s ease-out;
}

.button:hover {
opacity: 0.8;
}

.button:active {
transform: scale(0.97);
}

.button.primary {
background: var(--ink);
color: var(--white);
Expand Down
9 changes: 9 additions & 0 deletions tests/test_styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,12 @@ def test_images_decode_without_blocking_rendering():

assert parser.images
assert all(image.get("decoding") == "async" for image in parser.images)


def test_interactive_elements_have_tactile_active_states():
"""Buttons and interactive elements scale down slightly on active state."""
button_active = _rule(".button:active")
lang_button_active = _rule(".language-switch button:active")

assert "transform: scale(0.97);" in button_active
assert "transform: scale(0.94);" in lang_button_active
Loading