Improving Lookbook UX Flow Readability — Mermaid Flowchart + Step Template Redesign

While documenting UX flows with Rails + Lookbook, I hit a moment of “something feels off.” Each Step only showed wireframe fragments, so looking at the Lookbook list gave zero sense of the overall flow. I fixed two things: Add a Mermaid flowchart Overview step to each flow Redesign all Step template structures The Problem: Lookbook Step Previews Feel Like “Context-Free Fragments” # @label Admin UX Flow # @logical_path ux_flows class UxFlows::AdminFlowPreview < ViewComponent::Preview # @label 1. Login -> Admin Dashboard def step_1_login_dashboard render_with_template end # ... end Each step_* method renders an ERB template via render_with_template. The ERB contains a wireframe with a simple step navigation bar at the top. ...

2026-03-10 · 5 min read · Seunghan

Flutter image_picker Camera/Gallery Bottom Sheet + Riverpod Frequency-Based Category Sorter

While building a civic reporting Flutter app, I ran into three UX problems in a row: The photo button only opened the gallery — no camera option Categories kept growing, making the grid scroll-heavy Switching to an emergency report target didn’t change the submit button color Here’s how I fixed each one. Problem 1: image_picker only opens the gallery The issue The photo button called pickImage(source: ImageSource.gallery) directly. Camera permissions were in place, but the UI never offered the option. ...

2026-03-09 · 5 min read · Seunghan
Uxui Review And Fix Svelte Rails

Rails + Svelte App UX/UI Full Review and Improvement Record

Rails 8 + Inertia.js + Svelte 5 조합으로 만든 웹앱을 운영하다가, 기능은 돌아가는데 세부 UX가 들쭉날쭉하다는 걸 느꼈다. 이번 글은 전수 점검 후 우선순위 높은 4가지를 직접 고친 기록이다. Problem 발견: 같은 기능인데 UI가 다르다 가장 먼저 눈에 띈 건 시작일 입력 UI가 화면마다 다르게 동작하는 문제였다. 앱에는 할일을 만들 수 있는 진입점이 4곳이다. 대시보드 빠른 추가 모달(생성) 전체 페이지 생성 모달(수정) 위치 시작일 동작 대시보드 빠른추가 피커가 항상 노출 + + 시작일 버튼도 따로 존재 생성 모달 마감일 설정 후 + 시작일 추가 버튼 클릭 시 피커 표시 전체 페이지 피커 항상 노출 수정 모달 피커 항상 노출 생성 모달만 UX가 깔끔했고, 나머지 3곳은 피커가 항상 보여서 폼이 불필요하게 복잡해 보였다. + 시작일 버튼이 있는데 피커도 이미 떠 있으니 버튼의 의미가 모호했다. ...

2026-03-06 · 4 min read · Seunghan
Calendar Print Browser Print Bug Paper Sizes

The Trap of Web Calendar Printing: window.print() Ignores Off-Screen Elements

I built a calendar printing feature for the web. PDF and PNG downloads worked perfectly, but when hitting the browser print button, image positions weren’t reflected at all. Same data, so why different results? Structure: Preview and Hidden Export Target The calendar print page had this structure: +-- Visible Area ----------------------------+ | [Settings Panel] [Preview Area] | | - Date range Calendar preview | | - Theme/Color | | - Image position slider | +--------------------------------------------+ +-- Hidden Export Target --------------------+ | <div class="fixed -left-[9999px]"> | <- off-screen | <PrintableCalendar ... /> | | </div> | +--------------------------------------------+ The preview is a scaled-down thumbnail, while the actual export calendar is rendered at full size off-screen (-left-[9999px]). PDF/PNG capture this hidden element. ...

2026-01-20 · 4 min read · Seunghan
Flutter Bloc Infinite Scroll Pagination

Flutter BLoC Infinite Scroll Implementation — Layer-by-Layer Design Without External Packages

Loading the entire list upfront is slow. I needed infinite scroll that naturally loads the next batch of data as the user scrolls. Packages like infinite_scroll_pagination exist, but fitting them into an existing BLoC structure sometimes means redesigning your state to match the package’s approach, which can actually make things more complex. Since it’s perfectly achievable with just ScrollController and no external dependencies, I went that route. Why Offset-Based There are two pagination approaches. ...

2025-09-20 · 6 min read · Seunghan
Flutter Bloc Complex State Management

Flutter BLoC - Designing State Management for Complex Q&A Sessions

A BLoC that just loads and displays a list isn’t hard. The challenge comes when you need to manage session-based workflows in a single BLoC – things like “create a session -> add questions -> receive answers -> complete.” Draw the States First Before coding the BLoC, define the states first. Listing all the states the UI needs to display for this workflow: Initial (nothing loaded) Session list loading Session list displayed Creating new session Session detail loading Session detail displayed (with question list) Adding question Submitting answer Error abstract class ReviewQaState {} class ReviewQaInitial extends ReviewQaState {} class ReviewQaLoading extends ReviewQaState {} class ReviewQaSessionListLoaded extends ReviewQaState { final List<QaSession> sessions; ReviewQaSessionListLoaded(this.sessions); } class ReviewQaSessionLoaded extends ReviewQaState { final QaSession session; final List<ReviewQuestion> questions; ReviewQaSessionLoaded({required this.session, required this.questions}); } class ReviewQaQuestionAdded extends ReviewQaState { final ReviewQuestion question; ReviewQaQuestionAdded(this.question); } class ReviewQaError extends ReviewQaState { final String message; ReviewQaError(this.message); } State classes need to be this specific so the UI can branch clearly with if (state is ReviewQaSessionLoaded). ...

2025-07-06 · 4 min read · Seunghan
Privacy Policy Terms Disclaimer Contact