Skip to content

Conversation

@moondev03
Copy link
Member

@moondev03 moondev03 commented Jan 27, 2026

📌 작업 내용

디자인 시스템에 사용될 공통 텍스트 필드 컴포넌트인 PrezelTextField를 추가했습니다.

Interaction

value, enabled, focused, feedback 값들을 통해 Default, Typing, Typed, Disabled 상태를 계산하는 rememberPrezelTextFieldState()를 구현했습니다.

테스트 가능한 프리뷰 작성

image

🧩 관련 이슈


📸 스크린샷

image image image

📢 논의하고 싶은 내용

Summary by CodeRabbit

릴리스 노트

  • 신규 기능

    • 레이블·자리표시자·후행 아이콘·피드백 메시지를 지원하는 커스터마이징 텍스트 필드 추가
    • 포커스 시 자리표시자 자동 숨김, 입력 유휴 감지를 통한 상태 전환(입력 중/완료/비활성) 반영
    • 후행 취소 아이콘으로 입력 초기화, 포커스 제거 버튼 등 사용 예시 포함된 데모·프리뷰 제공
  • 기타

    • 코드 분석 규칙 일부 비활성화 (품질 도구 설정 변경)

✏️ Tip: You can customize this high-level summary in your review settings.

Detekt의 `LongParameterList` 규칙을 비활성화하여 함수 및 생성자의 파라미터 개수 제한을 제거합니다.
디자인 시스템에 `PrezelTextField`의 상태와 그에 따른 스타일을 관리하기 위한 `PrezelTextFieldStyle`을 추가했습니다. 이 클래스는 TextField의 상호작용 상태와 피드백 상태를 조합하여 동적으로 스타일을 결정합니다.

*   **상태 정의**:
    *   `PrezelTextFieldInteraction`: TextField의 상호작용 상태(`DEFAULT`, `TYPING`, `TYPED`, `DISABLED`)를 정의하는 `enum`을 추가했습니다.
    *   `PrezelTextFieldFeedback`: 입력 완료 후의 피드백 상태(`DEFAULT`, `GOOD`, `BAD`)를 정의하는 `enum`을 추가했습니다.

*   **스타일 계산 로직 구현**:
    *   `PrezelTextFieldStyle` 데이터 클래스를 통해 `interaction`과 `feedback` 상태를 관리합니다.
    *   상태에 따라 배경색(`containerColor`), 텍스트 색상(`textColor`), 아이콘 색상(`trailingIconColor`), 테두리 스타일(`borderStroke`)을 동적으로 계산하는 `@Composable` 확장 함수를 구현했습니다.
디자인 시스템에 사용될 공통 텍스트 필드 컴포넌트인 `PrezelTextField`를 추가했습니다.
`PrezelTextField`의 상태(`PrezelTextFieldInteraction`)를 결정하는 로직을 `remember` 블록에서 `PrezelTextFieldInteraction`의 `companion object` 내 `calculate` 함수로 분리하여 재사용성과 가독성을 높였습니다.

*   **리팩토링**: `PrezelTextFieldInteraction`에 `calculate` 함수를 추가하고, `rememberPrezelTextFieldState` 내에서 이 함수를 호출하도록 변경했습니다.
*   **기타**: 코드 스타일에 맞춰 일부 `when` 표현식의 포맷팅을 수정했습니다.
`PrezelTextFieldState.kt` 파일 내 `when` 표현식의 코딩 스타일을 일관성 있게 수정했습니다.

*   `PrezelTextFieldInteraction.from` 메서드 내에서 불필요한 클래스 이름 반복을 제거했습니다.
*   `when` 블록의 화살표(->) 정렬을 통일하여 가독성을 개선했습니다.
@moondev03 moondev03 self-assigned this Jan 27, 2026
@moondev03 moondev03 added the ✨ feat 새로운 기능 추가 또는 기존 기능 확장 label Jan 27, 2026
@moondev03 moondev03 linked an issue Jan 27, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 27, 2026

Walkthrough

Prezel 디자인 시스템에 PrezelTextField 컴포저블이 추가되었습니다. 퍼블릭 엔트리 포인트와 내부 렌더링 오버로드, 상태 기반 PrezelTextFieldState 및 상호작용 열거형(PrezelTextFieldInteraction), 피드백 봉합형(PrezelTextFieldFeedback), 입력/포커스/비활성/아이들 상태를 계산하는 rememberPrezelTextFieldInteraction 훅이 포함됩니다. 내부적으로 데코레이션 박스, 레이블, 서포팅 텍스트, 트레일링 아이콘 처리, 포커스·플레이스홀더 동작과 여러 Preview가 구현되었고, detekt 설정에서 LongParameterList 검사가 비활성화되었습니다.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 변경 사항의 주요 내용인 PrezelTextField 구현을 명확하게 설명하고 있습니다.
Description check ✅ Passed 설명 템플릿의 모든 필수 섹션(작업 내용, 관련 이슈, 스크린샷)이 포함되어 있고 충분히 상세합니다.
Linked Issues check ✅ Passed PR은 이슈 #28의 모든 요구사항을 충족합니다: PrezelTextField 컴포넌트 구현, 상태 관리, UI 렌더링 분리, 프리뷰 포함.
Out of Scope Changes check ✅ Passed detekt-config.yml 변경은 LongParameterList 검사 비활성화로, 긴 파라미터를 가진 PrezelTextField 구현을 위한 관련 변경입니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

`PrezelTextField`의 `TrailingIconFilledEnabled` 프리뷰에서 `trailingIcon` 파라미터가 누락되어 발생하는 렌더링 오류를 수정했습니다.

*   `trailingIcon`에 `PrezelIcons.Blank`를 기본값으로 추가하여 컴포저블이 정상적으로 렌더링되도록 수정
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextField.kt`:
- Around line 151-161: The placeholder isn't reliably shown because
value.ifEmpty { Text(...) } uses String.ifEmpty which returns the lambda result
(Unit) instead of conditionally composing UI; replace that with an explicit
conditional composition so the Text placeholder is only composed when the string
is empty — e.g., inside PrezelTextField's Box (where innerTextField() is called)
change the value.ifEmpty usage to an if (value.isEmpty()) { Text(...) }
conditional so the placeholder composable is actually emitted; keep the same
Text parameters (placeholder, maxLines, style =
PrezelTheme.typography.body2Regular, color = PrezelTheme.colors.textSmall) and
leave innerTextField() as-is.

In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextFieldState.kt`:
- Around line 152-162: The else branch in supportingTextColor uses
PrezelTheme.colors.textRegular directly which is inconsistent with the function
parameter; change that to use the passed-in colors parameter
(colors.textRegular) so supportingTextColor consistently references the colors
argument instead of PrezelTheme.colors; update the function supportingTextColor
in PrezelTextFieldState to replace PrezelTheme.colors.textRegular with
colors.textRegular.
- Around line 233-240: LaunchedEffect currently uses (value, focused, enabled)
as keys so every value change restarts the effect and defeats
snapshotFlow+debounce; change the effect to only key off focused and enabled
(remove value from the LaunchedEffect keys) and keep snapshotFlow { value
}.distinctUntilChanged().debounce(idleMillis)...collectLatest { idleTyped = true
} so the debounce timer runs inside a single coroutine rather than being reset
on each value change; update the LaunchedEffect invocation that wraps
snapshotFlow accordingly (symbols: LaunchedEffect, value, focused, enabled,
snapshotFlow, debounce, idleMillis, idleTyped).
🧹 Nitpick comments (2)
Prezel/detekt-config.yml (1)

37-38: 전역 규칙 비활성화 대신 대상 지정 억제 사용을 권장합니다.

LongParameterList 규칙을 전역으로 비활성화하면 프로젝트 전체의 코드 품질 검사가 약해집니다. 대신 필요한 함수에만 @Suppress("LongParameterList") 어노테이션을 사용하는 것이 좋습니다.

♻️ 제안된 수정

detekt-config.yml에서 규칙을 다시 활성화:

 LongParameterList:
-    active: false
+    active: true

그리고 PrezelTextField.kt에서 필요한 함수에만 억제 적용:

`@Suppress`("LongParameterList")
`@Composable`
fun PrezelTextField(
    value: String,
    onValueChange: (String) -> Unit,
    // ...
)
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextFieldState.kt (1)

67-89: 네이밍 컨벤션: 데이터 클래스에 SCREAMING_CASE 사용.

Kotlin 컨벤션에서 클래스명은 일반적으로 PascalCase를 사용합니다. 현재 DEFAULT, GOOD, BAD는 enum 상수나 companion object 값처럼 보일 수 있습니다.

의도적인 설계라면 무시해도 되지만, 컨벤션을 따르려면 Default, Good, Bad로 변경을 고려해 보세요.

moondev03 and others added 5 commits January 29, 2026 15:34
`PrezelTextField` 컴포넌트 내에서 플레이스홀더(`Text`)가 표시되는 조건을 기존의 확장 함수 `value.ifEmpty { ... }`에서 표준 `if (value.isEmpty()) { ... }` 조건문으로 변경했습니다. 이로 인해 코드의 명확성이 향상되었습니다.
`PrezelTextFieldState` 내부에서 `PrezelTheme.colors`를 직접 참조하던 부분을 파라미터로 주입된 `colors` 객체를 사용하도록 수정하여, 컴포넌트가 올바른 테마 색상을 참조하도록 수정했습니다.
`PrezelTextField`의 상태 관리 로직을 개선하여 `Interaction` 계산과 `State` 생성을 분리하고, 타이핑 후 유휴 상태를 판별하는 로직을 최적화했습니다.

*   **관심사 분리**: 기존 `rememberPrezelTextFieldState` 함수를 `rememberPrezelTextFieldInteraction`으로 변경하여 상호작용(Interaction) 상태 계산을 전담하도록 수정했습니다.
*   **상태 감지 최적화**: `snapshotFlow`와 `rememberUpdatedState`를 사용하여 `value`, `enabled`, `focused`의 최신 상태를 안정적으로 감지하고, 이를 기반으로 유휴 상태(`isIdle`)를 판별하는 로직을 개선했습니다.
*   **로직 명료화**: `idleTyped` 파라미터를 `isIdle`로 변경하여 유휴 상태 여부를 더 명확하게 표현했습니다.
*   **상태 생성**: `PrezelTextField` 컴포저블 내에서 `rememberPrezelTextFieldInteraction`을 통해 얻은 `interaction` 값과 `feedback`을 조합하여 최종 `PrezelTextFieldState`를 생성하도록 구조를 변경했습니다.
*   **기타**: 디버깅 목적으로 추가되었던 `supportingText`의 임시 코드를 확인했습니다. (실제 텍스트 대신 `interaction` 상태를 표시하도록 변경됨)
`PrezelTextFieldFeedback`의 하위 데이터 클래스(`DEFAULT`, `GOOD`, `BAD`)의 이름을 PascalCase 네이밍 컨벤션에 맞춰 `Default`, `Good`, `Bad`로 변경했습니다.

이는 Kotlin의 클래스 및 객체 네이밍 표준을 따르기 위함이며, 코드의 일관성과 가독성을 개선합니다. 관련 클래스를 사용하는 `PrezelTextFieldState`와 `PrezelTextField`의 Preview 코드도 새로운 이름에 맞게 수정되었습니다.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextField.kt`:
- Around line 192-194: The Text composable in PrezelTextField.kt is showing
debug output by using state.interaction.toString() instead of the intended
supporting text; revert to using state.supportingText in the Text call (replace
the reference to state.interaction.toString() with state.supportingText) and
remove any leftover debug expression so users no longer see internal enum values
(ensure the commented original line Text(text = state.supportingText) is
restored and the debug line removed).
🧹 Nitpick comments (1)
Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextFieldState.kt (1)

142-146: 일관성 없는 색상 참조.

Line 144에서 다크 테마일 때 PrezelColorScheme.Light.textLarge를 직접 참조하고 있습니다. 다른 헬퍼 함수들은 colors 파라미터를 일관되게 사용하고 있어, 테스트 용이성과 커스텀 테마 지원을 위해 수정이 권장됩니다.

♻️ 제안된 수정

PrezelColors에 대비용 색상 속성을 추가하거나, 라이트/다크 색상 쌍을 파라미터로 받는 방식을 고려해 주세요:

     PrezelTextFieldInteraction.TYPED -> when (feedback) {
         is PrezelTextFieldFeedback.Default -> colors.textRegular
-        else -> if (isDarkTheme) PrezelColorScheme.Light.textLarge else colors.textLarge
+        else -> colors.textLarge // 또는 별도의 고대비 색상 속성 사용
     }

피드백 배경에서 대비를 위해 라이트 스킴 색상이 필요한 경우, PrezelColorstextLargeContrast 같은 속성을 추가하여 테마별로 적절한 값을 제공하는 것이 더 유연한 설계입니다.

디버깅 목적으로 `state.interaction.toString()`을 출력하던 코드를 원래 의도인 `state.supportingText`로 복원하여 텍스트 필드의 보조 텍스트가 올바르게 표시되도록 수정했습니다.
Copy link
Contributor

@HamBeomJoon HamBeomJoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@moondev03 moondev03 merged commit 41550d7 into develop Jan 29, 2026
2 checks passed
@moondev03 moondev03 deleted the feat/#28-textfield branch January 29, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat 새로운 기능 추가 또는 기존 기능 확장

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PrezelTextField 구현

3 participants