1- import React from 'react' ;
2- import { Tabs } from 'antd' ;
1+ import React , { useState , useEffect } from 'react' ;
2+ import { Collapse } from 'antd' ;
33import { useNavigate , useLocation } from 'react-router-dom' ;
44import styled from 'styled-components' ;
55import {
6- SettingOutlined ,
76 FilterOutlined ,
87 PictureOutlined ,
98 ApiOutlined ,
@@ -15,10 +14,51 @@ import {
1514 DatabaseOutlined
1615} from '@ant-design/icons' ;
1716
18- const { TabPane } = Tabs ;
17+ const { Panel } = Collapse ;
1918
20- const StyledTabs = styled ( Tabs ) `
19+ const StyledCollapse = styled ( Collapse ) `
2120 margin-bottom: 1.5rem;
21+
22+ .ant-collapse-header {
23+ display: flex;
24+ align-items: center;
25+ padding: 12px 16px !important;
26+
27+ .ant-collapse-arrow {
28+ right: 16px;
29+ left: auto !important;
30+ }
31+ }
32+
33+ .ant-collapse-content-box {
34+ padding: 0 !important;
35+ }
36+
37+ .panel-icon {
38+ margin-right: 12px;
39+ font-size: 16px;
40+ }
41+ ` ;
42+
43+ const NavigationItem = styled . div `
44+ padding: 12px 16px;
45+ cursor: pointer;
46+ transition: all 0.3s;
47+ display: flex;
48+ align-items: center;
49+
50+ &:hover {
51+ background-color: rgba(255, 255, 255, 0.1);
52+ }
53+
54+ &.active {
55+ background-color: rgba(255, 255, 255, 0.05);
56+ }
57+
58+ .item-icon {
59+ margin-right: 12px;
60+ font-size: 16px;
61+ }
2262` ;
2363
2464interface SettingsTab {
@@ -32,95 +72,104 @@ const settingsTabs: SettingsTab[] = [
3272 {
3373 key : 'image_moderation' ,
3474 label : 'Image Moderation' ,
35- icon : < PictureOutlined /> ,
75+ icon : < PictureOutlined className = "item-icon" /> ,
3676 path : '/settings/image-moderation'
3777 } ,
3878 {
3979 key : 'content_filter' ,
4080 label : 'Content Filter' ,
41- icon : < FilterOutlined /> ,
81+ icon : < FilterOutlined className = "item-icon" /> ,
4282 path : '/settings/content-filter'
4383 } ,
4484 {
4585 key : 'nest_feeder' ,
4686 label : 'Nest Feeder' ,
47- icon : < ApiOutlined /> ,
87+ icon : < ApiOutlined className = "item-icon" /> ,
4888 path : '/settings/nest-feeder'
4989 } ,
5090 {
5191 key : 'ollama' ,
5292 label : 'Ollama' ,
53- icon : < RobotOutlined /> ,
93+ icon : < RobotOutlined className = "item-icon" /> ,
5494 path : '/settings/ollama'
5595 } ,
5696 {
5797 key : 'xnostr' ,
5898 label : 'XNostr' ,
59- icon : < TwitterOutlined /> ,
99+ icon : < TwitterOutlined className = "item-icon" /> ,
60100 path : '/settings/xnostr'
61101 } ,
62102 {
63103 key : 'relay_info' ,
64104 label : 'Relay Info' ,
65- icon : < InfoCircleOutlined /> ,
105+ icon : < InfoCircleOutlined className = "item-icon" /> ,
66106 path : '/settings/relay-info'
67107 } ,
68108 {
69109 key : 'wallet' ,
70110 label : 'Wallet' ,
71- icon : < WalletOutlined /> ,
111+ icon : < WalletOutlined className = "item-icon" /> ,
72112 path : '/settings/wallet'
73113 } ,
74114 {
75115 key : 'general' ,
76116 label : 'General' ,
77- icon : < GlobalOutlined /> ,
117+ icon : < GlobalOutlined className = "item-icon" /> ,
78118 path : '/settings/general'
79119 } ,
80120 {
81121 key : 'query_cache' ,
82122 label : 'Query Cache' ,
83- icon : < DatabaseOutlined /> ,
123+ icon : < DatabaseOutlined className = "item-icon" /> ,
84124 path : '/settings/query-cache'
85125 }
86126] ;
87127
88128const SettingsNavigation : React . FC = ( ) => {
89129 const navigate = useNavigate ( ) ;
90130 const location = useLocation ( ) ;
131+ const [ activeKey , setActiveKey ] = useState < string | undefined > ( undefined ) ;
91132
92133 // Determine active tab based on current path
93- const getActiveKey = ( ) => {
134+ useEffect ( ( ) => {
94135 const path = location . pathname ;
95136 const tab = settingsTabs . find ( tab => tab . path === path ) ;
96- return tab ? tab . key : 'general' ;
97- } ;
98-
99- const handleTabChange = ( key : string ) => {
100- const tab = settingsTabs . find ( tab => tab . key === key ) ;
101137 if ( tab ) {
102- navigate ( tab . path ) ;
138+ setActiveKey ( tab . key ) ;
103139 }
140+ } , [ location . pathname ] ) ;
141+
142+ const handleItemClick = ( tab : SettingsTab ) => {
143+ navigate ( tab . path ) ;
144+ setActiveKey ( tab . key ) ;
104145 } ;
105146
106147 return (
107- < StyledTabs
108- activeKey = { getActiveKey ( ) }
109- onChange = { handleTabChange }
110- type = "card"
111- size = "large"
148+ < StyledCollapse
149+ accordion
150+ expandIconPosition = "end"
151+ ghost
152+ activeKey = { activeKey }
153+ onChange = { ( key ) => setActiveKey ( key as string | undefined ) }
112154 >
113155 { settingsTabs . map ( tab => (
114- < TabPane
115- tab = {
156+ < Panel
157+ key = { tab . key }
158+ header = {
116159 < span >
117- { tab . icon } { tab . label }
160+ { React . cloneElement ( tab . icon as React . ReactElement , { className : 'panel-icon' } ) } { tab . label }
118161 </ span >
119162 }
120- key = { tab . key }
121- />
163+ >
164+ < NavigationItem
165+ className = { activeKey === tab . key ? 'active' : '' }
166+ onClick = { ( ) => handleItemClick ( tab ) }
167+ >
168+ { tab . label }
169+ </ NavigationItem >
170+ </ Panel >
122171 ) ) }
123- </ StyledTabs >
172+ </ StyledCollapse >
124173 ) ;
125174} ;
126175
0 commit comments