diff --git a/frontend/include/frontend/settings.hpp b/frontend/include/frontend/settings.hpp index f44b1f52..3174f8c5 100644 --- a/frontend/include/frontend/settings.hpp +++ b/frontend/include/frontend/settings.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +28,8 @@ class Settings std::function()> const& obtainCurrentLayout, InputDialog& inputDialog, ConfirmDialog& confirmDialog, - MultiInputDialog& multiInputDialog + MultiInputDialog& multiInputDialog, + NewSessionDialog& newSessionDialog ); ROAR_PIMPL_SPECIAL_FUNCTIONS(Settings); @@ -35,6 +37,12 @@ class Settings void applySettingsToUi(); + /** @brief Open the new-session dialog; on confirm, create the session, persist it, + * activate it in Settings and scroll to its Host field. Safe to call when + * the Settings panel is closed -- it will open via requestOpenSettingsAtId. + */ + void addNewSession(); + private: Nui::ElementRenderer side(); Nui::ElementRenderer header(); @@ -58,7 +66,6 @@ class Settings Nui::ElementRenderer sectionSelector(SectionSelectorOptions const& options); bool isActive(SectionSelectorOptions const& options); - void addNewSession(); void onChange(); void save(); void applySettingsToState(Persistence::State& state); diff --git a/frontend/include/frontend/toolbar.hpp b/frontend/include/frontend/toolbar.hpp index 1c1bd12c..0bff20cc 100644 --- a/frontend/include/frontend/toolbar.hpp +++ b/frontend/include/frontend/toolbar.hpp @@ -10,6 +10,7 @@ #include class SessionArea; +class Settings; class Toolbar { @@ -24,6 +25,7 @@ class Toolbar ROAR_PIMPL_SPECIAL_FUNCTIONS(Toolbar); void sessionArea(SessionArea& sessionArea); + void settings(Settings& settings); Nui::ElementRenderer operator()(); std::string selectedLayout() const; diff --git a/frontend/source/frontend/main_page.cpp b/frontend/source/frontend/main_page.cpp index 1dd7b1c8..2f0d233d 100644 --- a/frontend/source/frontend/main_page.cpp +++ b/frontend/source/frontend/main_page.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,7 @@ struct MainPage::Implementation FilePropertyDialog filePropertyDialog; ArchiveTransferDialog archiveTransferDialog; DirectConnectDialog directConnectDialog; + NewSessionDialog newSessionDialog; PasswordPrompter prompter; MultiInputDialog multiInputDialog; Sidebar sidebar; @@ -47,6 +49,7 @@ struct MainPage::Implementation , filePropertyDialog{"FilePropertyDialog"} , archiveTransferDialog{"ArchiveTransferDialog"} , directConnectDialog{"DirectConnectDialog", stateHolder} + , newSessionDialog{"NewSessionDialog"} , prompter{} , multiInputDialog{"MultiInputDialog"} , sidebar{stateHolder, events} @@ -54,7 +57,7 @@ struct MainPage::Implementation , sessionArea{stateHolder, events, &newItemAskDialog, &confirmDialog, &filePropertyDialog, &archiveTransferDialog, &toolbar} , settings{stateHolder, events, [this](){ return sessionArea.getActiveSessionLayout(); - }, newItemAskDialog, confirmDialog, multiInputDialog} + }, newItemAskDialog, confirmDialog, multiInputDialog, newSessionDialog} , licenses{events} , onboarding{stateHolder, events} , darkMode{true} @@ -62,6 +65,7 @@ struct MainPage::Implementation { Log::info("MainPage::Implementation()"); toolbar.sessionArea(sessionArea); + toolbar.settings(settings); } ~Implementation() @@ -96,6 +100,11 @@ void MainPage::onSetupComplete() impl_->onboarding.maybeStart(); return; } + if (!impl_->stateHolder->stateCache().uiOptions.onboardingCompleted) + { + impl_->onboarding.maybeStart(); + return; + } impl_->confirmDialog.open({ .styleVariant = ScriptNuiComponents::StyleVariant::Warning, .headerText = language->get("persistence", "warningLoadingState"), @@ -156,6 +165,7 @@ Nui::ElementRenderer MainPage::render() impl_->filePropertyDialog(), impl_->archiveTransferDialog(), impl_->directConnectDialog(), + impl_->newSessionDialog(), impl_->multiInputDialog(), impl_->settings(), impl_->licenses(), diff --git a/frontend/source/frontend/settings.cpp b/frontend/source/frontend/settings.cpp index ba91e7e4..325c241a 100644 --- a/frontend/source/frontend/settings.cpp +++ b/frontend/source/frontend/settings.cpp @@ -78,7 +78,7 @@ struct Settings::Implementation InputDialog* inputDialog; ConfirmDialog* confirmDialog; MultiInputDialog* multiInputDialog; - NewSessionDialog newSessionDialog{"settings"}; + NewSessionDialog* newSessionDialog{nullptr}; Nui::ThrottledFunction throttledSave{}; Nui::ThrottledFunction throttledReloadInheritance{}; Nui::Observed activeSection{Settings::Section::GeneralSettings}; @@ -152,6 +152,7 @@ struct Settings::Implementation InputDialog& inputDialog, ConfirmDialog& confirmDialog, MultiInputDialog& multiInputDialog, + NewSessionDialog& newSessionDialog, std::invocable auto const& onChange, std::invocable auto const& reloadInheritance ) @@ -160,6 +161,7 @@ struct Settings::Implementation , inputDialog{&inputDialog} , confirmDialog{&confirmDialog} , multiInputDialog{&multiInputDialog} + , newSessionDialog{&newSessionDialog} , generalSettings{onChange, events, inputDialog, multiInputDialog} , termiosSettings{[onChange, reloadInheritance]() { @@ -196,7 +198,8 @@ Settings::Settings( std::function()> const& obtainCurrentLayout, InputDialog& inputDialog, ConfirmDialog& confirmDialog, - MultiInputDialog& multiInputDialog + MultiInputDialog& multiInputDialog, + NewSessionDialog& newSessionDialog ) : impl_{std::make_unique( stateHolder, @@ -205,6 +208,7 @@ Settings::Settings( inputDialog, confirmDialog, multiInputDialog, + newSessionDialog, [this]() { if (impl_->applyingToUi) @@ -760,7 +764,6 @@ Nui::ElementRenderer Settings::operator()() }( Nui::Elements::span{}(language->get("settings", "loadingSettings")) ), - impl_->newSessionDialog(), div{ class_ = "settings-page", }( @@ -928,7 +931,7 @@ bool Settings::isActive(SectionSelectorOptions const& options) void Settings::addNewSession() { impl_->events->onAddNewSessionRequested.modify(); - impl_->newSessionDialog.open({ + impl_->newSessionDialog->open({ .onConfirm = [this](auto const& result) { Log::info("New session created: {}.", result.sessionName); @@ -1324,7 +1327,7 @@ void Settings::renameActiveSession() return; const auto oldSessionId = **impl_->activeSession; - impl_->newSessionDialog.open({ + impl_->newSessionDialog->open({ .onConfirm = [this, oldSessionId](NewSessionDialog::ConfirmResult const& result) { @@ -1395,7 +1398,7 @@ void Settings::copyActiveSession() const auto sourceIcon = impl_->stateHolder->stateCache().sessions.count(sourceSessionId) ? impl_->stateHolder->stateCache().sessions.at(sourceSessionId).icon : std::string{"laptop"}; - impl_->newSessionDialog.open({ + impl_->newSessionDialog->open({ .onConfirm = [this, sourceSessionId](NewSessionDialog::ConfirmResult const& result) { diff --git a/frontend/source/frontend/toolbar.cpp b/frontend/source/frontend/toolbar.cpp index c23908e4..ab244d93 100644 --- a/frontend/source/frontend/toolbar.cpp +++ b/frontend/source/frontend/toolbar.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -11,6 +12,7 @@ #include #include +#include #include @@ -21,6 +23,7 @@ #include #include #include +#include #include #include @@ -32,6 +35,7 @@ struct Toolbar::Implementation Persistence::StateHolder* stateHolder; FrontendEvents* events; SessionArea* sessionArea; + Settings* settings{nullptr}; ConfirmDialog* confirmDialog; DirectConnectDialog* directConnectDialog; ThemeController* themeController; @@ -218,14 +222,26 @@ Nui::ElementRenderer Toolbar::operator()() } }), Snc::button({ - .text = language->get("toolbar", "newSession"), - .icon = GeneratedSvgs::add(), + .text = language->get("toolbar", "connect"), + .icon = Ui5Icons::begin(), .attributes = { + disabled = Nui::observe(impl_->terminalEngines).generate( + [](auto const& engines) -> std::optional { + return engines.empty() ? std::optional{true} : std::nullopt; + } + ), onClick = [this]() { + if (impl_->terminalEngines.value().empty()) + return; impl_->events->onNewSession = impl_->activeTerminalEngine.value(); impl_->events->onNewSession.modifyNow(); }, }, + .styleVariant = Nui::observe(impl_->terminalEngines).generate( + [](auto const& engines) { + return engines.empty() ? Snc::StyleVariant::Regular : Snc::StyleVariant::Primary; + } + ), }), Snc::button({ .text = language->get("toolbar", "endSession"), @@ -240,6 +256,24 @@ Nui::ElementRenderer Toolbar::operator()() }, }, }), + Snc::button({ + .text = language->get("toolbar", "newSession"), + .icon = GeneratedSvgs::add(), + .attributes = { + onClick = [this]() { + if (!impl_->settings) { + Log::error("Toolbar::AddServer: settings is not set."); + return; + } + impl_->settings->addNewSession(); + }, + }, + .styleVariant = Nui::observe(impl_->terminalEngines).generate( + [](auto const& engines) { + return engines.empty() ? Snc::StyleVariant::Primary : Snc::StyleVariant::Regular; + } + ), + }), Snc::button({ .text = language->get("toolbar", "directConnect"), .icon = Ui5Icons::connected(), @@ -342,4 +376,9 @@ std::string Toolbar::selectedLayout() const void Toolbar::sessionArea(SessionArea& sessionArea) { impl_->sessionArea = &sessionArea; +} + +void Toolbar::settings(Settings& settings) +{ + impl_->settings = &settings; } \ No newline at end of file diff --git a/persistence/source/persistence/state_holder_backend.cpp b/persistence/source/persistence/state_holder_backend.cpp index 19c42b70..4346a2bc 100644 --- a/persistence/source/persistence/state_holder_backend.cpp +++ b/persistence/source/persistence/state_holder_backend.cpp @@ -61,9 +61,10 @@ namespace Persistence const auto path = Nui::resolvePath(Constants::persistencePath); std::optional error{std::nullopt}; + bool fileExisted = false; try { - const auto before = [&path, &error]() + const auto before = [&path, &error, &fileExisted]() { try { @@ -73,6 +74,7 @@ namespace Persistence Log::warn("Config file does not exist, creating it with defaults."); return nlohmann::json(nullptr); } + fileExisted = true; return nlohmann::json::parse(reader, nullptr, true, true); } catch (nlohmann::json::parse_error const& e) @@ -108,7 +110,12 @@ namespace Persistence if (before.is_null()) { // Save something valid - appendWarning(dataFixer(nlohmann::json::object())); + const auto warning = dataFixer(nlohmann::json::object()); + // On a true first run (no file existed) every default we just + // populated is expected behaviour, not something to warn about. + // Only surface warnings if the file existed but was unreadable. + if (fileExisted) + appendWarning(warning); error = std::nullopt; } else @@ -148,7 +155,8 @@ namespace Persistence std::optional StateHolder::dataFixer(nlohmann::json const& before) { const auto after = nlohmann::json(stateCache_); - bool mustSave = !nlohmann::json::diff(before, after).empty(); + const auto diff = nlohmann::json::diff(before, after); + bool mustSave = !diff.empty(); std::optional warning{std::nullopt}; auto extendWarning = [&](std::string const& msg) @@ -161,15 +169,29 @@ namespace Persistence if (mustSave) { - Log::warn("Config diff: {}", nlohmann::json::diff(before, after).dump()); - extendWarning( - fmt::format( - "Loaded json contains entries that are not understood by this version and were removed.\nThese " - "might have been some typos or entries from a newer version.\nPlease check the config file and " - "re-apply any necessary settings.\nDiff:\n{}", - nlohmann::json::diff(before, after).dump(4) - ) - ); + Log::warn("Config diff: {}", diff.dump()); + + // "Not understood by this version and were removed" only makes sense + // for actual remove ops. Pure-add diffs are the normal case when this + // version introduces fields the previous config didn't have -- not + // user-facing noise. + nlohmann::json droppedOps = nlohmann::json::array(); + for (auto const& op : diff) + { + if (op.is_object() && op.value("op", std::string{}) == "remove") + droppedOps.push_back(op); + } + if (!droppedOps.empty()) + { + extendWarning( + fmt::format( + "Loaded json contains entries that are not understood by this version and were removed.\n" + "These might have been some typos or entries from a newer version.\nPlease check the config " + "file and re-apply any necessary settings.\nDiff:\n{}", + droppedOps.dump(4) + ) + ); + } } bool hasMissingDefaults = false; @@ -212,6 +234,56 @@ namespace Persistence hasMissingDefaults = true; } + auto terminalOptionsNebula = stateCache_.terminalOptions.find("nebula"); + if (terminalOptionsNebula == stateCache_.terminalOptions.end()) + { + Log::warn("Config file misses 'nebula' terminal options, adding defaults."); + stateCache_.terminalOptions["nebula"] = TerminalOptions{ +#ifdef _WIN32 + .fontFamily = "consolas, monospace", +#else + .fontFamily = "Inconsolata, Hack, JetBrains Mono, Terminus, Fixed, monospace", +#endif + .fontSize = 14, + .lineHeight = 1.0, + .cursorBlink = false, +#ifdef __linux__ + .renderer = "dom", +#else + .renderer = "webgl", +#endif + .letterSpacing = 0, + .theme = TerminalTheme{ + .background = "#0e0e14", + .black = "#0a0a14", + .blue = "#7aa2f7", + .brightBlack = "#3a3a4a", + .brightBlue = "#9bbefb", + .brightCyan = "#88e0e8", + .brightGreen = "#a7f3c5", + .brightMagenta = "#c4a8ff", + .brightRed = "#ff8585", + .brightWhite = "#ecebf2", + .brightYellow = "#f4d999", + .cursor = "#5fc8d4", + .cursorAccent = "#0e0e14", + .cyan = "#5fc8d4", + .foreground = "#ecebf2", + .green = "#7ee8a2", + .magenta = "#a78bfa", + .red = "#e25c5c", + .selectionBackground = "rgba(140, 110, 220, 0.35)", + .selectionForeground = "#ecebf2", + .selectionInactiveBackground = "rgba(140, 110, 220, 0.18)", + .white = "#c5c2d4", + .yellow = "#e5c87a", + }, + }; + extendWarning("Added 'nebula' terminal options preset."); + mustSave = true; + hasMissingDefaults = true; + } + auto sshDefault = stateCache_.sshOptions.find("default"); if (sshDefault == stateCache_.sshOptions.end()) { diff --git a/static/assets/languages/de_DE.yaml b/static/assets/languages/de_DE.yaml index 77c89da7..1beb499d 100644 --- a/static/assets/languages/de_DE.yaml +++ b/static/assets/languages/de_DE.yaml @@ -674,7 +674,8 @@ rootWarning: text: "nui-sftp läuft mit Root-Rechten.\n\nDas ist gefährlich und unnötig:\n - Übertragene oder neu erstellte Dateien gehören anschließend root.\n - Ein Fehler, ein bösartiger Server oder ein kompromittiertes Gegenüber kann Ihr gesamtes System beschädigen.\n - Die Benutzer-D-Bus-Sitzung ist nicht verfügbar, daher funktioniert das Öffnen von Dateien mit externen Anwendungen nicht.\n - SSH-Schlüssel, Agents und Konfiguration aus Ihrem eigentlichen Heimatverzeichnis werden nicht verwendet.\n\nBitte schließen Sie die Anwendung und starten Sie sie als normaler Benutzer neu. Verwenden Sie sudo nur, wenn Sie wirklich Dateien bearbeiten müssen, die das erfordern, und ändern Sie lieber Dateiberechtigungen als die gesamte Oberfläche als root zu starten." toolbar: cannotUpdateLayouts: "Layouts können nicht aktualisiert werden." - newSession: "Neue Sitzung" + newSession: "Server Hinzufügen" + connect: "Verbinden" endSession: "Sitzung Beenden" directConnect: "Direktverbindung" settings: "Einstellungen" diff --git a/static/assets/languages/en_US.yaml b/static/assets/languages/en_US.yaml index 7b3a9b66..152225a1 100644 --- a/static/assets/languages/en_US.yaml +++ b/static/assets/languages/en_US.yaml @@ -671,7 +671,8 @@ rootWarning: text: "nui-sftp is running with root privileges.\n\nThis is dangerous and unnecessary:\n - Files transferred or created will be owned by root.\n - A bug, a malicious server, or a compromised remote can damage your entire system.\n - The user D-Bus session is unavailable, so opening files with external applications will not work.\n - SSH keys, agents and configuration normally found in your real home directory will not be picked up.\n\nClose the application and restart it as your normal user. Use sudo only when you genuinely need to manipulate files that require it, and prefer changing file ownership over running the whole GUI as root." toolbar: cannotUpdateLayouts: "Cannot update layouts." - newSession: "New Session" + newSession: "Add Server" + connect: "Connect" endSession: "End Session" directConnect: "Direct Connect" settings: "Settings" diff --git a/static/styles/main.css b/static/styles/main.css index 541b469d..3d967de6 100644 --- a/static/styles/main.css +++ b/static/styles/main.css @@ -139,6 +139,8 @@ --script-nui-components-button-color: var(--color); --script-nui-components-button-color-regular: var(--background-color-fields); --script-nui-components-button-border-color-regular: #5F5E5A; + --script-nui-components-button-color-primary: color-mix(in srgb, var(--theme-color) 22%, black 78%); + --script-nui-components-button-border-color-primary: color-mix(in srgb, var(--theme-color) 55%, black 45%); --nui-file-grid-color: var(--color); --nui-file-grid-background-color: var(--background-color); diff --git a/themes/Nebula.css b/themes/Nebula.css index 2cf44c74..f3187c39 100644 --- a/themes/Nebula.css +++ b/themes/Nebula.css @@ -64,6 +64,65 @@ --nui-file-grid-border-color: rgba(255, 255, 255, 0.07); --nui-file-grid-item-highlight: color-mix(in oklch, var(--accent-a) 30%, transparent); --nui-file-grid-symbolic-link-color: color-mix(in oklch, var(--accent-b) 70%, white 20%); + + --script-nui-components-field-background-color: rgba(255, 255, 255, 0.04); + --script-nui-components-field-color: var(--color); + --script-nui-components-field-border-color: rgba(255, 255, 255, 0.13); + --script-nui-components-field-border-radius: 6px; + --script-nui-components-field-hover-shadow: 0 0 0 1px var(--accent-b); + --script-nui-components-field-focus-shadow: 0 0 0 2px color-mix(in oklch, var(--accent-b) 45%, transparent); + + --script-nui-components-button-color-regular: rgba(255, 255, 255, 0.04); + --script-nui-components-button-border-color-regular: rgba(255, 255, 255, 0.13); + --script-nui-components-button-color: var(--color); + + --script-nui-components-tabs-background-color: transparent; + --script-nui-components-tabs-background-color-tab: rgba(255, 255, 255, 0.025); + --script-nui-components-tabs-background-color-tab-hover: rgba(255, 255, 255, 0.06); + --script-nui-components-tabs-background-color-tab-selected: rgba(255, 255, 255, 0.08); + --script-nui-components-tabs-bar-border-color: rgba(255, 255, 255, 0.07); + --script-nui-components-tabs-border-color-tab: transparent; + --script-nui-components-tabs-border-color-tab-hover: rgba(255, 255, 255, 0.10); + --script-nui-components-tabs-color-tab: var(--color-secondary); + --script-nui-components-tabs-color-tab-hover: var(--color); + --script-nui-components-tabs-color-tab-selected: var(--color); + --script-nui-components-tabs-tab-border-color-selected: rgba(255, 255, 255, 0.13); + + --script-nui-components-tree-row-hover-bg: rgba(255, 255, 255, 0.04); + --script-nui-components-tree-row-selected-bg: color-mix(in oklch, var(--accent-a) 22%, transparent); + --script-nui-components-tree-guide-color: rgba(255, 255, 255, 0.07); + + --script-nui-components-dialog-background-color--regular: rgba(22, 22, 30, 0.78); + --script-nui-components-dialog-border-color: rgba(255, 255, 255, 0.08); + --script-nui-components-dialog-color: var(--color); + --script-nui-components-dialog-header-color: var(--color); + --script-nui-components-dialog-footer-color: var(--color-secondary); + + --script-nui-components-table-color: var(--color); + --script-nui-components-table-header-color: var(--color); + --script-nui-components-table-footer-color: var(--color-secondary); + --script-nui-components-table-cell-background: rgba(20, 20, 28, 0.55); + --script-nui-components-table-header-background: linear-gradient(180deg, rgba(30, 30, 40, 0.65), rgba(14, 14, 20, 0.65)); + --script-nui-components-table-footer-background: rgba(14, 14, 20, 0.65); + --script-nui-components-table-border-color: rgba(255, 255, 255, 0.07); + --script-nui-components-table-row-hover: rgba(255, 255, 255, 0.04); + --script-nui-components-table-handle-color: rgba(255, 255, 255, 0.18); + --script-nui-components-table-handle-active: var(--accent-b); + + --script-nui-popup-menu-bg-color: #14141c; + --script-nui-popup-menu-surface-color: #1c1c26; + --script-nui-popup-menu-border-color: rgba(255, 255, 255, 0.13); + --script-nui-popup-menu-text-color: var(--color); + --script-nui-popup-menu-text-muted-color: var(--color-secondary); + --script-nui-popup-menu-disabled-color: var(--subdued-text); + --script-nui-popup-menu-separator-color: rgba(255, 255, 255, 0.07); + --script-nui-popup-menu-shadow-color: rgba(0, 0, 0, 0.55); +} + +:root[data-custom-theme="Nebula"] .script-nui-select-popover { + background-color: #14141c !important; + border-color: rgba(255, 255, 255, 0.13) !important; + box-shadow: 0 12px 28px rgba(0, 0, 0, 0.55) !important; } :root[data-custom-theme="Nebula"] body { @@ -129,8 +188,7 @@ -webkit-backdrop-filter: blur(12px) saturate(120%) !important; } -:root[data-custom-theme="Nebula"] .script-nui-button.style-variant-primary, -:root[data-custom-theme="Nebula"] .script-nui-button[data-style-variant="primary"] { +:root[data-custom-theme="Nebula"] .script-nui-button[data-variant="primary"] { background: linear-gradient(135deg, var(--accent-a), var(--accent-b)) !important; color: #0a0a10 !important; border: 1px solid transparent !important; @@ -139,13 +197,13 @@ 0 0 0 1px rgba(255, 255, 255, 0.12) inset !important; } -:root[data-custom-theme="Nebula"] .script-nui-button:not(.style-variant-primary):not([data-style-variant="primary"]):not(.style-variant-danger):not([data-style-variant="danger"]) { +:root[data-custom-theme="Nebula"] .script-nui-button:not([data-variant="primary"]):not([data-variant="danger"]) { background: rgba(255, 255, 255, 0.04) !important; border: 1px solid rgba(255, 255, 255, 0.13) !important; color: var(--color) !important; } -:root[data-custom-theme="Nebula"] .script-nui-button:not(.style-variant-primary):not([data-style-variant="primary"]):not(.style-variant-danger):not([data-style-variant="danger"]):hover { +:root[data-custom-theme="Nebula"] .script-nui-button:not([data-variant="primary"]):not([data-variant="danger"]):hover { background: rgba(255, 255, 255, 0.08) !important; } @@ -203,6 +261,65 @@ --nui-file-grid-border-color: rgba(0, 0, 0, 0.07); --nui-file-grid-item-highlight: color-mix(in oklch, var(--accent-a) 22%, transparent); --nui-file-grid-symbolic-link-color: color-mix(in oklch, var(--accent-a) 70%, black 10%); + + --script-nui-components-field-background-color: rgba(255, 255, 255, 0.65); + --script-nui-components-field-color: var(--color); + --script-nui-components-field-border-color: rgba(0, 0, 0, 0.13); + --script-nui-components-field-border-radius: 6px; + --script-nui-components-field-hover-shadow: 0 0 0 1px var(--accent-b); + --script-nui-components-field-focus-shadow: 0 0 0 2px color-mix(in oklch, var(--accent-b) 35%, transparent); + + --script-nui-components-button-color-regular: rgba(255, 255, 255, 0.55); + --script-nui-components-button-border-color-regular: rgba(0, 0, 0, 0.13); + --script-nui-components-button-color: var(--color); + + --script-nui-components-tabs-background-color: transparent; + --script-nui-components-tabs-background-color-tab: rgba(255, 255, 255, 0.40); + --script-nui-components-tabs-background-color-tab-hover: rgba(255, 255, 255, 0.70); + --script-nui-components-tabs-background-color-tab-selected: rgba(255, 255, 255, 0.85); + --script-nui-components-tabs-bar-border-color: rgba(0, 0, 0, 0.07); + --script-nui-components-tabs-border-color-tab: transparent; + --script-nui-components-tabs-border-color-tab-hover: rgba(0, 0, 0, 0.10); + --script-nui-components-tabs-color-tab: var(--color-secondary); + --script-nui-components-tabs-color-tab-hover: var(--color); + --script-nui-components-tabs-color-tab-selected: var(--color); + --script-nui-components-tabs-tab-border-color-selected: rgba(0, 0, 0, 0.13); + + --script-nui-components-tree-row-hover-bg: rgba(0, 0, 0, 0.04); + --script-nui-components-tree-row-selected-bg: color-mix(in oklch, var(--accent-a) 18%, transparent); + --script-nui-components-tree-guide-color: rgba(0, 0, 0, 0.10); + + --script-nui-components-dialog-background-color--regular: rgba(255, 255, 255, 0.85); + --script-nui-components-dialog-border-color: rgba(0, 0, 0, 0.08); + --script-nui-components-dialog-color: var(--color); + --script-nui-components-dialog-header-color: var(--color); + --script-nui-components-dialog-footer-color: var(--color-secondary); + + --script-nui-components-table-color: var(--color); + --script-nui-components-table-header-color: var(--color); + --script-nui-components-table-footer-color: var(--color-secondary); + --script-nui-components-table-cell-background: rgba(255, 255, 255, 0.55); + --script-nui-components-table-header-background: linear-gradient(180deg, rgba(255, 255, 255, 0.85), rgba(244, 246, 250, 0.85)); + --script-nui-components-table-footer-background: rgba(244, 246, 250, 0.85); + --script-nui-components-table-border-color: rgba(0, 0, 0, 0.08); + --script-nui-components-table-row-hover: rgba(0, 0, 0, 0.04); + --script-nui-components-table-handle-color: rgba(0, 0, 0, 0.18); + --script-nui-components-table-handle-active: var(--accent-b); + + --script-nui-popup-menu-bg-color: #ffffff; + --script-nui-popup-menu-surface-color: #f4f5f8; + --script-nui-popup-menu-border-color: rgba(0, 0, 0, 0.13); + --script-nui-popup-menu-text-color: var(--color); + --script-nui-popup-menu-text-muted-color: var(--color-secondary); + --script-nui-popup-menu-disabled-color: var(--subdued-text); + --script-nui-popup-menu-separator-color: rgba(0, 0, 0, 0.07); + --script-nui-popup-menu-shadow-color: rgba(60, 70, 110, 0.25); +} + +:root[data-custom-theme="Nebula"][data-theme="light"] .script-nui-select-popover { + background-color: #ffffff !important; + border-color: rgba(0, 0, 0, 0.13) !important; + box-shadow: 0 12px 28px rgba(60, 70, 110, 0.25) !important; } :root[data-custom-theme="Nebula"][data-theme="light"] body { @@ -257,8 +374,7 @@ -webkit-backdrop-filter: blur(12px) saturate(120%) !important; } -:root[data-custom-theme="Nebula"][data-theme="light"] .script-nui-button.style-variant-primary, -:root[data-custom-theme="Nebula"][data-theme="light"] .script-nui-button[data-style-variant="primary"] { +:root[data-custom-theme="Nebula"][data-theme="light"] .script-nui-button[data-variant="primary"] { background: linear-gradient(135deg, var(--accent-a), var(--accent-b)) !important; color: #ffffff !important; border: 1px solid transparent !important; @@ -267,12 +383,12 @@ 0 0 0 1px rgba(255, 255, 255, 0.20) inset !important; } -:root[data-custom-theme="Nebula"][data-theme="light"] .script-nui-button:not(.style-variant-primary):not([data-style-variant="primary"]):not(.style-variant-danger):not([data-style-variant="danger"]) { +:root[data-custom-theme="Nebula"][data-theme="light"] .script-nui-button:not([data-variant="primary"]):not([data-variant="danger"]) { background: rgba(255, 255, 255, 0.55) !important; border: 1px solid rgba(0, 0, 0, 0.13) !important; color: var(--color) !important; } -:root[data-custom-theme="Nebula"][data-theme="light"] .script-nui-button:not(.style-variant-primary):not([data-style-variant="primary"]):not(.style-variant-danger):not([data-style-variant="danger"]):hover { +:root[data-custom-theme="Nebula"][data-theme="light"] .script-nui-button:not([data-variant="primary"]):not([data-variant="danger"]):hover { background: rgba(255, 255, 255, 0.85) !important; } \ No newline at end of file