diff --git a/src/components/layout/TopBar.tsx b/src/components/layout/TopBar.tsx
index 67e1405..b32da5a 100644
--- a/src/components/layout/TopBar.tsx
+++ b/src/components/layout/TopBar.tsx
@@ -7,7 +7,7 @@
import { Link, useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import * as LucideIcons from 'lucide-react';
-const { Sun, Moon, User, LogOut, Check, Menu, Sparkles, Search } = LucideIcons;
+const { Sun, Moon, User, LogOut, Check, Menu, Sparkles, Search, Radius } = LucideIcons;
import { Button } from '@/components/ui/button';
import { CommandPalette } from '@/components/common/CommandPalette';
import {
@@ -43,6 +43,8 @@ export function TopBar() {
const navigate = useNavigate();
const theme = useUIStore((s) => s.theme);
const toggleTheme = useUIStore((s) => s.toggleTheme);
+ const radius = useUIStore((s) => s.radius);
+ const toggleRadius = useUIStore((s) => s.toggleRadius);
const toggleSidebar = useUIStore((s) => s.toggleSidebar);
const setActiveSection = useUIStore((s) => s.setActiveSection);
const accounts = useAuthStore((s) => s.accounts);
@@ -189,6 +191,13 @@ export function TopBar() {
>
)}
+
+
+ {t('squareCorners', 'Square corners')}
+ {radius === 'square' && }
+
+
+
{
const endSessionEndpoint = useAuthStore.getState().endSessionEndpoint;
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 3eeb1fd..efe6b32 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -337,6 +337,7 @@
"periodValue": "Period value"
},
"sections": "Sections",
+ "squareCorners": "Square corners",
"toggleTheme": "Toggle theme",
"tracing": {
"addFilter": "Add filter",
diff --git a/src/index.css b/src/index.css
index 67a2012..208ecdb 100644
--- a/src/index.css
+++ b/src/index.css
@@ -90,6 +90,12 @@
--chart-5: 340 75% 60%;
}
+/* Square mode: every radius token derives multiplicatively from --radius,
+ so zeroing it here flattens all corners (rounded-full stays untouched). */
+:root[data-radius='square'] {
+ --radius: 0px;
+}
+
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
@@ -127,10 +133,10 @@
--color-chart-4: hsl(var(--chart-4));
--color-chart-5: hsl(var(--chart-5));
- --radius-sm: calc(var(--radius) - 4px);
- --radius-md: calc(var(--radius) - 2px);
+ --radius-sm: calc(var(--radius) * 0.5);
+ --radius-md: calc(var(--radius) * 0.75);
--radius-lg: var(--radius);
- --radius-xl: calc(var(--radius) + 4px);
+ --radius-xl: calc(var(--radius) * 1.5);
--animate-collapsible-down: collapsible-down 0.2s ease-out;
--animate-collapsible-up: collapsible-up 0.2s ease-out;
diff --git a/src/stores/uiStore.ts b/src/stores/uiStore.ts
index 8bfd068..ee0d44b 100644
--- a/src/stores/uiStore.ts
+++ b/src/stores/uiStore.ts
@@ -8,14 +8,18 @@ import { create } from 'zustand';
import { persist } from 'zustand/middleware';
type Theme = 'light' | 'dark';
+type Radius = 'rounded' | 'square';
interface UIState {
theme: Theme;
+ radius: Radius;
sidebarOpen: boolean;
activeSection: string;
toggleTheme: () => void;
setTheme: (theme: Theme) => void;
+ toggleRadius: () => void;
+ setRadius: (radius: Radius) => void;
toggleSidebar: () => void;
setSidebarOpen: (open: boolean) => void;
setActiveSection: (section: string) => void;
@@ -29,11 +33,16 @@ function applyThemeClass(theme: Theme) {
}
}
+function applyRadiusAttribute(radius: Radius) {
+ document.documentElement.dataset.radius = radius;
+}
+
export const useUIStore = create()(
persist(
(set, get) => ({
theme:
typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light',
+ radius: 'rounded',
sidebarOpen: typeof window !== 'undefined' ? (window.matchMedia?.('(min-width: 768px)').matches ?? true) : true,
activeSection: '',
@@ -48,6 +57,17 @@ export const useUIStore = create()(
set({ theme });
},
+ toggleRadius: () => {
+ const next = get().radius === 'rounded' ? 'square' : 'rounded';
+ applyRadiusAttribute(next);
+ set({ radius: next });
+ },
+
+ setRadius: (radius) => {
+ applyRadiusAttribute(radius);
+ set({ radius });
+ },
+
toggleSidebar: () => {
set({ sidebarOpen: !get().sidebarOpen });
},
@@ -64,11 +84,13 @@ export const useUIStore = create()(
name: 'stalwart-ui',
partialize: (state) => ({
theme: state.theme,
+ radius: state.radius,
}),
onRehydrateStorage: () => {
return (state) => {
if (state) {
applyThemeClass(state.theme);
+ applyRadiusAttribute(state.radius ?? 'rounded');
}
};
},