Fix LSP tooltip cutoff, style hover/autocomplete tooltips, add text wrapping setting (#404)

* Fix: allow tooltips to overflow code pane
while keeping the same vertical and horizontal
scroll behavior that we've had.

Signed-off-by: Frank Noirot <frank@kittycad.io>

* Style tooltips in light and dark mode

* Fix: properly display autocomplete info as HTML
We were parsing it from md to html, but displaying
the parsed html as a string in the info box.

Signed-off-by: Frank Noirot <frank@kittycad.io>

* Fix z-index of command bar to show over code panel

* Let user set text wrapping in editor

* Style hover tooltips

* Fix failing tests
by not including line wrapping plugin in test mode

---------

Signed-off-by: Frank Noirot <frank@kittycad.io>
This commit is contained in:
Frank Noirot
2023-09-06 21:27:30 -04:00
committed by GitHub
parent 0b4b93932d
commit fba6c422a8
7 changed files with 105 additions and 30 deletions

View File

@ -10,7 +10,7 @@ import { DebugPanel } from './components/DebugPanel'
import { v4 as uuidv4 } from 'uuid'
import { asyncParser } from './lang/abstractSyntaxTree'
import { _executor } from './lang/executor'
import CodeMirror from '@uiw/react-codemirror'
import CodeMirror, { Extension } from '@uiw/react-codemirror'
import { linter, lintGutter } from '@codemirror/lint'
import { ViewUpdate, EditorView } from '@codemirror/view'
import {
@ -54,6 +54,7 @@ import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
import { onboardingPaths } from 'routes/Onboarding'
import { LanguageServerClient } from 'editor/lsp'
import kclLanguage from 'editor/lsp/language'
import { CSSRuleObject } from 'tailwindcss/types/config'
export function App() {
const { code: loadedCode, project } = useLoaderData() as IndexLoaderData
@ -138,7 +139,7 @@ export function App() {
context: { token },
},
settings: {
context: { showDebugPanel, theme, onboardingStatus },
context: { showDebugPanel, theme, onboardingStatus, textWrapping },
},
} = useGlobalStateContext()
@ -422,17 +423,6 @@ export function App() {
}
}
const extraExtensions = useMemo(() => {
if (TEST) return []
return [
lintGutter(),
linter((_view) => {
return kclErrToDiagnostic(useStore.getState().kclErrors)
}),
EditorView.lineWrapping,
]
}, [])
// So this is a bit weird, we need to initialize the lsp server and client.
// But the server happens async so we break this into two parts.
// Below is the client and server promise.
@ -472,6 +462,25 @@ export function App() {
return plugin
}, [lspClient, isLSPServerReady])
const editorExtensions = useMemo(() => {
const extensions = [lineHighlightField] as Extension[]
if (kclLSP) extensions.push(kclLSP)
// These extensions have proven to mess with vitest
if (!TEST) {
extensions.push(
lintGutter(),
linter((_view) => {
return kclErrToDiagnostic(useStore.getState().kclErrors)
})
)
if (textWrapping === 'On') extensions.push(EditorView.lineWrapping)
}
return extensions
}, [kclLSP, textWrapping])
return (
<div
className="h-screen overflow-hidden relative flex flex-col cursor-pointer select-none"
@ -513,7 +522,7 @@ export function App() {
<CollapsiblePanel
title="Code"
icon={faCode}
className="open:!mb-2 overflow-x-hidden"
className="open:!mb-2"
open={openPanes.includes('code')}
>
<div className="px-2 py-1">
@ -527,16 +536,13 @@ export function App() {
</div>
<div
id="code-mirror-override"
className="overflow-x-hidden h-full"
className="full-height-subtract"
style={{ '--height-subtract': '4.25rem' } as CSSRuleObject}
>
<CodeMirror
className="h-full overflow-hidden-x"
className="h-full"
value={code}
extensions={
kclLSP
? [kclLSP, lineHighlightField, ...extraExtensions]
: [lineHighlightField, ...extraExtensions]
}
extensions={editorExtensions}
onChange={onChange}
onUpdate={onUpdate}
theme={editorTheme}

View File

@ -1,5 +1,5 @@
.panel {
@apply relative overflow-auto z-0;
@apply relative z-0;
@apply bg-chalkboard-10/70 backdrop-blur-sm;
}

View File

@ -196,7 +196,7 @@ const CommandBar = () => {
setCommandBarOpen(false)
clearState()
}}
className="fixed inset-0 overflow-y-auto p-4 pt-[25vh]"
className="fixed inset-0 z-40 overflow-y-auto p-4 pt-[25vh]"
>
<Transition.Child
enter="duration-100 ease-out"
@ -207,7 +207,7 @@ const CommandBar = () => {
leaveTo="opacity-0"
as={Fragment}
>
<Dialog.Overlay className="fixed z-40 inset-0 bg-chalkboard-10/70 dark:bg-chalkboard-110/50" />
<Dialog.Overlay className="fixed inset-0 bg-chalkboard-10/70 dark:bg-chalkboard-110/50" />
</Transition.Child>
<Transition.Child
enter="duration-100 ease-out"
@ -221,7 +221,7 @@ const CommandBar = () => {
<Combobox
value={selectedCommand}
onChange={handleCommandSelection}
className="rounded relative mx-auto z-40 p-2 bg-chalkboard-10 dark:bg-chalkboard-100 border dark:border-chalkboard-70 max-w-xl w-full shadow-lg"
className="rounded relative mx-auto p-2 bg-chalkboard-10 dark:bg-chalkboard-100 border dark:border-chalkboard-70 max-w-xl w-full shadow-lg"
as="div"
>
<div className="flex gap-2 items-center">

View File

@ -208,7 +208,13 @@ export class LanguageServerPlugin implements PluginValue {
filterText: filterText ?? label,
}
if (documentation) {
completion.info = formatContents(documentation)
completion.info = () => {
const htmlString = formatContents(documentation)
const htmlNode = document.createElement('div')
htmlNode.style.display = 'contents'
htmlNode.innerHTML = htmlString
return { dom: htmlNode }
}
}
return completion

View File

@ -82,11 +82,22 @@ code {
monospace;
}
.full-height-subtract {
--height-subtract: 2.25rem;
height: 100%;
max-height: calc(100% - var(--height-subtract));
}
#code-mirror-override .cm-editor {
@apply bg-transparent;
@apply h-full bg-transparent;
}
#code-mirror-override .cm-scroller {
@apply h-full;
}
#code-mirror-override .cm-scroller::-webkit-scrollbar {
@apply h-0;
}
#code-mirror-override .cm-activeLine,
@ -137,14 +148,39 @@ code {
}
#code-mirror-override .cm-tooltip {
font-size: 80%;
@apply text-xs shadow-md;
@apply bg-chalkboard-10 text-chalkboard-80;
@apply rounded-sm border-solid border border-chalkboard-40/30 border-l-liquid-10;
}
.dark #code-mirror-override .cm-tooltip {
@apply bg-chalkboard-110 text-chalkboard-40;
@apply border-chalkboard-70/20 border-l-liquid-70;
}
#code-mirror-override .cm-tooltip-hover {
@apply py-1 px-2 w-max max-w-md;
}
#code-mirror-override .cm-tooltip-hover .documentation {
padding: 5;
#code-mirror-override .cm-completionInfo {
@apply px-4 rounded-l-none;
@apply bg-chalkboard-10 text-liquid-90;
@apply border-liquid-40/30;
}
.dark #code-mirror-override .cm-completionInfo {
@apply bg-liquid-120 text-liquid-50;
@apply border-liquid-90/60;
}
#code-mirror-override .cm-tooltip-autocomplete li {
@apply px-2 py-1;
}
#code-mirror-override .cm-tooltip-autocomplete li[aria-selected='true'] {
@apply bg-liquid-10 text-liquid-110;
}
.dark #code-mirror-override .cm-tooltip-autocomplete li[aria-selected='true'] {
@apply bg-liquid-100 text-liquid-20;
}
#code-mirror-override .cm-content {

View File

@ -62,6 +62,17 @@ export const settingsCommandBarMeta: CommandBarMeta = {
},
],
},
'Set Text Wrapping': {
displayValue: (args: string[]) => 'Set whether text in the editor wraps',
args: [
{
name: 'textWrapping',
type: 'select',
defaultValue: 'textWrapping',
options: [{ name: 'On' }, { name: 'Off' }],
},
],
},
'Set Onboarding Status': {
hide: 'both',
},
@ -78,6 +89,7 @@ export const settingsMachine = createMachine(
unitSystem: UnitSystem.Imperial,
baseUnit: 'in' as BaseUnit,
defaultDirectory: '',
textWrapping: 'On' as 'On' | 'Off',
showDebugPanel: false,
onboardingStatus: '',
},
@ -142,6 +154,17 @@ export const settingsMachine = createMachine(
target: 'idle',
internal: true,
},
'Set Text Wrapping': {
actions: [
assign({
textWrapping: (_, event) => event.data.textWrapping,
}),
'persistSettings',
'toastSuccess',
],
target: 'idle',
internal: true,
},
'Toggle Debug Panel': {
actions: [
assign({
@ -182,6 +205,7 @@ export const settingsMachine = createMachine(
data: { unitSystem: UnitSystem }
}
| { type: 'Set Base Unit'; data: { baseUnit: BaseUnit } }
| { type: 'Set Text Wrapping'; data: { textWrapping: 'On' | 'Off' } }
| { type: 'Set Onboarding Status'; data: { onboardingStatus: string } }
| { type: 'Toggle Debug Panel' },
},

View File

@ -18,6 +18,7 @@ export interface Typegen0 {
| 'Set Default Directory'
| 'Set Default Project Name'
| 'Set Onboarding Status'
| 'Set Text Wrapping'
| 'Set Theme'
| 'Set Unit System'
| 'Toggle Debug Panel'
@ -26,6 +27,7 @@ export interface Typegen0 {
| 'Set Default Directory'
| 'Set Default Project Name'
| 'Set Onboarding Status'
| 'Set Text Wrapping'
| 'Set Theme'
| 'Set Unit System'
| 'Toggle Debug Panel'
@ -34,6 +36,7 @@ export interface Typegen0 {
| 'Set Base Unit'
| 'Set Default Directory'
| 'Set Default Project Name'
| 'Set Text Wrapping'
| 'Set Theme'
| 'Set Unit System'
| 'Toggle Debug Panel'