Skip to content

Commit

Permalink
Refactor Chat components to enhance styling and structure
Browse files Browse the repository at this point in the history
- Replaced CSS files with LESS for improved styling management in Header, Container, and Menu components.
- Updated class names to follow a consistent naming convention, enhancing code readability and maintainability.
- Improved the logic for calculating visible menu items and their widths, ensuring a more responsive layout.
- Enhanced the rendering of menu items and dropdowns for better user interaction and visual feedback.

These changes significantly improve the organization and usability of the Chat interface, providing a more cohesive user experience.
  • Loading branch information
trheyi committed Dec 23, 2024
1 parent de50804 commit 6e4cc47
Show file tree
Hide file tree
Showing 7 changed files with 694 additions and 677 deletions.
88 changes: 51 additions & 37 deletions packages/xgen/layouts/wrappers/Chat/Container/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { container } from 'tsyringe'
import { GlobalModel } from '@/context/app'
import Icon from '@/widgets/Icon'
import clsx from 'clsx'
import './styles.css'
import './header.less'

interface HeaderProps {
openSidebar: (temporaryLink?: string, title?: string) => void
Expand Down Expand Up @@ -223,29 +223,30 @@ const Header: FC<HeaderProps> = ({

const calculateVisibleItems = () => {
// Get the header element's width
const header = container.closest('.header') as HTMLElement
const header = container.closest('.header_container') as HTMLElement
if (!header) return

// Get the header-right width
const headerRight = header.querySelector('.header-right') as HTMLElement
const headerRight = header.querySelector('.header_right') as HTMLElement
if (!headerRight) return

// Calculate available width
const headerWidth = header.getBoundingClientRect().width
const headerRightWidth = headerRight.getBoundingClientRect().width
const logo = header.querySelector('.header-logo') as HTMLElement
const createNew = header.querySelector('.current-function') as HTMLElement
const logo = header.querySelector('.header_logo') as HTMLElement
const createNew = header.querySelector('.header_current_function') as HTMLElement

if (!logo || !createNew) return

const usedWidth =
headerRightWidth +
logo.getBoundingClientRect().width +
createNew.getBoundingClientRect().width +
64 // Total padding and gaps
// Add some buffer for padding and spacing
const BUFFER_SPACE = 80
const logoWidth = logo.getBoundingClientRect().width
const createNewWidth = createNew.getBoundingClientRect().width

const usedWidth = headerRightWidth + logoWidth + createNewWidth + BUFFER_SPACE

const availableWidth = headerWidth - usedWidth
const moreMenuWidth = 40
const moreMenuWidth = 48
let currentWidth = 0
let count = 0

Expand All @@ -255,15 +256,26 @@ const Header: FC<HeaderProps> = ({
const remainingItems = itemWidthsRef.current.length - (i + 1)
const needMoreMenu = remainingItems > 0

if (currentWidth + itemWidth + (needMoreMenu ? moreMenuWidth : 0) <= availableWidth) {
// Add the "More" menu width if there will be hidden items
const totalWidthNeeded = currentWidth + itemWidth + (needMoreMenu ? moreMenuWidth : 0)

if (totalWidthNeeded <= availableWidth) {
currentWidth += itemWidth
count = i + 1
} else {
break
}
}

setVisibleMenuItems(Math.max(1, count))
// Ensure we show at least one item
const finalCount = Math.max(1, Math.min(count, itemWidthsRef.current.length))

// If we're showing all items except one, show the more menu anyway
if (finalCount === itemWidthsRef.current.length - 1) {
setVisibleMenuItems(finalCount - 1)
} else {
setVisibleMenuItems(finalCount)
}
}

// Initial measurement and calculation
Expand All @@ -279,7 +291,7 @@ const Header: FC<HeaderProps> = ({
const resizeObserver = new ResizeObserver(recalculate)

// Observe the header element instead
const header = container.closest('.header')
const header = container.closest('.header_container')
if (header) {
resizeObserver.observe(header)
}
Expand Down Expand Up @@ -322,10 +334,10 @@ const Header: FC<HeaderProps> = ({
const activeFunction = commonFunctions.find((func) => func.id === activeCommonFunctionId)

return (
<div className='header-normal'>
<div className='header-left'>
<div className='header_normal'>
<div className='header_left'>
{/* Logo */}
<div className='header-logo'>
<div className='header_logo'>
<img src={global.app_info?.logo} alt='Logo' />
</div>

Expand All @@ -336,7 +348,7 @@ const Header: FC<HeaderProps> = ({
key: func.id,
label: (
<div
className={clsx('common-function-item', {
className={clsx('header_common_function_item', {
active: func.id === activeCommonFunctionId
})}
>
Expand All @@ -346,12 +358,12 @@ const Header: FC<HeaderProps> = ({
),
onClick: func.onClick
})),
className: 'common-functions-dropdown'
className: 'header_common_functions_dropdown'
}}
trigger={['hover']}
>
<div
className={clsx('current-function', {
className={clsx('header_current_function', {
active: !!activeCommonFunctionId
})}
>
Expand All @@ -364,21 +376,21 @@ const Header: FC<HeaderProps> = ({
</Dropdown>

{/* Hidden container for measurements */}
<div className='menu-items-measure' ref={measureContainerRef}>
<div className='header_menu_items_measure' ref={measureContainerRef}>
{menuItems.map((item) => (
<div key={item.id} className='menu-item'>
<div key={item.id} className='header_menu_item'>
{item.icon && <Icon name={item.icon} size={14} />}
<span>{item.name}</span>
</div>
))}
</div>

{/* Visible menu items */}
<div className='menu-items' ref={menuContainerRef}>
<div className='header_menu_items' ref={menuContainerRef}>
{finalVisibleItems.map((item) => (
<div
key={item.id}
className={clsx('menu-item', {
className={clsx('header_menu_item', {
active: item.isActive
})}
onClick={item.onClick}
Expand All @@ -394,7 +406,7 @@ const Header: FC<HeaderProps> = ({
key: item.id,
label: (
<div
className={clsx('menu-item', {
className={clsx('header_menu_item', {
active: item.isActive
})}
>
Expand All @@ -406,29 +418,29 @@ const Header: FC<HeaderProps> = ({
),
onClick: item.onClick
})),
className: 'more-menu-items'
className: 'header_more_menu_items'
}}
trigger={['hover']}
>
<div className='more-menu'>
<div className='header_more_menu'>
<Icon name='material-more_horiz' size={14} />
</div>
</Dropdown>
)}
</div>
</div>

<div className='header-right'>
<div className='header_right'>
<Tooltip title='Terminal'>
<Button
type='text'
className='header-icon-btn'
className='header_icon_btn'
icon={<Icon name='material-terminal' size={16} />}
/>
</Tooltip>
<Button
type='text'
className='header-icon-btn'
className='header_icon_btn'
icon={<Icon name='material-close' size={16} />}
onClick={closeSidebar}
/>
Expand All @@ -438,14 +450,14 @@ const Header: FC<HeaderProps> = ({
}

const renderTemporaryView = () => (
<div className='header-temporary'>
<div className='header-left'>
<span className='current-page'>{currentPageName}</span>
<div className='header_temporary'>
<div className='header_left'>
<span className='header_current_page'>{currentPageName}</span>
</div>
<div className='header-right'>
<div className='header_right'>
<Button
type='text'
className='header-icon-btn back-btn'
className='header_icon_btn back-btn'
style={{ marginRight: '2px', width: 'auto' }}
onClick={onBackToNormal}
>
Expand All @@ -454,15 +466,17 @@ const Header: FC<HeaderProps> = ({
</Button>
<Button
type='text'
className='header-icon-btn'
className='header_icon_btn'
icon={<Icon name='material-close' size={16} />}
onClick={closeSidebar}
/>
</div>
</div>
)

return <header className='header'>{isTemporaryView ? renderTemporaryView() : renderNormalMenu()}</header>
return (
<header className='header_container'>{isTemporaryView ? renderTemporaryView() : renderNormalMenu()}</header>
)
}

export default Header
24 changes: 12 additions & 12 deletions packages/xgen/layouts/wrappers/Chat/Container/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { FC, useState, useEffect, useRef } from 'react'
import { Input } from 'antd'
import Icon from '@/widgets/Icon'
import clsx from 'clsx'
import './styles.css'
import './menu.less'

interface MenuItem {
id: string
Expand Down Expand Up @@ -208,9 +208,9 @@ const MenuItem: FC<{
}

return (
<div className={clsx('menu-item-wrapper', `level-${level}`)}>
<div className={clsx('menu_item_wrapper', `level-${level}`)}>
<div
className={clsx('menu-item', {
className={clsx('menu_item', {
expanded: isExpanded,
'has-children': hasChildren,
active: isActive(item)
Expand All @@ -226,21 +226,21 @@ const MenuItem: FC<{
}
}}
>
<div className='menu-item-content'>
<div className='menu_item_content'>
{item.icon && <Icon name={item.icon} size={16} />}
{item.image && <img src={item.image} alt={item.name} className='menu-item-image' />}
<span className='menu-item-name'>{item.name}</span>
{item.image && <img src={item.image} alt={item.name} className='menu_item_image' />}
<span className='menu_item_name'>{item.name}</span>
</div>
{hasChildren && (
<Icon
name={isExpanded ? 'material-expand_less' : 'material-expand_more'}
size={16}
className={clsx('expand-icon', { active: isActive(item) })}
className={clsx('menu_expand_icon', { active: isActive(item) })}
/>
)}
</div>
{hasChildren && isExpanded && (
<div className='menu-children'>
<div className='menu_children'>
{item.children?.map((child) => (
<MenuItem
key={child.id}
Expand Down Expand Up @@ -277,16 +277,16 @@ const Menu: FC<MenuProps> = ({ isVisible = true, onToggle }) => {
}

return (
<aside className={clsx('menu', { hidden: !isVisible })} ref={menuRef}>
<div className='menu-search'>
<aside className={clsx('menu_container', { hidden: !isVisible })} ref={menuRef}>
<div className='menu_search'>
<Input
prefix={<Icon name='material-search' size={16} />}
placeholder='Search menu...'
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</div>
<div className='menu-items-container'>
<div className='menu_items_container'>
{testMenuItems.map((item) => (
<MenuItem
key={item.id}
Expand All @@ -301,7 +301,7 @@ const Menu: FC<MenuProps> = ({ isVisible = true, onToggle }) => {
))}
</div>
{isVisible && (
<button className='menu-toggle menu-toggle-close' onClick={onToggle}>
<button className='menu_toggle menu_toggle_close' onClick={onToggle}>
<Icon name='material-first_page' size={16} />
</button>
)}
Expand Down
Loading

0 comments on commit 6e4cc47

Please sign in to comment.