구현의 첫 단계는 기본적인 데이터 모델 설정입니다. ActiveModel::Model을 포함하는 Card 클래스를 정의하여 subject와 description을 관리하고, PagesController에서 샘플 Card 객체들을 생성하여 뷰에 전달합니다. 각 카드는 간단한 _card.html.erb 부분 템플릿을 통해 렌더링됩니다. 시각적 구현을 위해 application.html.erb 레이아웃에 Tailwind CSS 그라디언트 배경을 추가하고, pages/show.html.erb에서 카드 목록을 화면 하단에 고정 배치합니다. 개별 카드는 bg-white/80, backdrop-blur-sm, rounded-lg, shadow-lg 등의 Tailwind 클래스를 사용하여 시각적으로 매력적인 디자인을 갖도록 스타일링됩니다.
카드들이 겹쳐진 스택 효과를 만들기 위해 Rails의 class_names 헬퍼를 활용합니다. card_counter 변수를 기반으로 각 카드에 scale, opacity, translate-y 속성을 조건부로 적용하여 입체적인 스택 형태를 구현합니다. 예를 들어, 가장 위에 있는 카드는 scale-100 translate-y-0이 적용되고, 그 아래 카드는 scale-95 opacity-75 -translate-y-2와 같이 점진적으로 변화합니다.
다음으로, 카드 스택의 펼침/접힘 기능을 제어하기 위해 간단한 Stimulus 컨트롤러(cards_controller.js)를 구현합니다. 이 컨트롤러는 open이라는 불리언 static value를 통해 상태를 관리하며, show() 및 hide() 메서드를 통해 openValue를 토글합니다. HTML에서는 data-controller="cards"와 data-cards-open-value="false"를 설정하고, click->cards#show 액션을 통해 클릭 시 스택이 펼쳐지도록 합니다.
카드 부분 템플릿에서는 group-data-[cards-open-value=false]/cards: 및 group-data-[cards-open-value=true]/cards:와 같은 Tailwind CSS 그룹 데이터 변형자를 사용하여 Stimulus 컨트롤러의 open 상태에 따라 카드의 scale, translate, rotate 속성을 동적으로 변경합니다. 이를 통해 카드가 펼쳐질 때 부드럽게 회전하며 분산되는 ‘팬’ 효과를 연출합니다.
사용자 경험을 향상시키기 위해 카드 스택 외부 클릭 시 스택을 접는 기능을 추가합니다. 이를 위해 Stimulus FX 패키지를 설치하고 registerActionOptions를 통해 애플리케이션에 등록합니다. data-action="click->cards#show click@window->cards#hide:stop:whenOutside" 액션을 사용하여, 카드 스택 내부 클릭 시 show() 메서드를 호출하고, 윈도우 전체에서 발생하는 클릭 이벤트 중 스택 외부에서 발생한 경우에만 whenOutside 수정자를 통해 hide() 메서드를 호출하도록 설정합니다.
마지막으로, 카드 스택이 닫힌 상태에서 개별 카드를 클릭했을 때 링크가 활성화되어 페이지가 이동하는 버그를 해결합니다. 이는 Tailwind CSS의 pointer-events-none 유틸리티 클래스를 group-data-[cards-open-value=false]/cards:pointer-events-none와 같이 조건부로 적용하여 해결합니다. 이 CSS 속성은 요소가 마우스 이벤트를 수신하지 않도록 하여, 클릭 이벤트가 하위 요소로 전달되도록 합니다. 이를 통해 JavaScript 없이 CSS만으로 인터랙션 문제를 해결하는 우아한 방법을 제시합니다.