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일 때는 표시 안 함
|
// Auto 윈도우 < 5일 때는 표시 안 함
|
||||||
val showMeasurement = if (isAutoMeasuring) autoVolumeWindow.size >= 5 && lastVolumeMl > 0 else lastVolumeMl > 0
|
val showMeasurement = if (isAutoMeasuring) autoVolumeWindow.size >= 5 && lastVolumeMl > 0 else lastVolumeMl > 0
|
||||||
val currentMeasurement = if (showMeasurement) "%.0f".format(lastVolumeMl) else "—"
|
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 maxMeasured = if (displayMaxVolumeMl > 0) "%.0f".format(displayMaxVolumeMl) else "—"
|
||||||
val bladderMax = "${appState.piezoSettings.maxVolume}"
|
InfoCard("Session Max", maxMeasured, "mL", urgency.accentColor, Modifier.weight(1f))
|
||||||
val fillMain = if (fillPct > 0) "${"%.0f".format(fillPct)}%" else "—"
|
|
||||||
InfoCard("$maxMeasured mL / $bladderMax mL", fillMain, "", urgency.accentColor, Modifier.weight(1f))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control buttons: Void/Catheterize / Auto / Spot
|
// Control buttons: Void/Catheterize / Auto / Spot
|
||||||
@@ -1129,12 +1130,14 @@ fun PiezoMonitoringView(appState: AppState) {
|
|||||||
modifier = Modifier.weight(1f).height(btnHeight),
|
modifier = Modifier.weight(1f).height(btnHeight),
|
||||||
shape = RoundedCornerShape(14.dp),
|
shape = RoundedCornerShape(14.dp),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = MlPrimary.copy(alpha = 0.1f),
|
// 환자가 가장 자주 누르는 액션 — Auto/Single과 동일한 fill 강도로 격상.
|
||||||
disabledContainerColor = Color.Gray.copy(alpha = 0.1f)
|
// MlPrimary 솔리드 (이전: alpha 0.1로 묻혀있던 옅은 파랑)
|
||||||
|
containerColor = MlPrimary,
|
||||||
|
disabledContainerColor = Color.Gray.copy(alpha = 0.3f)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
// 단일 라벨로 단순화 — 이전 2줄(Voiding/Catheterization)이 좁은 폭에서 3줄로 깨짐
|
Text("Voiding", fontSize = (14 * fontScale).sp,
|
||||||
Text("Voiding", fontSize = (14 * fontScale).sp, fontWeight = FontWeight.SemiBold, color = MlPrimary)
|
fontWeight = FontWeight.SemiBold, color = Color.White)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto (Spot 진행 중 봉인)
|
// Auto (Spot 진행 중 봉인)
|
||||||
|
|||||||
+36
-11
@@ -198,19 +198,41 @@ fun PlacementGuideView(appState: AppState) {
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
// Step indicator + mode badge (이미지 위에 배치)
|
// Step indicator + mode badge (이미지 위에 배치)
|
||||||
|
// Step progress — 텍스트 + 3-dot indicator (현재 단계 강조)
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||||
modifier = Modifier.padding(vertical = 4.dp)
|
modifier = Modifier.padding(vertical = 6.dp)
|
||||||
) {
|
) {
|
||||||
|
val currentStepIdx = when (placementPhase) {
|
||||||
|
PlacementPhase.VERTICAL -> 0
|
||||||
|
PlacementPhase.LATERAL -> 1
|
||||||
|
PlacementPhase.GREEN -> 2
|
||||||
|
}
|
||||||
Text(
|
Text(
|
||||||
text = when (placementPhase) {
|
text = "Step ${currentStepIdx + 1}/3",
|
||||||
PlacementPhase.VERTICAL -> "Step 1/3"
|
fontSize = 14.sp, fontWeight = FontWeight.Bold, color = MlPrimary
|
||||||
PlacementPhase.LATERAL -> "Step 2/3"
|
|
||||||
PlacementPhase.GREEN -> "Step 3/3"
|
|
||||||
},
|
|
||||||
fontSize = 13.sp, fontWeight = FontWeight.SemiBold, color = MlSecondaryText
|
|
||||||
)
|
)
|
||||||
|
// 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) {
|
if (isSweepMode) {
|
||||||
Text(
|
Text(
|
||||||
"SWEEP",
|
"SWEEP",
|
||||||
@@ -263,16 +285,19 @@ fun PlacementGuideView(appState: AppState) {
|
|||||||
append(rawHint)
|
append(rawHint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Hint 톤다운 — 28sp+큰 박스+빨강 강조 3중 중첩이었음.
|
||||||
|
// 폰트 28→20sp, padding 18→12dp, 박스 alpha 살짝 ↓.
|
||||||
|
// "pubic bone" 빨강 강조는 유지 (의도된 1점 강조).
|
||||||
Text(
|
Text(
|
||||||
text = displayHint,
|
text = displayHint,
|
||||||
fontSize = 28.sp,
|
fontSize = 20.sp,
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
color = hintFg,
|
color = hintFg,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.background(hintBg, RoundedCornerShape(16.dp))
|
.background(hintBg.copy(alpha = 0.7f), RoundedCornerShape(14.dp))
|
||||||
.padding(horizontal = 20.dp, vertical = 18.dp)
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
// 큰 타이틀과 몸 사이 간격 (Body 상단 Spacer 32→8dp)
|
// 큰 타이틀과 몸 사이 간격 (Body 상단 Spacer 32→8dp)
|
||||||
|
|||||||
Reference in New Issue
Block a user