diff --git a/src/renderer/src/pages/profile/profile-content/profile-animations.ts b/src/renderer/src/pages/profile/profile-content/profile-animations.ts
new file mode 100644
index 00000000..f9ac0593
--- /dev/null
+++ b/src/renderer/src/pages/profile/profile-content/profile-animations.ts
@@ -0,0 +1,91 @@
+export const sectionVariants = {
+ collapsed: {
+ opacity: 0,
+ y: -20,
+ height: 0,
+ transition: {
+ duration: 0.3,
+ ease: [0.25, 0.1, 0.25, 1],
+ opacity: { duration: 0.1 },
+ y: { duration: 0.1 },
+ height: { duration: 0.2 },
+ },
+ },
+ expanded: {
+ opacity: 1,
+ y: 0,
+ height: "auto",
+ transition: {
+ duration: 0.3,
+ ease: [0.25, 0.1, 0.25, 1],
+ opacity: { duration: 0.2, delay: 0.1 },
+ y: { duration: 0.3 },
+ height: { duration: 0.3 },
+ },
+ },
+};
+
+export const gameCardVariants = {
+ hidden: {
+ opacity: 0,
+ y: 20,
+ scale: 0.95,
+ },
+ visible: {
+ opacity: 1,
+ y: 0,
+ scale: 1,
+ transition: {
+ duration: 0.4,
+ ease: [0.25, 0.1, 0.25, 1],
+ },
+ },
+ exit: {
+ opacity: 0,
+ y: -20,
+ scale: 0.95,
+ transition: {
+ duration: 0.3,
+ ease: [0.25, 0.1, 0.25, 1],
+ },
+ },
+};
+
+export const gameGridVariants = {
+ hidden: {
+ opacity: 0,
+ },
+ visible: {
+ opacity: 1,
+ transition: {
+ duration: 0.3,
+ staggerChildren: 0.1,
+ delayChildren: 0.1,
+ },
+ },
+ exit: {
+ opacity: 0,
+ transition: {
+ duration: 0.2,
+ },
+ },
+};
+
+export const chevronVariants = {
+ collapsed: {
+ rotate: 0,
+ transition: {
+ duration: 0.2,
+ ease: "easeInOut",
+ },
+ },
+ expanded: {
+ rotate: 90,
+ transition: {
+ duration: 0.2,
+ ease: "easeInOut",
+ },
+ },
+};
+
+export const GAME_STATS_ANIMATION_DURATION_IN_MS = 3500;
diff --git a/src/renderer/src/pages/profile/profile-content/profile-content.scss b/src/renderer/src/pages/profile/profile-content/profile-content.scss
index 2f274e11..bd580b74 100644
--- a/src/renderer/src/pages/profile/profile-content/profile-content.scss
+++ b/src/renderer/src/pages/profile/profile-content/profile-content.scss
@@ -77,7 +77,6 @@
flex-shrink: 0;
}
-
&__collapse-button {
background: none;
border: none;
diff --git a/src/renderer/src/pages/profile/profile-content/sort-options.scss b/src/renderer/src/pages/profile/profile-content/sort-options.scss
new file mode 100644
index 00000000..e36f3727
--- /dev/null
+++ b/src/renderer/src/pages/profile/profile-content/sort-options.scss
@@ -0,0 +1,56 @@
+@use "../../../scss/globals.scss";
+
+.sort-options {
+ &__container {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: calc(globals.$spacing-unit);
+ margin-bottom: calc(globals.$spacing-unit * 2);
+ }
+
+ &__label {
+ color: rgba(255, 255, 255, 0.6);
+ font-size: 14px;
+ font-weight: 400;
+ }
+
+ &__options {
+ display: flex;
+ align-items: center;
+ gap: calc(globals.$spacing-unit);
+ font-size: 14px;
+ }
+
+ &__option {
+ background: none;
+ border: none;
+ color: rgba(255, 255, 255, 0.4);
+ cursor: pointer;
+ padding: 4px 0;
+ font-size: 14px;
+ font-weight: 300;
+ transition: all ease 0.2s;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+
+ &:hover:not(:disabled) {
+ color: rgba(255, 255, 255, 0.6);
+ }
+
+ &.active {
+ color: rgba(255, 255, 255, 0.9);
+ font-weight: 500;
+ }
+
+ span {
+ display: inline-block;
+ }
+ }
+
+ &__separator {
+ color: rgba(255, 255, 255, 0.3);
+ font-size: 14px;
+ }
+}
diff --git a/src/renderer/src/pages/profile/profile-content/sort-options.tsx b/src/renderer/src/pages/profile/profile-content/sort-options.tsx
new file mode 100644
index 00000000..53da8e40
--- /dev/null
+++ b/src/renderer/src/pages/profile/profile-content/sort-options.tsx
@@ -0,0 +1,45 @@
+import { TrophyIcon, ClockIcon, HistoryIcon } from "@primer/octicons-react";
+import { useTranslation } from "react-i18next";
+import "./sort-options.scss";
+
+type SortOption = "playtime" | "achievementCount" | "playedRecently";
+
+interface SortOptionsProps {
+ sortBy: SortOption;
+ onSortChange: (sortBy: SortOption) => void;
+}
+
+export function SortOptions({ sortBy, onSortChange }: SortOptionsProps) {
+ const { t } = useTranslation("user_profile");
+
+ return (
+
+
Sort by:
+
+
+ |
+
+ |
+
+
+
+ );
+}
diff --git a/src/renderer/src/pages/settings/settings-general.tsx b/src/renderer/src/pages/settings/settings-general.tsx
index c698440d..b952dfa0 100644
--- a/src/renderer/src/pages/settings/settings-general.tsx
+++ b/src/renderer/src/pages/settings/settings-general.tsx
@@ -35,6 +35,7 @@ export function SettingsGeneral() {
const [form, setForm] = useState({
downloadsPath: "",
+ ggDealsApiKey: "",
downloadNotificationsEnabled: false,
repackUpdatesNotificationsEnabled: false,
friendRequestNotificationsEnabled: false,
@@ -100,6 +101,7 @@ export function SettingsGeneral() {
setForm((prev) => ({
...prev,
downloadsPath: userPreferences.downloadsPath ?? defaultDownloadsPath,
+ ggDealsApiKey: userPreferences.ggDealsApiKey ?? "",
downloadNotificationsEnabled:
userPreferences.downloadNotificationsEnabled ?? false,
repackUpdatesNotificationsEnabled:
@@ -206,6 +208,12 @@ export function SettingsGeneral() {
}
/>
+
handleChange({ ggDealsApiKey: e.target.value })}
+ />
+