From 1e74fe0cb7a16b5505721211b48e4bad1aefebcf Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 27 Feb 2024 09:24:26 +0000 Subject: [PATCH] Improve popover positioning, improve drawer styles and performance --- .../bbui/src/Actions/position_dropdown.js | 6 +- packages/bbui/src/Drawer/Drawer.svelte | 2 +- .../common/CodeEditor/CodeEditor.svelte | 133 +++++++++++++----- .../src/components/common/CodeEditor/index.js | 97 +------------ .../common/bindings/BindingPanel.svelte | 2 +- 5 files changed, 114 insertions(+), 126 deletions(-) diff --git a/packages/bbui/src/Actions/position_dropdown.js b/packages/bbui/src/Actions/position_dropdown.js index 31a1044ba4..b0dd94ad46 100644 --- a/packages/bbui/src/Actions/position_dropdown.js +++ b/packages/bbui/src/Actions/position_dropdown.js @@ -40,8 +40,12 @@ export default function positionDropdown(element, opts) { } else { // Determine vertical styles if (align === "right-outside" || align === "left-outside") { - styles.top = anchorBounds.bottom - elementBounds.height + styles.top = + anchorBounds.top + anchorBounds.height / 2 - elementBounds.height / 2 styles.maxHeight = maxHeight + if (styles.top + elementBounds.height > window.innerHeight) { + styles.top = window.innerHeight - elementBounds.height + } } else if ( window.innerHeight - anchorBounds.bottom < (maxHeight || 100) diff --git a/packages/bbui/src/Drawer/Drawer.svelte b/packages/bbui/src/Drawer/Drawer.svelte index d05f59bc41..ff7497b905 100644 --- a/packages/bbui/src/Drawer/Drawer.svelte +++ b/packages/bbui/src/Drawer/Drawer.svelte @@ -60,7 +60,7 @@ export let headless = false const dispatch = createEventDispatcher() - const spacing = 10 + const spacing = 11 let visible = false let drawerId = generate() diff --git a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte index 172380e251..9b3d01fbbc 100644 --- a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte +++ b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte @@ -42,7 +42,7 @@ } from "@codemirror/commands" import { Compartment } from "@codemirror/state" import { javascript } from "@codemirror/lang-javascript" - import { EditorModes, getDefaultTheme } from "./" + import { EditorModes } from "./" import { themeStore } from "stores/portal" export let label @@ -164,14 +164,7 @@ dispatch("change", docStr) }), keymap.of(buildKeymap()), - themeConfig.of([ - getDefaultTheme({ - height: editorHeight, - resize, - dark: isDark, - }), - ...(isDark ? [oneDark] : []), - ]), + themeConfig.of([...(isDark ? [oneDark] : [])]), ] } @@ -182,7 +175,7 @@ complete.push( autocompletion({ override: [...completions], - closeOnBlur: true, + closeOnBlur: false, icons: false, optionClass: () => "autocomplete-option", }) @@ -264,14 +257,7 @@ // Issue theme compartment update editor.dispatch({ - effects: themeConfig.reconfigure([ - getDefaultTheme({ - height: editorHeight, - resize, - dark: isDark, - }), - ...(isDark ? [oneDark] : []), - ]), + effects: themeConfig.reconfigure([...(isDark ? [oneDark] : [])]), }) } } @@ -312,6 +298,7 @@ .code-editor :global(.cm-line) { height: 16px; padding: 0 var(--spacing-s); + color: var(--spectrum-alias-text-color); } .code-editor :global(.cm-activeLine) { position: relative; @@ -358,30 +345,103 @@ position: relative; } + /* Cursor color */ + .code-editor :global(.cm-focused .cm-cursor) { + border-left-color: var(--spectrum-alias-text-color); + } + + /* Placeholder */ + .code-editor :global(.cm-placeholder) { + color: var(--spectrum-global-color-gray-700); + font-style: italic; + } + + /* Highlight bindings */ + .code-editor :global(.binding-wrap) { + color: var(--spectrum-global-color-blue-700); + } + /* Completion popover */ - .code-editor :global(.cm-tooltip.cm-completionInfo) { + .code-editor :global(.cm-tooltip-autocomplete) { + background: var(--spectrum-global-color-gray-75); + border-radius: 4px; + border: 1px solid var(--spectrum-global-color-gray-200); + } + .code-editor :global(.cm-tooltip-autocomplete > ul) { + max-height: 20em; + } + + /* Completion section header*/ + .code-editor :global(.info-section) { + display: flex; + align-items: center; padding: var(--spacing-m); + font-family: var(--font-sans); + font-size: var(--font-size-s); + gap: var(--spacing-m); + color: var(--spectrum-alias-text-color); + font-weight: 600; } - .code-editor :global(.cm-tooltip-autocomplete > ul > li[aria-selected]) { - border-radius: var( - --spectrum-popover-border-radius, - var(--spectrum-alias-border-radius-regular) - ), - var( - --spectrum-popover-border-radius, - var(--spectrum-alias-border-radius-regular) - ), - 0, 0; + .code-editor :global(.info-section:not(:first-of-type)) { + border-top: 1px solid var(--spectrum-global-color-gray-200); } + + /* Completion item container */ + .code-editor :global(.autocomplete-option) { + padding: var(--spacing-s) var(--spacing-m) !important; + padding-left: calc(16px + 2 * var(--spacing-m)) !important; + display: flex; + gap: var(--spacing-m); + align-items: center; + color: var(--spectrum-alias-text-color); + } + + /* Highlighted completion item */ + .code-editor :global(.autocomplete-option[aria-selected]) { + background: var(--spectrum-global-color-blue-400); + color: white; + } + .code-editor + :global(.autocomplete-option[aria-selected] .cm-completionDetail) { + color: white; + } + + /* Completion item label */ + .code-editor :global(.cm-completionLabel) { + flex: 1 1 auto; + font-size: var(--font-size-s); + font-family: var(--font-sans); + text-transform: capitalize; + } + + /* Completion item type */ .code-editor :global(.autocomplete-option .cm-completionDetail) { - background-color: var(--spectrum-global-color-gray-200); + font-family: var(--font-mono); + color: var(--spectrum-global-color-gray-700); + font-style: normal; + text-transform: capitalize; + font-size: 10px; + } + + /* Live binding value / helper container */ + .code-editor :global(.cm-completionInfo) { + margin-left: var(--spacing-s); + border: 1px solid var(--spectrum-global-color-gray-300); border-radius: var(--border-radius-s); - padding: 4px 6px; + background-color: var(--spectrum-global-color-gray-50); + padding: var(--spacing-m); + margin-top: -2px; + } + + /* Live binding value / helper value */ + .code-editor :global(.binding__description) { + color: var(--spectrum-global-color-gray-700); + font-size: var(--font-size-s); } .code-editor :global(.binding__example) { padding: 0; margin: 0; - font-size: 12px; + font-size: var(--font-size-s); font-family: var(--font-mono); white-space: pre; text-overflow: ellipsis; @@ -393,4 +453,13 @@ text-overflow: ellipsis !important; white-space: nowrap !important; } + + /* Wrapper around helpers */ + .code-editor :global(.info-bubble) { + font-size: var(--font-size-s); + display: grid; + grid-gap: var(--spacing-s); + grid-template-columns: 1fr; + color: var(--spectrum-global-color-gray-800); + } diff --git a/packages/builder/src/components/common/CodeEditor/index.js b/packages/builder/src/components/common/CodeEditor/index.js index f05617b73c..c877907e9c 100644 --- a/packages/builder/src/components/common/CodeEditor/index.js +++ b/packages/builder/src/components/common/CodeEditor/index.js @@ -27,94 +27,6 @@ export const SECTIONS = { }, } -export const getDefaultTheme = opts => { - const { height, resize, dark } = opts - return EditorView.theme( - { - "&.cm-focused .cm-cursor": { - borderLeftColor: "var(--spectrum-alias-text-color)", - }, - "&": { - height: height ? `${height}` : "", - lineHeight: "1.3", - border: - "var(--spectrum-alias-border-size-thin) solid var(--spectrum-alias-border-color)", - borderRadius: "var(--border-radius-s)", - resize: resize ? `${resize}` : "", - overflow: "hidden", - color: "var(--spectrum-alias-text-color)", - }, - "& .cm-tooltip.cm-tooltip-autocomplete > ul": { - fontFamily: - "var(--spectrum-alias-body-text-font-family, var(--spectrum-global-font-family-base))", - maxHeight: "16em", - }, - "& .cm-placeholder": { - color: "var(--spectrum-alias-text-color)", - fontStyle: "italic", - }, - "&.cm-focused": { - outline: "none", - borderColor: "var(--spectrum-alias-border-color-mouse-focus)", - }, - // AUTO COMPLETE - "& .cm-completionDetail": { - fontStyle: "unset", - textTransform: "uppercase", - fontSize: "10px", - backgroundColor: "var(--spectrum-global-color-gray-100)", - color: "var(--spectrum-global-color-gray-600)", - }, - "& .cm-completionLabel": { - marginLeft: - "calc(var(--spectrum-alias-workflow-icon-size-m) + var(--spacing-m))", - }, - "& .info-bubble": { - fontSize: "var(--font-size-s)", - display: "grid", - gridGap: "var(--spacing-s)", - gridTemplateColumns: "1fr", - color: "var(--spectrum-global-color-gray-800)", - }, - "& .cm-tooltip": { - marginLeft: "var(--spacing-s)", - border: "1px solid var(--spectrum-global-color-gray-300)", - borderRadius: - "var( --spectrum-popover-border-radius, var(--spectrum-alias-border-radius-regular) )", - backgroundColor: "var(--spectrum-global-color-gray-50)", - }, - // Section header - "& .info-section": { - display: "flex", - padding: "var(--spacing-s)", - gap: "var(--spacing-m)", - borderBottom: "1px solid var(--spectrum-global-color-gray-200)", - color: "var(--spectrum-global-color-gray-800)", - fontWeight: "bold", - }, - "& .info-section .spectrum-Icon": { - color: "var(--spectrum-global-color-gray-600)", - }, - // Autocomplete Option - "& .cm-tooltip.cm-tooltip-autocomplete .autocomplete-option": { - display: "flex", - justifyContent: "space-between", - alignItems: "center", - fontSize: "var(--spectrum-alias-font-size-default)", - padding: "var(--spacing-s)", - color: "var(--spectrum-global-color-gray-800)", - }, - "& .cm-tooltip-autocomplete ul li[aria-selected].autocomplete-option": { - backgroundColor: "var(--spectrum-global-color-gray-200)", - }, - "& .binding-wrap": { - color: "var(--spectrum-global-color-orange-600)", - }, - }, - { dark } - ) -} - export const buildHelperInfoNode = (completion, helper) => { const ele = document.createElement("div") ele.classList.add("info-bubble") @@ -137,10 +49,11 @@ export const buildHelperInfoNode = (completion, helper) => { const toSpectrumIcon = name => { return ` ` @@ -149,7 +62,9 @@ const toSpectrumIcon = name => { export const buildSectionHeader = (type, sectionName, icon, rank) => { const ele = document.createElement("div") ele.classList.add("info-section") - ele.classList.add(type) + if (type) { + ele.classList.add(type) + } ele.innerHTML = `${toSpectrumIcon(icon)}${sectionName}` return { name: sectionName, @@ -171,7 +86,7 @@ export const helpersToCompletion = (helpers, mode) => { }, type: "helper", section: helperSection, - detail: "FUNCTION", + detail: "Function", apply: (view, completion, from, to) => { insertBinding(view, from, to, key, mode) }, diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index 07e01c7ebd..02a5b99495 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -332,7 +332,7 @@ /* Tabs */ .tabs { padding: var(--spacing-m); - border-bottom: 2px solid transparent; + border-bottom: var(--border-light); } .editor-tabs, .side-tabs {