diff --git a/e2e/settings.spec.ts b/e2e/settings.spec.ts
index b61d10ea7b..a6291a3382 100644
--- a/e2e/settings.spec.ts
+++ b/e2e/settings.spec.ts
@@ -33,7 +33,10 @@ electronTest('Settings', async (app, page) => {
})
await test.step('shows the Advanced settings', async () => {
- await page.getByTestId('settings').click()
+ await page
+ .locator('.Sidebar')
+ .locator('.Sidebar__item', { hasText: 'Settings' })
+ .click()
page.getByText('Global Settings')
await page.getByText('Advanced').click()
})
diff --git a/src/backend/main.ts b/src/backend/main.ts
index 8cbc1fecfc..0c1b10f2d5 100644
--- a/src/backend/main.ts
+++ b/src/backend/main.ts
@@ -1668,7 +1668,7 @@ ipcMain.on('processShortcut', async (e, combination: string) => {
break
// hotkey to open the settings on frontend
case 'ctrl+k':
- sendFrontendMessage('openScreen', '/settings/app/default/general')
+ sendFrontendMessage('openScreen', '/settings/general')
break
// hotkey to open the downloads screen on frontend
case 'ctrl+j':
diff --git a/src/frontend/App.tsx b/src/frontend/App.tsx
index 91c4e38ef8..aec937b571 100644
--- a/src/frontend/App.tsx
+++ b/src/frontend/App.tsx
@@ -118,7 +118,7 @@ const router = createHashRouter([
lazy: makeLazyFunc(import('./screens/WebView'))
},
{
- path: 'settings/:runner/:appName/:type',
+ path: 'settings/:type',
lazy: makeLazyFunc(import('./screens/Settings'))
},
{
diff --git a/src/frontend/components/UI/Sidebar/components/CurrentDownload/index.css b/src/frontend/components/UI/Sidebar/components/CurrentDownload/index.css
new file mode 100644
index 0000000000..ba2d772af7
--- /dev/null
+++ b/src/frontend/components/UI/Sidebar/components/CurrentDownload/index.css
@@ -0,0 +1,52 @@
+.Sidebar {
+ .currentDownload {
+ font-size: var(--text-sm);
+ padding: var(--space-md) 0;
+ transition: 300ms;
+ margin-top: var(--space-sm);
+ align-self: end;
+
+ & > .gameTitle {
+ font-size: var(--text-md);
+ transition: 600ms;
+ font-weight: var(--bold);
+ }
+
+ &:hover > .gameTitle {
+ color: var(--accent-overlay);
+ transition: 600ms;
+ }
+
+ .downloadStatus {
+ color: var(--success);
+ font-family: var(--secondary-font-family);
+ font-style: italic;
+ font-weight: normal;
+ font-size: var(--text-sm);
+ line-height: var(--text-sm);
+ }
+
+ .MuiLinearProgress-bar1Determinate {
+ background-color: var(--success);
+ }
+
+ .statusIcon {
+ display: none;
+ margin-inline-end: 10px;
+ svg {
+ width: 27px;
+ height: auto;
+ color: var(--success);
+ }
+ }
+ }
+
+ &.collapsed {
+ .statusIcon {
+ display: block;
+ }
+ .full-size {
+ display: none;
+ }
+ }
+}
diff --git a/src/frontend/components/UI/Sidebar/components/CurrentDownload/index.scss b/src/frontend/components/UI/Sidebar/components/CurrentDownload/index.scss
deleted file mode 100644
index 14375cd181..0000000000
--- a/src/frontend/components/UI/Sidebar/components/CurrentDownload/index.scss
+++ /dev/null
@@ -1,40 +0,0 @@
-.currentDownload {
- font-size: var(--text-sm);
- padding: var(--space-md) 0;
- transition: 300ms;
- margin-top: var(--space-sm);
-
- & > .gameTitle {
- font-size: var(--text-md);
- transition: 600ms;
- font-weight: var(--bold);
- }
-
- &:hover > .gameTitle {
- color: var(--accent-overlay);
- transition: 600ms;
- }
-
- .downloadStatus {
- color: var(--success);
- font-family: var(--secondary-font-family);
- font-style: italic;
- font-weight: normal;
- font-size: var(--text-sm);
- line-height: var(--text-sm);
- }
-
- .MuiLinearProgress-bar1Determinate {
- background-color: var(--success);
- }
-
- .statusIcon {
- display: none;
- margin-inline-end: 10px;
- svg {
- width: 27px;
- height: auto;
- color: var(--success);
- }
- }
-}
diff --git a/src/frontend/components/UI/Sidebar/components/CurrentDownload/index.tsx b/src/frontend/components/UI/Sidebar/components/CurrentDownload/index.tsx
index 77ea259484..c56a0fcae9 100644
--- a/src/frontend/components/UI/Sidebar/components/CurrentDownload/index.tsx
+++ b/src/frontend/components/UI/Sidebar/components/CurrentDownload/index.tsx
@@ -8,7 +8,7 @@ import Box from '@mui/material/Box'
import { getGameInfo } from 'frontend/helpers'
import { hasProgress } from 'frontend/hooks/hasProgress'
import { Runner } from 'common/types'
-import './index.scss'
+import './index.css'
import { useTranslation } from 'react-i18next'
import ContextProvider from 'frontend/state/ContextProvider'
import Badge from '@mui/material/Badge'
@@ -52,37 +52,35 @@ export default React.memo(function CurrentDownload({ appName, runner }: Props) {
}
return (
- <>
-
-
-
-
-
-
+
+
+
+
+
+
-
-
{gameTitle ?? 'GameName'}
-
-
{getStatus()}
-
-
-
-
-
-
- {`${Math.round(
- progress.percent || 0
- )}%`}
-
+
+ {gameTitle ?? 'GameName'}
+
+ {getStatus()}
+
+
+
+
-
-
- >
+
+ {`${Math.round(
+ progress.percent || 0
+ )}%`}
+
+
+
+
)
})
diff --git a/src/frontend/components/UI/Sidebar/components/HeroicVersion/index.css b/src/frontend/components/UI/Sidebar/components/HeroicVersion/index.css
new file mode 100644
index 0000000000..e3a3626036
--- /dev/null
+++ b/src/frontend/components/UI/Sidebar/components/HeroicVersion/index.css
@@ -0,0 +1,47 @@
+.Sidebar {
+ .heroicVersion {
+ display: flex;
+ gap: 5px;
+ font-size: var(--text-sm);
+ cursor: pointer;
+ transition: 300ms;
+ color: var(--brand-text-01);
+
+ &:hover {
+ color: var(--accent);
+ }
+ }
+
+ .heroicNewReleases {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-around;
+ font-size: var(--text-sm);
+
+ & > a {
+ color: var(--accent);
+ transition: 300ms;
+ -webkit-app-region: no-drag;
+ cursor: pointer;
+
+ &:hover {
+ color: var(--accent-overlay);
+ }
+ }
+ }
+
+ &.collapsed {
+ .heroicVersion {
+ font-size: var(--text-xs);
+ text-align: center;
+ }
+
+ .heroicVersion__title {
+ display: none;
+ }
+
+ .heroicNewReleases {
+ display: none;
+ }
+ }
+}
diff --git a/src/frontend/components/UI/Sidebar/components/HeroicVersion/index.tsx b/src/frontend/components/UI/Sidebar/components/HeroicVersion/index.tsx
index d594b4fb94..7001f3e6e5 100644
--- a/src/frontend/components/UI/Sidebar/components/HeroicVersion/index.tsx
+++ b/src/frontend/components/UI/Sidebar/components/HeroicVersion/index.tsx
@@ -2,6 +2,7 @@ import React, { useContext, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import ContextProvider from 'frontend/state/ContextProvider'
import { ChangelogModal } from '../../../ChangelogModal'
+import './index.css'
type Release = {
html_url: string
diff --git a/src/frontend/components/UI/Sidebar/components/SidebarItem/index.css b/src/frontend/components/UI/Sidebar/components/SidebarItem/index.css
new file mode 100644
index 0000000000..c11a3e1988
--- /dev/null
+++ b/src/frontend/components/UI/Sidebar/components/SidebarItem/index.css
@@ -0,0 +1,111 @@
+.Sidebar {
+ .Sidebar__item {
+ --sidebar-item-inactive-text-color: var(
+ --navbar-inactive,
+ var(--navbar-accent)
+ );
+ --sidebar-hover-text-color: var(--text-hover);
+ --sidebar-item-active-text-color: var(
+ --navbar-active,
+ var(--accent-overlay, var(--accent))
+ );
+ --sidebar-active-item-background: var(--navbar-active-background);
+
+ display: flex;
+ gap: 10px;
+ width: 100%;
+ padding: var(--space-xs) var(--sidebar-horizontal-padding);
+ border: none;
+ background: none;
+ cursor: pointer;
+ font-size: var(--text-md);
+ color: var(--sidebar-item-inactive-text-color);
+ transition: color 250ms;
+ text-align: start;
+ font-family: var(--primary-font-family);
+
+ .Sidebar__itemIcon {
+ width: 24px;
+ display: inline-flex;
+ justify-content: center;
+ }
+
+ &:focus-visible {
+ outline: 2px solid var(--sidebar-hover-text-color);
+ outline-offset: -2px;
+ }
+
+ &.active {
+ color: var(--sidebar-item-active-text-color);
+
+ .Sidebar__itemIcon {
+ color: currentColor;
+ }
+
+ &.SidebarLinks__subItem {
+ font-weight: var(--bold);
+ }
+ }
+ &.active:not(.SidebarLinks__subItem) {
+ background-color: var(--sidebar-active-item-background);
+ }
+
+ &.SidebarLinks__subItem {
+ &,
+ &:hover {
+ padding-block: var(--space-3xs);
+ padding-inline: var(--space-xl) var(--sidebar-horizontal-padding);
+ font-size: var(--text-sm);
+ line-height: 20px;
+ white-space: break-spaces;
+ }
+ &::before {
+ content: '• ';
+ }
+ & + .Sidebar__item:not(.SidebarLinks__subItem) {
+ margin-top: 4px;
+ }
+ }
+
+ &:hover {
+ background-color: var(--navbar-active-background);
+ transition: 0.1s;
+ padding-inline-start: 12px;
+ }
+
+ @media screen and (max-width: 730px) {
+ &,
+ &:hover {
+ padding: var(--space-3xs) var(--sidebar-horizontal-padding)
+ var(--space-3xs) var(--space-lg);
+ }
+ }
+ }
+
+ &.collapsed {
+ .Sidebar__item {
+ padding: var(--space-xs) 0;
+
+ & > span {
+ display: none;
+ }
+
+ &.SidebarLinks__subItem {
+ padding: var(--space-xs) var(--sidebar-horizontal-padding);
+ &::before {
+ display: none;
+ }
+ }
+
+ &.active svg,
+ & svg {
+ transform: scale(1.2);
+ padding: var(--space-2xs) 0;
+ }
+
+ .Sidebar__itemIcon {
+ margin: 0 auto;
+ }
+ }
+ }
+}
diff --git a/src/frontend/components/UI/Sidebar/components/SidebarItem/index.tsx b/src/frontend/components/UI/Sidebar/components/SidebarItem/index.tsx
new file mode 100644
index 0000000000..2bf3e21955
--- /dev/null
+++ b/src/frontend/components/UI/Sidebar/components/SidebarItem/index.tsx
@@ -0,0 +1,60 @@
+import React, { MouseEventHandler } from 'react'
+import classNames from 'classnames'
+import { NavLink } from 'react-router-dom'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { IconProp } from '@fortawesome/fontawesome-svg-core'
+import './index.css'
+
+interface SidebarItemProps {
+ label: string
+ url?: string
+ icon?: IconProp
+ isActiveFallback?: boolean
+ onClick?: MouseEventHandler
+ className?: string
+ elementType?: 'a' | 'button'
+}
+
+export default function SidebarItem({
+ icon,
+ label,
+ url = '',
+ isActiveFallback = false,
+ onClick,
+ className,
+ elementType
+}: SidebarItemProps) {
+ const itemContent = (
+ <>
+ {icon && (
+
+
+
+ )}
+ {label}
+ >
+ )
+
+ switch (elementType) {
+ case 'button':
+ return (
+
+ )
+ default:
+ return (
+
+ classNames('Sidebar__item', className, {
+ active: isActive || isActiveFallback
+ })
+ }
+ to={url}
+ onClick={onClick}
+ >
+ {itemContent}
+
+ )
+ }
+}
diff --git a/src/frontend/components/UI/Sidebar/components/SidebarLinks/index.css b/src/frontend/components/UI/Sidebar/components/SidebarLinks/index.css
deleted file mode 100644
index f34fd1c38b..0000000000
--- a/src/frontend/components/UI/Sidebar/components/SidebarLinks/index.css
+++ /dev/null
@@ -1,35 +0,0 @@
-.SidebarLinks {
- grid-area: links;
- font-size: var(--text-lg);
-}
-
-.Sidebar__item.SidebarLinks__subItem,
-.Sidebar__item.SidebarLinks__subItem:hover {
- padding-block: var(--space-3xs);
- padding-inline: var(--space-xl) var(--sidebar-horizontal-padding);
- font-size: var(--text-sm);
- line-height: 20px;
- white-space: break-spaces;
-}
-
-.Sidebar__item:hover {
- background-color: var(--navbar-active-background);
- transition: 0.1s;
- padding-inline-start: 12px;
-}
-
-.Sidebar__item.SidebarLinks__subItem::before {
- content: '• ';
-}
-
-.SidebarLinks__subItem + .Sidebar__item:not(.SidebarLinks__subItem) {
- margin-top: 4px;
-}
-
-@media screen and (max-width: 730px) {
- .Sidebar__item.SidebarLinks__subItem,
- .Sidebar__item.SidebarLinks__subItem:hover {
- padding: var(--space-3xs) var(--sidebar-horizontal-padding) var(--space-3xs)
- var(--space-lg);
- }
-}
diff --git a/src/frontend/components/UI/Sidebar/components/SidebarLinks/index.tsx b/src/frontend/components/UI/Sidebar/components/SidebarLinks/index.tsx
index d89e47e78c..b199a46b88 100644
--- a/src/frontend/components/UI/Sidebar/components/SidebarLinks/index.tsx
+++ b/src/frontend/components/UI/Sidebar/components/SidebarLinks/index.tsx
@@ -10,34 +10,23 @@ import {
faWineGlass,
faBarsProgress
} from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { NavLink, useLocation } from 'react-router-dom'
-import classNames from 'classnames'
+import { useLocation } from 'react-router-dom'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { faDiscord, faPatreon } from '@fortawesome/free-brands-svg-icons'
import { openDiscordLink } from 'frontend/helpers'
import ContextProvider from 'frontend/state/ContextProvider'
-import { Runner } from 'common/types'
-import './index.css'
import QuitButton from '../QuitButton'
-import { LocationState } from 'frontend/types'
import { SHOW_EXTERNAL_LINK_DIALOG_STORAGE_KEY } from 'frontend/components/UI/ExternalLinkDialog'
+import SidebarItem from '../SidebarItem'
-type PathSplit = [
- a: undefined,
- b: undefined,
- runner: Runner | 'app',
- appName: string,
- type: string
-]
+type PathSplit = [a: undefined, b: undefined, type: string]
export default function SidebarLinks() {
const { t } = useTranslation()
- const { state } = useLocation() as { state: LocationState }
const location = useLocation() as { pathname: string }
- const [, , runner, appName, type] = location.pathname.split('/') as PathSplit
+ const [, , type] = location.pathname.split('/') as PathSplit
const {
amazon,
@@ -54,8 +43,6 @@ export default function SidebarLinks() {
const isSettings = location.pathname.includes('settings')
const isWin = platform === 'win32'
- const settingsPath = '/settings/app/default/general'
-
const loggedIn = epic.username || gog.username || amazon.user_id
async function handleRefresh() {
@@ -101,288 +88,159 @@ export default function SidebarLinks() {
return (
{!loggedIn && (
-
- classNames('Sidebar__item', { active: isActive })
- }
- to={'/login'}
- >
- <>
-
-
-
- {t('button.login', 'Login')}
- >
-
+
)}
-
- classNames('Sidebar__item', {
- active: isActive || location.pathname.includes('gamepage')
- })
- }
- to={'/'}
+ handleRefresh()}
- >
- <>
-
-
-
- {t('Library')}
- >
-
+ />
+
-
- classNames('Sidebar__item', {
- active: isActive || location.pathname.includes('store')
- })
- }
- to={`/store/${defaultStore}`}
- >
- <>
-
-
-
- {t('stores', 'Stores')}
- >
-
+
{inWebviewScreen && (
-
- classNames('Sidebar__item', 'SidebarLinks__subItem', {
- active: isActive
- })
- }
- to="/store/epic"
- >
- {t('store', 'Epic Store')}
-
-
- classNames('Sidebar__item', 'SidebarLinks__subItem', {
- active: isActive
- })
- }
- to="/store/gog"
- >
- {t('gog-store', 'GOG Store')}
-
-
- classNames('Sidebar__item', 'SidebarLinks__subItem', {
- active: isActive
- })
- }
- to="/store/amazon"
- >
- {t('prime-gaming', 'Prime Gaming')}
-
+
+
+
)}
-
- classNames('Sidebar__item', {
- active: isActive || location.pathname.includes('settings')
- })
- }
- to={{ pathname: settingsPath }}
- state={{
- fromGameCard: false
- }}
- >
- <>
-
-
-
- {t('Settings', 'Settings')}
- >
-
+
{isSettings && (
-
- {t('settings.navbar.general')}
-
+
+
{!isWin && (
-
-
- {t(
- 'settings.navbar.games_settings_defaults',
- 'Game Defaults'
- )}
-
-
+
)}
-
- {t('settings.navbar.advanced', 'Advanced')}
-
-
-
- {t('settings.navbar.systemInformation', 'System Information')}
-
-
-
- {t('settings.navbar.log', 'Log')}
-
+
+
+
+
+
+
)}
-
- classNames('Sidebar__item', { active: isActive })
- }
- to={{ pathname: '/download-manager' }}
- >
- <>
-
-
-
- {t('download-manager.link', 'Downloads')}
- >
-
+
+
{!isWin && (
-
- classNames('Sidebar__item', { active: isActive })
- }
- to={{ pathname: '/wine-manager' }}
- >
- <>
-
-
-
- {t('wine.manager.link', 'Wine Manager')}
- >
-
+
)}
+
{loggedIn && (
-
-
-
-
- {t('userselector.manageaccounts', 'Manage Accounts')}
-
+
)}
-
- classNames('Sidebar__item', { active: isActive })
- }
- to={{ pathname: '/accessibility' }}
- >
- <>
-
-
-
- {t('accessibility.title', 'Accessibility')}
- >
-
+
+
+
-
- classNames('Sidebar__item', { active: isActive })
- }
- to={{ pathname: '/wiki' }}
- >
- <>
-
-
-
- {t('docs', 'Documentation')}
- >
-
-
+
+
handleExternalLink(openDiscordLink)}
- >
-
-
-
- {t('userselector.discord', 'Discord')}
-
-
+
+ handleExternalLink(window.api.openPatreonPage)}
- >
-
-
-
- Patreon
-
-
+
+ handleExternalLink(window.api.openKofiPage)}
- >
-
-
-
- Ko-fi
-
+ icon={faCoffee}
+ label="Ko-fi"
+ />
+
)
diff --git a/src/frontend/components/UI/Sidebar/index.css b/src/frontend/components/UI/Sidebar/index.css
new file mode 100644
index 0000000000..f08e0dea5d
--- /dev/null
+++ b/src/frontend/components/UI/Sidebar/index.css
@@ -0,0 +1,140 @@
+.Sidebar {
+ --sidebar-horizontal-padding: var(--space-md);
+ --sidebar-vertical-padding: var(--space-lg);
+ --sidebar-width: 350px;
+ --sidebar-background: var(--navbar-background);
+ --sidebar-divider-color: var(--divider);
+
+ width: var(--sidebar-width);
+ position: relative;
+ z-index: 10;
+ display: grid;
+ grid-template-rows: min-content 2fr min-content min-content;
+ grid-template-areas: 'icon' 'links' 'utils' 'updates' 'version';
+ grid-area: sidebar;
+ padding: 0;
+ font-family: var(--secondary-font-family);
+ text-align: start;
+ background: var(--sidebar-background);
+ overflow: auto;
+ overflow-x: hidden;
+ -webkit-app-region: drag;
+
+ .heroicIcon {
+ grid-area: icon;
+ width: 50px;
+ height: 68px;
+ margin-top: var(--space-xs);
+ justify-self: center;
+ }
+
+ .SidebarLinks {
+ grid-area: links;
+ }
+
+ .heroicVersion {
+ grid-area: version;
+ margin-block: 0 var(--sidebar-vertical-padding);
+ margin-inline: var(--sidebar-horizontal-padding) var(--space-3xs);
+ -webkit-app-region: no-drag;
+ }
+
+ .heroicNewReleases {
+ grid-area: updates;
+ margin-block: 0 var(--space-sm);
+ margin-inline: var(--sidebar-horizontal-padding) var(--space-3xs);
+ }
+
+ .Sidebar__section {
+ -webkit-app-region: no-drag;
+ }
+
+ .currentDownloads {
+ grid-area: utils;
+ margin-block: 0 var(--sidebar-vertical-padding);
+ margin-inline: var(--sidebar-horizontal-padding) var(--space-3xs);
+ }
+
+ .divider {
+ height: 1px;
+ margin: var(--space-3xs) var(--space-xs);
+ background-color: var(--sidebar-divider-color);
+ }
+
+ .resizer {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 10px;
+ height: 100%;
+ z-index: 1;
+ cursor: col-resize;
+ }
+
+ &.collapsed {
+ --sidebar-vertical-padding: var(--space-xs);
+ --sidebar-horizontal-padding: var(--space-lg);
+ overflow-x: hidden;
+ overflow-y: auto;
+
+ .currentDownloads {
+ margin-inline: auto;
+ }
+
+ .heroicVersion {
+ margin: var(--space-sm);
+ }
+
+ .divider {
+ margin: var(--space-3xs) 0;
+ }
+
+ .SidebarItemWithSubmenu {
+ &:has(.SidebarSubmenu) {
+ position: relative;
+ z-index: 2;
+ }
+
+ .SidebarSubmenu {
+ display: none;
+ }
+
+ &:hover,
+ &:focus-within {
+ .SidebarSubmenu {
+ display: block;
+ position: fixed;
+ left: var(--sidebar-width);
+ top: 66px;
+ background-color: var(--sidebar-background);
+ padding: var(--space-2xs) 0;
+
+ & span {
+ display: block;
+ }
+
+ &.settings {
+ top: 114px;
+ }
+ }
+ }
+ }
+ }
+}
+
+.isRTL .Sidebar {
+ &.collapsed .SidebarItemWithSubmenu {
+ &:hover,
+ &:focus-within {
+ .SidebarSubmenu {
+ right: var(--sidebar-width);
+ left: auto;
+ }
+ }
+ }
+
+ & .resizer {
+ left: 0;
+ right: auto;
+ }
+}
diff --git a/src/frontend/components/UI/Sidebar/index.scss b/src/frontend/components/UI/Sidebar/index.scss
deleted file mode 100644
index 50c1ac6bea..0000000000
--- a/src/frontend/components/UI/Sidebar/index.scss
+++ /dev/null
@@ -1,251 +0,0 @@
-.Sidebar {
- --sidebar-horizontal-padding: var(--space-md);
- --sidebar-vertical-padding: var(--space-lg);
- position: relative;
- z-index: 10;
- display: grid;
- grid-template-rows: min-content 2fr min-content min-content;
- grid-template-areas: 'icon' 'links' 'utils' 'updates' 'version';
- grid-area: sidebar;
- height: 100%;
- padding: 0;
- font-family: var(--secondary-font-family);
- text-align: start;
- background: var(--navbar-background);
- overflow: auto;
- overflow-x: hidden;
- --sidebar-width: 350px;
- width: var(--sidebar-width);
- -webkit-app-region: drag;
-
- .heroicIcon {
- grid-area: icon;
- width: 50px;
- height: 68px;
- display: flex;
- margin-top: var(--space-xs);
- justify-self: center;
- }
-}
-
-.Sidebar.collapsed {
- --sidebar-vertical-padding: var(--space-xs);
- --sidebar-horizontal-padding: var(--space-lg);
- overflow-x: hidden;
- overflow-y: auto;
-}
-
-.Sidebar__section {
- display: flex;
- width: 100%;
- height: fit-content;
- font-family: var(--secondary-font-family);
- flex-direction: column;
- -webkit-app-region: no-drag;
-}
-
-.Sidebar__item {
- display: flex;
- width: 100%;
- padding: var(--space-xs) var(--sidebar-horizontal-padding);
- border: none;
- background: none;
- cursor: pointer;
- font-size: var(--text-md);
- color: var(--navbar-accent);
- color: var(--navbar-inactive, var(--navbar-accent));
- transition: color 250ms;
- text-align: start;
- font-family: var(--primary-font-family);
- border-radius: 0;
-}
-
-.collapsed .Sidebar__item {
- padding: var(--space-xs) 0;
-}
-
-.collapsed .Sidebar__itemIcon {
- margin: 0 auto;
-}
-.Sidebar__item:focus-visible {
- outline: 2px solid var(--text-hover);
- outline-offset: -2px;
-}
-
-.Sidebar__item.active {
- color: var(--accent);
- color: var(--navbar-active, var(--accent-overlay));
-
- .Sidebar__itemIcon {
- color: var(--accent);
- color: var(--navbar-active, var(--accent-overlay));
- }
-}
-
-.Sidebar__item.active:not(.SidebarLinks__subItem) {
- background-color: var(--navbar-active-background);
-}
-
-.Sidebar__item.active.SidebarLinks__subItem {
- font-weight: var(--bold);
-}
-
-.Sidebar__itemIcon {
- box-sizing: border-box;
- width: 24px;
- margin-inline-end: 10px;
- display: inline-flex;
- justify-content: center;
- color: var(--accent);
- color: var(--navbar-inactive, var(--accent));
-}
-
-.currentDownloads {
- grid-area: utils;
- align-self: end;
- margin-block: 0 var(--sidebar-vertical-padding);
- margin-inline: var(--sidebar-horizontal-padding) var(--space-3xs);
-}
-
-.divider {
- height: 1px;
- opacity: 0.5;
- margin: var(--space-3xs) var(--space-xs);
- background-color: var(--divider);
-}
-
-.heroicVersion {
- display: flex;
- gap: 5px;
- grid-area: version;
- margin-block: 0 var(--sidebar-vertical-padding);
- margin-inline: var(--sidebar-horizontal-padding) var(--space-3xs);
- font-size: var(--text-sm);
- cursor: pointer;
- transition: 300ms;
- color: var(--brand-text-01);
- -webkit-app-region: no-drag;
-}
-
-.heroicVersion:hover {
- color: var(--accent);
-}
-
-.heroicNewReleases {
- grid-area: updates;
- display: flex;
- flex-direction: column;
- justify-content: space-around;
- margin-block: 0 var(--space-sm);
- margin-inline: var(--space-3xs) var(--sidebar-horizontal-padding);
- font-size: var(--text-sm);
-}
-
-.heroicNewReleases > a {
- color: var(--accent);
- transition: 300ms;
- -webkit-app-region: no-drag;
-}
-
-.heroicNewReleases > a:hover {
- color: var(--accent-overlay);
-}
-
-.Sidebar.collapsed {
- .heroicVersion {
- margin: var(--space-sm);
- font-size: var(--text-xs);
- text-align: center;
- &__title {
- display: none;
- }
- }
-
- .heroicNewReleases {
- display: none;
- }
-
- .currentDownloads {
- margin-inline: auto;
- .statusIcon {
- display: block;
- }
- .full-size {
- display: none;
- }
- }
-}
-
-.Sidebar.collapsed .divider {
- margin: var(--space-3xs) 0;
-}
-
-.Sidebar.collapsed .Sidebar__item.active span,
-.Sidebar.collapsed .Sidebar__item > span {
- display: none;
-}
-
-.Sidebar.collapsed .SidebarItemWithSubmenu:has(.SidebarSubmenu) {
- position: relative;
- z-index: 2;
-}
-
-.Sidebar.collapsed .SidebarItemWithSubmenu .SidebarSubmenu {
- display: none;
-}
-
-.Sidebar.collapsed .SidebarItemWithSubmenu:hover .SidebarSubmenu span,
-.Sidebar.collapsed .SidebarItemWithSubmenu:focus-within .SidebarSubmenu span {
- display: block;
-}
-
-.Sidebar.collapsed .SidebarItemWithSubmenu:hover .SidebarSubmenu,
-.Sidebar.collapsed .SidebarItemWithSubmenu:focus-within .SidebarSubmenu {
- display: block;
- position: fixed;
- left: var(--sidebar-width);
- top: 66px;
- background-color: var(--navbar-background);
- padding: var(--space-2xs) 0;
-}
-
-.isRTL .Sidebar.collapsed .SidebarItemWithSubmenu:hover .SidebarSubmenu,
-.isRTL .Sidebar.collapsed .SidebarItemWithSubmenu:focus-within .SidebarSubmenu {
- right: var(--sidebar-width);
- left: auto;
-}
-
-.Sidebar.collapsed .SidebarItemWithSubmenu:hover .SidebarSubmenu.settings,
-.Sidebar.collapsed
- .SidebarItemWithSubmenu:focus-within
- .SidebarSubmenu.settings {
- top: 114px;
-}
-
-.Sidebar.collapsed .Sidebar__item.SidebarLinks__subItem::before {
- display: none;
-}
-
-.Sidebar.collapsed .Sidebar__item.SidebarLinks__subItem {
- padding: var(--space-xs) var(--sidebar-horizontal-padding);
-}
-.Sidebar.collapsed .Sidebar__item.active svg,
-.Sidebar.collapsed .Sidebar__item svg {
- transform: scale(1.2);
- padding: var(--space-2xs) 0;
-}
-
-.resizer {
- position: absolute;
- top: 0;
- right: 0;
- width: 10px;
- height: 100%;
- z-index: 1;
- cursor: col-resize;
-}
-
-.isRTL .resizer {
- left: 0;
- right: auto;
-}
diff --git a/src/frontend/components/UI/Sidebar/index.tsx b/src/frontend/components/UI/Sidebar/index.tsx
index 8477ba77fe..4617b04306 100644
--- a/src/frontend/components/UI/Sidebar/index.tsx
+++ b/src/frontend/components/UI/Sidebar/index.tsx
@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from 'react'
import CurrentDownload from './components/CurrentDownload'
import SidebarLinks from './components/SidebarLinks'
-import './index.scss'
+import './index.css'
import HeroicVersion from './components/HeroicVersion'
import { DMQueueElement } from 'common/types'
diff --git a/src/frontend/components/UI/Winetricks/index.tsx b/src/frontend/components/UI/Winetricks/index.tsx
index 2047fdcae7..6631278730 100644
--- a/src/frontend/components/UI/Winetricks/index.tsx
+++ b/src/frontend/components/UI/Winetricks/index.tsx
@@ -4,13 +4,15 @@ import { ProgressDialog } from '../ProgressDialog'
import WinetricksSearchBar from './WinetricksSearch'
import { useTranslation } from 'react-i18next'
import SettingsContext from 'frontend/screens/Settings/SettingsContext'
+import { Runner } from 'common/types'
interface Props {
onClose: () => void
+ runner: Runner
}
-export default function Winetricks({ onClose }: Props) {
- const { appName, runner } = useContext(SettingsContext)
+export default function Winetricks({ onClose, runner }: Props) {
+ const { appName } = useContext(SettingsContext)
const { t } = useTranslation()
const [loading, setLoading] = useState(true)
diff --git a/src/frontend/hooks/useSettingsContext.ts b/src/frontend/hooks/useSettingsContext.ts
index cd0b704471..43f8489063 100644
--- a/src/frontend/hooks/useSettingsContext.ts
+++ b/src/frontend/hooks/useSettingsContext.ts
@@ -6,8 +6,8 @@ import ContextProvider from 'frontend/state/ContextProvider'
type Props = {
appName: string
- gameInfo: GameInfo
- runner: Runner
+ gameInfo?: GameInfo
+ runner?: Runner
}
const useSettingsContext = ({ appName, gameInfo, runner }: Props) => {
diff --git a/src/frontend/screens/Settings/SettingsContext.tsx b/src/frontend/screens/Settings/SettingsContext.tsx
index 0a28dff343..cff8965bd4 100644
--- a/src/frontend/screens/Settings/SettingsContext.tsx
+++ b/src/frontend/screens/Settings/SettingsContext.tsx
@@ -9,7 +9,7 @@ const initialContext: SettingsContextType = {
isDefault: true,
appName: 'default',
runner: 'legendary',
- gameInfo: null,
+ gameInfo: undefined,
isMacNative: false,
isLinuxNative: false
}
diff --git a/src/frontend/screens/Settings/components/OfflineMode.tsx b/src/frontend/screens/Settings/components/OfflineMode.tsx
index a3af91e6b7..c6f31a6fae 100644
--- a/src/frontend/screens/Settings/components/OfflineMode.tsx
+++ b/src/frontend/screens/Settings/components/OfflineMode.tsx
@@ -14,6 +14,9 @@ const OfflineMode = () => {
useEffect(() => {
const getInfo = async () => {
+ if (!runner) {
+ return
+ }
const info = await getGameInfo(appName, runner)
if (info) {
const { canRunOffline: can_run_offline } = info
@@ -21,9 +24,7 @@ const OfflineMode = () => {
}
}
- if (!isDefault) {
- getInfo()
- }
+ getInfo()
}, [])
const [offlineMode, setOfflineMode] = useSetting('offlineMode', false)
diff --git a/src/frontend/screens/Settings/components/Tools/index.tsx b/src/frontend/screens/Settings/components/Tools/index.tsx
index 8ea01942af..9caab7f93e 100644
--- a/src/frontend/screens/Settings/components/Tools/index.tsx
+++ b/src/frontend/screens/Settings/components/Tools/index.tsx
@@ -19,11 +19,11 @@ export default function Tools() {
const { platform } = useContext(ContextProvider)
const isWindows = platform === 'win32'
- if (isDefault || isWindows) {
+ if (isDefault || isWindows || !runner) {
return <>>
}
- async function callTools(tool: 'winecfg' | 'runExe', exe?: string) {
+ const callTools = async (tool: 'winecfg' | 'runExe', exe?: string) => {
const toolStates = {
winecfg: setWinecfgRunning,
runExe: setRunExeRunning
@@ -64,7 +64,7 @@ export default function Tools() {
}
}
- async function dropHandler(ev: React.DragEvent) {
+ const dropHandler = async (ev: React.DragEvent) => {
// Prevent default behavior (Prevent file from being opened)
ev.preventDefault()
@@ -97,7 +97,9 @@ export default function Tools() {
return (
<>
- {winetricksRunning &&
}
+ {winetricksRunning && (
+
+ )}