lms/resources/js/components/css-editor/theme.ts
2025-12-15 12:26:23 +01:00

92 lines
3.3 KiB
TypeScript

import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
import { Extension } from '@codemirror/state';
import { EditorView } from '@codemirror/view';
import { tags } from '@lezer/highlight';
export const themeConfig = EditorView.theme({
'&': {
color: 'inherit',
fontSize: '90%',
backgroundColor: 'inherit',
outline: 'none !important',
display: 'block !important',
width: '100%',
minHeight: 'inherit',
cursor: 'text',
height: '100%',
},
'.cm-content': {
lineHeight: 1.75,
fontFamily: 'var(--font-mono)',
// Ensure caret is visible against dark backgrounds
caretColor: 'hsl(var(--foreground, 0 0% 100%))',
padding: '10px 0',
},
'.cm-scroller': {
minHeight: 'inherit',
height: '100%',
},
// Make caret and selections visible in dark mode
'.cm-cursor': {
borderLeftColor: 'inherit',
},
'&.cm-focused .cm-selectionBackground, .cm-selectionBackground, ::selection': {
backgroundColor: 'rgba(59, 130, 246, 0.25)', // blue-500/25
},
'.cm-gutters': {
color: 'inherit',
backgroundColor: 'inherit',
borderRight: 'unset',
},
'.cm-lineNumbers .cm-gutterElement': {
paddingRight: '24px',
opacity: '75%',
},
'.cm-lineWrapping ': {
wordBreak: 'break-all !important',
},
// Autocomplete tooltip styling that adapts to app theme tokens
'.cm-tooltip': {
backgroundColor: 'hsl(var(--popover, 0 0% 10%))',
color: 'hsl(var(--popover-foreground, 0 0% 98%))',
border: '1px solid hsl(var(--border, 0 0% 25%))',
boxShadow: '0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)',
zIndex: 60,
},
'.cm-tooltip-autocomplete': {
'& > ul': { maxHeight: '240px', overflow: 'auto' },
},
'.cm-tooltip-autocomplete ul li': {
padding: '6px 8px',
},
'.cm-tooltip-autocomplete ul li[aria-selected]': {
backgroundColor: 'hsl(var(--accent, 0 0% 20%))',
color: 'hsl(var(--accent-foreground, 0 0% 98%))',
},
// Highlight of matching text in the autocomplete suggestion list
'.cm-completionMatchedText': {
color: '#60a5fa', // tailwind sky-400
fontWeight: 600,
textDecoration: 'none',
},
});
// Inline colors to avoid requiring external CSS
export const highlightStyle = HighlightStyle.define([
{ tag: [tags.comment], color: '#64748b' }, // slate-500
{ tag: [tags.keyword, tags.typeName, tags.typeOperator], color: '#7c3aed', fontWeight: '500' }, // violet-600
{ tag: [tags.string, tags.meta, tags.regexp], color: '#16a34a' }, // green-600
{ tag: [tags.number, tags.bool], color: '#ea580c' }, // orange-600
{ tag: [tags.operator, tags.name], color: '#0ea5e9' }, // sky-500
{ tag: [tags.variableName, tags.attributeName, tags.propertyName], color: '#0ea5e9' },
{ tag: [tags.className], color: '#22d3ee' }, // cyan-400
{ tag: [tags.tagName], color: '#e11d48' }, // rose-600
{ tag: [tags.heading, tags.strong], color: '#111827', fontWeight: 'bold' },
{ tag: [tags.emphasis], color: '#111827', fontStyle: 'italic' },
{ tag: [tags.link], textDecoration: 'underline' },
{ tag: [tags.strikethrough], textDecoration: 'line-through' },
{ tag: [tags.invalid], color: '#ef4444' }, // red-500
]);
export const theme: Extension = [themeConfig, syntaxHighlighting(highlightStyle)];