refactor(DomainManager): improve expand/collapse UI with card style and chevron toggles

- Collapsed state: card style, ChevronDown button, no hover effect
- Expanded state: card style, ChevronUp in header
- Selected domain: 3px left indicator bar with primary color
- Remove bottom toggle areas
- Add expand/collapse translation keys
This commit is contained in:
2026-03-17 09:26:39 +08:00
parent 8b096fcf53
commit 95acfd2b3b
4 changed files with 61 additions and 85 deletions

View File

@@ -2,19 +2,14 @@
* DomainManager Component
* Main container for domain management
* Supports collapsed/expanded view
* Expand/collapse triggered by clicking bottom area
* Expand/collapse triggered by clicking header chevron
*/
import React from "react";
import { Spin, Space } from "antd";
import { Spin } from "antd";
import { Button, Tooltip, Avatar, Empty } from "@lobehub/ui";
import { useTranslation } from "react-i18next";
import {
Plus,
Cloud,
ChevronUp,
ChevronDown,
} from "lucide-react";
import { Plus, Cloud, ChevronUp, ChevronDown } from "lucide-react";
import { createStyles } from "antd-style";
import { useDomainStore, useUIStore } from "@renderer/stores";
import DomainList from "./DomainList";
@@ -25,13 +20,17 @@ const useStyles = createStyles(({ token, css }) => ({
height: 100%;
display: flex;
flex-direction: column;
background: ${token.colorBgContainer};
background: ${token.colorFillSecondary};
border-radius: ${token.borderRadiusLG}px;
padding: ${token.paddingSM}px;
`,
collapsedContainer: css`
height: 100%;
display: flex;
flex-direction: column;
background: ${token.colorBgContainer};
background: ${token.colorFillSecondary};
border-radius: ${token.borderRadiusLG}px;
padding: ${token.paddingSM}px;
position: relative;
`,
header: css`
@@ -70,10 +69,6 @@ const useStyles = createStyles(({ token, css }) => ({
padding: ${token.paddingSM}px ${token.paddingMD}px;
cursor: pointer;
transition: background 0.2s;
&:hover {
background: ${token.colorBgTextHover};
}
`,
collapsedInfo: css`
display: flex;
@@ -105,31 +100,6 @@ const useStyles = createStyles(({ token, css }) => ({
font-size: ${token.fontSizeSM}px;
padding: ${token.paddingSM}px ${token.paddingMD}px;
`,
// Bottom toggle icon - minimal style
bottomToggleIcon: css`
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: ${token.colorTextTertiary};
font-size: 12px;
z-index: 10;
opacity: 0.6;
transition: all 0.2s;
&:hover {
opacity: 1;
background: ${token.colorFillTertiary};
}
`,
bottomToggleVisible: css`
opacity: 0.6;
`,
}));
interface DomainManagerProps {
@@ -147,7 +117,6 @@ const DomainManager: React.FC<DomainManagerProps> = ({
const { domainIconColors } = useUIStore();
const [formOpen, setFormOpen] = React.useState(false);
const [editingDomain, setEditingDomain] = React.useState<string | null>(null);
const [isHoveringToggle, setIsHoveringToggle] = React.useState(false);
React.useEffect(() => {
loadDomains();
@@ -177,7 +146,7 @@ const DomainManager: React.FC<DomainManagerProps> = ({
if (collapsed) {
return (
<div className={styles.collapsedContainer}>
<div className={styles.collapsedHeader}>
<div className={styles.collapsedHeader} onClick={onToggleCollapse}>
<div className={styles.collapsedInfo}>
<Avatar
icon={<Cloud size={14} />}
@@ -203,27 +172,30 @@ const DomainManager: React.FC<DomainManagerProps> = ({
)}
</div>
</div>
<Tooltip title={t("addDomain")}>
<Button
type="text"
size="small"
icon={<Plus size={16} />}
onClick={(e) => {
e.stopPropagation();
handleAdd();
}}
/>
</Tooltip>
</div>
{/* Bottom toggle icon */}
<div
className={`${styles.bottomToggleIcon} ${isHoveringToggle ? styles.bottomToggleVisible : ""}`}
onClick={onToggleCollapse}
onMouseEnter={() => setIsHoveringToggle(true)}
onMouseLeave={() => setIsHoveringToggle(false)}
>
<ChevronDown size={16} />
<div className={styles.collapsedActions}>
<Tooltip title={t("expand")}>
<Button
type="text"
size="small"
icon={<ChevronDown size={16} />}
onClick={(e) => {
e.stopPropagation();
onToggleCollapse?.();
}}
/>
</Tooltip>
<Tooltip title={t("addDomain")}>
<Button
type="text"
size="small"
icon={<Plus size={16} />}
onClick={(e) => {
e.stopPropagation();
handleAdd();
}}
/>
</Tooltip>
</div>
</div>
<DomainForm
@@ -237,12 +209,23 @@ const DomainManager: React.FC<DomainManagerProps> = ({
// Expanded view - full list
return (
<div className={styles.container} style={{ position: "relative" }}>
<div className={styles.container}>
<div className={styles.header}>
<h2 className={styles.title}>{t("domainManagement")}</h2>
<div className={styles.actions}>
<Button type="primary" icon={<Plus size={16} />} onClick={handleAdd}>
</Button>
<Tooltip title={t("collapse")}>
<Button
type="text"
size="small"
icon={<ChevronUp size={16} />}
onClick={onToggleCollapse}
/>
</Tooltip>
<Button
type="primary"
icon={<Plus size={16} />}
onClick={handleAdd}
></Button>
</div>
</div>
@@ -252,25 +235,12 @@ const DomainManager: React.FC<DomainManagerProps> = ({
<Spin size="large" />
</div>
) : domains.length === 0 ? (
<Empty
description={t("noDomainConfig")}
>
</Empty>
<Empty description={t("noDomainConfig")}></Empty>
) : (
<DomainList onEdit={handleEdit} />
)}
</div>
{/* Bottom toggle icon */}
<div
className={`${styles.bottomToggleIcon} ${isHoveringToggle ? styles.bottomToggleVisible : ""}`}
onClick={onToggleCollapse}
onMouseEnter={() => setIsHoveringToggle(true)}
onMouseLeave={() => setIsHoveringToggle(false)}
>
<ChevronUp size={16} />
</div>
<DomainForm
open={formOpen}
onClose={handleCloseForm}

View File

@@ -57,5 +57,7 @@
"createConnectionFailed": "Connection failed during creation",
"domainDuplicate": "This domain and username combination already exists",
"createFailed": "Creation failed",
"updateFailed": "Update failed"
}
"updateFailed": "Update failed",
"expand": "Expand",
"collapse": "Collapse"
}

View File

@@ -57,5 +57,7 @@
"createConnectionFailed": "接続に失敗しました",
"domainDuplicate": "このドメインとユーザー名の組み合わせは既に存在します",
"createFailed": "作成に失敗しました",
"updateFailed": "更新に失敗しました"
}
"updateFailed": "更新に失敗しました",
"expand": "展開",
"collapse": "折りたたむ"
}

View File

@@ -57,5 +57,7 @@
"createConnectionFailed": "创建时连接失败",
"domainDuplicate": "该域名和用户名组合已存在",
"createFailed": "创建失败",
"updateFailed": "更新失败"
}
"updateFailed": "更新失败",
"expand": "展开",
"collapse": "折叠"
}