all should work now

This commit is contained in:
2025-09-26 21:59:20 -04:00
parent e7dd34d323
commit 8b9e092329
4 changed files with 367 additions and 168 deletions

219
README.md
View File

@@ -1,10 +1,20 @@
# Menu Plugin for Obsidian
# Obsidian Menus
Create custom navigation menus in Obsidian using simple code blocks. Supports internal links, external URLs, and local file links with built-in themes and full customization.
Create simple, stylable menus from code blocks. You write links inside a `menu` code block, and the plugin renders:
- a single div with class `menu-container`
- a set of anchor tags inside it
You can:
- Pick a built-in template (default, minimal, slate, horizon, aether)
- Use your own CSS class (no plugin CSS applied)
- Override styles using a small, safe set of YAML-like variables
- Mix template + extra classes (e.g., `layout: horizon wide`)
CSS stays clean and predictable.
## Basic Usage
Create a menu using a `menu` code block with one of the built-in layouts:
Create a menu using a `menu` code block with one of the built-in templates:
````markdown
```menu
@@ -16,32 +26,21 @@ layout: default
```
````
## Built-in Layouts
- `[[Note]]` or `[[Note|Alias]]` creates internal links.
- `[Text](https://example.com)` creates web links.
- `[Text](file:///C:/path/to/file)` opens local files/folders.
### `default`
Standard buttons with borders and backgrounds
````markdown
```menu
layout: default
[[Dashboard]]
[GitHub](https://github.com)
[Files](file:///C:/Users/Documents)
```
````
## Built-in Templates
### `minimal`
Clean text links with subtle colors
````markdown
```menu
layout: minimal
[[Notes]]
[Web](https://example.com)
[Folder](file:///C:/Projects)
```
````
Available out of the box:
- default
- minimal
- slate
- horizon
- aether
Example:
### `slate`
Solid background buttons
````markdown
```menu
layout: slate
@@ -50,37 +49,95 @@ layout: slate
```
````
### `horizon`
Modern outlined style
You can also add extra classes like `wide` next to the layout:
````markdown
```menu
layout: horizon
layout: horizon wide
[[Dashboard]]
[Resources](https://example.com)
```
````
### `aether`
Grid layout with equal-width items
Note: Built-in template CSS only applies when a built-in layout is selected. Internally, the container gets a `data-layout="..."` attribute which gates the plugin CSS. If you dont select a built-in layout, none of the plugin CSS will affect your menu.
## Custom CSS Class Mode (No Plugin CSS)
Use your own CSS by providing a custom class via `class:` or `layout:` with a non-built-in value. In this mode, the plugin does not apply any of its CSS. It only renders the HTML and exposes inline CSS variables from the YAML-like overrides.
````markdown
```menu
layout: aether
[[Projects]]
[GitHub](https://github.com)
[Documents](file:///C:/Users/Documents)
class: my-menu wide
bg: #111
text: #eee
hover-text: #0af
internal-hover-text: orange
[[Home]]
[Web](https://example.com)
[Folder](file:///C:/Projects)
```
````
## Link Types
Then, in a CSS snippet:
- **Internal**: `[[Note Name]]` or `[[Note Name|Display Text]]`
- **External**: `[Display Text](https://example.com)`
- **Files**: `[Display Text](file:///C:/path/to/file)`
```css
/* Example custom styling */
.menu-container.my-menu {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
## Color Customization
.menu-container.my-menu a {
text-decoration: none;
padding: 0.5rem 0.8rem;
border-radius: 6px;
color: var(--text, var(--text-normal));
background: var(--bg, transparent);
border: 1px solid var(--border, var(--background-modifier-border));
}
Add color properties using YAML syntax:
.menu-container.my-menu a:hover {
color: var(--hover-text, var(--text-accent));
background: var(--hover-bg, transparent);
border-color: var(--hover-border, var(--text-accent));
}
```
## YAML-like Overrides (Safe Whitelist)
The code block supports a small set of variables. No raw CSS properties are accepted in the code block. If you need full CSS power, use a CSS snippet in your IDE.
Global variables:
- bg
- text
- border
- font
- hover-text
- hover-bg
- hover-border
- hover-font
Per link type variants (prefix with internal-, external-, file-):
- internal-bg, internal-text, internal-border, internal-font
- internal-hover-text, internal-hover-bg, internal-hover-border, internal-hover-font
- external-... (same set)
- file-... (same set)
Naming aliases supported:
- text-hover -> hover-text
- bg-hover -> hover-bg
- border-hover -> hover-border
- font-hover -> hover-font
- accent -> hover-text (and internal-accent/external-accent/file-accent -> corresponding -hover-text)
Behavior of keys:
- bg applies to the buttons (anchors), not the container
- hover-* applies to the hover state of the buttons
- type-specific keys (e.g., internal-text) override the global ones for that link type
Examples (template mode):
````markdown
```menu
layout: default
@@ -88,49 +145,51 @@ bg: #1a1a1a
text: #ffffff
hover-text: #ff6b6b
border: #333333
[[Home]]
[GitHub](https://github.com)
```
````
### Global Color Variables
- `bg`: Background color
- `text`: Text color
- `border`: Border color
- `hover-text`: Hover text color
- `hover-bg`: Hover background
- `hover-border`: Hover border color
- `font`: Font family
### Link-Type Specific Colors
Customize each link type individually:
Per-link-type overrides:
````markdown
```menu
layout: minimal
internal-text: #00ff00
external-text: #ff6600
file-text: #0066ff
internal-font: "Arial"
internal-font: "Fira Code"
external-font: "Georgia"
file-font: "Arial"
[[Internal Link]]
[External Link](https://example.com)
[File Link](file:///C:/Documents)
```
````
**Available for each type** (`internal`, `external`, `file`):
- `{type}-text`: Text color
- `{type}-bg`: Background color
- `{type}-border`: Border color
- `{type}-font`: Font family
- `{type}-hover-text`: Hover text color
- `{type}-hover-bg`: Hover background
- `{type}-hover-border`: Hover border color
## Link Types
## Advanced Examples
- Internal: `[[Note Name]]` or `[[Note Name|Display Text]]`
- External: `[Display Text](https://example.com)`
- Files: `[Display Text](file:///C:/path/to/file)`
### Gradient Background
Behavior:
- Internal links open within Obsidian.
- External links open in your browser.
- File links open via the OS.
## Notes
- Use either `layout:` or `class:`. If the value contains a built-in template, the template is applied. Otherwise, its treated as a pure CSS class (no plugin CSS).
- If no `layout:` or `class:` is provided, `layout: default` is assumed.
- Colors support hex, rgb, hsl, CSS variables, and gradients.
- Font names with spaces need quotes: `font: "Work Sans"`.
- You can append additional classes after the layout or class: `layout: horizon wide my-extra`.
## Examples
Built-in template with overrides:
````markdown
```menu
layout: horizon
@@ -142,23 +201,25 @@ hover-text: #ffd700
```
````
### Different Fonts Per Link Type
Custom class with overrides:
````markdown
```menu
layout: default
font: "Inter"
internal-font: "Fira Code"
external-font: "Georgia"
file-font: "Arial"
[[Code Notes]]
[Articles](https://medium.com)
[Local Files](file:///C:/Documents)
class: my-toolbar
text: var(--text-normal)
hover-text: var(--text-accent)
[[Inbox]]
[Wiki](https://example.com)
```
````
## Notes
- Use either `layout:` or `class:` (both work the same)
- File paths use `file://` protocol
- Colors support hex, rgb, hsl, CSS variables, and gradients
- Font names with spaces need quotes: `font: "Work Sans"`
Minimal template focusing on text colors:
````markdown
```menu
layout: minimal
internal-text: var(--text-accent)
external-text: var(--text-faint)
file-text: var(--text-muted)
[[Notes]]
[Web](https://example.com)
[Folder](file:///C:/Projects)
```

94
main.js

File diff suppressed because one or more lines are too long

131
main.ts
View File

@@ -1,30 +1,13 @@
import { Plugin } from 'obsidian';
import { fileURLToPath } from 'url';
const { shell } = require('electron');
// Simple YAML parser for color properties
function parseYAML(text: string) {
const result: Record<string, string> = {};
const lines = text.split('\n');
for (const line of lines) {
const trimmed = line.trim();
if (trimmed && trimmed.includes(':')) {
const [key, ...valueParts] = trimmed.split(':');
const value = valueParts.join(':').trim();
if (key && value) {
result[key.trim()] = value;
}
}
}
return result;
}
export default class MenuPlugin extends Plugin {
async onload() {
this.registerMarkdownCodeBlockProcessor('menu', (source, el, ctx) => {
const lines = source.trim().split('\n');
let layout = '';
let layoutOrClass = '';
let colors: Record<string, string> = {};
const links: string[] = [];
@@ -33,7 +16,7 @@ export default class MenuPlugin extends Plugin {
const trimmed = line.trim();
if (trimmed.startsWith('layout:') || trimmed.startsWith('class:')) {
const colonIndex = trimmed.indexOf(':');
layout = trimmed.substring(colonIndex + 1).trim();
layoutOrClass = trimmed.substring(colonIndex + 1).trim();
} else if (trimmed.includes(':') && !trimmed.startsWith('[') && !trimmed.startsWith('[[')) {
// Parse color properties
const [key, ...valueParts] = trimmed.split(':');
@@ -48,23 +31,102 @@ export default class MenuPlugin extends Plugin {
}
}
const finalLayout = layout || 'default';
const container = el.createEl('div', { cls: `menu-container ${finalLayout}` });
// Apply custom colors as CSS variables
if (Object.keys(colors).length > 0) {
for (const [key, value] of Object.entries(colors)) {
// Replace 'accent' with 'hover-text' for consistency
let cssKey = key.replace(/accent/g, 'hover-text');
container.style.setProperty(`--${cssKey}`, value);
// Determine layout and classes
const builtInLayouts = new Set(['default', 'minimal', 'slate', 'horizon', 'aether']);
const container = el.createEl('div', { cls: 'menu-container' });
let selectedLayout = '';
let extraClasses: string[] = [];
if (layoutOrClass) {
const tokens = layoutOrClass.split(/\s+/).filter(Boolean);
if (tokens.length) {
// Allow built-in layout to appear anywhere in the list (e.g., "class: my-class horizon wide")
const builtInIndex = tokens.findIndex(t => builtInLayouts.has(t));
if (builtInIndex !== -1) {
selectedLayout = tokens[builtInIndex];
extraClasses = tokens.filter((_, i) => i !== builtInIndex);
} else {
// Custom class mode: do not apply plugin CSS (no data-layout)
extraClasses = tokens;
}
}
// Example: ensure hover-text is set and add a comment for usage
if (colors['hover-text']) {
container.style.setProperty('--hover-text', colors['hover-text']);
// To use in CSS: a:hover { color: var(--hover-text); }
} else {
// No layout/class provided: use default built-in template
selectedLayout = 'default';
}
// Apply selected built-in template via data attribute (gates plugin CSS)
if (selectedLayout) {
container.setAttr('data-layout', selectedLayout);
}
// Apply any extra classes (e.g., "wide" or user-provided classes)
for (const cls of extraClasses) {
container.addClass(cls);
}
// Apply custom properties (whitelist only: bg, text, border, font and their -hover variants,
// plus internal-, external-, file- prefixed versions). No raw CSS props allowed.
if (Object.keys(colors).length > 0) {
const baseKeys = new Set([
'bg','text','border','font',
'hover-text','hover-bg','hover-border','hover-font',
]);
const normalizeKey = (raw: string) => {
let s = raw.trim().toLowerCase();
// Normalize synonyms/order for hover variants
s = s
// Prefer "hover-*" (matches CSS)
.replace(/\btext-hover\b/g, 'hover-text')
.replace(/\bbg-hover\b/g, 'hover-bg')
.replace(/\bborder-hover\b/g, 'hover-border')
// Old naming from earlier versions -> new "hover-*" order
.replace(/\binternal-text-hover\b/g, 'internal-hover-text')
.replace(/\binternal-bg-hover\b/g, 'internal-hover-bg')
.replace(/\binternal-border-hover\b/g, 'internal-hover-border')
.replace(/\bexternal-text-hover\b/g, 'external-hover-text')
.replace(/\bexternal-bg-hover\b/g, 'external-hover-bg')
.replace(/\bexternal-border-hover\b/g, 'external-hover-border')
.replace(/\bfile-text-hover\b/g, 'file-hover-text')
.replace(/\bfile-bg-hover\b/g, 'file-hover-bg')
.replace(/\bfile-border-hover\b/g, 'file-hover-border')
// Back-compat for "accent" -> "hover-text"
.replace(/\baccent\b/g, 'hover-text')
.replace(/\binternal-accent\b/g, 'internal-hover-text')
.replace(/\bexternal-accent\b/g, 'external-hover-text')
.replace(/\bfile-accent\b/g, 'file-hover-text')
.replace(/\bbackground\b/g, 'bg');
return s;
};
const isAllowed = (key: string) => {
if (baseKeys.has(key)) return true;
const m = key.match(/^(internal|external|file)-(.*)$/);
return !!(m && baseKeys.has(m[2]));
};
for (const [rawKey, value] of Object.entries(colors)) {
const key = normalizeKey(rawKey);
if (!isAllowed(key)) continue;
container.style.setProperty(`--${key}`, value);
}
}
// In custom class mode (no built-in layout), apply base inline styles to anchors so whitelist vars work without CSS.
const applyInlineBaseStyles = (a: HTMLElement, variant: 'internal' | 'external' | 'file' | 'generic') => {
const prefix = variant === 'generic' ? '' : `${variant}-`;
const get = (k: string) => (colors[`${prefix}${k}`] ?? colors[k]);
const bgVal = get('bg'); if (bgVal) a.style.background = bgVal as string;
const textVal = get('text'); if (textVal) a.style.color = textVal as string;
const borderVal = get('border'); if (borderVal) a.style.borderColor = borderVal as string;
const fontVal = get('font'); if (fontVal) a.style.fontFamily = fontVal as string;
// Expose hover values as CSS variables on the anchor for user CSS to consume if desired
const hoverKeys = ['hover-bg','hover-text','hover-border','hover-font'];
for (const hk of hoverKeys) {
const v = get(hk);
if (v) a.style.setProperty(`--${hk}`, v as string);
}
};
// Process each link
for (const link of links) {
if (link.startsWith('[[') && link.endsWith(']]')) {
@@ -80,6 +142,7 @@ export default class MenuPlugin extends Plugin {
attr: { 'data-href': href }
});
a.addClass('menu-internal-link');
if (!selectedLayout) applyInlineBaseStyles(a, 'internal');
a.style.cursor = 'pointer';
a.addEventListener('click', (e) => {
e.preventDefault();
@@ -103,8 +166,10 @@ export default class MenuPlugin extends Plugin {
// Add appropriate class based on link type
if (url.startsWith('file://')) {
a.addClass('menu-file-link');
if (!selectedLayout) applyInlineBaseStyles(a, 'file');
} else {
a.addClass('menu-external-link');
if (!selectedLayout) applyInlineBaseStyles(a, 'external');
}
a.addEventListener('click', (e) => {
e.preventDefault();

View File

@@ -1,6 +1,6 @@
/* Special styles to hide the border and </> icon on hover */
.markdown-source-view.mod-cm6 .cm-embed-block:not(.cm-table-widget, .cm-lang-base):has(.menu-container):hover {
.markdown-source-view.mod-cm6 .cm-embed-block:not(.cm-table-widget, .cm-lang-base):has(.menu-container[data-layout]):hover {
border-width: 0;
outline: 0;
box-shadow: var(--background-primary) 0 0 0 1px inset !important;
@@ -22,8 +22,8 @@
}
}
.menu-container,
.menu-container a {
.menu-container[data-layout],
.menu-container[data-layout] a {
transition: 125ms;
}
@@ -35,12 +35,11 @@
/* Default style variant */
.menu-container.default {
.menu-container[data-layout='default'] {
display: flex;
gap: 1em;
gap: 0.7em;
flex-wrap: wrap;
border-radius: 6px;
background-color: var(--bg, var(--background-primary));
font-family: var(--font, inherit);
a {
@@ -51,49 +50,51 @@
font-weight: 500;
border: 1px solid var(--border, var(--background-modifier-border));
color: var(--text, var(--text-normal));
background: var(--bg, var(--background-primary));
font-family: var(--font, inherit);
&:hover {
color: var(--hover-text, var(--accent, var(--text-accent)));
border-color: var(--hover-border, var(--accent, var(--text-accent)));
background: var(--hover-bg, transparent);
}
&.menu-internal-link {
color: var(--internal-text, var(--text, var(--text-normal)));
border-color: var(--internal-border, var(--border, var(--background-modifier-border)));
background-color: var(--internal-bg, transparent);
background: var(--internal-bg, var(--bg, var(--background-primary)));
font-family: var(--internal-font, var(--font, inherit));
&:hover {
color: var(--internal-hover-text, var(--internal-accent, var(--hover-text, var(--accent, var(--text-accent)))));
border-color: var(--internal-hover-border, var(--hover-border, var(--accent, var(--text-accent))));
background-color: var(--internal-hover-bg, var(--hover-bg, transparent));
background: var(--internal-hover-bg, var(--hover-bg, transparent));
}
}
&.menu-external-link {
color: var(--external-text, var(--text, var(--text-normal)));
border-color: var(--external-border, var(--border, var(--background-modifier-border)));
background-color: var(--external-bg, transparent);
background: var(--external-bg, var(--bg, var(--background-primary)));
font-family: var(--external-font, var(--font, inherit));
&:hover {
color: var(--external-hover-text, var(--external-accent, var(--hover-text, var(--accent, var(--text-accent)))));
border-color: var(--external-hover-border, var(--hover-border, var(--accent, var(--text-accent))));
background-color: var(--external-hover-bg, var(--hover-bg, transparent));
background: var(--external-hover-bg, var(--hover-bg, transparent));
}
}
&.menu-file-link {
color: var(--file-text, var(--text, var(--text-normal)));
border-color: var(--file-border, var(--border, var(--background-modifier-border)));
background-color: var(--file-bg, transparent);
background: var(--file-bg, var(--bg, var(--background-primary)));
font-family: var(--file-font, var(--font, inherit));
&:hover {
color: var(--file-hover-text, var(--file-accent, var(--hover-text, var(--accent, var(--text-accent)))));
border-color: var(--file-hover-border, var(--hover-border, var(--accent, var(--text-accent))));
background-color: var(--file-hover-bg, var(--hover-bg, transparent));
background: var(--file-hover-bg, var(--hover-bg, transparent));
}
}
}
@@ -112,12 +113,11 @@
/* Minimal style variant */
.menu-container.minimal {
.menu-container[data-layout='minimal'] {
display: flex;
gap: 0.2em;
flex-wrap: wrap;
transition: 125ms;
background-color: var(--bg, transparent);
font-family: var(--font, inherit);
a {
@@ -128,10 +128,11 @@
font-size: 0.9em;
font-weight: normal;
color: var(--text, var(--text-normal));
background: var(--bg, transparent);
font-family: var(--font, inherit);
&:hover {
background-color: var(--hover-bg, var(--background-secondary));
background: var(--hover-bg, var(--background-secondary));
color: var(--hover-text, var(--accent, var(--text-accent)));
}
@@ -141,7 +142,7 @@
&:hover {
color: var(--internal-hover-text, var(--internal-accent, var(--hover-text, var(--internal-hover, var(--text-accent-hover)))));
background-color: var(--internal-hover-bg, var(--hover-bg, var(--background-secondary)));
background: var(--internal-hover-bg, var(--hover-bg, var(--background-secondary)));
}
}
@@ -151,7 +152,7 @@
&:hover {
color: var(--external-hover-text, var(--external-accent, var(--hover-text, var(--external-hover, var(--text-normal)))));
background-color: var(--external-hover-bg, var(--hover-bg, var(--background-secondary)));
background: var(--external-hover-bg, var(--hover-bg, var(--background-secondary)));
}
}
@@ -161,18 +162,17 @@
&:hover {
color: var(--file-hover-text, var(--file-accent, var(--hover-text, var(--file-hover, var(--text-normal)))));
background-color: var(--file-hover-bg, var(--hover-bg, var(--background-secondary)));
background: var(--file-hover-bg, var(--hover-bg, var(--background-secondary)));
}
}
}
}
/* Minimal style variant */
.menu-container.slate {
.menu-container[data-layout='slate'] {
display: flex;
gap: 0.2em;
flex-wrap: wrap;
background-color: var(--bg, transparent);
font-family: var(--font, inherit);
a {
@@ -182,13 +182,13 @@
transition: color 0.15s ease;
font-size: 0.9em;
font-weight: normal;
background-color: var(--item-bg, var(--background-secondary));
background: var(--bg, var(--background-secondary));
border: 1px solid var(--border, var(--background-secondary));
color: var(--text, var(--text-faint));
font-family: var(--font, inherit);
&:hover {
background-color: var(--hover-bg, var(--background-secondary));
background: var(--hover-bg, var(--background-secondary));
color: var(--hover-text, var(--accent, var(--text-accent)));
border: 1px solid var(--hover-border, var(--accent, var(--text-accent)));
}
@@ -196,51 +196,50 @@
&.menu-internal-link {
color: var(--internal-text, var(--text, var(--text-faint)));
border-color: var(--internal-border, var(--border, var(--background-secondary)));
background-color: var(--internal-bg, var(--item-bg, var(--background-secondary)));
background: var(--internal-bg, var(--bg, var(--background-secondary)));
font-family: var(--internal-font, var(--font, inherit));
&:hover {
color: var(--internal-hover-text, var(--internal-accent, var(--hover-text, var(--accent, var(--text-accent)))));
border-color: var(--internal-hover-border, var(--hover-border, var(--accent, var(--text-accent))));
background-color: var(--internal-hover-bg, var(--hover-bg, var(--background-secondary)));
background: var(--internal-hover-bg, var(--hover-bg, var(--background-secondary)));
}
}
&.menu-external-link {
color: var(--external-text, var(--text, var(--text-faint)));
border-color: var(--external-border, var(--border, var(--background-secondary)));
background-color: var(--external-bg, var(--item-bg, var(--background-secondary)));
background: var(--external-bg, var(--bg, var(--background-secondary)));
font-family: var(--external-font, var(--font, inherit));
&:hover {
color: var(--external-hover-text, var(--external-accent, var(--hover-text, var(--accent, var(--text-accent)))));
border-color: var(--external-hover-border, var(--hover-border, var(--accent, var(--text-accent))));
background-color: var(--external-hover-bg, var(--hover-bg, var(--background-secondary)));
background: var(--external-hover-bg, var(--hover-bg, var(--background-secondary)));
}
}
&.menu-file-link {
color: var(--file-text, var(--text, var(--text-faint)));
border-color: var(--file-border, var(--border, var(--background-secondary)));
background-color: var(--file-bg, var(--item-bg, var(--background-secondary)));
background: var(--file-bg, var(--bg, var(--background-secondary)));
font-family: var(--file-font, var(--font, inherit));
&:hover {
color: var(--file-hover-text, var(--file-accent, var(--hover-text, var(--accent, var(--text-accent)))));
border-color: var(--file-hover-border, var(--hover-border, var(--accent, var(--text-accent))));
background-color: var(--file-hover-bg, var(--hover-bg, var(--background-secondary)));
background: var(--file-hover-bg, var(--hover-bg, var(--background-secondary)));
}
}
}
}
.menu-container.horizon {
.menu-container[data-layout='horizon'] {
display: flex;
gap: 0.5em;
flex-wrap: wrap;
border-radius: 8px;
background-color: var(--bg, var(--background-primary));
font-family: var(--font, 'Space Grotesk', Inter, sans-serif);
a {
@@ -254,49 +253,51 @@
border-radius: 3px;
padding-block: var(--size-2, 0.5em);
padding-inline: var(--size-3, 2em);
background: var(--bg, transparent);
transition: 250ms;
&:hover {
color: var(--hover-text, var(--accent, var(--orange-500, darkorange)));
border: 1px solid var(--hover-border, var(--accent, var(--orange-500, darkorange)));
background: var(--hover-bg, transparent);
}
&.menu-internal-link {
color: var(--internal-text, var(--text, var(--cyan-500, darkcyan)));
border-color: var(--internal-border, var(--border, var(--cyan-500, darkcyan)));
background-color: var(--internal-bg, transparent);
background: var(--internal-bg, var(--bg, transparent));
font-family: var(--internal-font, var(--font, 'Space Grotesk', Inter, sans-serif));
&:hover {
color: var(--internal-hover-text, var(--internal-accent, var(--hover-text, var(--accent, var(--orange-500, darkorange)))));
border-color: var(--internal-hover-border, var(--hover-border, var(--accent, var(--orange-500, darkorange))));
background-color: var(--internal-hover-bg, var(--hover-bg, transparent));
background: var(--internal-hover-bg, var(--hover-bg, transparent));
}
}
&.menu-external-link {
color: var(--external-text, var(--text, var(--cyan-500, darkcyan)));
border-color: var(--external-border, var(--border, var(--cyan-500, darkcyan)));
background-color: var(--external-bg, transparent);
background: var(--external-bg, var(--bg, transparent));
font-family: var(--external-font, var(--font, 'Space Grotesk', Inter, sans-serif));
&:hover {
color: var(--external-hover-text, var(--external-accent, var(--hover-text, var(--accent, var(--orange-500, darkorange)))));
border-color: var(--external-hover-border, var(--hover-border, var(--accent, var(--orange-500, darkorange))));
background-color: var(--external-hover-bg, var(--hover-bg, transparent));
background: var(--external-hover-bg, var(--hover-bg, transparent));
}
}
&.menu-file-link {
color: var(--file-text, var(--text, var(--cyan-500, darkcyan)));
border-color: var(--file-border, var(--border, var(--cyan-500, darkcyan)));
background-color: var(--file-bg, transparent);
background: var(--file-bg, var(--bg, transparent));
font-family: var(--file-font, var(--font, 'Space Grotesk', Inter, sans-serif));
&:hover {
color: var(--file-hover-text, var(--file-accent, var(--hover-text, var(--accent, var(--orange-500, darkorange)))));
border-color: var(--file-hover-border, var(--hover-border, var(--accent, var(--orange-500, darkorange))));
background-color: var(--file-hover-bg, var(--hover-bg, transparent));
background: var(--file-hover-bg, var(--hover-bg, transparent));
}
}
}
@@ -308,11 +309,10 @@
}
}
.menu-container.aether {
.menu-container[data-layout='aether'] {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 0.5em;
background-color: var(--bg, transparent);
font-family: var(--font, inherit);
a {
@@ -323,50 +323,51 @@
border-radius: 8px;
color: var(--text, var(--text-normal));
border: 1px solid var(--border, var(--background-modifier-border));
background: var(--bg, transparent);
font-family: var(--font, inherit);
&:hover {
color: var(--hover-text, var(--accent, var(--text-accent)));
border-color: var(--hover-border, var(--accent, var(--text-accent)));
background-color: var(--hover-bg, var(--background-modifier-hover));
background: var(--hover-bg, var(--background-modifier-hover));
}
&.menu-internal-link {
color: var(--internal-text, var(--text, var(--text-normal)));
border-color: var(--internal-border, var(--border, var(--background-modifier-border)));
background-color: var(--internal-bg, transparent);
background: var(--internal-bg, var(--bg, transparent));
font-family: var(--internal-font, var(--font, inherit));
&:hover {
color: var(--internal-hover-text, var(--internal-accent, var(--hover-text, var(--accent, var(--text-accent)))));
border-color: var(--internal-hover-border, var(--hover-border, var(--accent, var(--text-accent))));
background-color: var(--internal-hover-bg, var(--hover-bg, var(--background-modifier-hover)));
background: var(--internal-hover-bg, var(--hover-bg, var(--background-modifier-hover)));
}
}
&.menu-external-link {
color: var(--external-text, var(--text, var(--text-normal)));
border-color: var(--external-border, var(--border, var(--background-modifier-border)));
background-color: var(--external-bg, transparent);
background: var(--external-bg, var(--bg, transparent));
font-family: var(--external-font, var(--font, inherit));
&:hover {
color: var(--external-hover-text, var(--external-accent, var(--hover-text, var(--accent, var(--text-accent)))));
border-color: var(--external-hover-border, var(--hover-border, var(--accent, var(--text-accent))));
background-color: var(--external-hover-bg, var(--hover-bg, var(--background-modifier-hover)));
background: var(--external-hover-bg, var(--hover-bg, var(--background-modifier-hover)));
}
}
&.menu-file-link {
color: var(--file-text, var(--text, var(--text-normal)));
border-color: var(--file-border, var(--border, var(--background-modifier-border)));
background-color: var(--file-bg, transparent);
background: var(--file-bg, var(--bg, transparent));
font-family: var(--file-font, var(--font, inherit));
&:hover {
color: var(--file-hover-text, var(--file-accent, var(--hover-text, var(--accent, var(--text-accent)))));
border-color: var(--file-hover-border, var(--hover-border, var(--accent, var(--text-accent))));
background-color: var(--file-hover-bg, var(--hover-bg, var(--background-modifier-hover)));
background: var(--file-hover-bg, var(--hover-bg, var(--background-modifier-hover)));
}
}
}