Skip to content

[UX] Improve gamepage #3613

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Jun 2, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b053340
WIP: Better UX for new gamepage
Kajot-dev Mar 3, 2024
db59f11
WIP: Update formatting
Kajot-dev Mar 3, 2024
c1930a8
Sticky topbar + UI polish
Kajot-dev Mar 16, 2024
ed1c854
HLTB styles improvement
Kajot-dev Mar 16, 2024
b7e388b
Fix formatting
Kajot-dev Mar 16, 2024
9b2547b
Implement install button
Kajot-dev Mar 16, 2024
8980dd4
Merge remote-tracking branch 'fork/main' into improve_gamepage
Kajot-dev Mar 16, 2024
0557466
Fix aria-control attribute
Kajot-dev Mar 16, 2024
3199362
Remove unnecessary code
Kajot-dev Mar 16, 2024
2144987
Fix HLTB breaking when hours were triple digits
Kajot-dev Mar 16, 2024
23e2a4a
Fix keyboard focus issues
Kajot-dev Mar 16, 2024
2adb5ad
Formatting
Kajot-dev Mar 16, 2024
9aec2d8
Remove opts wrapper
Kajot-dev Mar 16, 2024
ec788fa
Hardcode 'mainBtn' class
Kajot-dev Mar 17, 2024
d74fd3e
Do not show focus outline when using a mouse
Kajot-dev Mar 17, 2024
649cb06
Scaling and scrolling
Kajot-dev Mar 17, 2024
a797148
Fix shadow on dots menu
Kajot-dev Mar 17, 2024
ec8df26
Merge HLTBInline and HLTB
Kajot-dev Mar 17, 2024
85a70f8
Remove unnecessary outline on root element
Kajot-dev Mar 17, 2024
17a84b7
Merge branch 'Heroic-Games-Launcher:main' into improve_gamepage
Kajot-dev Mar 17, 2024
103b26c
Add nowrap to hte HLTB hour count
Kajot-dev Mar 17, 2024
cdc142d
Scale bg-image correctly
Kajot-dev Mar 17, 2024
f621e71
Merge branch 'Heroic-Games-Launcher:main' into improve_gamepage
Kajot-dev Mar 23, 2024
2d0da15
Add support for the RTL
Kajot-dev Mar 26, 2024
72858db
Style the progressbar
Kajot-dev Mar 29, 2024
82ce1b9
Merge branch 'Heroic-Games-Launcher:main' into improve_gamepage
Kajot-dev Mar 29, 2024
79fc52a
Merge branch 'Heroic-Games-Launcher:main' into improve_gamepage
Kajot-dev Mar 29, 2024
bf3029c
Make nav buttons respect current theme
Kajot-dev Apr 1, 2024
5cc2672
use MUI Progress for consistency
Kajot-dev Apr 1, 2024
6214096
Better placed/scaled icons
Kajot-dev Apr 1, 2024
5fa27e2
Icon scaling
Kajot-dev Apr 1, 2024
41b59fd
Formatting
Kajot-dev Apr 1, 2024
8a3db0a
Merge branch 'Heroic-Games-Launcher:main' into improve_gamepage
Kajot-dev Apr 1, 2024
e9b4a8f
Make new gamepage work on light themes
Kajot-dev Apr 2, 2024
e224bcf
Bad icon order when game is uninstalled
Kajot-dev Apr 3, 2024
7a6ed76
Reduce background opacity
Kajot-dev Apr 4, 2024
d2417e2
Merge branch 'Heroic-Games-Launcher:main' into improve_gamepage
Kajot-dev Apr 6, 2024
b0b1b85
Merge branch 'Heroic-Games-Launcher:main' into improve_gamepage
Kajot-dev Jun 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions public/locales/en/gamepage.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,11 @@
},
"changelogFor": "Changelog for {{gameTitle}}",
"downloadSize": "Download Size",
"extra_info": "Extra info",
"firstPlayed": "First Played",
"getting-download-size": "Getting download size",
"getting-install-size": "Getting install size",
"install_info": "Install info",
"installSize": "Install Size",
"language": "Language",
"lastPlayed": "Last Played",
Expand Down
24 changes: 24 additions & 0 deletions src/frontend/components/UI/TabPanel/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, { HTMLProps } from 'react'

type TabPanelProps = HTMLProps<HTMLDivElement> & {
children?: React.ReactNode
index: string
value: string
}

function TabPanel(props: Readonly<TabPanelProps>) {
const { children, value, index, ...other } = props

return (
<div
role="tabpanel"
id={`tabpanel-${index}`}
aria-labelledby={`tab-${index}`}
{...other}
>
{value === index && <div>{children}</div>}
</div>
)
}

export default TabPanel
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
.howLongToBeat {
display: flex;
justify-content: space-around;
gap: var(--space-sm-fixed);

.circle {
width: 100px;
Expand All @@ -11,10 +13,10 @@
border-radius: 50%; /* change to a circle */
border: 2px solid; /* add a border */
color: var(--text-secondary);
margin-inline-end: 10px;
padding: 0 var(--space-xs);
background-color: transparent;
cursor: pointer;
position: relative;

&.green {
border: 3px solid green;
Expand All @@ -30,6 +32,9 @@

.circle__title {
font-size: 0.8rem;
white-space: normal;
max-width: 90%;
text-align: center;
}

.circle__value {
Expand All @@ -38,6 +43,9 @@
}
}
.circle {
flex-basis: 33.3%;
aspect-ratio: 1 / 1;
height: auto;
width: fit-content;
min-width: 100px;
justify-content: center;
Expand Down
1 change: 1 addition & 0 deletions src/frontend/components/UI/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export { default as InfoBox } from './InfoBox'
export { default as LanguageSelector } from './LanguageSelector'
export { default as SelectField } from './SelectField'
export { default as SmallInfo } from './SmallInfo'
export { default as TabPanel } from './TabPanel'
export { default as TextInputField } from './TextInputField'
export { default as ToggleSwitch } from './ToggleSwitch'
export { default as UpdateComponent } from './UpdateComponent'
Expand Down
48 changes: 48 additions & 0 deletions src/frontend/screens/Game/GamePage/components/HLTBInline.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { useContext, useState } from 'react'
import { useTranslation } from 'react-i18next'
import GameContext from '../../GameContext'
import { Speed, ExpandMore } from '@mui/icons-material'
import { Accordion, AccordionSummary, AccordionDetails } from '@mui/material'
import HowLongToBeat from 'frontend/components/UI/WikiGameInfo/components/HowLongToBeat'

const HLTBInline = () => {
const { t } = useTranslation('gamepage')
const { wikiInfo } = useContext(GameContext)

const [isExpanded, setIsExpanded] = useState(false)

function handleChange() {
setIsExpanded((prevExpanded) => !prevExpanded)
}

if (!wikiInfo) {
return null
}

const howlongtobeat = wikiInfo.howlongtobeat

if (!howlongtobeat) {
return null
}

return (
<div className="hltbWrapper">
<Accordion expanded={isExpanded} onChange={handleChange}>
<AccordionSummary
expandIcon={<ExpandMore />}
aria-control="hltb-content"
id="hltb-header"
title={t('info.clickToOpen', 'Click to open')}
>
<Speed />
<b>{t('howLongToBeat', 'How Long To Beat')}</b>
</AccordionSummary>
<AccordionDetails>
<HowLongToBeat info={howlongtobeat} />
</AccordionDetails>
</Accordion>
</div>
)
}

export default HLTBInline
80 changes: 57 additions & 23 deletions src/frontend/screens/Game/GamePage/components/MainButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import React, { useContext } from 'react'
import React, {
useContext,
DetailedHTMLProps,
ButtonHTMLAttributes
} from 'react'
import { useTranslation } from 'react-i18next'
import GameContext from '../../GameContext'
import {
Expand All @@ -14,15 +18,25 @@ import {
import classNames from 'classnames'
import { GameInfo } from 'common/types'

interface Props {
// we can't just use HTMLProps because of inconsistency in button's "type" attribute
interface Props
extends DetailedHTMLProps<
ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
> {
gameInfo: GameInfo
handlePlay: (gameInfo: GameInfo) => Promise<void>
handleInstall: (
is_installed: boolean
) => Promise<void | { status: 'done' | 'error' | 'abort' }>
}

const MainButton = ({ gameInfo, handlePlay, handleInstall }: Props) => {
const MainButton = ({
gameInfo,
handlePlay,
handleInstall,
...other
}: Props) => {
const { t } = useTranslation('gamepage')
const { is } = useContext(GameContext)

Expand Down Expand Up @@ -128,6 +142,13 @@ const MainButton = ({ gameInfo, handlePlay, handleInstall }: Props) => {

const is_installed = gameInfo.is_installed

const extraClassName = other.className

if (extraClassName) {
// do not override internal classNames
delete other.className
}

return (
<>
{is_installed && !is.queued && (
Expand All @@ -144,17 +165,25 @@ const MainButton = ({ gameInfo, handlePlay, handleInstall }: Props) => {
}
autoFocus={true}
onClick={async () => handlePlay(gameInfo)}
className={classNames('button', {
'is-secondary': !is_installed && !is.queued,
'is-success':
is.syncing ||
(!is.updating && !is.playing && is_installed && !is.notAvailable),
'is-tertiary':
is.playing ||
(!is_installed && is.queued) ||
(is_installed && is.notAvailable),
'is-disabled': is.updating
})}
className={classNames(
'button',
{
'is-secondary': !is_installed && !is.queued,
'is-success':
is.syncing ||
(!is.updating &&
!is.playing &&
is_installed &&
!is.notAvailable),
'is-tertiary':
is.playing ||
(!is_installed && is.queued) ||
(is_installed && is.notAvailable),
'is-disabled': is.updating
},
extraClassName
)}
{...other}
>
{getPlayLabel()}
</button>
Expand All @@ -172,15 +201,20 @@ const MainButton = ({ gameInfo, handlePlay, handleInstall }: Props) => {
is.notInstallable
}
autoFocus={true}
className={classNames('button', {
'is-primary': is_installed,
'is-tertiary':
is.notAvailable ||
is.installing ||
is.queued ||
is.notInstallable,
'is-secondary': !is_installed && !is.queued
})}
className={classNames(
'button',
{
'is-primary': is_installed,
'is-tertiary':
is.notAvailable ||
is.installing ||
is.queued ||
is.notInstallable,
'is-secondary': !is_installed && !is.queued
},
extraClassName
)}
{...other}
>
{getButtonLabel()}
</button>
Expand Down
1 change: 1 addition & 0 deletions src/frontend/screens/Game/GamePage/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export { default as DownloadSizeInfo } from './DownloadSizeInfo'
export { default as InstalledInfo } from './InstalledInfo'
export { default as Scores } from './Scores'
export { default as HLTB } from './HLTB'
export { default as HLTBInline } from './HLTBInline'
export { default as AppleWikiInfo } from './AppleWikiInfo'
export { default as Requirements } from './Requirements'
export { default as MainButton } from './MainButton'
Expand Down
Loading