Files
cozsweet-frontend-nextjs/src/app/_components/core/settings-section.tsx
T
admin 674df49e24 style(sidebar): align /sidebar screen with Flutter original
Match the Dart lib/ui/sidebar/sidebar_screen.dart + profile_view.dart
exactly:
- White inner shell with 24px padding
- Back button row (arrow icon + "Back" text, no "Profile" header)
- Single "Other" section with one "Log out" row
- Drop profile card, Account/Data/Session sections, and Sign-in CTA

Match Flutter row visuals in the shared SettingsSection:
- Gray (#f5f5f5) rounded row pill on a white card
- 20px chevron, 1px rgba(61,49,74,0.5) divider
- Destructive color #ff6b6b, 14px/600 black section title

Add tokens: --color-settings-card-background, --color-settings-row-background,
--color-settings-divider, --color-chevron-icon, --color-destructive.

Wire the BlocConsumer listener equivalent: on currentUser transitioning to
null, dispatch ChatAuthStatusChanged + AuthReset and router.replace("/chat").

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-11 14:02:52 +08:00

83 lines
2.3 KiB
TypeScript

"use client";
/**
* 设置项列表 Section
*
* 原始 Dart: lib/ui/core/settings_section.dart
*
* 渲染一组 SettingItem:图标 + 标题 + 副标题/值 + 右侧 chevron + 可选 divider。
*/
import { type ReactNode } from "react";
import styles from "./settings-section.module.css";
export interface SettingsItemModel {
id: string;
title: string;
subtitle?: string;
trailing?: string;
icon?: ReactNode;
onClick?: () => void;
destructive?: boolean;
}
export interface SettingsSectionProps {
title?: string;
items: SettingsItemModel[];
}
export function SettingsSection({ title, items }: SettingsSectionProps) {
return (
<section className={styles.section}>
{title ? <h3 className={styles.title}>{title}</h3> : null}
<ul className={styles.list}>
{items.map((item, idx) => (
<li key={item.id}>
<button
type="button"
onClick={item.onClick}
className={[
styles.row,
item.destructive ? styles.destructive : "",
]
.filter(Boolean)
.join(" ")}
>
{item.icon ? (
<span className={styles.icon}>{item.icon}</span>
) : null}
<span className={styles.body}>
<span className={styles.rowTitle}>{item.title}</span>
{item.subtitle ? (
<span className={styles.subtitle}>{item.subtitle}</span>
) : null}
</span>
{item.trailing ? (
<span className={styles.trailing}>{item.trailing}</span>
) : null}
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
aria-hidden="true"
className={styles.chevron}
>
<path
d="M9 6l6 6-6 6"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>
{idx < items.length - 1 ? (
<div className={styles.divider} />
) : null}
</li>
))}
</ul>
</section>
);
}