style: overlay scroller
This commit is contained in:
@@ -8,7 +8,7 @@ import React, {
|
||||
useRef,
|
||||
useState
|
||||
} from 'react';
|
||||
import TitleTip from './title-tip';
|
||||
import { TooltipOverlayScroller } from '../overlay-scroller';
|
||||
|
||||
// type TagProps = React.ComponentProps<typeof Tag>;
|
||||
|
||||
@@ -91,23 +91,12 @@ const AutoTooltip: React.FC<AutoTooltipProps> = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
overlayInnerStyle={{ paddingInline: 0 }}
|
||||
destroyTooltipOnHide={false}
|
||||
title={
|
||||
isOverflowing || showTitle ? (
|
||||
<TitleTip
|
||||
isOverflowing={isOverflowing}
|
||||
title={title}
|
||||
showTitle={showTitle}
|
||||
>
|
||||
{children}
|
||||
</TitleTip>
|
||||
) : (
|
||||
false
|
||||
)
|
||||
}
|
||||
{...tooltipProps}
|
||||
<TooltipOverlayScroller
|
||||
toolTipProps={{
|
||||
...tooltipProps,
|
||||
destroyTooltipOnHide: false
|
||||
}}
|
||||
title={isOverflowing || showTitle ? children : false}
|
||||
>
|
||||
{ghost ? (
|
||||
<div ref={contentRef} style={tagStyle} data-overflow={isOverflowing}>
|
||||
@@ -139,7 +128,7 @@ const AutoTooltip: React.FC<AutoTooltipProps> = ({
|
||||
{children}
|
||||
</Tag>
|
||||
)}
|
||||
</Tooltip>
|
||||
</TooltipOverlayScroller>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import useOverlayScroller from '@/hooks/use-overlay-scroller';
|
||||
import { OverlayScroller } from '@/components/overlay-scroller';
|
||||
import React from 'react';
|
||||
|
||||
interface TitleTipProps {
|
||||
@@ -10,27 +10,18 @@ interface TitleTipProps {
|
||||
|
||||
const TitleTip: React.FC<TitleTipProps> = (props) => {
|
||||
const { isOverflowing, showTitle, title, children } = props;
|
||||
const { initialize } = useOverlayScroller();
|
||||
const scrollRef = React.useRef<any>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (scrollRef.current) {
|
||||
initialize(scrollRef.current);
|
||||
}
|
||||
}, [initialize, scrollRef.current]);
|
||||
|
||||
return (
|
||||
<div style={{ maxHeight: 200, overflowY: 'auto' }} ref={scrollRef}>
|
||||
<OverlayScroller maxHeight={200}>
|
||||
<div
|
||||
style={{
|
||||
width: 'fit-content',
|
||||
maxWidth: 'var(--width-tooltip-max)',
|
||||
paddingInline: 8
|
||||
maxWidth: 'var(--width-tooltip-max)'
|
||||
}}
|
||||
>
|
||||
{isOverflowing || showTitle ? title || children : ''}
|
||||
</div>
|
||||
</div>
|
||||
</OverlayScroller>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -13,24 +13,9 @@
|
||||
padding-inline: 12px 10px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: rgb(56, 56, 56);
|
||||
|
||||
.ant-select-selector {
|
||||
background-color: rgba(255, 255, 255, 9%) !important;
|
||||
color: rgba(255, 255, 255, 70%);
|
||||
border-radius: var(--border-radius-2px);
|
||||
|
||||
.ant-select-selection-item {
|
||||
color: rgba(255, 255, 255, 70%);
|
||||
}
|
||||
}
|
||||
|
||||
.ant-select-arrow {
|
||||
color: rgba(255, 255, 255, 70%);
|
||||
}
|
||||
background-color: var(--color-editor-header-bg);
|
||||
}
|
||||
// set scrollbar style
|
||||
|
||||
.scrollbar {
|
||||
.slider {
|
||||
border-radius: 6px;
|
||||
|
||||
@@ -36,7 +36,7 @@ const CodeHeaderWrapper = styled.div`
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
&.dark {
|
||||
background-color: #383838;
|
||||
background-color: var(--color-editor-header-bg);
|
||||
color: rgba(255, 255, 255, 0.65);
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -9,6 +9,7 @@ const HighlightCode: React.FC<{
|
||||
lang?: string;
|
||||
copyable?: boolean;
|
||||
theme?: 'light' | 'dark';
|
||||
fixedTheme?: 'light' | 'dark';
|
||||
height?: string | number;
|
||||
style?: React.CSSProperties;
|
||||
copyValue?: string;
|
||||
@@ -19,14 +20,16 @@ const HighlightCode: React.FC<{
|
||||
copyValue,
|
||||
lang = 'bash',
|
||||
copyable = true,
|
||||
theme = 'dark',
|
||||
theme,
|
||||
height = 'auto'
|
||||
} = props;
|
||||
|
||||
const { userSettings } = useUserSettings();
|
||||
|
||||
const currentTheme = React.useMemo(() => {
|
||||
return theme || userSettings.theme === 'realDark' ? 'dark' : 'light';
|
||||
const res = theme || userSettings.theme === 'realDark' ? 'dark' : 'light';
|
||||
console.log('currentTheme:', res, userSettings.theme, '===>', theme);
|
||||
return res;
|
||||
}, [theme, userSettings.theme]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -31,7 +31,9 @@ const LogsList: React.FC<LogsListProps> = forwardRef((props, ref) => {
|
||||
initialized
|
||||
} = useOverlayScroller({
|
||||
options: {
|
||||
theme: 'os-theme-light'
|
||||
scrollbars: {
|
||||
theme: 'os-theme-light'
|
||||
}
|
||||
}
|
||||
});
|
||||
const [innerHieght, setInnerHeight] = useState(
|
||||
|
||||
@@ -33,10 +33,7 @@ const CodeViewer = (props: any) => {
|
||||
);
|
||||
};
|
||||
|
||||
const FullMarkdown: React.FC<FullMarkdownProps> = ({
|
||||
content,
|
||||
theme = 'light'
|
||||
}) => {
|
||||
const FullMarkdown: React.FC<FullMarkdownProps> = ({ content, theme }) => {
|
||||
const escapedContent = useMemo(() => {
|
||||
return escapeMhchem(escapeBrackets(escapeDollarNumber(content)));
|
||||
}, [content]);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
.markdown-viewer {
|
||||
font-family: var(--font-family) !important;
|
||||
word-break: break-word;
|
||||
font-size: var(--font-size-base);
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import useOverlayScroller from '@/hooks/use-overlay-scroller';
|
||||
import useOverlayScroller, {
|
||||
OverlayScrollerOptions
|
||||
} from '@/hooks/use-overlay-scroller';
|
||||
import { Tooltip, TooltipProps } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
@@ -10,16 +12,18 @@ const Wrapper = styled.div<{ $maxHeight?: number }>`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const OverlayScroller: React.FC<any> = ({
|
||||
children,
|
||||
maxHeight,
|
||||
theme,
|
||||
style
|
||||
}) => {
|
||||
export const OverlayScroller: React.FC<
|
||||
OverlayScrollerOptions & {
|
||||
maxHeight?: number;
|
||||
style?: React.CSSProperties;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
> = ({ children, maxHeight, scrollbars, oppositeTheme, style }) => {
|
||||
const scroller = React.useRef<any>(null);
|
||||
const { initialize } = useOverlayScroller({
|
||||
options: {
|
||||
theme: theme || 'os-theme-light'
|
||||
scrollbars,
|
||||
oppositeTheme
|
||||
}
|
||||
});
|
||||
|
||||
@@ -36,7 +40,6 @@ const OverlayScroller: React.FC<any> = ({
|
||||
className="overlay-scroller-wrapper"
|
||||
$maxHeight={maxHeight || 200}
|
||||
hidden={false}
|
||||
as="div"
|
||||
style={{
|
||||
paddingInlineStart: 8,
|
||||
paddingInlineEnd: 8,
|
||||
@@ -48,17 +51,43 @@ const OverlayScroller: React.FC<any> = ({
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param maxHeight: use for scrollbars
|
||||
* @param theme: because this component is used for tooltip, so the default theme always is light
|
||||
* @returns
|
||||
*/
|
||||
export const TooltipOverlayScroller: React.FC<
|
||||
TooltipProps & { maxHeight?: number }
|
||||
> = ({ children, maxHeight, title, ...rest }) => {
|
||||
OverlayScrollerOptions & {
|
||||
maxHeight?: number;
|
||||
title?: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
toolTipProps?: TooltipProps;
|
||||
}
|
||||
> = ({
|
||||
children,
|
||||
maxHeight,
|
||||
title,
|
||||
toolTipProps,
|
||||
scrollbars,
|
||||
oppositeTheme
|
||||
}) => {
|
||||
const { overlayInnerStyle, ...rest } = toolTipProps || {};
|
||||
return (
|
||||
<Tooltip
|
||||
overlayInnerStyle={{
|
||||
paddingInline: 0
|
||||
paddingInline: 0,
|
||||
...overlayInnerStyle
|
||||
}}
|
||||
title={
|
||||
title && (
|
||||
<OverlayScroller maxHeight={maxHeight}>{title}</OverlayScroller>
|
||||
<OverlayScroller
|
||||
scrollbars={{ ...scrollbars, theme: 'os-theme-light' }}
|
||||
maxHeight={maxHeight}
|
||||
oppositeTheme={oppositeTheme}
|
||||
>
|
||||
{title}
|
||||
</OverlayScroller>
|
||||
)
|
||||
}
|
||||
{...rest}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import useOverlayScroller from '@/hooks/use-overlay-scroller';
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import 'simplebar-react/dist/simplebar.min.css';
|
||||
@@ -37,29 +36,19 @@ export interface ColumnProps {
|
||||
|
||||
interface SimpleTableProps {
|
||||
theme?: 'dark' | 'light';
|
||||
maxHeight?: number | string;
|
||||
columns: ColumnProps[];
|
||||
dataSource: any[];
|
||||
bordered?: boolean;
|
||||
rowKey?: string;
|
||||
rowKey: string;
|
||||
}
|
||||
const SimpleTabel: React.FC<SimpleTableProps> = (props) => {
|
||||
const {
|
||||
columns,
|
||||
dataSource,
|
||||
rowKey,
|
||||
bordered = true,
|
||||
theme = 'dark'
|
||||
} = props;
|
||||
const scroller = React.useRef<any>(null);
|
||||
const { initialize } = useOverlayScroller();
|
||||
const { columns, dataSource, rowKey, bordered = true } = props;
|
||||
|
||||
React.useEffect(() => {
|
||||
initialize(scroller.current);
|
||||
}, [initialize]);
|
||||
return (
|
||||
<div style={{ maxHeight: 240 }} ref={scroller}>
|
||||
<div>
|
||||
<table
|
||||
className={classNames('simple-table', theme, {
|
||||
className={classNames('simple-table', {
|
||||
'simple-table-bordered': bordered
|
||||
})}
|
||||
>
|
||||
@@ -74,7 +63,7 @@ const SimpleTabel: React.FC<SimpleTableProps> = (props) => {
|
||||
rowIndex={index}
|
||||
columns={columns}
|
||||
dataList={dataSource}
|
||||
key={rowKey ? item[rowKey] : index}
|
||||
key={item[rowKey]}
|
||||
></TableRow>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -25,8 +25,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.simplebar-scrollbar::before {
|
||||
background: var(--color-scroll-bg);
|
||||
width: var(--scrollbar-size);
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ import { StatusType } from '@/config/types';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import { Button, Divider, Tooltip } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import 'simplebar-react/dist/simplebar.min.css';
|
||||
import CopyButton from '../copy-button';
|
||||
import SimpleOverlay from '../simple-overlay';
|
||||
import { TooltipOverlayScroller } from '../overlay-scroller';
|
||||
import CopyStyle from './copy-btn.less';
|
||||
import './index.less';
|
||||
|
||||
@@ -47,17 +47,13 @@ const StatusTag: React.FC<StatusTagProps> = ({
|
||||
type = 'tag'
|
||||
}) => {
|
||||
const { text, status } = statusValue;
|
||||
const [statusColor, setStatusColor] = useState<{
|
||||
|
||||
const statusColor = useMemo<{
|
||||
text: string;
|
||||
bg: string;
|
||||
border?: string;
|
||||
}>({
|
||||
text: '',
|
||||
bg: ''
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setStatusColor(StatusColorMap[status]);
|
||||
}>(() => {
|
||||
return StatusColorMap[status];
|
||||
}, [status]);
|
||||
|
||||
const statusMessage = useMemo(() => {
|
||||
@@ -85,6 +81,7 @@ const StatusTag: React.FC<StatusTagProps> = ({
|
||||
}
|
||||
return <span>{text}</span>;
|
||||
};
|
||||
|
||||
const renderTitle = useMemo(() => {
|
||||
return (
|
||||
<div className={CopyStyle['status-content-wrapper']}>
|
||||
@@ -118,24 +115,21 @@ const StatusTag: React.FC<StatusTagProps> = ({
|
||||
})}
|
||||
</div>
|
||||
|
||||
<SimpleOverlay style={{ maxHeight: 200 }}>
|
||||
<div
|
||||
style={{
|
||||
width: 'max-content',
|
||||
maxWidth: 250,
|
||||
paddingInline: 10,
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word'
|
||||
}}
|
||||
>
|
||||
{statusMessage}
|
||||
{statusMessage && <span className="m-r-5"></span>}
|
||||
{extra}
|
||||
{messageLink && (
|
||||
<span dangerouslySetInnerHTML={{ __html: messageLink }}></span>
|
||||
)}
|
||||
</div>
|
||||
</SimpleOverlay>
|
||||
<div
|
||||
style={{
|
||||
width: 'max-content',
|
||||
maxWidth: 250,
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word'
|
||||
}}
|
||||
>
|
||||
{statusMessage}
|
||||
{statusMessage && <span className="m-r-5"></span>}
|
||||
{extra}
|
||||
{messageLink && (
|
||||
<span dangerouslySetInnerHTML={{ __html: messageLink }}></span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}, [statusValue]);
|
||||
@@ -150,11 +144,14 @@ const StatusTag: React.FC<StatusTagProps> = ({
|
||||
}}
|
||||
>
|
||||
{statusValue.message ? (
|
||||
<Tooltip
|
||||
trigger={['hover']}
|
||||
<TooltipOverlayScroller
|
||||
title={renderTitle}
|
||||
destroyTooltipOnHide={true}
|
||||
overlayInnerStyle={{ paddingInline: 0 }}
|
||||
scrollbars={{
|
||||
autoHide: 'never'
|
||||
}}
|
||||
toolTipProps={{
|
||||
destroyTooltipOnHide: true
|
||||
}}
|
||||
>
|
||||
<span className="txt err">
|
||||
<span className="m-r-5">
|
||||
@@ -162,7 +159,7 @@ const StatusTag: React.FC<StatusTagProps> = ({
|
||||
</span>
|
||||
{renderContent()}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</TooltipOverlayScroller>
|
||||
) : (
|
||||
<span className="txt">{renderContent()}</span>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user