Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

27 changes: 0 additions & 27 deletions frontend/src/components/settings/settings-navigation-item.tsx

This file was deleted.

47 changes: 47 additions & 0 deletions frontend/src/components/ui/navigation-row.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { ListGroup } from '@/components/ui/list-group'
import { NavigationRow } from '@/components/ui/navigation-row'
import type { Meta, StoryObj } from '@storybook/react-vite'

const meta = {
title: 'UI/NavigationRow',
component: NavigationRow,
tags: ['autodocs'],
args: {
label: '프로필 수정',
onClick: () => {},
},
// 행은 ListGroup(둥근 배경·구분선 컨텍스트) 안에서 쓰이므로 감싸서 실제 모습을 보여준다.
decorators: [
(Story) => (
<div className="w-80">
<ListGroup>
<Story />
</ListGroup>
</div>
),
],
} satisfies Meta<typeof NavigationRow>

export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {}

export const Destructive: Story = {
args: { label: '인물 삭제', tone: 'destructive', withDivider: false },
}

export const WithoutDivider: Story = {
args: { withDivider: false },
}

export const Disabled: Story = {
args: { label: '인물 삭제', tone: 'destructive', disabled: true },
}

export const LongText: Story = {
args: {
label: '오랜만에 연락한 사람에게 보낼 안부 리마인더를 지금 설정하기',
},
}
49 changes: 49 additions & 0 deletions frontend/src/components/ui/navigation-row.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ChevronRight } from 'lucide-react'
import { ListGroupItem } from '@/components/ui/list-group-item'

// 오른쪽 chevron을 가진 라벨 행 버튼. label + onClick만 받고 라우팅/도메인은 호출부가 소유한다.
// tone='destructive'는 인물 삭제 등 되돌릴 수 없는 동작의 시각 경고(라벨·chevron을 destructive 색)로만 쓴다.
// 터치 앱이라 hover(포인터 기기)와 active(누름) 피드백을 함께 유지한다.
export function NavigationRow({
label,
onClick,
tone = 'default',
withDivider = true,
disabled = false,
}: {
label: string
onClick: () => void
tone?: 'default' | 'destructive'
withDivider?: boolean
disabled?: boolean
}) {
const isDestructive = tone === 'destructive'

return (
<ListGroupItem className="p-0" withDivider={withDivider}>
<button
type="button"
onClick={onClick}
disabled={disabled}
className="flex min-h-14 w-full items-center justify-between gap-4 px-4 py-3.5 text-left transition-colors hover:bg-muted/70 active:opacity-70 disabled:opacity-60"
>
<span
className={
isDestructive
? 'text-body font-extrabold text-destructive'
: 'text-body font-extrabold text-foreground'
}
>
{label}
</span>
<ChevronRight
className={
isDestructive
? 'size-5 shrink-0 text-destructive/70'
: 'size-5 shrink-0 text-muted-foreground'
}
/>
</button>
</ListGroupItem>
)
}
47 changes: 16 additions & 31 deletions frontend/src/stackflow/activities/person/person-profile-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { MonogramAvatar } from '@/components/ui/monogram-avatar'
import { ListGroup } from '@/components/ui/list-group'
import { ListGroupItem } from '@/components/ui/list-group-item'
import { ListGroupLabel } from '@/components/ui/list-group-label'
import { NavigationRow } from '@/components/ui/navigation-row'
import { StatusMessage } from '@/components/ui/status-message'
import { TagChip } from '@/components/ui/tag-chip'
import { optimizedImageUrl } from '@/lib/image-url'
Expand Down Expand Up @@ -224,37 +225,21 @@ export function PersonProfileView({
<section>
<ListGroupLabel>작업</ListGroupLabel>
<ListGroup>
<ListGroupItem className="py-0">
<button
type="button"
onClick={() => push('Record', { personId })}
className="flex w-full items-center justify-between py-3.5 text-body font-extrabold text-foreground transition-colors active:opacity-70"
>
상황 기록 작성
<ChevronRight className="size-5 text-muted-foreground" />
</button>
</ListGroupItem>
<ListGroupItem className="py-0">
<button
type="button"
onClick={() => push('PersonEdit', { personId })}
className="flex w-full items-center justify-between py-3.5 text-body font-extrabold text-foreground transition-colors active:opacity-70"
>
프로필 수정
<ChevronRight className="size-5 text-muted-foreground" />
</button>
</ListGroupItem>
<ListGroupItem withDivider={false} className="py-0">
<button
type="button"
onClick={() => del.setOpen(true)}
disabled={del.pending}
className="flex w-full items-center justify-between py-3.5 text-left text-body font-extrabold text-destructive transition-colors active:opacity-70 disabled:opacity-60"
>
인물 삭제
<ChevronRight className="size-5 text-destructive/70" />
</button>
</ListGroupItem>
<NavigationRow
label="상황 기록 작성"
onClick={() => push('Record', { personId })}
/>
<NavigationRow
label="프로필 수정"
onClick={() => push('PersonEdit', { personId })}
/>
<NavigationRow
label="인물 삭제"
tone="destructive"
withDivider={false}
disabled={del.pending}
onClick={() => del.setOpen(true)}
/>
</ListGroup>
</section>
</div>
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/stackflow/tabs/settings-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { useFlow } from '@stackflow/react'
import { RotateCcw } from 'lucide-react'
import { useState } from 'react'
import { MongleLogo } from '@/components/brand/mongle-logo'
import { SettingsNavigationItem } from '@/components/settings/settings-navigation-item'
import { useTheme } from '@/components/theme-provider'
import { Button } from '@/components/ui/button'
import { ConfirmPopup } from '@/components/ui/confirm-popup'
import { NavigationRow } from '@/components/ui/navigation-row'
import { PageTitle } from '@/components/ui/page-title'
import { ListGroup } from '@/components/ui/list-group'
import { ListGroupItem } from '@/components/ui/list-group-item'
Expand Down Expand Up @@ -48,11 +48,11 @@ export function SettingsTab() {

<div className="min-h-0 min-w-0 flex-1 space-y-6 overflow-y-auto pb-24 [scrollbar-gutter:stable] [-webkit-overflow-scrolling:touch]">
<ListGroup>
<SettingsNavigationItem
<NavigationRow
label="홈 설정"
onClick={() => push('HomeSettings', {})}
/>
<SettingsNavigationItem
<NavigationRow
label="태그 설정"
withDivider={false}
onClick={() => push('TagSettings', {})}
Expand Down
Loading