UX Phase 2: Important — 위계/일관성 회복
스크린샷에서 발견된 시각 위계/정보 비대칭 4건 fix.
5. Voiding 버튼 fill 격상 (가장 자주 누르는 액션을 primary로)
- containerColor: MlPrimary.copy(alpha=0.1f) → MlPrimary 솔리드
- text color: MlPrimary → White
- Auto Scan(주황) / Single Scan(청록)과 동급 강도로 일관성 회복
- 환자가 가장 자주 누르는 액션이 옅게 디자인되어 있던 문제 해결
6. InfoCard 우측 라벨 명시 ("Session Max")
- 이전: title="X mL / Y mL" + value="65%" (라벨 없음, 의미 모호)
- 새로: title="Session Max", value="X" + unit="mL"
- 좌측 "Current"와 같은 톤. fill % 정보는 도넛이 이미 시각화 중이라 카드는 raw 숫자만
- 좌측 title도 "Current Measurement" → "Current"로 단순화
7. Alignment Hint 박스 톤다운 (3중 강조 해소)
- fontSize 28sp → 20sp
- padding horizontal 20→16dp, vertical 18→12dp
- 배경 alpha 1.0 → 0.7
- corner 16→14dp
- "pubic bone" 빨강 강조는 유지 (의도된 1점 강조)
8. Step 1/3 도트 indicator 추가 (텍스트 한 줄 → 시각 progress)
- 이전: 13sp 회색 텍스트 한 줄 (정보 위계 너무 약함)
- 새로: 14sp Bold MlPrimary + 3-dot indicator
○ 완료된 step: MlPrimary 0.6 alpha, 8dp
● 현재 step: MlPrimary 솔리드, 12dp (강조)
○ 미완료 step: 회색 0.3 alpha, 8dp
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+11
-8
@@ -1095,11 +1095,12 @@ fun PiezoMonitoringView(appState: AppState) {
|
||||
// Auto 윈도우 < 5일 때는 표시 안 함
|
||||
val showMeasurement = if (isAutoMeasuring) autoVolumeWindow.size >= 5 && lastVolumeMl > 0 else lastVolumeMl > 0
|
||||
val currentMeasurement = if (showMeasurement) "%.0f".format(lastVolumeMl) else "—"
|
||||
InfoCard("Current Measurement", currentMeasurement, "mL", urgency.accentColor, Modifier.weight(1f))
|
||||
InfoCard("Current", currentMeasurement, "mL", urgency.accentColor, Modifier.weight(1f))
|
||||
// 우측 카드: title 명시 "Session Max", 값은 maxMeasured (단위 mL).
|
||||
// 이전엔 title이 "X mL / Y mL"로 들어가고 값에 % 표기되어 의미 모호했음.
|
||||
// % 정보는 도넛 차트가 이미 시각화 중 → 카드는 raw 숫자만.
|
||||
val maxMeasured = if (displayMaxVolumeMl > 0) "%.0f".format(displayMaxVolumeMl) else "—"
|
||||
val bladderMax = "${appState.piezoSettings.maxVolume}"
|
||||
val fillMain = if (fillPct > 0) "${"%.0f".format(fillPct)}%" else "—"
|
||||
InfoCard("$maxMeasured mL / $bladderMax mL", fillMain, "", urgency.accentColor, Modifier.weight(1f))
|
||||
InfoCard("Session Max", maxMeasured, "mL", urgency.accentColor, Modifier.weight(1f))
|
||||
}
|
||||
|
||||
// Control buttons: Void/Catheterize / Auto / Spot
|
||||
@@ -1129,12 +1130,14 @@ fun PiezoMonitoringView(appState: AppState) {
|
||||
modifier = Modifier.weight(1f).height(btnHeight),
|
||||
shape = RoundedCornerShape(14.dp),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = MlPrimary.copy(alpha = 0.1f),
|
||||
disabledContainerColor = Color.Gray.copy(alpha = 0.1f)
|
||||
// 환자가 가장 자주 누르는 액션 — Auto/Single과 동일한 fill 강도로 격상.
|
||||
// MlPrimary 솔리드 (이전: alpha 0.1로 묻혀있던 옅은 파랑)
|
||||
containerColor = MlPrimary,
|
||||
disabledContainerColor = Color.Gray.copy(alpha = 0.3f)
|
||||
)
|
||||
) {
|
||||
// 단일 라벨로 단순화 — 이전 2줄(Voiding/Catheterization)이 좁은 폭에서 3줄로 깨짐
|
||||
Text("Voiding", fontSize = (14 * fontScale).sp, fontWeight = FontWeight.SemiBold, color = MlPrimary)
|
||||
Text("Voiding", fontSize = (14 * fontScale).sp,
|
||||
fontWeight = FontWeight.SemiBold, color = Color.White)
|
||||
}
|
||||
|
||||
// Auto (Spot 진행 중 봉인)
|
||||
|
||||
+36
-11
@@ -198,19 +198,41 @@ fun PlacementGuideView(appState: AppState) {
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
// Step indicator + mode badge (이미지 위에 배치)
|
||||
// Step progress — 텍스트 + 3-dot indicator (현재 단계 강조)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier.padding(vertical = 4.dp)
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||
modifier = Modifier.padding(vertical = 6.dp)
|
||||
) {
|
||||
val currentStepIdx = when (placementPhase) {
|
||||
PlacementPhase.VERTICAL -> 0
|
||||
PlacementPhase.LATERAL -> 1
|
||||
PlacementPhase.GREEN -> 2
|
||||
}
|
||||
Text(
|
||||
text = when (placementPhase) {
|
||||
PlacementPhase.VERTICAL -> "Step 1/3"
|
||||
PlacementPhase.LATERAL -> "Step 2/3"
|
||||
PlacementPhase.GREEN -> "Step 3/3"
|
||||
},
|
||||
fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = MlSecondaryText
|
||||
text = "Step ${currentStepIdx + 1}/3",
|
||||
fontSize = 14.sp, fontWeight = FontWeight.Bold, color = MlPrimary
|
||||
)
|
||||
// 3-dot indicator: 완료(○ → ●), 현재(큰 ●), 미완료(○)
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
verticalAlignment = Alignment.CenterVertically) {
|
||||
repeat(3) { i ->
|
||||
val isDone = i < currentStepIdx
|
||||
val isCurrent = i == currentStepIdx
|
||||
val dotSize = if (isCurrent) 12.dp else 8.dp
|
||||
val dotColor = when {
|
||||
isCurrent -> MlPrimary
|
||||
isDone -> MlPrimary.copy(alpha = 0.6f)
|
||||
else -> Color.Gray.copy(alpha = 0.3f)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(dotSize)
|
||||
.clip(CircleShape)
|
||||
.background(dotColor)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (isSweepMode) {
|
||||
Text(
|
||||
"SWEEP",
|
||||
@@ -263,16 +285,19 @@ fun PlacementGuideView(appState: AppState) {
|
||||
append(rawHint)
|
||||
}
|
||||
}
|
||||
// Hint 톤다운 — 28sp+큰 박스+빨강 강조 3중 중첩이었음.
|
||||
// 폰트 28→20sp, padding 18→12dp, 박스 alpha 살짝 ↓.
|
||||
// "pubic bone" 빨강 강조는 유지 (의도된 1점 강조).
|
||||
Text(
|
||||
text = displayHint,
|
||||
fontSize = 28.sp,
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
color = hintFg,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(hintBg, RoundedCornerShape(16.dp))
|
||||
.padding(horizontal = 20.dp, vertical = 18.dp)
|
||||
.background(hintBg.copy(alpha = 0.7f), RoundedCornerShape(14.dp))
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||
)
|
||||
|
||||
// 큰 타이틀과 몸 사이 간격 (Body 상단 Spacer 32→8dp)
|
||||
|
||||
Reference in New Issue
Block a user