Co-Authored-By: Quentin Torroba <quentin.torroba@mistral.ai>
Co-Authored-By: Vincent Guilloux <vincent.guilloux@mistral.ai>
Co-Authored-By: Luis Cardoso <luis.cardoso@mistral.ai>
This commit is contained in:
Mathias Gesbert 2026-01-07 17:57:27 +01:00 committed by Mathias Gesbert
parent 4d449be276
commit add3ab5245
36 changed files with 399 additions and 259 deletions

View file

@ -12,6 +12,7 @@ from textual.validation import Length
from textual.widgets import Input, Link, Static
from vibe.cli.clipboard import copy_selection_to_clipboard
from vibe.cli.textual_ui.widgets.no_markup_static import NoMarkupStatic
from vibe.core.config import VibeConfig
from vibe.core.paths.global_paths import GLOBAL_ENV_FILE
from vibe.setup.onboarding.base import OnboardingScreen
@ -48,10 +49,10 @@ class ApiKeyScreen(OnboardingScreen):
return
help_url, help_name = PROVIDER_HELP[self.provider.name]
yield Static(f"Grab your {provider_name} API key from the {help_name}:")
yield NoMarkupStatic(f"Grab your {provider_name} API key from the {help_name}:")
yield Center(
Horizontal(
Static("", classes="link-chevron"),
NoMarkupStatic("", classes="link-chevron"),
Link(help_url, url=help_url),
classes="link-row",
)
@ -60,7 +61,7 @@ class ApiKeyScreen(OnboardingScreen):
def _compose_config_docs(self) -> ComposeResult:
yield Static("[dim]Learn more about Vibe configuration:[/]")
yield Horizontal(
Static("", classes="link-chevron"),
NoMarkupStatic("", classes="link-chevron"),
Link(CONFIG_DOCS_URL, url=CONFIG_DOCS_URL),
classes="link-row",
)
@ -76,17 +77,17 @@ class ApiKeyScreen(OnboardingScreen):
)
with Vertical(id="api-key-outer"):
yield Static("", classes="spacer")
yield Center(Static("One last thing...", id="api-key-title"))
yield NoMarkupStatic("", classes="spacer")
yield Center(NoMarkupStatic("One last thing...", id="api-key-title"))
with Center():
with Vertical(id="api-key-content"):
yield from self._compose_provider_link(provider_name)
yield Static(
yield NoMarkupStatic(
"...and paste it below to finish the setup:", id="paste-hint"
)
yield Center(Horizontal(self.input_widget, id="input-box"))
yield Static("", id="feedback")
yield Static("", classes="spacer")
yield NoMarkupStatic("", id="feedback")
yield NoMarkupStatic("", classes="spacer")
yield Vertical(
Vertical(*self._compose_config_docs(), id="config-docs-group"),
id="config-docs-section",
@ -96,7 +97,7 @@ class ApiKeyScreen(OnboardingScreen):
self.input_widget.focus()
def on_input_changed(self, event: Input.Changed) -> None:
feedback = self.query_one("#feedback", Static)
feedback = self.query_one("#feedback", NoMarkupStatic)
input_box = self.query_one("#input-box")
if event.validation_result is None:

View file

@ -10,6 +10,7 @@ from textual.theme import BUILTIN_THEMES
from textual.widgets import Markdown, Static
from vibe.cli.textual_ui.terminal_theme import TERMINAL_THEME_NAME
from vibe.cli.textual_ui.widgets.no_markup_static import NoMarkupStatic
from vibe.core.config import VibeConfig
from vibe.setup.onboarding.base import OnboardingScreen
@ -67,19 +68,19 @@ class ThemeSelectionScreen(OnboardingScreen):
def _compose_theme_list(self) -> ComposeResult:
for _ in range(VISIBLE_NEIGHBORS * 2 + 1):
widget = Static("", classes="theme-item")
widget = NoMarkupStatic("", classes="theme-item")
self._theme_widgets.append(widget)
yield widget
def compose(self) -> ComposeResult:
with Center(id="theme-outer"):
with Vertical(id="theme-content"):
yield Static("Select your preferred theme", id="theme-title")
yield NoMarkupStatic("Select your preferred theme", id="theme-title")
yield Center(
Horizontal(
Static("Navigate ↑ ↓", id="nav-hint"),
NoMarkupStatic("Navigate ↑ ↓", id="nav-hint"),
Vertical(*self._compose_theme_list(), id="theme-list"),
Static("Press Enter \u21b5", id="enter-hint"),
NoMarkupStatic("Press Enter \u21b5", id="enter-hint"),
id="theme-row",
)
)

View file

@ -8,6 +8,7 @@ from textual.containers import Center, Vertical
from textual.timer import Timer
from textual.widgets import Static
from vibe.cli.textual_ui.widgets.no_markup_static import NoMarkupStatic
from vibe.setup.onboarding.base import OnboardingScreen
WELCOME_PREFIX = "Welcome to "
@ -68,7 +69,7 @@ class WelcomeScreen(OnboardingScreen):
with Center():
yield Static("", id="welcome-text")
with Center():
yield Static("", id="enter-hint", classes="hidden")
yield NoMarkupStatic("", id="enter-hint", classes="hidden")
def on_mount(self) -> None:
self._welcome_text = self.query_one("#welcome-text", Static)

View file

@ -15,6 +15,7 @@ from vibe.cli.textual_ui.terminal_theme import (
TERMINAL_THEME_NAME,
capture_terminal_theme,
)
from vibe.cli.textual_ui.widgets.no_markup_static import NoMarkupStatic
from vibe.core.paths.global_paths import GLOBAL_CONFIG_FILE, TRUSTED_FOLDERS_FILE
@ -50,14 +51,14 @@ class TrustFolderDialog(CenterMiddle):
def compose(self) -> ComposeResult:
with CenterMiddle(id="trust-dialog"):
yield Static("⚠ Trust this folder?", id="trust-dialog-title")
yield Static(
yield NoMarkupStatic("⚠ Trust this folder?", id="trust-dialog-title")
yield NoMarkupStatic(
str(self.folder_path),
id="trust-dialog-path",
classes="trust-dialog-path",
)
yield Static(
"A .vibe/ directory was found here. Should Vibe load custom configuration and tools from it?",
yield NoMarkupStatic(
"Files that can modify your Mistral Vibe setup were found here. Do you trust this folder?",
id="trust-dialog-message",
classes="trust-dialog-message",
)
@ -65,13 +66,17 @@ class TrustFolderDialog(CenterMiddle):
with Horizontal(id="trust-options-container"):
options = ["Yes", "No"]
for idx, text in enumerate(options):
widget = Static(f" {idx + 1}. {text}", classes="trust-option")
widget = NoMarkupStatic(
f" {idx + 1}. {text}", classes="trust-option"
)
self.option_widgets.append(widget)
yield widget
yield Static("← → navigate Enter select", classes="trust-dialog-help")
yield NoMarkupStatic(
"← → navigate Enter select", classes="trust-dialog-help"
)
yield Static(
yield NoMarkupStatic(
f"Setting will be saved in: {TRUSTED_FOLDERS_FILE.path}",
id="trust-dialog-save-info",
classes="trust-dialog-save-info",