mirror of
https://github.com/netbirdio/netbird.git
synced 2026-07-19 15:01:29 +02:00
Merge remote-tracking branch 'origin/ui-refactor' into ui-refactor
This commit is contained in:
@@ -11,7 +11,7 @@ const Root = forwardRef<
|
||||
<Tabs.Root
|
||||
ref={ref}
|
||||
orientation={"vertical"}
|
||||
className={cn("flex flex-1 min-h-0 gap-4", className)}
|
||||
className={cn("flex flex-1 min-h-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -22,7 +22,7 @@ const List = forwardRef<HTMLDivElement, Tabs.TabsListProps>(
|
||||
return (
|
||||
<Tabs.List
|
||||
ref={ref}
|
||||
className={cn("w-full flex flex-col gap-1", className)}
|
||||
className={cn("w-full flex flex-col gap-1 p-4 pr-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -20,7 +20,7 @@ export const AppRightPanel = ({ children, overlay, overlayOpen = false }: Props)
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"wails-no-draggable relative",
|
||||
"wails-no-draggable relative m-4",
|
||||
"bg-nb-gray-940 border border-nb-gray-920",
|
||||
"flex-1 min-h-0 min-w-0 flex flex-col rounded-xl rounded-br-2xl overflow-hidden",
|
||||
)}
|
||||
|
||||
@@ -143,10 +143,10 @@ export const MainHeader = () => {
|
||||
<div
|
||||
className={cn(
|
||||
"shrink-0 cursor-default wails-draggable relative",
|
||||
"flex items-center h-12 px-3 top-2.5",
|
||||
"flex items-center h-12 top-2.5",
|
||||
)}
|
||||
>
|
||||
<div className={"grid grid-cols-3 items-center w-[356px] shrink-0"}>
|
||||
<div className={"grid grid-cols-3 items-center w-[364px] shrink-0"}>
|
||||
<div />
|
||||
<div className={"flex justify-center ml-4"}>{profileSlot}</div>
|
||||
<div />
|
||||
|
||||
@@ -35,9 +35,9 @@ const MainBody = () => {
|
||||
const isAdvanced = viewMode === "advanced";
|
||||
|
||||
return (
|
||||
<div className={"wails-draggable flex flex-1 min-h-0 p-4 gap-4"}>
|
||||
<div className={"wails-draggable flex flex-1 min-h-0 gap-4r"}>
|
||||
<div
|
||||
className={"flex flex-col items-center shrink-0 w-[348px]"}
|
||||
className={"flex flex-col items-center shrink-0 w-[364px]"}
|
||||
>
|
||||
<MainConnectionStatusSwitch />
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useLocation } from "react-router-dom";
|
||||
import { Events } from "@wailsio/runtime";
|
||||
import * as ScrollArea from "@radix-ui/react-scroll-area";
|
||||
import { cn } from "@/lib/cn";
|
||||
import { isMacOS } from "@/lib/platform";
|
||||
import { AppRightPanel } from "@/layouts/AppRightPanel.tsx";
|
||||
import { VerticalTabs } from "@/components/VerticalTabs.tsx";
|
||||
import { SettingsNavigation } from "@/modules/settings/SettingsNavigation.tsx";
|
||||
@@ -50,15 +51,18 @@ export const SettingsPage = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={
|
||||
"wails-draggable cursor-default select-none h-12 shrink-0"
|
||||
}
|
||||
/>
|
||||
{isMacOS() ? (
|
||||
<div
|
||||
className={
|
||||
"wails-draggable cursor-default select-none h-12 shrink-0"
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<div className={"h-px shrink-0 bg-nb-gray-920/0"} />
|
||||
)}
|
||||
<VerticalTabs
|
||||
value={active}
|
||||
onValueChange={setActive}
|
||||
className={"p-4"}
|
||||
>
|
||||
<SettingsNavigation />
|
||||
<AppRightPanel>
|
||||
|
||||
@@ -288,19 +288,13 @@ func newMainWindow(app *application.App, prefStore *preferences.Store) *applicat
|
||||
Width: initialWidth,
|
||||
Height: 640,
|
||||
Hidden: true,
|
||||
BackgroundColour: application.NewRGB(24, 26, 29),
|
||||
BackgroundColour: services.WindowBackgroundColour,
|
||||
URL: "/",
|
||||
DisableResize: true,
|
||||
MinimiseButtonState: application.ButtonHidden,
|
||||
MaximiseButtonState: application.ButtonHidden,
|
||||
Mac: application.MacWindow{
|
||||
InvisibleTitleBarHeight: 38,
|
||||
Backdrop: application.MacBackdropNormal,
|
||||
TitleBar: application.MacTitleBarHiddenInset,
|
||||
CollectionBehavior: application.MacWindowCollectionBehaviorFullScreenNone,
|
||||
},
|
||||
Windows: application.WindowsWindow{
|
||||
Theme: application.Dark,
|
||||
},
|
||||
Mac: services.AppleMacOSAppearanceOptions(),
|
||||
Windows: services.MicrosoftWindowsAppearanceOptions(),
|
||||
Linux: application.LinuxWindow{
|
||||
Icon: iconWindow,
|
||||
},
|
||||
|
||||
@@ -28,6 +28,81 @@ const EventBrowserLoginCancel = "browser-login:cancel"
|
||||
// flashed the SettingsSkeleton between opens.
|
||||
const EventSettingsOpen = "netbird:settings:open"
|
||||
|
||||
// WindowBackgroundColour is the shared in-window background for every
|
||||
// NetBird webview (matches the bg-nb-gray utility in the Tailwind config
|
||||
// at #181A1D / nb-gray-950, used by AppLayout's <html> background).
|
||||
var WindowBackgroundColour = application.NewRGB(24, 26, 29)
|
||||
|
||||
// Wails reads CustomTheme colours as 0x00BBGGRR (RGB byte order reversed).
|
||||
// Border + title bar match AppRightPanel's bg-nb-gray-940 (#1C1E21);
|
||||
// title text matches text-nb-gray-100 (#E4E7E9). u32ptr exists only
|
||||
// because WindowTheme fields are *uint32 and Go has no literal address-of.
|
||||
func u32ptr(v uint32) *uint32 { return &v }
|
||||
|
||||
var microsoftWindowsTheme = &application.WindowTheme{
|
||||
BorderColour: u32ptr(0x00211E1C),
|
||||
TitleBarColour: u32ptr(0x00211E1C),
|
||||
TitleTextColour: u32ptr(0x00E9E7E4),
|
||||
}
|
||||
|
||||
// MicrosoftWindowsAppearanceOptions is the per-window Microsoft Windows OS
|
||||
// chrome shared by every NetBird webview window. Mica backdrop (no-op on
|
||||
// pre-22621), dark theme, custom title bar/border colours so the chrome
|
||||
// reads as an extension of the in-window AppRightPanel.
|
||||
func MicrosoftWindowsAppearanceOptions() application.WindowsWindow {
|
||||
return application.WindowsWindow{
|
||||
BackdropType: application.Mica,
|
||||
Theme: application.Dark,
|
||||
CustomTheme: application.ThemeSettings{
|
||||
DarkModeActive: microsoftWindowsTheme,
|
||||
DarkModeInactive: microsoftWindowsTheme,
|
||||
LightModeActive: microsoftWindowsTheme,
|
||||
LightModeInactive: microsoftWindowsTheme,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// AppleMacOSAppearanceOptions is the per-window macOS chrome shared by
|
||||
// every NetBird webview window. The hidden title bar inset clears space
|
||||
// for the traffic-light buttons; the FullScreenNone collection behavior
|
||||
// keeps the green button from offering a full-screen mode that breaks
|
||||
// our fixed-size layouts.
|
||||
func AppleMacOSAppearanceOptions() application.MacWindow {
|
||||
return application.MacWindow{
|
||||
InvisibleTitleBarHeight: 38,
|
||||
Backdrop: application.MacBackdropNormal,
|
||||
TitleBar: application.MacTitleBarHiddenInset,
|
||||
CollectionBehavior: application.MacWindowCollectionBehaviorFullScreenNone,
|
||||
}
|
||||
}
|
||||
|
||||
// DialogWindowOptions is the baseline for every auxiliary dialog window
|
||||
// (BrowserLogin, SessionExpired, SessionAboutToExpire, InstallProgress).
|
||||
// All four share size (360x320), the no-resize / no-min / no-max chrome,
|
||||
// Hidden-on-create (so the React side can auto-size before first paint),
|
||||
// AlwaysOnTop (the dialogs interrupt the user, the SSO popup overrides
|
||||
// this), and the shared background/Mac/Windows appearance. Callers fill
|
||||
// in per-dialog overrides (URL params, screen targeting, etc.) on the
|
||||
// returned value before passing it to Window.NewWithOptions.
|
||||
func DialogWindowOptions(name, title, url string) application.WebviewWindowOptions {
|
||||
return application.WebviewWindowOptions{
|
||||
Name: name,
|
||||
Title: title,
|
||||
Width: 360,
|
||||
Height: 320,
|
||||
DisableResize: true,
|
||||
AlwaysOnTop: true,
|
||||
Hidden: true,
|
||||
MinimiseButtonState: application.ButtonHidden,
|
||||
MaximiseButtonState: application.ButtonHidden,
|
||||
CloseButtonState: application.ButtonEnabled,
|
||||
BackgroundColour: WindowBackgroundColour,
|
||||
URL: url,
|
||||
Mac: AppleMacOSAppearanceOptions(),
|
||||
Windows: MicrosoftWindowsAppearanceOptions(),
|
||||
}
|
||||
}
|
||||
|
||||
// WindowManager opens auxiliary application windows on demand from the
|
||||
// frontend. The main window is created up-front in main.go; this service is
|
||||
// for secondary surfaces (Settings, BrowserLogin, Session*, InstallProgress).
|
||||
@@ -68,7 +143,7 @@ func NewWindowManager(app *application.App, mainWindow *application.WebviewWindo
|
||||
s := &WindowManager{app: app, mainWindow: mainWindow}
|
||||
s.settings = app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Name: "settings",
|
||||
Title: "NetBird Settings",
|
||||
Title: "Settings",
|
||||
Width: 900,
|
||||
Height: 640,
|
||||
Hidden: true,
|
||||
@@ -76,17 +151,10 @@ func NewWindowManager(app *application.App, mainWindow *application.WebviewWindo
|
||||
MinimiseButtonState: application.ButtonHidden,
|
||||
MaximiseButtonState: application.ButtonHidden,
|
||||
CloseButtonState: application.ButtonEnabled,
|
||||
BackgroundColour: application.NewRGB(24, 26, 29),
|
||||
BackgroundColour: WindowBackgroundColour,
|
||||
URL: "/#/settings",
|
||||
Mac: application.MacWindow{
|
||||
InvisibleTitleBarHeight: 38,
|
||||
Backdrop: application.MacBackdropNormal,
|
||||
TitleBar: application.MacTitleBarHiddenInset,
|
||||
CollectionBehavior: application.MacWindowCollectionBehaviorFullScreenNone,
|
||||
},
|
||||
Windows: application.WindowsWindow{
|
||||
Theme: application.Dark,
|
||||
},
|
||||
Mac: AppleMacOSAppearanceOptions(),
|
||||
Windows: MicrosoftWindowsAppearanceOptions(),
|
||||
})
|
||||
// Hide on close instead of destroying — preserves in-window React state
|
||||
// across reopens. Mirrors the main window's close behaviour. Resetting
|
||||
@@ -143,36 +211,17 @@ func (s *WindowManager) OpenBrowserLogin(uri string) {
|
||||
screen = sc
|
||||
}
|
||||
}
|
||||
s.browserLogin = s.app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Name: "browser-login",
|
||||
Title: "NetBird Sign-in",
|
||||
Width: 360,
|
||||
Height: 320,
|
||||
DisableResize: true,
|
||||
// Hidden so the React side can measure its content via
|
||||
// useAutoSizeWindow and call Window.SetSize + Show before the
|
||||
// user sees the placeholder snapping to the measured height,
|
||||
// matching the Session* windows.
|
||||
Hidden: true,
|
||||
// WindowCentered + Screen centers on the chosen display's
|
||||
// WorkArea (see WebviewWindowOptions.Screen docs).
|
||||
InitialPosition: application.WindowCentered,
|
||||
Screen: screen,
|
||||
MinimiseButtonState: application.ButtonHidden,
|
||||
MaximiseButtonState: application.ButtonHidden,
|
||||
CloseButtonState: application.ButtonEnabled,
|
||||
BackgroundColour: application.NewRGB(24, 26, 29),
|
||||
URL: startURL,
|
||||
Mac: application.MacWindow{
|
||||
InvisibleTitleBarHeight: 38,
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInset,
|
||||
CollectionBehavior: application.MacWindowCollectionBehaviorFullScreenNone,
|
||||
},
|
||||
Windows: application.WindowsWindow{
|
||||
Theme: application.Dark,
|
||||
},
|
||||
})
|
||||
opts := DialogWindowOptions("browser-login", "NetBird Sign-in", startURL)
|
||||
// SSO popup deliberately is NOT always-on-top — the user moves
|
||||
// between the browser tab and our popup; pinning it would obscure
|
||||
// the browser at the moment they need to interact with it.
|
||||
opts.AlwaysOnTop = false
|
||||
// WindowCentered + Screen centers on the chosen display's
|
||||
// WorkArea (see WebviewWindowOptions.Screen docs) so the popup
|
||||
// follows the user onto the screen they're already looking at.
|
||||
opts.InitialPosition = application.WindowCentered
|
||||
opts.Screen = screen
|
||||
s.browserLogin = s.app.Window.NewWithOptions(opts)
|
||||
bl := s.browserLogin
|
||||
// User-initiated close (red X) means cancel. Emit the event so
|
||||
// startLogin() can tear the SSO wait down, then let the window
|
||||
@@ -271,29 +320,9 @@ func (s *WindowManager) OpenSessionExpired() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.sessionExpired == nil {
|
||||
s.sessionExpired = s.app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Name: "session-expired",
|
||||
Title: "NetBird",
|
||||
Width: 360,
|
||||
Height: 320,
|
||||
DisableResize: true,
|
||||
AlwaysOnTop: true,
|
||||
Hidden: true,
|
||||
MinimiseButtonState: application.ButtonHidden,
|
||||
MaximiseButtonState: application.ButtonHidden,
|
||||
CloseButtonState: application.ButtonEnabled,
|
||||
BackgroundColour: application.NewRGB(24, 26, 29),
|
||||
URL: "/#/dialog/session-expired",
|
||||
Mac: application.MacWindow{
|
||||
InvisibleTitleBarHeight: 38,
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInset,
|
||||
CollectionBehavior: application.MacWindowCollectionBehaviorFullScreenNone,
|
||||
},
|
||||
Windows: application.WindowsWindow{
|
||||
Theme: application.Dark,
|
||||
},
|
||||
})
|
||||
s.sessionExpired = s.app.Window.NewWithOptions(
|
||||
DialogWindowOptions("session-expired", "NetBird", "/#/dialog/session-expired"),
|
||||
)
|
||||
s.sessionExpired.OnWindowEvent(events.Common.WindowClosing, func(_ *application.WindowEvent) {
|
||||
s.mu.Lock()
|
||||
s.sessionExpired = nil
|
||||
@@ -326,29 +355,9 @@ func (s *WindowManager) OpenSessionAboutToExpire(seconds int) {
|
||||
defer s.mu.Unlock()
|
||||
startURL := "/#/dialog/session-about-to-expire?seconds=" + strconv.Itoa(seconds)
|
||||
if s.sessionAboutToExpire == nil {
|
||||
s.sessionAboutToExpire = s.app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Name: "session-about-to-expire",
|
||||
Title: "NetBird",
|
||||
Width: 360,
|
||||
Height: 320,
|
||||
DisableResize: true,
|
||||
AlwaysOnTop: true,
|
||||
Hidden: true,
|
||||
MinimiseButtonState: application.ButtonHidden,
|
||||
MaximiseButtonState: application.ButtonHidden,
|
||||
CloseButtonState: application.ButtonEnabled,
|
||||
BackgroundColour: application.NewRGB(24, 26, 29),
|
||||
URL: startURL,
|
||||
Mac: application.MacWindow{
|
||||
InvisibleTitleBarHeight: 38,
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInset,
|
||||
CollectionBehavior: application.MacWindowCollectionBehaviorFullScreenNone,
|
||||
},
|
||||
Windows: application.WindowsWindow{
|
||||
Theme: application.Dark,
|
||||
},
|
||||
})
|
||||
s.sessionAboutToExpire = s.app.Window.NewWithOptions(
|
||||
DialogWindowOptions("session-about-to-expire", "NetBird", startURL),
|
||||
)
|
||||
s.sessionAboutToExpire.OnWindowEvent(events.Common.WindowClosing, func(_ *application.WindowEvent) {
|
||||
s.mu.Lock()
|
||||
s.sessionAboutToExpire = nil
|
||||
@@ -392,29 +401,9 @@ func (s *WindowManager) OpenInstallProgress(version string) {
|
||||
}
|
||||
if s.installProgress == nil {
|
||||
s.hideOtherWindowsLocked("install-progress")
|
||||
s.installProgress = s.app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Name: "install-progress",
|
||||
Title: "NetBird",
|
||||
Width: 360,
|
||||
Height: 320,
|
||||
DisableResize: true,
|
||||
AlwaysOnTop: true,
|
||||
Hidden: true,
|
||||
MinimiseButtonState: application.ButtonHidden,
|
||||
MaximiseButtonState: application.ButtonHidden,
|
||||
CloseButtonState: application.ButtonEnabled,
|
||||
BackgroundColour: application.NewRGB(24, 26, 29),
|
||||
URL: startURL,
|
||||
Mac: application.MacWindow{
|
||||
InvisibleTitleBarHeight: 38,
|
||||
Backdrop: application.MacBackdropTranslucent,
|
||||
TitleBar: application.MacTitleBarHiddenInset,
|
||||
CollectionBehavior: application.MacWindowCollectionBehaviorFullScreenNone,
|
||||
},
|
||||
Windows: application.WindowsWindow{
|
||||
Theme: application.Dark,
|
||||
},
|
||||
})
|
||||
s.installProgress = s.app.Window.NewWithOptions(
|
||||
DialogWindowOptions("install-progress", "NetBird", startURL),
|
||||
)
|
||||
s.installProgress.OnWindowEvent(events.Common.WindowClosing, func(_ *application.WindowEvent) {
|
||||
s.mu.Lock()
|
||||
s.installProgress = nil
|
||||
|
||||
Reference in New Issue
Block a user