fix: improve mobile navigation and calculator usability
Publish GitHub Pages output / publish (push) Successful in 32s

This commit is contained in:
2026-09-21 11:30:22 +09:00
parent 3b1c1aeb6f
commit 0bdade44e3
11 changed files with 205 additions and 22 deletions
+49 -2
View File
@@ -1053,8 +1053,10 @@
<option value={card.id} disabled={selectedCardIds.some((id, index) => index !== slot && cardById.get(id)?.characterId === card.characterId)}>{collection[card.id]?.owned ? '● ' : ''}{cardLabel(card)}</option>
{/each}
</select>
{#if selectedId && cardById.get(selectedId)}<small class="selected-card-name">{cardLabel(cardById.get(selectedId)!)}</small>{/if}
</label>
<div class="awakening">
<span class="mobile-field-label">개화 (0~5)</span>
<div class="awakening-stepper">
<button
type="button"
@@ -1072,6 +1074,7 @@
</div>
</div>
<div class="cooldown-lock">
<span class="mobile-field-label">빈도 감소 고정</span>
<div class="reduction-options">
{#each REDUCTION_LOCK_OPTIONS as reduction}
<button
@@ -1084,6 +1087,8 @@
</div>
</div>
<div class="board-overrides">
<span class="mobile-field-label">파란 노드 전체</span>
<span class="mobile-field-label">기수 보너스 덮어쓰기 (0~900)</span>
<label class="override-checkbox">
<input type="checkbox" checked={allBlueNodes[slot]} aria-label={`${slot + 1}번 카드 파란 노드 전체 활성화`} on:change={() => toggleAllBlueNodes(slot)}>
<span aria-hidden="true"></span>
@@ -1237,7 +1242,26 @@
{/if}
</p>
{/if}
<div class="timeline-scroll" role="region" aria-label="스킬 발동 시간대 그래프">
{#if mode === 'analysis'}
<details class="active-window-list">
<summary>액티브 발동 목록 · 눌러서 미발동/복원</summary>
<p>작은 그래프 대신 아래 버튼으로도 조작할 수 있습니다. 미발동으로 설정한 구간은 다시 누르면 복원됩니다.</p>
<div>
{#each result.activeWindows as window}
{@const excluded = excludedActiveWindows.some((item) => item.cardId === window.cardId && item.startSeconds === window.startSeconds)}
{@const impact = activeImpacts.get(activeWindowKey(window))}
<button type="button" disabled={!simulationContext || running} aria-pressed={excluded} on:click={() => toggleActiveWindow(window)}>
<strong>{resultCardName(window.cardId)}</strong>
<span>{formatSeconds(window.startSeconds)}~{formatSeconds(window.endSeconds)} · 효과 {window.scoreUpPercent}% · {excluded ? '미발동 (눌러서 복원)' : '발동 (눌러서 제외)'}</span>
{#if impact}<span>변경 시 최고점 {signedScoreChange(impact.scoreChange)}</span>{/if}
</button>
{/each}
</div>
</details>
{/if}
<p class="board-guide">그래프를 좌우로 밀면 전체 시간대를 확인할 수 있습니다.</p>
<!-- svelte-ignore a11y_no_noninteractive_tabindex (Keyboard users must be able to scroll the timeline.) -->
<div class="timeline-scroll" role="region" aria-label="스킬 발동 시간대 그래프" tabindex="0">
<div class="timeline-canvas" style={`width: ${timelineWidth + 156}px;`}>
<ScoreTimelineChart notes={displayedResult!.notes} {maximumScoreProbabilities} durationSeconds={timelineDuration} minimumWidth={timelineWidth} timeTicks={timelineTicks} />
{#each result.order as cardId, slot}
@@ -1308,6 +1332,14 @@
</main>
<style>
.mobile-field-label, .selected-card-name { display: none; }
.active-window-list { margin: 12px 0; padding: 12px; border: 1px solid #343c49; border-radius: 10px; }
.active-window-list summary { min-height: 44px; align-content: center; cursor: pointer; font-size: 14px; }
.active-window-list p { color: #adb5c2; font-size: 13px; line-height: 1.6; }
.active-window-list > div { display: grid; gap: 8px; max-height: 360px; overflow-y: auto; }
.active-window-list button { display: grid; gap: 6px; min-height: 44px; padding: 12px; border: 1px solid #414b5b; border-radius: 8px; background: #202630; color: #e8ebf1; text-align: left; cursor: pointer; overflow-wrap: anywhere; }
.active-window-list button[aria-pressed='true'] { border-color: #ef8bb6; background: #37232e; }
.active-window-list button span { font-size: 12px; line-height: 1.5; }
#result-title { scroll-margin-top: 90px; }
.stale-warning { margin: 14px 0; padding: 11px 14px; border: 1px solid #665333; border-radius: 9px; color: #edcf92; background: #292319; font-size: 13px; line-height: 1.6; }
main { width: min(var(--page-max-width), calc(100% - var(--page-gutter))); margin: 0 auto; padding: var(--page-content-top) 0 80px; }
@@ -1475,7 +1507,7 @@
.card-field-header, .card-field { grid-template-columns: minmax(0, 1fr) 120px 280px 180px; }
}
@media (max-width: 700px) {
@media (max-width: 900px) {
.order-sections { grid-template-columns: 1fr; }
main { width: calc(100% - 24px); padding-top: var(--page-content-top); }
.page-header { align-items: flex-start; }
@@ -1504,4 +1536,19 @@
.lane-label { flex-basis: 118px; min-width: 118px; }
.timeline-canvas { padding-right: 0; }
}
@media (max-width: 900px) {
.song-fields { grid-template-columns: minmax(0, 1fr); }
.section-title { flex-wrap: wrap; }
.card-field { grid-template-columns: minmax(0, 1fr); padding: 14px 0; border-top: 1px solid #343c49; gap: 12px; }
.card-field > label { grid-template-columns: minmax(0, 1fr); gap: 7px; }
.mobile-field-label { display: block; color: #aab4c3; font-size: 13px; line-height: 1.5; margin-bottom: 6px; }
.selected-card-name { display: block; color: #c1c8d3; font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
.board-overrides { height: auto; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: end; }
.board-overrides .mobile-field-label { margin-bottom: 0; }
.override-checkbox, .generation-input { min-height: 44px; }
.awakening-stepper { height: 46px; grid-template-columns: 44px minmax(0, 1fr) 44px; }
.reduction-options { height: 46px; }
.chart-meta span { white-space: normal; }
}
</style>