feat: add position prop to ClaudeLogsSection for flexible rendering
- Introduced an optional `position` prop to the ClaudeLogsSection component, allowing it to be rendered in either 'sidebar' or 'inline' formats. - Updated the TeamDetailView to utilize the new `position` prop, ensuring consistent layout in the sidebar. - Enhanced styling in ClaudeLogsSection to adapt based on the position, improving overall UI consistency and user experience.
This commit is contained in:
parent
b76be0f634
commit
daae1ba82b
3 changed files with 18 additions and 7 deletions
|
|
@ -22,6 +22,7 @@ type StreamType = 'stdout' | 'stderr';
|
||||||
|
|
||||||
interface ClaudeLogsSectionProps {
|
interface ClaudeLogsSectionProps {
|
||||||
teamName: string;
|
teamName: string;
|
||||||
|
position?: 'sidebar' | 'inline';
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRecent(updatedAt: string | undefined): boolean {
|
function isRecent(updatedAt: string | undefined): boolean {
|
||||||
|
|
@ -367,7 +368,10 @@ function filterStreamJsonText(
|
||||||
return out.join('\n');
|
return out.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ClaudeLogsSection = ({ teamName }: ClaudeLogsSectionProps): React.JSX.Element => {
|
export const ClaudeLogsSection = ({
|
||||||
|
teamName,
|
||||||
|
position = 'inline',
|
||||||
|
}: ClaudeLogsSectionProps): React.JSX.Element => {
|
||||||
const isAlive = useStore((s) => s.selectedTeamData?.isAlive ?? false);
|
const isAlive = useStore((s) => s.selectedTeamData?.isAlive ?? false);
|
||||||
const [loadedCount, setLoadedCount] = useState(PAGE_SIZE);
|
const [loadedCount, setLoadedCount] = useState(PAGE_SIZE);
|
||||||
const [data, setData] = useState<TeamClaudeLogsResponse>({ lines: [], total: 0, hasMore: false });
|
const [data, setData] = useState<TeamClaudeLogsResponse>({ lines: [], total: 0, hasMore: false });
|
||||||
|
|
@ -390,6 +394,7 @@ export const ClaudeLogsSection = ({ teamName }: ClaudeLogsSectionProps): React.J
|
||||||
kinds: new Set(DEFAULT_CLAUDE_LOGS_FILTER.kinds),
|
kinds: new Set(DEFAULT_CLAUDE_LOGS_FILTER.kinds),
|
||||||
}));
|
}));
|
||||||
const [filterOpen, setFilterOpen] = useState(false);
|
const [filterOpen, setFilterOpen] = useState(false);
|
||||||
|
const isSidebar = position === 'sidebar';
|
||||||
const isNearBottom = useCallback(
|
const isNearBottom = useCallback(
|
||||||
(scrollTop: number, scrollHeight: number, clientHeight: number) => {
|
(scrollTop: number, scrollHeight: number, clientHeight: number) => {
|
||||||
return scrollHeight - scrollTop - clientHeight <= LOAD_MORE_THRESHOLD_PX;
|
return scrollHeight - scrollTop - clientHeight <= LOAD_MORE_THRESHOLD_PX;
|
||||||
|
|
@ -571,10 +576,15 @@ export const ClaudeLogsSection = ({ teamName }: ClaudeLogsSectionProps): React.J
|
||||||
<CollapsibleTeamSection
|
<CollapsibleTeamSection
|
||||||
sectionId="claude-logs"
|
sectionId="claude-logs"
|
||||||
title="Claude logs"
|
title="Claude logs"
|
||||||
icon={<Terminal size={14} />}
|
icon={
|
||||||
|
<span className="inline-flex h-5 w-5 items-center justify-center rounded-md border border-[var(--color-border)] bg-[var(--color-bg-secondary)] text-[var(--color-text-secondary)] shadow-sm">
|
||||||
|
<Terminal size={12} />
|
||||||
|
</span>
|
||||||
|
}
|
||||||
badge={badge}
|
badge={badge}
|
||||||
|
headerContentClassName={isSidebar ? 'flex-wrap items-center gap-y-1 py-1' : undefined}
|
||||||
headerExtra={
|
headerExtra={
|
||||||
<>
|
<span className={cn('flex min-w-0 items-center gap-2', isSidebar && 'basis-full pt-0.5')}>
|
||||||
{online ? (
|
{online ? (
|
||||||
<span
|
<span
|
||||||
className="pointer-events-none relative inline-flex size-2 shrink-0"
|
className="pointer-events-none relative inline-flex size-2 shrink-0"
|
||||||
|
|
@ -585,7 +595,7 @@ export const ClaudeLogsSection = ({ teamName }: ClaudeLogsSectionProps): React.J
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
{lastLogPreview ? <LogPreviewInline preview={lastLogPreview} /> : null}
|
{lastLogPreview ? <LogPreviewInline preview={lastLogPreview} /> : null}
|
||||||
</>
|
</span>
|
||||||
}
|
}
|
||||||
defaultOpen={false}
|
defaultOpen={false}
|
||||||
// Prevent scroll anchoring from "pulling" the parent container when logs update.
|
// Prevent scroll anchoring from "pulling" the parent container when logs update.
|
||||||
|
|
|
||||||
|
|
@ -964,9 +964,10 @@ export const TeamDetailView = ({ teamName }: TeamDetailViewProps): React.JSX.Ele
|
||||||
>
|
>
|
||||||
<div className="flex size-full min-h-0 flex-col overflow-hidden bg-[var(--color-surface)]">
|
<div className="flex size-full min-h-0 flex-col overflow-hidden bg-[var(--color-surface)]">
|
||||||
<div className="shrink-0 overflow-hidden px-3">
|
<div className="shrink-0 overflow-hidden px-3">
|
||||||
<ClaudeLogsSection teamName={teamName} />
|
<ClaudeLogsSection teamName={teamName} position="sidebar" />
|
||||||
</div>
|
</div>
|
||||||
<div className="min-h-0 flex-1 border-t border-[var(--color-border)]">
|
<div className="bg-[var(--color-text-muted)]/35 mx-3 h-px shrink-0" />
|
||||||
|
<div className="min-h-0 flex-1">
|
||||||
<MessagesPanel
|
<MessagesPanel
|
||||||
teamName={teamName}
|
teamName={teamName}
|
||||||
position="sidebar"
|
position="sidebar"
|
||||||
|
|
|
||||||
|
|
@ -366,7 +366,7 @@ export const MessagesPanel = ({
|
||||||
return (
|
return (
|
||||||
<div className="flex size-full flex-col overflow-hidden bg-[var(--color-surface)]">
|
<div className="flex size-full flex-col overflow-hidden bg-[var(--color-surface)]">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex shrink-0 items-center gap-2 border-b border-[var(--color-border)] px-3 py-2">
|
<div className="flex shrink-0 items-center gap-2 border-b border-[var(--color-border)] bg-[var(--color-section-bg)] px-3 py-2">
|
||||||
<MessageSquare size={14} className="shrink-0 text-[var(--color-text-muted)]" />
|
<MessageSquare size={14} className="shrink-0 text-[var(--color-text-muted)]" />
|
||||||
<span className="text-sm font-medium text-[var(--color-text)]">Messages</span>
|
<span className="text-sm font-medium text-[var(--color-text)]">Messages</span>
|
||||||
{filteredMessages.length > 0 && (
|
{filteredMessages.length > 0 && (
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue