Jump to error code on badge click (#3262)
* add function to scroll to view Signed-off-by: Jess Frazelle <github@jessfraz.com> * scroll into view on click Signed-off-by: Jess Frazelle <github@jessfraz.com> * add test for jump to code with error Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -8,12 +8,13 @@ import {
|
||||
import { KclEditorMenu } from 'components/ModelingSidebar/ModelingPanes/KclEditorMenu'
|
||||
import { CustomIconName } from 'components/CustomIcon'
|
||||
import { KclEditorPane } from 'components/ModelingSidebar/ModelingPanes/KclEditorPane'
|
||||
import { ReactNode } from 'react'
|
||||
import { MouseEventHandler, ReactNode } from 'react'
|
||||
import { MemoryPane, MemoryPaneMenu } from './MemoryPane'
|
||||
import { LogsPane } from './LoggingPanes'
|
||||
import { DebugPane } from './DebugPane'
|
||||
import { FileTreeInner, FileTreeMenu } from 'components/FileTree'
|
||||
import { useKclContext } from 'lang/KclProvider'
|
||||
import { editorManager } from 'lib/singletons'
|
||||
|
||||
export type SidebarType =
|
||||
| 'code'
|
||||
@ -24,6 +25,11 @@ export type SidebarType =
|
||||
| 'lspMessages'
|
||||
| 'variables'
|
||||
|
||||
export interface BadgeInfo {
|
||||
value: (props: PaneCallbackProps) => boolean | number
|
||||
onClick?: MouseEventHandler<any>
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface can be extended as more context is needed for the panes
|
||||
* to determine if they should show their badges or not.
|
||||
@ -40,7 +46,7 @@ export type SidebarPane = {
|
||||
Content: ReactNode | React.FC
|
||||
Menu?: ReactNode | React.FC
|
||||
hideOnPlatform?: 'desktop' | 'web'
|
||||
showBadge?: (props: PaneCallbackProps) => boolean | number
|
||||
showBadge?: BadgeInfo
|
||||
}
|
||||
|
||||
export const sidebarPanes: SidebarPane[] = [
|
||||
@ -51,7 +57,15 @@ export const sidebarPanes: SidebarPane[] = [
|
||||
Content: KclEditorPane,
|
||||
keybinding: 'Shift + C',
|
||||
Menu: KclEditorMenu,
|
||||
showBadge: ({ kclContext }) => kclContext.errors.length,
|
||||
showBadge: {
|
||||
value: ({ kclContext }) => {
|
||||
return kclContext.errors.length
|
||||
},
|
||||
onClick: (e) => {
|
||||
e.preventDefault()
|
||||
editorManager.scrollToFirstDiagnosticIfExists()
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'files',
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||
import { Resizable } from 're-resizable'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { MouseEventHandler, useCallback, useMemo } from 'react'
|
||||
import { useHotkeys } from 'react-hotkeys-hook'
|
||||
import { SidebarType, sidebarPanes } from './ModelingPanes'
|
||||
import Tooltip from 'components/Tooltip'
|
||||
@ -19,6 +19,11 @@ interface ModelingSidebarProps {
|
||||
paneOpacity: '' | 'opacity-20' | 'opacity-40'
|
||||
}
|
||||
|
||||
interface BadgeInfoComputed {
|
||||
value: number | boolean
|
||||
onClick?: MouseEventHandler<any>
|
||||
}
|
||||
|
||||
export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
|
||||
const { commandBarSend } = useCommandsContext()
|
||||
const kclContext = useKclContext()
|
||||
@ -88,13 +93,16 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
|
||||
[sidebarPanes, showDebugPanel.current]
|
||||
)
|
||||
|
||||
const paneBadgeMap: Record<SidebarType, number | boolean> = useMemo(() => {
|
||||
const paneBadgeMap: Record<SidebarType, BadgeInfoComputed> = useMemo(() => {
|
||||
return filteredPanes.reduce((acc, pane) => {
|
||||
if (pane.showBadge) {
|
||||
acc[pane.id] = pane.showBadge({ kclContext })
|
||||
acc[pane.id] = {
|
||||
value: pane.showBadge.value({ kclContext }),
|
||||
onClick: pane.showBadge.onClick,
|
||||
}
|
||||
}
|
||||
return acc
|
||||
}, {} as Record<SidebarType, number | boolean>)
|
||||
}, {} as Record<SidebarType, BadgeInfoComputed>)
|
||||
}, [kclContext.errors])
|
||||
|
||||
const togglePane = useCallback(
|
||||
@ -229,7 +237,7 @@ interface ModelingPaneButtonProps
|
||||
}
|
||||
onClick: () => void
|
||||
paneIsOpen?: boolean
|
||||
showBadge?: boolean | number
|
||||
showBadge?: BadgeInfoComputed
|
||||
}
|
||||
|
||||
function ModelingPaneButton({
|
||||
@ -244,59 +252,68 @@ function ModelingPaneButton({
|
||||
})
|
||||
|
||||
return (
|
||||
<button
|
||||
className="pointer-events-auto flex items-center justify-center border-transparent dark:border-transparent p-0 m-0 rounded-sm !outline-0 focus-visible:border-primary"
|
||||
onClick={onClick}
|
||||
name={paneConfig.title}
|
||||
data-testid={paneConfig.id + '-pane-button'}
|
||||
{...props}
|
||||
>
|
||||
<ActionIcon
|
||||
icon={paneConfig.icon}
|
||||
className={'p-1 ' + paneConfig.iconClassName || ''}
|
||||
size={paneConfig.iconSize || 'sm'}
|
||||
iconClassName={
|
||||
paneIsOpen
|
||||
? ' !text-chalkboard-10'
|
||||
: '!text-chalkboard-80 dark:!text-chalkboard-30'
|
||||
}
|
||||
bgClassName={
|
||||
'rounded-sm ' + (paneIsOpen ? '!bg-primary' : '!bg-transparent')
|
||||
}
|
||||
/>
|
||||
<span className="sr-only">
|
||||
{paneConfig.title}
|
||||
{paneIsOpen !== undefined ? ` pane` : ''}
|
||||
</span>
|
||||
{!!showBadge && (
|
||||
<p
|
||||
className={
|
||||
'absolute m-0 p-0 -top-1 -right-1 w-3 h-3 flex items-center justify-center text-[10px] font-semibold text-white bg-primary hue-rotate-90 rounded-full border border-chalkboard-10 dark:border-chalkboard-80'
|
||||
<div id={paneConfig.id + '-button-holder'}>
|
||||
<button
|
||||
className="pointer-events-auto flex items-center justify-center border-transparent dark:border-transparent p-0 m-0 rounded-sm !outline-0 focus-visible:border-primary"
|
||||
onClick={onClick}
|
||||
name={paneConfig.title}
|
||||
data-testid={paneConfig.id + '-pane-button'}
|
||||
{...props}
|
||||
>
|
||||
<ActionIcon
|
||||
icon={paneConfig.icon}
|
||||
className={'p-1 ' + paneConfig.iconClassName || ''}
|
||||
size={paneConfig.iconSize || 'sm'}
|
||||
iconClassName={
|
||||
paneIsOpen
|
||||
? ' !text-chalkboard-10'
|
||||
: '!text-chalkboard-80 dark:!text-chalkboard-30'
|
||||
}
|
||||
bgClassName={
|
||||
'rounded-sm ' + (paneIsOpen ? '!bg-primary' : '!bg-transparent')
|
||||
}
|
||||
/>
|
||||
<span className="sr-only">
|
||||
{paneConfig.title}
|
||||
{paneIsOpen !== undefined ? ` pane` : ''}
|
||||
</span>
|
||||
<Tooltip
|
||||
position="right"
|
||||
contentClassName="max-w-none flex items-center gap-4"
|
||||
hoverOnly
|
||||
>
|
||||
<span className="flex-1">
|
||||
{paneConfig.title}
|
||||
{paneIsOpen !== undefined ? ` pane` : ''}
|
||||
</span>
|
||||
<kbd className="hotkey text-xs capitalize">
|
||||
{paneConfig.keybinding}
|
||||
</kbd>
|
||||
</Tooltip>
|
||||
</button>
|
||||
{!!showBadge?.value && (
|
||||
<p
|
||||
id={`${paneConfig.id}-badge`}
|
||||
className={
|
||||
'absolute m-0 p-0 top-1 right-0 w-3 h-3 flex items-center justify-center text-[10px] font-semibold text-white bg-primary hue-rotate-90 rounded-full border border-chalkboard-10 dark:border-chalkboard-80 z-50 hover:cursor-pointer'
|
||||
}
|
||||
onClick={showBadge.onClick}
|
||||
title={`Click to view ${showBadge.value} notification${
|
||||
Number(showBadge.value) > 1 ? 's' : ''
|
||||
}`}
|
||||
>
|
||||
<span className="sr-only"> has </span>
|
||||
{typeof showBadge === 'number' ? (
|
||||
<span>{showBadge}</span>
|
||||
{typeof showBadge.value === 'number' ? (
|
||||
<span>{showBadge.value}</span>
|
||||
) : (
|
||||
<span className="sr-only">a</span>
|
||||
)}
|
||||
<span className="sr-only">
|
||||
notification{Number(showBadge) > 1 ? 's' : ''}
|
||||
notification{Number(showBadge.value) > 1 ? 's' : ''}
|
||||
</span>
|
||||
</p>
|
||||
)}
|
||||
<Tooltip
|
||||
position="right"
|
||||
contentClassName="max-w-none flex items-center gap-4"
|
||||
hoverOnly
|
||||
>
|
||||
<span className="flex-1">
|
||||
{paneConfig.title}
|
||||
{paneIsOpen !== undefined ? ` pane` : ''}
|
||||
</span>
|
||||
<kbd className="hotkey text-xs capitalize">{paneConfig.keybinding}</kbd>
|
||||
</Tooltip>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user