From ae05e2cbf40abc24c47a17445503427a6c6ddbd2 Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Tue, 24 Mar 2026 23:55:50 +0100
Subject: [PATCH 01/12] prototype
---
web/messages/en/components.json | 1 +
web/messages/en/support.json | 23 ++
web/project.inlang/settings.json | 3 +-
web/src/pages/SupportPage/SupportPage.tsx | 202 ++++++++++++++++++
web/src/pages/SupportPage/styles.scss | 122 +++++++++++
web/src/routeTree.gen.ts | 22 ++
.../routes/_authorized/_default/support.tsx | 6 +
web/src/shared/api/api.ts | 4 +
.../components/Navigation/Navigation.tsx | 6 +
web/src/shared/constants.ts | 7 +
web/src/shared/defguard-ui | 2 +-
11 files changed, 396 insertions(+), 2 deletions(-)
create mode 100644 web/messages/en/support.json
create mode 100644 web/src/pages/SupportPage/SupportPage.tsx
create mode 100644 web/src/pages/SupportPage/styles.scss
create mode 100644 web/src/routes/_authorized/_default/support.tsx
diff --git a/web/messages/en/components.json b/web/messages/en/components.json
index 5237298d31..5c9ca7845a 100644
--- a/web/messages/en/components.json
+++ b/web/messages/en/components.json
@@ -27,6 +27,7 @@
"cmp_nav_item_overview": "VPN Overview",
"cmp_nav_item_settings": "Settings",
"cmp_nav_item_edges": "Edge Components",
+ "cmp_nav_item_support": "Support",
"cmp_nav_item_activity_log": "Activity log",
"cmp_webhook_event_user_delete": "User deleted",
"cmp_webhook_event_user_add": "New user created",
diff --git a/web/messages/en/support.json b/web/messages/en/support.json
new file mode 100644
index 0000000000..8090cace5c
--- /dev/null
+++ b/web/messages/en/support.json
@@ -0,0 +1,23 @@
+{
+ "$schema": "https://inlang.com/schema/inlang-message-format",
+ "support_page_title": "Support",
+ "support_page_subtitle": "When you need support or must supply diagnostic information to our team, please use one of the options below.",
+ "support_page_docs_title": "Have questions? Check our documentation first.",
+ "support_page_docs_desc": "Before contacting or submitting any issues to GitHub please get familiar with Defguard documentation available.",
+ "support_page_docs_btn": "Go to documentation",
+ "support_page_bug_title": "Report a bug",
+ "support_page_bug_desc": "We aim to respond to all bug reports as quickly as possible and prioritize them based on severity before adding them to our development backlog. To give us more context, you can optionally download the support data and/or log file and attach it to your bug report.",
+ "support_page_bug_btn_report": "Report on Github",
+ "support_page_bug_btn_download": "Download",
+ "support_page_bug_btn_download_support_data": "Download support data",
+ "support_page_bug_btn_download_logs": "Download logs",
+ "support_page_feature_title": "Request feature",
+ "support_page_feature_desc": "We grow with the help of our community. If you have an idea or a missing feature to suggest, please share it \u2014 we'll review it.",
+ "support_page_feature_btn": "Submit on Github",
+ "support_page_email_title": "Contact us by email",
+ "support_page_email_desc": "For any additional requests, reach out to us at",
+ "support_page_assistance_title": "Need Assistance?",
+ "support_page_assistance_desc": "Let us know your issue or arrange a meeting with our support team.",
+ "support_page_assistance_btn_ticket": "Open a support ticket",
+ "support_page_assistance_btn_call": "Schedule a call with our support team"
+}
diff --git a/web/project.inlang/settings.json b/web/project.inlang/settings.json
index 862e3ed1fb..ded05da087 100644
--- a/web/project.inlang/settings.json
+++ b/web/project.inlang/settings.json
@@ -29,7 +29,8 @@
"./messages/{locale}/initial_wizard.json",
"./messages/{locale}/migration_wizard.json",
"./messages/{locale}/api-error.json",
- "./messages/{locale}/flow_end.json"
+ "./messages/{locale}/flow_end.json",
+ "./messages/{locale}/support.json"
]
}
}
diff --git a/web/src/pages/SupportPage/SupportPage.tsx b/web/src/pages/SupportPage/SupportPage.tsx
new file mode 100644
index 0000000000..40c18492ae
--- /dev/null
+++ b/web/src/pages/SupportPage/SupportPage.tsx
@@ -0,0 +1,202 @@
+import './styles.scss';
+import type { ReactNode } from 'react';
+import { m } from '../../paraglide/messages';
+import api from '../../shared/api/api';
+import { Page } from '../../shared/components/Page/Page';
+import { SettingsCard } from '../../shared/components/SettingsCard/SettingsCard';
+import { SettingsHeader } from '../../shared/components/SettingsHeader/SettingsHeader';
+import { SettingsLayout } from '../../shared/components/SettingsLayout/SettingsLayout';
+import { Button } from '../../shared/defguard-ui/components/Button/Button';
+import { ButtonMenu } from '../../shared/defguard-ui/components/ButtonMenu/MenuButton';
+import { Divider } from '../../shared/defguard-ui/components/Divider/Divider';
+import { Icon } from '../../shared/defguard-ui/components/Icon';
+import type { IconKindValue } from '../../shared/defguard-ui/components/Icon/icon-types';
+import docIllustration from '../../shared/defguard-ui/components/SectionSelect/assets/manual-user.png';
+import { externalLink } from '../../shared/constants';
+import { downloadFile, downloadText } from '../../shared/utils/download';
+
+export const SupportPage = () => {
+ return (
+
+
+
+
+
+
+
+
+
{m.support_page_docs_desc()}
+
window.open(externalLink.defguard.docs, '_blank', 'noopener,noreferrer')}
+ />
+
+
+
+
+ }
+ >
+
+
+ window.open(externalLink.github.bugReport, '_blank', 'noopener,noreferrer')
+ }
+ />
+ {
+ const res = await api.support.getSupportData();
+ const blob = new Blob([JSON.stringify(res.data, null, 2)], {
+ type: 'application/json',
+ });
+ const now = new Date().toISOString().replace(/[:.]/g, '-');
+ downloadFile(blob, `defguard-support-data-${now}`, 'json');
+ },
+ },
+ {
+ text: m.support_page_bug_btn_download_logs(),
+ onClick: async () => {
+ const res = await api.support.getLogs();
+ const now = new Date().toISOString().replace(/[:.]/g, '-');
+ downloadText(res.data, `defguard-logs-${now}`, 'txt');
+ },
+ },
+ ],
+ },
+ ]}
+ />
+
+
+
+
+
+
+ window.open(externalLink.github.featureRequest, '_blank', 'noopener,noreferrer')
+ }
+ />
+
+
+
+
+ {m.support_page_email_desc()}{' '}
+ support@defguard.net
+ >
+ }
+ />
+
+
+
+
+ window.open(externalLink.defguard.support, '_blank', 'noopener,noreferrer')
+ }
+ />
+
+ window.open(externalLink.defguard.scheduleCall, '_blank', 'noopener,noreferrer')
+ }
+ />
+
+
+
+
+
+ );
+};
+
+/**
+ * Renders the bug section description with the "you can optionally download"
+ * portion in bold, matching the Figma design.
+ */
+const BugDescription = () => {
+ const full = m.support_page_bug_desc();
+ const boldPhrase = 'you can optionally download';
+ const idx = full.indexOf(boldPhrase);
+ if (idx === -1) return <>{full}>;
+ const before = full.slice(0, idx);
+ const after = full.slice(idx + boldPhrase.length);
+ return (
+ <>
+ {before}
+ {boldPhrase}
+ {after}
+ >
+ );
+};
+
+interface SupportSectionProps {
+ icon: IconKindValue;
+ title: string;
+ subtitle?: ReactNode;
+ subtitleDark?: boolean;
+ children?: ReactNode;
+}
+
+const SupportSection = ({
+ icon,
+ title,
+ subtitle,
+ subtitleDark,
+ children,
+}: SupportSectionProps) => {
+ return (
+
+
+
+
+
{title}
+ {subtitle && (
+
{subtitle}
+ )}
+
+ {children}
+
+
+ );
+};
diff --git a/web/src/pages/SupportPage/styles.scss b/web/src/pages/SupportPage/styles.scss
new file mode 100644
index 0000000000..aa9abe3c42
--- /dev/null
+++ b/web/src/pages/SupportPage/styles.scss
@@ -0,0 +1,122 @@
+#support-page-content {
+ width: 784px;
+
+ .support-section {
+ display: grid;
+ grid-template-columns: 32px 1fr;
+ column-gap: var(--spacing-xl);
+ align-items: start;
+ padding: var(--spacing-xl) 0;
+
+ &:first-child {
+ padding-top: 0;
+ }
+
+ &:last-child {
+ padding-bottom: 0;
+ }
+ }
+
+ .support-section-icon {
+ position: relative;
+ display: grid;
+ width: 32px;
+ height: 32px;
+ place-items: center;
+
+ & > * {
+ grid-row: 1;
+ grid-column: 1;
+ }
+
+ .bg {
+ width: 100%;
+ height: 100%;
+ background-color: var(--bg-action-muted);
+ border-radius: var(--radius-full);
+ }
+
+ .icon path {
+ fill: var(--fg-action);
+ }
+ }
+
+ .support-section-content {
+ display: flex;
+ flex-direction: column;
+ gap: var(--spacing-xl);
+
+ .section-header {
+ display: flex;
+ flex-direction: column;
+ gap: var(--spacing-sm);
+ }
+
+ .section-title {
+ font: var(--t-body-primary-500);
+ color: var(--fg-default);
+ margin: 0;
+ }
+
+ > .section-header > p:not(.section-title) {
+ font: var(--t-body-sm-400);
+ color: var(--fg-muted) !important;
+ margin: 0;
+
+ &.subtitle-dark {
+ color: var(--fg-default) !important;
+ }
+
+ a {
+ color: var(--fg-action);
+ text-decoration: underline;
+
+ &:hover {
+ text-decoration: none;
+ }
+ }
+
+ strong {
+ font-weight: 500;
+ }
+ }
+ }
+
+ .doc-highlight {
+ background: var(--bg-action-muted);
+ border-radius: var(--radius-md);
+ padding: var(--spacing-xl);
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: var(--spacing-2xl);
+
+ .doc-highlight-illustration {
+ width: 80px;
+ height: auto;
+ flex-shrink: 0;
+ }
+
+ .doc-highlight-content {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: var(--spacing-lg);
+ flex: 1;
+
+ p {
+ margin: 0;
+ font: var(--t-body-sm-400);
+ color: var(--fg-default) !important;
+ }
+ }
+ }
+
+ .support-controls {
+ display: flex;
+ flex-wrap: wrap;
+ flex-direction: row;
+ align-items: stretch;
+ gap: var(--spacing-md);
+ }
+}
diff --git a/web/src/routeTree.gen.ts b/web/src/routeTree.gen.ts
index 443c5dd0e8..aba953680d 100644
--- a/web/src/routeTree.gen.ts
+++ b/web/src/routeTree.gen.ts
@@ -37,6 +37,7 @@ import { Route as AuthorizedWizardAddLocationRouteImport } from './routes/_autho
import { Route as AuthorizedWizardAddExternalOpenidRouteImport } from './routes/_authorized/_wizard/add-external-openid'
import { Route as AuthorizedDefaultWebhooksRouteImport } from './routes/_authorized/_default/webhooks'
import { Route as AuthorizedDefaultUsersRouteImport } from './routes/_authorized/_default/users'
+import { Route as AuthorizedDefaultSupportRouteImport } from './routes/_authorized/_default/support'
import { Route as AuthorizedDefaultOpenidRouteImport } from './routes/_authorized/_default/openid'
import { Route as AuthorizedDefaultNetworkDevicesRouteImport } from './routes/_authorized/_default/network-devices'
import { Route as AuthorizedDefaultGroupsRouteImport } from './routes/_authorized/_default/groups'
@@ -211,6 +212,12 @@ const AuthorizedDefaultUsersRoute = AuthorizedDefaultUsersRouteImport.update({
path: '/users',
getParentRoute: () => AuthorizedDefaultRoute,
} as any)
+const AuthorizedDefaultSupportRoute =
+ AuthorizedDefaultSupportRouteImport.update({
+ id: '/support',
+ path: '/support',
+ getParentRoute: () => AuthorizedDefaultRoute,
+ } as any)
const AuthorizedDefaultOpenidRoute = AuthorizedDefaultOpenidRouteImport.update({
id: '/openid',
path: '/openid',
@@ -410,6 +417,7 @@ export interface FileRoutesByFullPath {
'/groups': typeof AuthorizedDefaultGroupsRoute
'/network-devices': typeof AuthorizedDefaultNetworkDevicesRoute
'/openid': typeof AuthorizedDefaultOpenidRoute
+ '/support': typeof AuthorizedDefaultSupportRoute
'/users': typeof AuthorizedDefaultUsersRoute
'/webhooks': typeof AuthorizedDefaultWebhooksRoute
'/add-external-openid': typeof AuthorizedWizardAddExternalOpenidRoute
@@ -467,6 +475,7 @@ export interface FileRoutesByTo {
'/groups': typeof AuthorizedDefaultGroupsRoute
'/network-devices': typeof AuthorizedDefaultNetworkDevicesRoute
'/openid': typeof AuthorizedDefaultOpenidRoute
+ '/support': typeof AuthorizedDefaultSupportRoute
'/users': typeof AuthorizedDefaultUsersRoute
'/webhooks': typeof AuthorizedDefaultWebhooksRoute
'/add-external-openid': typeof AuthorizedWizardAddExternalOpenidRoute
@@ -528,6 +537,7 @@ export interface FileRoutesById {
'/_authorized/_default/groups': typeof AuthorizedDefaultGroupsRoute
'/_authorized/_default/network-devices': typeof AuthorizedDefaultNetworkDevicesRoute
'/_authorized/_default/openid': typeof AuthorizedDefaultOpenidRoute
+ '/_authorized/_default/support': typeof AuthorizedDefaultSupportRoute
'/_authorized/_default/users': typeof AuthorizedDefaultUsersRoute
'/_authorized/_default/webhooks': typeof AuthorizedDefaultWebhooksRoute
'/_authorized/_wizard/add-external-openid': typeof AuthorizedWizardAddExternalOpenidRoute
@@ -588,6 +598,7 @@ export interface FileRouteTypes {
| '/groups'
| '/network-devices'
| '/openid'
+ | '/support'
| '/users'
| '/webhooks'
| '/add-external-openid'
@@ -645,6 +656,7 @@ export interface FileRouteTypes {
| '/groups'
| '/network-devices'
| '/openid'
+ | '/support'
| '/users'
| '/webhooks'
| '/add-external-openid'
@@ -705,6 +717,7 @@ export interface FileRouteTypes {
| '/_authorized/_default/groups'
| '/_authorized/_default/network-devices'
| '/_authorized/_default/openid'
+ | '/_authorized/_default/support'
| '/_authorized/_default/users'
| '/_authorized/_default/webhooks'
| '/_authorized/_wizard/add-external-openid'
@@ -956,6 +969,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthorizedDefaultUsersRouteImport
parentRoute: typeof AuthorizedDefaultRoute
}
+ '/_authorized/_default/support': {
+ id: '/_authorized/_default/support'
+ path: '/support'
+ fullPath: '/support'
+ preLoaderRoute: typeof AuthorizedDefaultSupportRouteImport
+ parentRoute: typeof AuthorizedDefaultRoute
+ }
'/_authorized/_default/openid': {
id: '/_authorized/_default/openid'
path: '/openid'
@@ -1175,6 +1195,7 @@ interface AuthorizedDefaultRouteChildren {
AuthorizedDefaultGroupsRoute: typeof AuthorizedDefaultGroupsRoute
AuthorizedDefaultNetworkDevicesRoute: typeof AuthorizedDefaultNetworkDevicesRoute
AuthorizedDefaultOpenidRoute: typeof AuthorizedDefaultOpenidRoute
+ AuthorizedDefaultSupportRoute: typeof AuthorizedDefaultSupportRoute
AuthorizedDefaultUsersRoute: typeof AuthorizedDefaultUsersRoute
AuthorizedDefaultWebhooksRoute: typeof AuthorizedDefaultWebhooksRoute
AuthorizedDefaultAclAddAliasRoute: typeof AuthorizedDefaultAclAddAliasRoute
@@ -1210,6 +1231,7 @@ const AuthorizedDefaultRouteChildren: AuthorizedDefaultRouteChildren = {
AuthorizedDefaultGroupsRoute: AuthorizedDefaultGroupsRoute,
AuthorizedDefaultNetworkDevicesRoute: AuthorizedDefaultNetworkDevicesRoute,
AuthorizedDefaultOpenidRoute: AuthorizedDefaultOpenidRoute,
+ AuthorizedDefaultSupportRoute: AuthorizedDefaultSupportRoute,
AuthorizedDefaultUsersRoute: AuthorizedDefaultUsersRoute,
AuthorizedDefaultWebhooksRoute: AuthorizedDefaultWebhooksRoute,
AuthorizedDefaultAclAddAliasRoute: AuthorizedDefaultAclAddAliasRoute,
diff --git a/web/src/routes/_authorized/_default/support.tsx b/web/src/routes/_authorized/_default/support.tsx
new file mode 100644
index 0000000000..5589a6e367
--- /dev/null
+++ b/web/src/routes/_authorized/_default/support.tsx
@@ -0,0 +1,6 @@
+import { createFileRoute } from '@tanstack/react-router';
+import { SupportPage } from '../../../pages/SupportPage/SupportPage';
+
+export const Route = createFileRoute('/_authorized/_default/support')({
+ component: SupportPage,
+});
diff --git a/web/src/shared/api/api.ts b/web/src/shared/api/api.ts
index 439b964869..8f50498978 100644
--- a/web/src/shared/api/api.ts
+++ b/web/src/shared/api/api.ts
@@ -530,6 +530,10 @@ const api = {
fetchPage(`/activity_log`, data),
info: () => client.get('/info'),
getLicenseInfo: () => client.get(`/enterprise_info`),
+ support: {
+ getSupportData: () => client.get('/support/configuration'),
+ getLogs: () => client.get('/support/logs'),
+ },
} as const;
export default api;
diff --git a/web/src/shared/components/Navigation/Navigation.tsx b/web/src/shared/components/Navigation/Navigation.tsx
index f7cc59a092..c148b2fdc0 100644
--- a/web/src/shared/components/Navigation/Navigation.tsx
+++ b/web/src/shared/components/Navigation/Navigation.tsx
@@ -150,6 +150,12 @@ const navigationConfig: NavGroupProps[] = [
label: m.cmp_nav_item_settings(),
link: '/settings',
},
+ {
+ id: 'support',
+ icon: 'support',
+ label: m.cmp_nav_item_support(),
+ link: '/support',
+ },
{
id: 'edges',
icon: 'globe',
diff --git a/web/src/shared/constants.ts b/web/src/shared/constants.ts
index f6e8afa748..216f597fc9 100644
--- a/web/src/shared/constants.ts
+++ b/web/src/shared/constants.ts
@@ -6,6 +6,13 @@ export const externalLink = {
pricing: 'https://defguard.net/pricing',
download: 'https://defguard.net/download',
sales: 'mailto:sales@defguard.net',
+ support: 'https://defguard.net/support/',
+ scheduleCall: 'https://calendly.com/defguard',
+ },
+ github: {
+ bugReport: 'https://github.com/DefGuard/defguard/issues/new?template=bug_report.md',
+ featureRequest:
+ 'https://github.com/DefGuard/defguard/issues/new?template=feature_request.md',
},
client: {
desktop: {
diff --git a/web/src/shared/defguard-ui b/web/src/shared/defguard-ui
index e77b9152d9..c65255fd36 160000
--- a/web/src/shared/defguard-ui
+++ b/web/src/shared/defguard-ui
@@ -1 +1 @@
-Subproject commit e77b9152d960c7ce25c2ed06504f4e94238dfaaa
+Subproject commit c65255fd36f0b82b2136b61f692e587fad644d54
From da1d16399aa83d8b28c715f031574c5b252f087d Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Wed, 25 Mar 2026 00:12:03 +0100
Subject: [PATCH 02/12] format and adjust styles
---
web/src/pages/SupportPage/SupportPage.tsx | 42 +++++++++++++++++++----
web/src/pages/SupportPage/styles.scss | 13 +++----
2 files changed, 40 insertions(+), 15 deletions(-)
diff --git a/web/src/pages/SupportPage/SupportPage.tsx b/web/src/pages/SupportPage/SupportPage.tsx
index 40c18492ae..e73d79980b 100644
--- a/web/src/pages/SupportPage/SupportPage.tsx
+++ b/web/src/pages/SupportPage/SupportPage.tsx
@@ -6,13 +6,13 @@ import { Page } from '../../shared/components/Page/Page';
import { SettingsCard } from '../../shared/components/SettingsCard/SettingsCard';
import { SettingsHeader } from '../../shared/components/SettingsHeader/SettingsHeader';
import { SettingsLayout } from '../../shared/components/SettingsLayout/SettingsLayout';
+import { externalLink } from '../../shared/constants';
import { Button } from '../../shared/defguard-ui/components/Button/Button';
import { ButtonMenu } from '../../shared/defguard-ui/components/ButtonMenu/MenuButton';
import { Divider } from '../../shared/defguard-ui/components/Divider/Divider';
import { Icon } from '../../shared/defguard-ui/components/Icon';
import type { IconKindValue } from '../../shared/defguard-ui/components/Icon/icon-types';
import docIllustration from '../../shared/defguard-ui/components/SectionSelect/assets/manual-user.png';
-import { externalLink } from '../../shared/constants';
import { downloadFile, downloadText } from '../../shared/utils/download';
export const SupportPage = () => {
@@ -34,7 +34,13 @@ export const SupportPage = () => {
variant="primary"
text={m.support_page_docs_btn()}
iconRight="open-in-new-window"
- onClick={() => window.open(externalLink.defguard.docs, '_blank', 'noopener,noreferrer')}
+ onClick={() =>
+ window.open(
+ externalLink.defguard.docs,
+ '_blank',
+ 'noopener,noreferrer',
+ )
+ }
/>
@@ -51,7 +57,11 @@ export const SupportPage = () => {
text={m.support_page_bug_btn_report()}
iconLeft="github"
onClick={() =>
- window.open(externalLink.github.bugReport, '_blank', 'noopener,noreferrer')
+ window.open(
+ externalLink.github.bugReport,
+ '_blank',
+ 'noopener,noreferrer',
+ )
}
/>
{
text={m.support_page_feature_btn()}
iconLeft="github"
onClick={() =>
- window.open(externalLink.github.featureRequest, '_blank', 'noopener,noreferrer')
+ window.open(
+ externalLink.github.featureRequest,
+ '_blank',
+ 'noopener,noreferrer',
+ )
}
/>
@@ -128,7 +142,11 @@ export const SupportPage = () => {
text={m.support_page_assistance_btn_ticket()}
iconRight="open-in-new-window"
onClick={() =>
- window.open(externalLink.defguard.support, '_blank', 'noopener,noreferrer')
+ window.open(
+ externalLink.defguard.support,
+ '_blank',
+ 'noopener,noreferrer',
+ )
}
/>
{
text={m.support_page_assistance_btn_call()}
iconRight="calendar"
onClick={() =>
- window.open(externalLink.defguard.scheduleCall, '_blank', 'noopener,noreferrer')
+ window.open(
+ externalLink.defguard.scheduleCall,
+ '_blank',
+ 'noopener,noreferrer',
+ )
}
/>
@@ -192,7 +214,13 @@ const SupportSection = ({
{title}
{subtitle && (
-
{subtitle}
+
+ {subtitle}
+
)}
{children}
diff --git a/web/src/pages/SupportPage/styles.scss b/web/src/pages/SupportPage/styles.scss
index aa9abe3c42..14c0aee646 100644
--- a/web/src/pages/SupportPage/styles.scss
+++ b/web/src/pages/SupportPage/styles.scss
@@ -6,7 +6,7 @@
grid-template-columns: 32px 1fr;
column-gap: var(--spacing-xl);
align-items: start;
- padding: var(--spacing-xl) 0;
+ padding: var(--spacing-2xl) 0;
&:first-child {
padding-top: 0;
@@ -58,13 +58,13 @@
margin: 0;
}
- > .section-header > p:not(.section-title) {
+ .section-subtitle {
font: var(--t-body-sm-400);
- color: var(--fg-muted) !important;
+ color: var(--fg-muted);
margin: 0;
&.subtitle-dark {
- color: var(--fg-default) !important;
+ color: var(--fg-default);
}
a {
@@ -87,7 +87,6 @@
border-radius: var(--radius-md);
padding: var(--spacing-xl);
display: flex;
- flex-direction: row;
align-items: center;
gap: var(--spacing-2xl);
@@ -107,7 +106,7 @@
p {
margin: 0;
font: var(--t-body-sm-400);
- color: var(--fg-default) !important;
+ color: var(--fg-default);
}
}
}
@@ -115,8 +114,6 @@
.support-controls {
display: flex;
flex-wrap: wrap;
- flex-direction: row;
- align-items: stretch;
gap: var(--spacing-md);
}
}
From 0a2e81a23674171656acfffa47bf78ad7f63c247 Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Wed, 25 Mar 2026 00:14:02 +0100
Subject: [PATCH 03/12] change text color
---
web/src/pages/SupportPage/SupportPage.tsx | 4 ----
web/src/pages/SupportPage/styles.scss | 2 +-
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/web/src/pages/SupportPage/SupportPage.tsx b/web/src/pages/SupportPage/SupportPage.tsx
index e73d79980b..02dccc4030 100644
--- a/web/src/pages/SupportPage/SupportPage.tsx
+++ b/web/src/pages/SupportPage/SupportPage.tsx
@@ -169,10 +169,6 @@ export const SupportPage = () => {
);
};
-/**
- * Renders the bug section description with the "you can optionally download"
- * portion in bold, matching the Figma design.
- */
const BugDescription = () => {
const full = m.support_page_bug_desc();
const boldPhrase = 'you can optionally download';
diff --git a/web/src/pages/SupportPage/styles.scss b/web/src/pages/SupportPage/styles.scss
index 14c0aee646..69637d2c68 100644
--- a/web/src/pages/SupportPage/styles.scss
+++ b/web/src/pages/SupportPage/styles.scss
@@ -106,7 +106,7 @@
p {
margin: 0;
font: var(--t-body-sm-400);
- color: var(--fg-default);
+ color: var(--fg-muted) !important;
}
}
}
From 157407b055d94c8701a83d46c92115db204aaf31 Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Wed, 25 Mar 2026 00:27:23 +0100
Subject: [PATCH 04/12] remove redundant styles
---
web/src/pages/SupportPage/SupportPage.tsx | 20 +++++++++-----------
web/src/pages/SupportPage/styles.scss | 8 +-------
2 files changed, 10 insertions(+), 18 deletions(-)
diff --git a/web/src/pages/SupportPage/SupportPage.tsx b/web/src/pages/SupportPage/SupportPage.tsx
index 02dccc4030..d2a77971ce 100644
--- a/web/src/pages/SupportPage/SupportPage.tsx
+++ b/web/src/pages/SupportPage/SupportPage.tsx
@@ -1,4 +1,5 @@
import './styles.scss';
+import clsx from 'clsx';
import type { ReactNode } from 'react';
import { m } from '../../paraglide/messages';
import api from '../../shared/api/api';
@@ -9,6 +10,7 @@ import { SettingsLayout } from '../../shared/components/SettingsLayout/SettingsL
import { externalLink } from '../../shared/constants';
import { Button } from '../../shared/defguard-ui/components/Button/Button';
import { ButtonMenu } from '../../shared/defguard-ui/components/ButtonMenu/MenuButton';
+import { ButtonsGroup } from '../../shared/defguard-ui/components/ButtonsGroup/ButtonsGroup';
import { Divider } from '../../shared/defguard-ui/components/Divider/Divider';
import { Icon } from '../../shared/defguard-ui/components/Icon';
import type { IconKindValue } from '../../shared/defguard-ui/components/Icon/icon-types';
@@ -51,7 +53,7 @@ export const SupportPage = () => {
title={m.support_page_bug_title()}
subtitle={ }
>
-
+
{
},
]}
/>
-
+
{
title={m.support_page_feature_title()}
subtitle={m.support_page_feature_desc()}
>
-
+
{
)
}
/>
-
+
{
title={m.support_page_assistance_title()}
subtitle={m.support_page_assistance_desc()}
>
-
+
{
)
}
/>
-
+
@@ -210,11 +212,7 @@ const SupportSection = ({
{title}
{subtitle && (
-
+
{subtitle}
)}
diff --git a/web/src/pages/SupportPage/styles.scss b/web/src/pages/SupportPage/styles.scss
index 69637d2c68..6c8758721d 100644
--- a/web/src/pages/SupportPage/styles.scss
+++ b/web/src/pages/SupportPage/styles.scss
@@ -106,14 +106,8 @@
p {
margin: 0;
font: var(--t-body-sm-400);
- color: var(--fg-muted) !important;
+ color: var(--fg-muted);
}
}
}
-
- .support-controls {
- display: flex;
- flex-wrap: wrap;
- gap: var(--spacing-md);
- }
}
From bd9956d8313629b8ec8919d23fde39bbe65f2e46 Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Wed, 25 Mar 2026 09:52:44 +0100
Subject: [PATCH 05/12] remove redundant styles
---
web/src/pages/SupportPage/SupportPage.tsx | 122 +++++++++-------------
web/src/pages/SupportPage/styles.scss | 82 +--------------
2 files changed, 52 insertions(+), 152 deletions(-)
diff --git a/web/src/pages/SupportPage/SupportPage.tsx b/web/src/pages/SupportPage/SupportPage.tsx
index d2a77971ce..894f9f9100 100644
--- a/web/src/pages/SupportPage/SupportPage.tsx
+++ b/web/src/pages/SupportPage/SupportPage.tsx
@@ -1,6 +1,4 @@
import './styles.scss';
-import clsx from 'clsx';
-import type { ReactNode } from 'react';
import { m } from '../../paraglide/messages';
import api from '../../shared/api/api';
import { Page } from '../../shared/components/Page/Page';
@@ -8,13 +6,16 @@ import { SettingsCard } from '../../shared/components/SettingsCard/SettingsCard'
import { SettingsHeader } from '../../shared/components/SettingsHeader/SettingsHeader';
import { SettingsLayout } from '../../shared/components/SettingsLayout/SettingsLayout';
import { externalLink } from '../../shared/constants';
+import { AppText } from '../../shared/defguard-ui/components/AppText/AppText';
import { Button } from '../../shared/defguard-ui/components/Button/Button';
import { ButtonMenu } from '../../shared/defguard-ui/components/ButtonMenu/MenuButton';
import { ButtonsGroup } from '../../shared/defguard-ui/components/ButtonsGroup/ButtonsGroup';
import { Divider } from '../../shared/defguard-ui/components/Divider/Divider';
-import { Icon } from '../../shared/defguard-ui/components/Icon';
-import type { IconKindValue } from '../../shared/defguard-ui/components/Icon/icon-types';
+import { MarkedSection } from '../../shared/defguard-ui/components/MarkedSection/MarkedSection';
+import { MarkedSectionHeader } from '../../shared/defguard-ui/components/MarkedSectionHeader/MarkedSectionHeader';
import docIllustration from '../../shared/defguard-ui/components/SectionSelect/assets/manual-user.png';
+import { SizedBox } from '../../shared/defguard-ui/components/SizedBox/SizedBox';
+import { TextStyle, ThemeSpacing, ThemeVariable } from '../../shared/defguard-ui/types';
import { downloadFile, downloadText } from '../../shared/utils/download';
export const SupportPage = () => {
@@ -27,7 +28,11 @@ export const SupportPage = () => {
subtitle={m.support_page_subtitle()}
/>
-
+
+
+ {m.support_page_docs_title()}
+
+
@@ -46,13 +51,17 @@ export const SupportPage = () => {
/>
-
-
- }
- >
+
+
+
+
+ {m.support_page_bug_title()}
+
+
+
+
+
+
{
]}
/>
-
-
-
+
+
+
+
{
}
/>
-
-
-
- {m.support_page_email_desc()}{' '}
- support@defguard.net
- >
- }
- />
-
-
+
+
+
+
+ {m.support_page_email_title()}
+
+
+
+ {m.support_page_email_desc()}{' '}
+ support@defguard.net
+
+
+
+
+
{
}
/>
-
+
@@ -186,39 +194,3 @@ const BugDescription = () => {
>
);
};
-
-interface SupportSectionProps {
- icon: IconKindValue;
- title: string;
- subtitle?: ReactNode;
- subtitleDark?: boolean;
- children?: ReactNode;
-}
-
-const SupportSection = ({
- icon,
- title,
- subtitle,
- subtitleDark,
- children,
-}: SupportSectionProps) => {
- return (
-
-
-
-
-
{title}
- {subtitle && (
-
- {subtitle}
-
- )}
-
- {children}
-
-
- );
-};
diff --git a/web/src/pages/SupportPage/styles.scss b/web/src/pages/SupportPage/styles.scss
index 6c8758721d..46065fa67f 100644
--- a/web/src/pages/SupportPage/styles.scss
+++ b/web/src/pages/SupportPage/styles.scss
@@ -1,84 +1,12 @@
#support-page-content {
width: 784px;
- .support-section {
- display: grid;
- grid-template-columns: 32px 1fr;
- column-gap: var(--spacing-xl);
- align-items: start;
- padding: var(--spacing-2xl) 0;
+ a {
+ color: var(--fg-action);
+ text-decoration: underline;
- &:first-child {
- padding-top: 0;
- }
-
- &:last-child {
- padding-bottom: 0;
- }
- }
-
- .support-section-icon {
- position: relative;
- display: grid;
- width: 32px;
- height: 32px;
- place-items: center;
-
- & > * {
- grid-row: 1;
- grid-column: 1;
- }
-
- .bg {
- width: 100%;
- height: 100%;
- background-color: var(--bg-action-muted);
- border-radius: var(--radius-full);
- }
-
- .icon path {
- fill: var(--fg-action);
- }
- }
-
- .support-section-content {
- display: flex;
- flex-direction: column;
- gap: var(--spacing-xl);
-
- .section-header {
- display: flex;
- flex-direction: column;
- gap: var(--spacing-sm);
- }
-
- .section-title {
- font: var(--t-body-primary-500);
- color: var(--fg-default);
- margin: 0;
- }
-
- .section-subtitle {
- font: var(--t-body-sm-400);
- color: var(--fg-muted);
- margin: 0;
-
- &.subtitle-dark {
- color: var(--fg-default);
- }
-
- a {
- color: var(--fg-action);
- text-decoration: underline;
-
- &:hover {
- text-decoration: none;
- }
- }
-
- strong {
- font-weight: 500;
- }
+ &:hover {
+ text-decoration: none;
}
}
From b84ddbee67ac12e2e131b18fcb9b77001d515e11 Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Wed, 25 Mar 2026 09:56:52 +0100
Subject: [PATCH 06/12] change color
---
web/src/pages/SupportPage/SupportPage.tsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/web/src/pages/SupportPage/SupportPage.tsx b/web/src/pages/SupportPage/SupportPage.tsx
index 894f9f9100..1807bd42ef 100644
--- a/web/src/pages/SupportPage/SupportPage.tsx
+++ b/web/src/pages/SupportPage/SupportPage.tsx
@@ -36,7 +36,9 @@ export const SupportPage = () => {
-
{m.support_page_docs_desc()}
+
+ {m.support_page_docs_desc()}
+
Date: Wed, 25 Mar 2026 10:11:25 +0100
Subject: [PATCH 07/12] fix fonts
---
web/messages/en/support.json | 4 +++-
web/src/pages/SupportPage/SupportPage.tsx | 26 ++++++++---------------
2 files changed, 12 insertions(+), 18 deletions(-)
diff --git a/web/messages/en/support.json b/web/messages/en/support.json
index 8090cace5c..9c6e3b8e42 100644
--- a/web/messages/en/support.json
+++ b/web/messages/en/support.json
@@ -6,7 +6,9 @@
"support_page_docs_desc": "Before contacting or submitting any issues to GitHub please get familiar with Defguard documentation available.",
"support_page_docs_btn": "Go to documentation",
"support_page_bug_title": "Report a bug",
- "support_page_bug_desc": "We aim to respond to all bug reports as quickly as possible and prioritize them based on severity before adding them to our development backlog. To give us more context, you can optionally download the support data and/or log file and attach it to your bug report.",
+ "support_page_bug_desc_before": "We aim to respond to all bug reports as quickly as possible and prioritize them based on severity before adding them to our development backlog. To give us more context, ",
+ "support_page_bug_desc_bold": "you can optionally download",
+ "support_page_bug_desc_after": " the support data and/or log file and attach it to your bug report.",
"support_page_bug_btn_report": "Report on Github",
"support_page_bug_btn_download": "Download",
"support_page_bug_btn_download_support_data": "Download support data",
diff --git a/web/src/pages/SupportPage/SupportPage.tsx b/web/src/pages/SupportPage/SupportPage.tsx
index 1807bd42ef..0a02fe26b3 100644
--- a/web/src/pages/SupportPage/SupportPage.tsx
+++ b/web/src/pages/SupportPage/SupportPage.tsx
@@ -61,7 +61,15 @@ export const SupportPage = () => {
-
+ {m.support_page_bug_desc_before()}
+
+ {m.support_page_bug_desc_bold()}
+
+ {m.support_page_bug_desc_after()}
@@ -180,19 +188,3 @@ export const SupportPage = () => {
);
};
-
-const BugDescription = () => {
- const full = m.support_page_bug_desc();
- const boldPhrase = 'you can optionally download';
- const idx = full.indexOf(boldPhrase);
- if (idx === -1) return <>{full}>;
- const before = full.slice(0, idx);
- const after = full.slice(idx + boldPhrase.length);
- return (
- <>
- {before}
- {boldPhrase}
- {after}
- >
- );
-};
From a77923232308d034aa98359747cee265b5d69e7c Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Wed, 25 Mar 2026 10:14:55 +0100
Subject: [PATCH 08/12] change link
---
web/src/shared/constants.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/src/shared/constants.ts b/web/src/shared/constants.ts
index 216f597fc9..c1a53dd237 100644
--- a/web/src/shared/constants.ts
+++ b/web/src/shared/constants.ts
@@ -7,7 +7,7 @@ export const externalLink = {
download: 'https://defguard.net/download',
sales: 'mailto:sales@defguard.net',
support: 'https://defguard.net/support/',
- scheduleCall: 'https://calendly.com/defguard',
+ scheduleCall: 'https://defguard.net/',
},
github: {
bugReport: 'https://github.com/DefGuard/defguard/issues/new?template=bug_report.md',
From 3cbe9a2aa29c82b0a1231fb1c473ba3ae8b7a0b3 Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Wed, 25 Mar 2026 10:20:06 +0100
Subject: [PATCH 09/12] change submodule
---
web/src/shared/defguard-ui | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/src/shared/defguard-ui b/web/src/shared/defguard-ui
index c65255fd36..5a25beb88b 160000
--- a/web/src/shared/defguard-ui
+++ b/web/src/shared/defguard-ui
@@ -1 +1 @@
-Subproject commit c65255fd36f0b82b2136b61f692e587fad644d54
+Subproject commit 5a25beb88b60e9c3120c5f59c621ebfe3a51d1a2
From 6661115778e0162183f0f89be7a2b77eeb533a59 Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Wed, 25 Mar 2026 11:34:54 +0100
Subject: [PATCH 10/12] update
---
web/src/shared/defguard-ui | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/src/shared/defguard-ui b/web/src/shared/defguard-ui
index 5a25beb88b..a9177dfb6e 160000
--- a/web/src/shared/defguard-ui
+++ b/web/src/shared/defguard-ui
@@ -1 +1 @@
-Subproject commit 5a25beb88b60e9c3120c5f59c621ebfe3a51d1a2
+Subproject commit a9177dfb6eec895bb3e20e91990abf35e440cd56
From 53bf469e4e79e69a4499d19a88a34dbd03859a2a Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Wed, 25 Mar 2026 12:21:55 +0100
Subject: [PATCH 11/12] Update web/messages/en/support.json
Co-authored-by: Adam
---
web/messages/en/support.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/messages/en/support.json b/web/messages/en/support.json
index 9c6e3b8e42..2d787394b7 100644
--- a/web/messages/en/support.json
+++ b/web/messages/en/support.json
@@ -14,7 +14,7 @@
"support_page_bug_btn_download_support_data": "Download support data",
"support_page_bug_btn_download_logs": "Download logs",
"support_page_feature_title": "Request feature",
- "support_page_feature_desc": "We grow with the help of our community. If you have an idea or a missing feature to suggest, please share it \u2014 we'll review it.",
+ "support_page_feature_desc": "We grow with the help of our community. If you have an idea or a missing feature to suggest, please share it – we'll review it.",
"support_page_feature_btn": "Submit on Github",
"support_page_email_title": "Contact us by email",
"support_page_email_desc": "For any additional requests, reach out to us at",
From 177b3bceb3f54dc7ea0e7add4de4460a8c86ecf1 Mon Sep 17 00:00:00 2001
From: Kuba <78603704+jakub-tldr@users.noreply.github.com>
Date: Wed, 25 Mar 2026 12:22:02 +0100
Subject: [PATCH 12/12] Update web/messages/en/support.json
Co-authored-by: Adam
---
web/messages/en/support.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/web/messages/en/support.json b/web/messages/en/support.json
index 2d787394b7..003f4ef53f 100644
--- a/web/messages/en/support.json
+++ b/web/messages/en/support.json
@@ -3,7 +3,7 @@
"support_page_title": "Support",
"support_page_subtitle": "When you need support or must supply diagnostic information to our team, please use one of the options below.",
"support_page_docs_title": "Have questions? Check our documentation first.",
- "support_page_docs_desc": "Before contacting or submitting any issues to GitHub please get familiar with Defguard documentation available.",
+ "support_page_docs_desc": "Before contacting or submitting any issues to GitHub, please get familiar with Defguard documentation.",
"support_page_docs_btn": "Go to documentation",
"support_page_bug_title": "Report a bug",
"support_page_bug_desc_before": "We aim to respond to all bug reports as quickly as possible and prioritize them based on severity before adding them to our development backlog. To give us more context, ",