Lots of mobile and desktop edit view tweaks

This commit is contained in:
James Ketr 2025-07-19 14:23:28 -07:00
parent 97272d9175
commit 064868e96e
6 changed files with 505 additions and 350 deletions

View File

@ -6,8 +6,9 @@ import React, {
useState,
useImperativeHandle,
} from 'react';
import { useTheme } from '@mui/material/styles';
import { SxProps, useTheme } from '@mui/material/styles';
import './BackstoryTextField.css';
import { Box } from '@mui/material';
// Define ref interface for exposed methods
interface BackstoryTextFieldRef {
@ -23,11 +24,12 @@ interface BackstoryTextFieldProps {
onEnter?: (value: string) => void;
onChange?: (value: string) => void;
style?: CSSProperties;
sx?: SxProps;
}
const BackstoryTextField = React.forwardRef<BackstoryTextFieldRef, BackstoryTextFieldProps>(
(props, ref) => {
const { value = '', disabled = false, placeholder, onEnter, onChange, style } = props;
const { value = '', disabled = false, placeholder, onEnter, onChange, style, sx } = props;
const theme = useTheme();
const textareaRef = useRef<HTMLTextAreaElement>(null);
const shadowRef = useRef<HTMLTextAreaElement>(null);
@ -115,7 +117,7 @@ const BackstoryTextField = React.forwardRef<BackstoryTextFieldRef, BackstoryText
};
return (
<>
<Box sx={{ display: 'flex', flexGrow: 1, boxSizing: 'border-box', p: 1, ...sx }}>
<textarea
className="BackstoryTextField"
ref={textareaRef}
@ -148,7 +150,7 @@ const BackstoryTextField = React.forwardRef<BackstoryTextFieldRef, BackstoryText
readOnly
tabIndex={-1}
/>
</>
</Box>
);
}
);

View File

@ -5,13 +5,11 @@ import {
Typography,
SxProps,
Chip,
Stack,
CardHeader,
LinearProgress,
IconButton,
Tooltip,
} from '@mui/material';
import { Card, CardContent, Divider, useTheme } from '@mui/material';
import { useTheme } from '@mui/material';
import DeleteIcon from '@mui/icons-material/Delete';
import CloseIcon from '@mui/icons-material/Close';
import { useMediaQuery } from '@mui/material';
@ -128,7 +126,7 @@ const JobInfo: React.FC<JobInfoProps> = (props: JobInfoProps) => {
if (!items || items.length === 0) return <></>;
return (
<Box sx={{ mb: 2 }}>
<Box sx={{ mb: 2, display: 'flex', position: 'relative', flexDirection: 'column' }}>
<Box sx={{ display: 'flex', alignItems: 'center', mb: 1.5 }}>
{icon}
<Typography
@ -146,17 +144,22 @@ const JobInfo: React.FC<JobInfoProps> = (props: JobInfoProps) => {
/>
)}
</Box>
<Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap>
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5, position: 'relative' }}>
{items.map((item, index) => (
<Chip
<Box
key={index}
label={item}
variant="outlined"
size="small"
sx={{ mb: 1, fontSize: '0.75rem !important' }}
/>
sx={{
border: '1px solid grey',
p: 0.5,
borderRadius: 1,
fontSize: '0.75rem !important',
display: 'flex',
}}
>
{item}
</Box>
))}
</Stack>
</Box>
</Box>
);
};
@ -165,13 +168,24 @@ const JobInfo: React.FC<JobInfoProps> = (props: JobInfoProps) => {
if (!activeJob.requirements) return <></>;
return (
<Card elevation={0} sx={{ m: 0, p: 0, mt: 2, background: 'transparent !important' }}>
<CardHeader
title="Job Requirements Analysis"
avatar={<CheckCircle color="success" />}
sx={{ p: 0, pb: 1 }}
/>
<CardContent sx={{ p: 0 }}>
<Box
sx={{
maxWidth: '100%',
position: 'relative',
m: 0,
p: 0,
background: 'transparent !important',
display: 'flex',
flexDirection: 'column',
}}
>
<Box
sx={{ p: 0, pb: 1, alignItems: 'center', display: 'flex', flexDirection: 'row', gap: 1 }}
>
<CheckCircle color="success" />
<Box>Job Requirements Analysis</Box>
</Box>
<Box sx={{ p: 0 }}>
{renderRequirementSection(
'Technical Skills (Required)',
activeJob.requirements.technicalSkills.required,
@ -219,8 +233,8 @@ const JobInfo: React.FC<JobInfoProps> = (props: JobInfoProps) => {
activeJob.requirements.preferredAttributes,
<Star color="secondary" />
)}
</CardContent>
</Card>
</Box>
</Box>
);
};
@ -232,9 +246,9 @@ const JobInfo: React.FC<JobInfoProps> = (props: JobInfoProps) => {
borderColor: 'transparent',
borderWidth: 2,
borderStyle: 'solid',
transition: 'all 0.3s ease',
flexDirection: 'column',
minWidth: 0,
maxWidth: '100%',
opacity: deleted ? 0.5 : 1.0,
backgroundColor: deleted
? theme.palette.action.disabledBackground
@ -273,6 +287,7 @@ const JobInfo: React.FC<JobInfoProps> = (props: JobInfoProps) => {
whiteSpace: 'nowrap',
},
'& > div > div > :last-of-type': { mb: 0.75, mr: 1 },
position: 'relative',
}}
>
<Box
@ -401,12 +416,7 @@ const JobInfo: React.FC<JobInfoProps> = (props: JobInfoProps) => {
<StyledMarkdown sx={{ display: 'flex' }} content={activeJob.description} />
)}
{variant !== 'small' && variant !== 'minimal' && (
<Box>
<Divider />
{renderJobRequirements()}
</Box>
)}
{variant !== 'small' && variant !== 'minimal' && renderJobRequirements()}
{isAdmin && (
<Box sx={{ display: 'flex', flexDirection: 'column', p: 1 }}>

View File

@ -20,7 +20,7 @@ import { useAppState, useSelectedCandidate } from 'hooks/GlobalContext';
import PropagateLoader from 'react-spinners/PropagateLoader';
import { BackstoryTextField, BackstoryTextFieldRef } from 'components/BackstoryTextField';
import { Scrollable } from 'components/Scrollable';
import { StyledMarkdown } from './StyledMarkdown';
import { StyledMarkdown } from '../StyledMarkdown';
const emptyMetadata: ChatMessageMetaData = {
model: 'qwen2.5',
@ -259,6 +259,7 @@ const ResumeChat = forwardRef<ConversationHandle, ResumeChatProps>(
return (
<Box
className="ResumeChat"
ref={ref}
sx={{
display: 'flex',
@ -358,7 +359,18 @@ const ResumeChat = forwardRef<ConversationHandle, ResumeChatProps>(
</Scrollable>
)}
{/* Fixed Message Input */}
<Box sx={{ display: 'flex', flexShrink: 1, gap: 1 }}>
<Box
sx={{
display: 'flex',
flexGrow: 1,
gap: 1,
position: 'relative',
width: '100%',
minWidth: '100%',
flexDirection: 'row',
overflow: 'hidden',
}}
>
<DeleteConfirmation
onDelete={(): void => {
chatSession && onDelete(chatSession);

View File

@ -7,19 +7,19 @@ import {
IconButton,
Tooltip,
Tabs,
Tab,
Paper,
FormControl,
Select,
MenuItem,
InputLabel,
Chip,
Alert,
Stack,
SelectChangeEvent,
useTheme,
useMediaQuery,
} from '@mui/material';
import PrintIcon from '@mui/icons-material/Print';
import DifferenceIcon from '@mui/icons-material/Difference';
import ForumIcon from '@mui/icons-material/Forum';
import {
Save as SaveIcon,
ModelTraining,
@ -42,10 +42,12 @@ import { Scrollable } from 'components/Scrollable';
import * as Types from 'types/types';
import { StreamingOptions } from 'services/api-client';
import { StatusBox, StatusIcon } from './StatusIcon';
import { ResumeChat } from 'components/ResumeChat';
import { ResumeChat } from 'components/ui/ResumeChat';
import { DiffViewer } from 'components/DiffViewer';
import { ResumePreview, resumeStyles } from './ResumePreview';
import { useAppState } from 'hooks/GlobalContext';
import { useNavigate } from 'react-router-dom';
import { TabWithTooltip } from './TabWithTooltip';
interface ResumeRevision {
revisionId: string;
@ -65,13 +67,17 @@ interface ResumeEditProps {
const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
const { setSnack } = useAppState();
const { onClose, resumeId, onSave } = props;
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const isLarge = useMediaQuery(theme.breakpoints.up('md'));
const navigate = useNavigate();
const { selectedCandidate, selectedJob } = useAppState();
const { apiClient } = useAuth();
const [editContent, setEditContent] = useState<string>('');
const [saving, setSaving] = useState<boolean>(false);
const [tabValue, setTabValue] = useState('markdown');
const [jobTabValue, setJobTabValue] = useState('chat');
const [leftColumn, setLeftColumn] = useState('markdown');
const [rightColumn, setRightColumn] = useState('chat');
const [status, setStatus] = useState<string>('');
const [statusType, setStatusType] = useState<Types.ApiActivityType | null>(null);
const [error, setError] = useState<Types.ChatMessageError | null>(null);
@ -79,6 +85,7 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
const [resume, setResume] = useState<Resume | null>(null);
const [isAIGenerated, setIsAIGenerated] = useState<boolean>(false);
const [editPrompt, setEditPrompt] = useState<string>('');
const [columnView, setColumnView] = useState<'left' | 'right'>('left');
// Revision-related state
const [revisions, setRevisions] = useState<ResumeRevision[]>([]);
@ -325,7 +332,8 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
return generatedResume;
};
const handleTabChange = (event: React.SyntheticEvent, newValue: string): void => {
const handleLeftColumnChange = (event: React.SyntheticEvent, newValue: string): void => {
setColumnView('left');
if (newValue === 'print') {
console.log('Printing resume...');
reactToPrintFn();
@ -333,7 +341,7 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
}
if (newValue === 'regenerate') {
setSnack('Regenerating resume...');
setTabValue('markdown');
setLeftColumn('markdown');
generateResume();
return;
}
@ -341,14 +349,15 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
setEditContent(current?.resume || '');
setEditPrompt(current?.prompt || '');
setIsAIGenerated(current?.aiGenerated || false);
setTabValue('markdown');
setLeftColumn('markdown');
return;
}
setTabValue(newValue);
setLeftColumn(newValue);
};
const handleJobTabChange = (event: React.SyntheticEvent, newValue: string): void => {
setJobTabValue(newValue);
const handleRightColumnChange = (event: React.SyntheticEvent, newValue: string): void => {
setColumnView('right');
setRightColumn(newValue);
};
const handleClose = (): void => {
@ -359,12 +368,10 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
(selectedRevision !== 'current' && resume?.aiGenerated ? resume?.prompt : '') ||
(isAIGenerated ? editPrompt : '') ||
'Manual edits';
console.log(
`Change log: ${changeLog}, isAIGenerated: ${isAIGenerated}, editPrompt: ${editPrompt}, selectedRevision: ${selectedRevision}, resume?.aiGenerated: ${resume?.aiGenerated}`
);
return (
<Box
className="ResumeEdit"
sx={{
display: 'flex',
flexGrow: 1,
@ -375,6 +382,7 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
}}
>
<Box
className="ResumeEditHeader"
sx={{
display: 'flex',
flexDirection: 'row',
@ -384,7 +392,14 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
}}
>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Box sx={{ display: 'flex', flexDirection: 'row', gap: 1 }}>
<Box
sx={{
display: 'flex',
flexDirection: isMobile ? 'column' : 'row',
gap: 2,
flexWrap: 'wrap',
}}
>
<Box
sx={{
display: 'flex',
@ -392,7 +407,7 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
gap: 0.5,
m: 0,
p: 0,
minWidth: '25rem',
minWidth: '20rem',
}}
>
{resume && (
@ -402,8 +417,21 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
{resume.job?.title || 'No Job Title Assigned'},{' '}
{resume.job?.company || 'No Company Assigned'}
</Typography>
<Typography variant="caption" display="block" color="text.secondary">
Resume ID: {resume.id}
<Typography
variant="caption"
display="block"
color="text.secondary"
sx={{ display: 'flex', flexDirection: 'row' }}
>
Resume ID:{' '}
<Box
sx={{ cursor: 'pointer', textDecoration: 'underline' }}
onClick={() => {
navigate(`/chat/${resume.id}`);
}}
>
{resume.id}
</Box>
</Typography>
</>
)}
@ -413,7 +441,7 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
</Typography>
)}
</Box>
<Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 1, flexWrap: 'wrap' }}>
{/* Style Selector */}
<FormControl size="small" sx={{ minWidth: 'min-content' }}>
<InputLabel id="resume-style-label">Resume Style</InputLabel>
@ -444,8 +472,7 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
</Select>
</FormControl>
<Box sx={{ display: 'flex', flexDirection: 'row' }}>
<Stack direction="row" spacing={2} alignItems="center">
<Box sx={{ display: 'flex', flexDirection: 'row', gap: 1 }}>
<FormControl size="small" sx={{ minWidth: 200 }}>
<InputLabel id="revision-select-label">
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
@ -518,13 +545,13 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
</Tooltip>
</>
)}
</Stack>
</Box>
</Box>
</Box>
</Box>
</Box>
<Box
className="ResumeEditContent"
sx={{
position: 'relative',
display: 'flex',
@ -533,52 +560,83 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
height: '100%',
}}
>
<Box
<Box className="ResumeEditTabs" sx={{ display: 'flex', m: 0, p: 0 }}>
<Tabs
value={isLarge ? leftColumn : columnView === 'left' ? leftColumn : undefined}
onChange={handleLeftColumnChange}
sx={{
display: 'flex',
flexDirection: 'row',
height: '100%',
gap: 1,
pt: 1,
width: '100%',
position: 'relative',
overflow: 'hidden',
'& .MuiTab-root': {
minWidth: 'fit-content',
width: 'fit-content',
fontSize: isLarge ? '0.6rem' : '0.5rem',
},
}}
>
<Paper
sx={{
flex: 1,
display: 'flex',
flexDirection: 'column',
position: 'relative',
maxWidth: '100%',
height: '100%',
overflow: 'hidden',
alignItems: 'center',
}}
>
<Box sx={{ display: 'flex', m: 0, p: 0 }}>
<Tabs value={tabValue} onChange={handleTabChange}>
<Tab value="markdown" icon={<EditDocumentIcon />} label="Markdown" />
<Tab
<TabWithTooltip
tooltip="Markdown Editor"
value="markdown"
icon={<EditDocumentIcon />}
label={isLarge ? 'Markdown' : ''}
/>
<TabWithTooltip
tooltip="View Changes"
value="diff"
disabled={editContent === current?.resume}
icon={<DifferenceIcon />}
label="Changes"
label={isLarge ? 'Changes' : undefined}
/>
<Tab value="preview" icon={<PreviewIcon />} label="Preview" />
<Tab
disabled={tabValue !== 'preview'}
<TabWithTooltip
tooltip="Preview Resume"
value="preview"
icon={<PreviewIcon />}
label={isLarge ? 'Preview' : undefined}
/>
<TabWithTooltip
tooltip="Print Resume"
disabled={leftColumn !== 'preview'}
value="print"
icon={<PrintIcon />}
label="Print"
label={isLarge ? 'Print' : undefined}
/>
<Tab value="regenerate" icon={<ModelTraining />} label="Regenerate" />
<Tab
<TabWithTooltip
tooltip="Regenerate Resume"
value="regenerate"
icon={<ModelTraining />}
label={isLarge ? 'Regenerate' : undefined}
/>
<TabWithTooltip
tooltip="Undo Changes"
value="undo"
disabled={editContent === resume?.resume}
icon={<UndoIcon />}
label="Revert"
label={isLarge ? 'Revert' : undefined}
/>
</Tabs>
<Tabs
value={isLarge ? rightColumn : columnView === 'right' ? rightColumn : undefined}
onChange={handleRightColumnChange}
sx={{
'& .MuiTab-root': {
minWidth: 'fit-content',
width: 'fit-content',
fontSize: isLarge ? '0.6rem' : '0.5rem',
},
borderLeft: isLarge ? '1px solid #ccc' : 'none',
}}
>
{resume && resume.job !== undefined && (
<TabWithTooltip
tooltip="Job"
value="job"
icon={<WorkIcon />}
label={isLarge ? 'Job' : ''}
/>
)}
<TabWithTooltip
tooltip="AI Edit"
value="chat"
icon={<ForumIcon />}
label={isLarge ? 'AI Edit' : ''}
/>
</Tabs>
</Box>
@ -595,6 +653,31 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
</Box>
)}
<Box
sx={{
display: 'flex',
flexDirection: 'row',
height: '100%',
gap: 1,
pt: 1,
width: '100%',
position: 'relative',
overflow: 'hidden',
}}
>
{(isLarge || columnView === 'left') && (
<Box
sx={{
flex: 1,
display: 'flex',
flexDirection: 'column',
position: 'relative',
maxWidth: '100%',
height: '100%',
overflow: 'hidden',
alignItems: 'center',
}}
>
<Box
sx={{
display: 'flex',
@ -609,15 +692,15 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
>
{selectedRevision !== 'current' && (
<Alert severity="info" sx={{ width: '100%' }}>
You are viewing a previous version. Click &quot;Restore&quot; to load this content
into the editor.
You are viewing a previous version. Click &quot;Restore&quot; to load this
content into the editor.
</Alert>
)}
{isAIGenerated && (
<Alert severity="warning" sx={{ width: '100%' }}>
This resume was generated by AI and has not been manually edited. Review and then
selecte &apos;Save&apos;.
This resume was generated by AI and has not been manually edited. Review and
then selecte &apos;Save&apos;.
</Alert>
)}
</Box>
@ -635,7 +718,7 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
position: 'relative',
}}
>
{tabValue === 'markdown' && (
{leftColumn === 'markdown' && (
<>
{selectedRevision === 'current' ? (
<BackstoryTextField
@ -681,17 +764,18 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
)}
</>
)}
{tabValue === 'diff' && current && (
{leftColumn === 'diff' && current && (
<DiffViewer
changeLog={changeLog}
original={{ content: current.resume || '', name: 'original' }}
modified={{
content: selectedRevision !== 'current' && resume ? resume.resume : editContent,
content:
selectedRevision !== 'current' && resume ? resume.resume : editContent,
name: 'modified',
}}
/>
)}
{tabValue === 'preview' && resume && resume.candidate && (
{leftColumn === 'preview' && resume && resume.candidate && (
<Box
className="document-container"
ref={printContentRef}
@ -701,44 +785,68 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
</Box>
)}
</Scrollable>
</Paper>
{resume && (
<Box
sx={{
display: 'flex',
flexDirection: 'row',
gap: 1,
alignItems: 'center',
p: 1,
}}
>
{onClose && <Button onClick={handleClose}>Cancel</Button>}
<Button
onClick={() => {
handleSave();
}}
variant="contained"
disabled={saveDisabled}
startIcon={<SaveIcon />}
>
{saving ? 'Saving...' : 'Save'}
</Button>
<Typography variant="caption" display="block" color="text.secondary">
Last saved:{' '}
{resume.updatedAt ? new Date(resume.updatedAt).toLocaleString() : 'N/A'}
</Typography>
</Box>
)}
</Box>
)}
{(isLarge || columnView === 'right') && (
<Box
sx={{
display: 'flex',
flexDirection: 'column',
flex: 1,
position: 'relative',
width: '100%',
}}
>
<Scrollable
sx={{
flex: 1,
display: 'flex',
height: '100%',
width: '100%',
overflowY: 'auto',
position: 'relative',
}}
>
<Paper
sx={{
p: 1,
flex: 1,
display: 'flex',
flexDirection: 'column',
position: 'relative',
overflow: 'hidden',
}}
>
<Tabs value={jobTabValue} onChange={handleJobTabChange}>
{resume && resume.job !== undefined && (
<Tab value="job" icon={<WorkIcon />} label="Job" />
{resume && rightColumn === 'job' && (
<>
{resume.job !== undefined ? (
<JobInfo variant={'all'} job={resume.job} />
) : (
<Box>No matching job found.</Box>
)}
<Tab value="chat" icon={<ModelTraining />} label="AI Edit" />
</Tabs>
{resume && resume.job !== undefined && jobTabValue === 'job' && (
<JobInfo
variant={'all'}
job={resume.job}
sx={{
m: 0,
p: 1,
backgroundColor: '#f8f0e0',
}}
/>
</>
)}
{jobTabValue === 'chat' && resume && (
{rightColumn === 'chat' && resume && (
<ResumeChat
session={resume.id || ''}
resume={editContent}
@ -756,36 +864,15 @@ const ResumeEdit: React.FC<ResumeEditProps> = (props: ResumeEditProps) => {
p: 1,
flexGrow: 1,
position: 'relative',
maxWidth: 'fit-content',
minWidth: '100%',
}}
/>
)}
</Paper>
</Scrollable>
</Box>
</Box>
{resume && (
<Box
sx={{ display: 'flex', flexDirection: 'row', gap: 1, alignItems: 'center', pl: 1, pt: 1 }}
>
{onClose && <Button onClick={handleClose}>Cancel</Button>}
<Button
onClick={() => {
handleSave();
}}
variant="contained"
disabled={saveDisabled}
startIcon={<SaveIcon />}
>
{saving ? 'Saving...' : 'Save'}
</Button>
<Typography variant="caption" display="block" color="text.secondary">
Last saved: {resume.updatedAt ? new Date(resume.updatedAt).toLocaleString() : 'N/A'}
</Typography>
</Box>
)}
</Box>
</Box>
</Box>
);
};

View File

@ -528,9 +528,9 @@ const ResumeViewer: React.FC<ResumeViewerProps> = ({ onSelect, candidateId, jobI
if (mode === 'edit' && selectedResume) {
return (
<ResumeEdit
onClose={() => {
navigate(window.location.pathname.replace('/edit', ''));
}}
// onClose={() => {
// navigate(window.location.pathname.replace('/edit', ''));
// }}
resumeId={selectedResume.id}
onSave={handleSave}
/>

View File

@ -0,0 +1,44 @@
import React from 'react';
import { Tab, Tooltip, TabProps } from '@mui/material';
interface TabWithTooltipProps extends TabProps {
tooltip: string;
showTooltip?: boolean; // Optional prop to control when tooltip shows
}
const TabWithTooltip: React.FC<TabWithTooltipProps> = ({
tooltip,
showTooltip = true,
disabled = false,
children,
...tabProps
}) => {
const tabElement = (
<Tab disabled={disabled} {...tabProps}>
{children}
</Tab>
);
// Don't show tooltip if showTooltip is false
if (!showTooltip) {
return tabElement;
}
// For disabled tabs, wrap in span since Tooltip doesn't work on disabled elements
if (disabled) {
return (
<Tooltip title={tooltip} placement="bottom">
<span style={{ display: 'inline-block' }}>{tabElement}</span>
</Tooltip>
);
}
// Normal case with tooltip
return (
<Tooltip title={tooltip} placement="bottom">
{tabElement}
</Tooltip>
);
};
export { TabWithTooltip };