chore: sources tab render polish (#32055)

This commit is contained in:
Pavel Feldman 2024-08-08 10:53:59 -07:00 committed by GitHub
parent 69287f26bc
commit 80e014f4b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 29 additions and 14 deletions

View File

@ -63,6 +63,6 @@ export const LogTab: React.FunctionComponent<{
<span className='log-list-duration'>{entry.time}</span> <span className='log-list-duration'>{entry.time}</span>
{entry.message} {entry.message}
</div>} </div>}
noHighlightOnHover={true} notSelectable={true}
/>; />;
}; };

View File

@ -29,3 +29,9 @@
align-items: center; align-items: center;
flex: 1 1 auto; flex: 1 1 auto;
} }
.source-tab-file-name div {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

View File

@ -95,6 +95,7 @@ export const SourceTab: React.FunctionComponent<{
}, [onOpenExternally, location]); }, [onOpenExternally, location]);
const showStackFrames = (stack?.length ?? 0) > 1; const showStackFrames = (stack?.length ?? 0) > 1;
const shortFileName = getFileName(fileName);
return <SplitView return <SplitView
sidebarSize={200} sidebarSize={200}
@ -102,8 +103,10 @@ export const SourceTab: React.FunctionComponent<{
sidebarHidden={!showStackFrames} sidebarHidden={!showStackFrames}
main={<div className='vbox' data-testid='source-code'> main={<div className='vbox' data-testid='source-code'>
{ fileName && <Toolbar> { fileName && <Toolbar>
<span className='source-tab-file-name'>{fileName}</span> <div className='source-tab-file-name' title={fileName}>
<CopyToClipboard description='Copy filename' value={getFileName(fileName)}/> <div>{shortFileName}</div>
</div>
<CopyToClipboard description='Copy filename' value={shortFileName}/>
{location && <ToolbarButton icon='link-external' title='Open in VS Code' onClick={openExternally}></ToolbarButton>} {location && <ToolbarButton icon='link-external' title='Open in VS Code' onClick={openExternally}></ToolbarButton>}
</Toolbar> } </Toolbar> }
<CodeMirrorWrapper text={source.content || ''} language='javascript' highlight={highlight} revealLine={targetLine} readOnly={true} lineNumbers={true} /> <CodeMirrorWrapper text={source.content || ''} language='javascript' highlight={highlight} revealLine={targetLine} readOnly={true} lineNumbers={true} />

View File

@ -121,7 +121,7 @@ export function GridView<T>(model: GridViewProps<T>) {
onIconClicked={model.onIconClicked} onIconClicked={model.onIconClicked}
noItemsMessage={model.noItemsMessage} noItemsMessage={model.noItemsMessage}
dataTestId={model.dataTestId} dataTestId={model.dataTestId}
noHighlightOnHover={model.noHighlightOnHover} notSelectable={model.notSelectable}
></ListView> ></ListView>
</div> </div>
</div>; </div>;

View File

@ -34,6 +34,10 @@
padding-left: 5px; padding-left: 5px;
} }
.list-view-content.not-selectable > .list-view-entry {
cursor: inherit;
}
.list-view-entry.highlighted:not(.selected) { .list-view-entry.highlighted:not(.selected) {
background-color: var(--vscode-list-inactiveSelectionBackground) !important; background-color: var(--vscode-list-inactiveSelectionBackground) !important;
} }

View File

@ -16,6 +16,7 @@
import * as React from 'react'; import * as React from 'react';
import './listView.css'; import './listView.css';
import { clsx } from '@web/uiUtils';
export type ListViewProps<T> = { export type ListViewProps<T> = {
name: string, name: string,
@ -36,7 +37,7 @@ export type ListViewProps<T> = {
onIconClicked?: (item: T, index: number) => void, onIconClicked?: (item: T, index: number) => void,
noItemsMessage?: string, noItemsMessage?: string,
dataTestId?: string, dataTestId?: string,
noHighlightOnHover?: boolean, notSelectable?: boolean,
}; };
const scrollPositions = new Map<string, number>(); const scrollPositions = new Map<string, number>();
@ -60,7 +61,7 @@ export function ListView<T>({
onIconClicked, onIconClicked,
noItemsMessage, noItemsMessage,
dataTestId, dataTestId,
noHighlightOnHover, notSelectable,
}: ListViewProps<T>) { }: ListViewProps<T>) {
const itemListRef = React.useRef<HTMLDivElement>(null); const itemListRef = React.useRef<HTMLDivElement>(null);
const [highlightedItem, setHighlightedItem] = React.useState<any>(); const [highlightedItem, setHighlightedItem] = React.useState<any>();
@ -85,9 +86,9 @@ export function ListView<T>({
itemListRef.current.scrollTop = scrollPositions.get(name) || 0; itemListRef.current.scrollTop = scrollPositions.get(name) || 0;
}, [name]); }, [name]);
return <div className={`list-view vbox ` + name + '-list-view' } role={items.length > 0 ? 'list' : undefined} data-testid={dataTestId || (name + '-list')}> return <div className={clsx(`list-view vbox`, name + '-list-view')} role={items.length > 0 ? 'list' : undefined} data-testid={dataTestId || (name + '-list')}>
<div <div
className='list-view-content' className={clsx('list-view-content', notSelectable && 'not-selectable')}
tabIndex={0} tabIndex={0}
onKeyDown={event => { onKeyDown={event => {
if (selectedItem && event.key === 'Enter') { if (selectedItem && event.key === 'Enter') {
@ -134,18 +135,19 @@ export function ListView<T>({
> >
{noItemsMessage && items.length === 0 && <div className='list-view-empty'>{noItemsMessage}</div>} {noItemsMessage && items.length === 0 && <div className='list-view-empty'>{noItemsMessage}</div>}
{items.map((item, index) => { {items.map((item, index) => {
const selectedSuffix = selectedItem === item ? ' selected' : '';
const highlightedSuffix = !noHighlightOnHover && highlightedItem === item ? ' highlighted' : '';
const errorSuffix = isError?.(item, index) ? ' error' : '';
const warningSuffix = isWarning?.(item, index) ? ' warning' : '';
const infoSuffix = isInfo?.(item, index) ? ' info' : '';
const indentation = indent?.(item, index) || 0; const indentation = indent?.(item, index) || 0;
const rendered = render(item, index); const rendered = render(item, index);
return <div return <div
key={id?.(item, index) || index} key={id?.(item, index) || index}
onDoubleClick={() => onAccepted?.(item, index)} onDoubleClick={() => onAccepted?.(item, index)}
role='listitem' role='listitem'
className={'list-view-entry' + selectedSuffix + highlightedSuffix + errorSuffix + warningSuffix + infoSuffix} className={clsx(
'list-view-entry',
selectedItem === item && 'selected',
!notSelectable && highlightedItem === item && 'highlighted',
isError?.(item, index) && 'error',
isWarning?.(item, index) && 'warning',
isInfo?.(item, index) && 'info')}
onClick={() => onSelected?.(item, index)} onClick={() => onSelected?.(item, index)}
onMouseEnter={() => setHighlightedItem(item)} onMouseEnter={() => setHighlightedItem(item)}
onMouseLeave={() => setHighlightedItem(undefined)} onMouseLeave={() => setHighlightedItem(undefined)}