Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions branding/mintlify/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions branding/mintlify/logo-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions branding/mintlify/logo-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
83 changes: 83 additions & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,89 @@ export default withFolderTree(
['meta', { name: 'application-name', content: SITE.name }],
['meta', { name: 'keywords', content: 'nuxt,i18n,internationalization,nuxt-module,localization,vue,ssr,seo' }],
['link', { rel: 'dns-prefetch', href: 'https://github.com' }],
['link', { rel: 'dns-prefetch', href: 'https://widget.mintlify.com' }],
['script', { type: 'module', src: 'https://widget.mintlify.com/v1/embed.js' }],
[
'script',
{ type: 'module' },
`const isDark = () => document.documentElement.classList.contains('dark')
const theme = () => (isDark() ? 'dark' : 'light')

const trigger = document.createElement('button')
trigger.type = 'button'
trigger.className = 'ni18n-ask-ai'
trigger.setAttribute('aria-label', 'Ask AI')
trigger.innerHTML = '<span class="ni18n-ask-ai__icon" aria-hidden="true">✦</span><span>Ask AI</span>'
trigger.hidden = true
document.body.appendChild(trigger)

const setTriggerVisible = (visible) => {
trigger.hidden = !visible
}

await window.MintlifyAssistant.init({
id: "mint_widget_fe4a84f3-0f6c-4dc0-94d6-3941d70125c2",
appearance: {
variant: "widget",
theme: theme(),
accent: "#32ba8c",
radius: "16px",
side: "bottom",
align: "end",
logo: "${SITE.url}/favicon.svg",
zIndex: 40,
},
labels: {
title: "Ask AI",
trigger: "Ask AI",
placeholder: "Ask about Nuxt I18n Micro…",
suggestions: "Try asking",
},
starterQuestions: [
"How do I install nuxt-i18n-micro?",
"Which routing strategy should I use?",
"How do page-level translations work?",
],
hooks: {
event(event) {
if (event.type === 'open') setTriggerVisible(false)
if (event.type === 'close' || event.type === 'init') setTriggerVisible(true)
},
},
})

setTriggerVisible(true)

trigger.addEventListener('click', () => {
void window.MintlifyAssistant.open({ source: 'custom-trigger', focus: true })
})

// Built-in trigger is closed Shadow DOM and stays white — cover it with our button.
const hideBuiltInTrigger = () => {
const host = document.querySelector('mintlify-assistant')
if (!host) return
const root = host.shadowRoot
Comment thread
s00d marked this conversation as resolved.
Outdated
if (!root) return
for (const el of root.querySelectorAll('button, [role="button"]')) {
const text = (el.textContent || '').trim()
if (text.includes('Ask AI') || el.getAttribute('aria-label')?.includes('Ask')) {
el.style.setProperty('visibility', 'hidden', 'important')
el.style.setProperty('pointer-events', 'none', 'important')
}
}
}
hideBuiltInTrigger()
new MutationObserver(hideBuiltInTrigger).observe(document.body, { childList: true, subtree: true })

new MutationObserver(() => {
void window.MintlifyAssistant.update({
appearance: { theme: theme() },
})
}).observe(document.documentElement, {
attributes: true,
attributeFilter: ["class"],
})`,
],
],

themeConfig: {
Expand Down
70 changes: 70 additions & 0 deletions docs/.vitepress/theme/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,73 @@
border: none;
box-shadow: none;
}

/* Custom Ask AI trigger — Mintlify built-in button stays white (closed Shadow DOM) */
.ni18n-ask-ai {
position: fixed;
right: 24px;
bottom: 24px;
z-index: 50;
display: inline-flex;
align-items: center;
gap: 8px;
margin: 0;
padding: 12px 18px;
border: none;
border-radius: 999px;
background: #32ba8c;
color: #fff;
font: 600 14px/1 Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, sans-serif;
letter-spacing: -0.01em;
cursor: pointer;
box-shadow:
0 10px 28px rgba(26, 80, 81, 0.28),
0 2px 8px rgba(50, 186, 140, 0.35);
transition:
transform 0.15s ease,
background-color 0.15s ease,
box-shadow 0.15s ease;
}

.ni18n-ask-ai:hover {
background: #2aa67c;
transform: translateY(-1px);
box-shadow:
0 14px 32px rgba(26, 80, 81, 0.32),
0 4px 12px rgba(50, 186, 140, 0.4);
}

.ni18n-ask-ai:active {
transform: translateY(0);
}

.ni18n-ask-ai:focus-visible {
Comment thread
s00d marked this conversation as resolved.
outline: 2px solid #1a5051;
outline-offset: 3px;
}

.ni18n-ask-ai__icon {
font-size: 15px;
line-height: 1;
}

.dark .ni18n-ask-ai {
background: #32ba8c;
color: #0b1f1c;
box-shadow:
0 10px 28px rgba(0, 0, 0, 0.45),
0 0 0 1px rgba(95, 224, 174, 0.25);
}

.dark .ni18n-ask-ai:hover {
background: #5fe0ae;
}

@media (max-width: 640px) {
.ni18n-ask-ai {
right: 16px;
bottom: 16px;
padding: 11px 16px;
}
}

1 change: 1 addition & 0 deletions docs/api/module-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ Parts of the module you can switch off.
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `hreflangBaseLanguage` | `boolean` | `false` | Also emit a bare-language `hreflang` derived from each locale's `iso` (e.g. `es-ES` → also `es`). The first regional locale in `locales` claims the bare tag for that language. Routing `code` is never used — only `iso \|\| code`. |
| `vueDevtools` | `boolean` | `true` | Register Vue DevTools inspector and timeline in dev (browser extension). Separate from the Nuxt DevTools custom tab. |
| `localizedRouteNamePrefix` | `string` | `'localized-'` | Prefix prepended to localized route names (e.g. `'localized-index'`). Used internally to distinguish original routes from generated locale variants. |
| `routeDisableMeta` | `Record<string, boolean \| string[]>` | — | Per-route meta tag disabling, extracted from `defineI18nRoute()` calls. Maps a route path to `true` (disable all meta) or an array of locale codes for which meta should be disabled. |
| `missingWarn` | `boolean` | `true` | Show console warnings when a translation key is missing. |
Expand Down
Loading
Loading