diff --git a/public/app/plugins/datasource/tempo/traceql/QueryEditor.tsx b/public/app/plugins/datasource/tempo/traceql/QueryEditor.tsx index a88677957a3..f950c630045 100644 --- a/public/app/plugins/datasource/tempo/traceql/QueryEditor.tsx +++ b/public/app/plugins/datasource/tempo/traceql/QueryEditor.tsx @@ -34,6 +34,7 @@ export function QueryEditor(props: Props) { void; onRunQuery: () => void; @@ -21,9 +22,11 @@ interface Props { } export function TraceQLEditor(props: Props) { - const { onRunQuery } = props; + const { onRunQuery, placeholder } = props; const setupAutocompleteFn = useAutocomplete(props.datasource); - const styles = useStyles2(getStyles); + const theme = useTheme2(); + const styles = getStyles(theme, placeholder); + return ( { setupAutocompleteFn(editor, monaco); setupActions(editor, monaco, onRunQuery); + setupPlaceholder(editor, monaco, styles); }} /> ); } +function setupPlaceholder(editor: monacoTypes.editor.IStandaloneCodeEditor, monaco: Monaco, styles: EditorStyles) { + const placeholderDecorators = [ + { + range: new monaco.Range(1, 1, 1, 1), + options: { + className: styles.placeholder, // The placeholder text is in styles.placeholder + isWholeLine: true, + }, + }, + ]; + + let decorators: string[] = []; + + const checkDecorators = (): void => { + const model = editor.getModel(); + + if (!model) { + return; + } + + const newDecorators = model.getValueLength() === 0 ? placeholderDecorators : []; + decorators = model.deltaDecorations(decorators, newDecorators); + }; + + checkDecorators(); + editor.onDidChangeModelContent(checkDecorators); +} + function setupActions(editor: monacoTypes.editor.IStandaloneCodeEditor, monaco: Monaco, onRunQuery: () => void) { editor.addAction({ id: 'run-query', @@ -135,12 +167,24 @@ function ensureTraceQL(monaco: Monaco) { } } -const getStyles = (theme: GrafanaTheme2) => { +interface EditorStyles { + placeholder: string; + queryField: string; +} + +const getStyles = (theme: GrafanaTheme2, placeholder: string): EditorStyles => { return { queryField: css` border-radius: ${theme.shape.borderRadius()}; border: 1px solid ${theme.components.input.borderColor}; flex: 1; `, + placeholder: css` + ::after { + content: '${placeholder}'; + font-family: ${theme.typography.fontFamilyMonospace}; + opacity: 0.3; + } + `, }; };