f6752130ac
Reproduce the maintainer-provided ContainerLogs mockup faithfully: dark card (#0c0c0d), his header + single toolbar row styling, his custom search box / 'Filter search results' checkbox / Copy+Download buttons, his toggle-button style (Line numbers / Timestamp / Wrap — no Auto refresh), and the dark log area with a right-aligned line-number gutter. Palette carried inline in this one component (deliberate dark log-viewer design). Deviations from the mockup, by design: fonts/sizes use the project scale and monospace (no Google Fonts / hardcoded Inter/JetBrains); real streaming data via useLogViewer rendered as safe React span nodes (no dangerouslySetInnerHTML); mock page chrome dropped (Portainer's page provides breadcrumb/title); the datetime range keeps the functional react-datetimerange-picker. Live-tails by default; selecting an upper bound in the range picker shows a bounded snapshot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
64 lines
1.7 KiB
TypeScript
64 lines
1.7 KiB
TypeScript
import { ComponentType, CSSProperties } from 'react';
|
|
|
|
import { AutomationTestingProps } from '@/types';
|
|
|
|
interface Props extends AutomationTestingProps {
|
|
active: boolean;
|
|
onChange: (active: boolean) => void;
|
|
label: string;
|
|
/** A lucide-style icon component (rendered at a small fixed size). */
|
|
icon: ComponentType<{ size?: number | string }>;
|
|
title?: string;
|
|
}
|
|
|
|
// Toggle pill matching the maintainer's log-viewer mockup: rounded, icon + label,
|
|
// active = lighter border/background/text, inactive = transparent + muted colors.
|
|
// Font family/size are left to the project (text-xs + inherited UI font) instead
|
|
// of the mockup's hardcoded Inter/13px.
|
|
function toggleStyle(active: boolean): CSSProperties {
|
|
return {
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 7,
|
|
height: 36,
|
|
padding: '0 13px',
|
|
borderRadius: 8,
|
|
fontWeight: 500,
|
|
cursor: 'pointer',
|
|
whiteSpace: 'nowrap',
|
|
border: `1px solid ${active ? '#6a6f76' : '#3a3d42'}`,
|
|
background: active ? 'rgba(255,255,255,0.04)' : 'transparent',
|
|
color: active ? '#f2f4f5' : '#9aa1a8',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* An independent on/off toggle rendered as a real <button> with `aria-pressed`.
|
|
* The viewer's Line numbers / Timestamp / Wrap lines controls are independent
|
|
* toggles (not a single-select segmented control), so each is its own
|
|
* ToggleButton.
|
|
*/
|
|
export function ToggleButton({
|
|
active,
|
|
onChange,
|
|
label,
|
|
icon: Icon,
|
|
title,
|
|
'data-cy': dataCy,
|
|
}: Props) {
|
|
return (
|
|
<button
|
|
type="button"
|
|
className="text-xs"
|
|
style={toggleStyle(active)}
|
|
title={title}
|
|
aria-pressed={active}
|
|
onClick={() => onChange(!active)}
|
|
data-cy={dataCy}
|
|
>
|
|
<Icon size={14} />
|
|
{label}
|
|
</button>
|
|
);
|
|
}
|