mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
feat: redoing page
This commit is contained in:
parent
2700f27d03
commit
ab27fd21d7
3 changed files with 170 additions and 205 deletions
|
@ -1,4 +1,4 @@
|
||||||
import { useCallback } from "react";
|
import { useCallback, useMemo } from "react";
|
||||||
import { useAppDispatch, useAppSelector } from "./redux";
|
import { useAppDispatch, useAppSelector } from "./redux";
|
||||||
import {
|
import {
|
||||||
setProfileBackground,
|
setProfileBackground,
|
||||||
|
@ -129,7 +129,16 @@ export function useUserDetails() {
|
||||||
|
|
||||||
const unblockUser = (userId: string) => window.electron.unblockUser(userId);
|
const unblockUser = (userId: string) => window.electron.unblockUser(userId);
|
||||||
|
|
||||||
const hasActiveSubscription = userDetails?.subscription?.status === "active";
|
const hasActiveSubscription = useMemo(() => {
|
||||||
|
if (!userDetails?.subscription) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
userDetails.subscription.expiresAt == null ||
|
||||||
|
new Date(userDetails.subscription.expiresAt) > new Date()
|
||||||
|
);
|
||||||
|
}, [userDetails]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userDetails,
|
userDetails,
|
||||||
|
|
|
@ -5,15 +5,19 @@ import { useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import * as styles from "./achievements.css";
|
import * as styles from "./achievements.css";
|
||||||
import { formatDownloadProgress } from "@renderer/helpers";
|
import { formatDownloadProgress } from "@renderer/helpers";
|
||||||
import { LockIcon, PersonIcon, TrophyIcon } from "@primer/octicons-react";
|
import {
|
||||||
|
CheckCircleIcon,
|
||||||
|
LockIcon,
|
||||||
|
PersonIcon,
|
||||||
|
TrophyIcon,
|
||||||
|
UnlockIcon,
|
||||||
|
} from "@primer/octicons-react";
|
||||||
import { SPACING_UNIT, vars } from "@renderer/theme.css";
|
import { SPACING_UNIT, vars } from "@renderer/theme.css";
|
||||||
import { gameDetailsContext } from "@renderer/context";
|
import { gameDetailsContext } from "@renderer/context";
|
||||||
import { UserAchievement } from "@types";
|
import { UserAchievement } from "@types";
|
||||||
import { average } from "color.js";
|
import { average } from "color.js";
|
||||||
import Color from "color";
|
import Color from "color";
|
||||||
|
|
||||||
const HERO_ANIMATION_THRESHOLD = 25;
|
|
||||||
|
|
||||||
interface UserInfo {
|
interface UserInfo {
|
||||||
userId: string;
|
userId: string;
|
||||||
displayName: string;
|
displayName: string;
|
||||||
|
@ -32,152 +36,58 @@ interface AchievementListProps {
|
||||||
|
|
||||||
interface AchievementPanelProps {
|
interface AchievementPanelProps {
|
||||||
user: UserInfo;
|
user: UserInfo;
|
||||||
otherUser: UserInfo | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function AchievementPanel({ user, otherUser }: AchievementPanelProps) {
|
function AchievementPanel({ user }: AchievementPanelProps) {
|
||||||
const { t } = useTranslation("achievement");
|
const { userDetails, hasActiveSubscription } = useUserDetails();
|
||||||
const { userDetails } = useUserDetails();
|
|
||||||
|
|
||||||
const userTotalAchievementCount = user.achievements.length;
|
const userTotalAchievementCount = user.achievements.length;
|
||||||
const userUnlockedAchievementCount = user.achievements.filter(
|
const userUnlockedAchievementCount = user.achievements.filter(
|
||||||
(achievement) => achievement.unlocked
|
(achievement) => achievement.unlocked
|
||||||
).length;
|
).length;
|
||||||
|
|
||||||
if (!otherUser) {
|
const getProfileImage = (user: UserInfo) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={styles.profileAvatar}>
|
||||||
style={{
|
{user.profileImageUrl ? (
|
||||||
display: "flex",
|
<img
|
||||||
flexDirection: "row",
|
className={styles.profileAvatar}
|
||||||
width: "100%",
|
src={user.profileImageUrl}
|
||||||
gap: `${SPACING_UNIT * 2}px`,
|
alt={user.displayName}
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
width: "100%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<h1 style={{ fontSize: "1.2em", marginBottom: "8px" }}>
|
|
||||||
{t("your_achievements")}
|
|
||||||
</h1>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
marginBottom: 8,
|
|
||||||
width: "100%",
|
|
||||||
color: vars.color.muted,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: 8,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<TrophyIcon size={13} />
|
|
||||||
<span>
|
|
||||||
{userUnlockedAchievementCount} / {userTotalAchievementCount}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
{formatDownloadProgress(
|
|
||||||
userUnlockedAchievementCount / userTotalAchievementCount
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<progress
|
|
||||||
max={1}
|
|
||||||
value={userUnlockedAchievementCount / userTotalAchievementCount}
|
|
||||||
className={styles.achievementsProgressBar}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
) : (
|
||||||
|
<PersonIcon size={24} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const otherUserUnlockedAchievementCount = otherUser.achievements.filter(
|
if (userDetails?.id == user.userId && !hasActiveSubscription) {
|
||||||
(achievement) => achievement.unlocked
|
return <></>;
|
||||||
).length;
|
}
|
||||||
const otherUserTotalAchievementCount = otherUser.achievements.length;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "grid",
|
display: "flex",
|
||||||
gridTemplateColumns: "2fr 1fr 1fr",
|
|
||||||
gap: `${SPACING_UNIT * 2}px`,
|
gap: `${SPACING_UNIT * 2}px`,
|
||||||
padding: `${SPACING_UNIT}px`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ display: "flex", flexDirection: "column" }}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<h1 style={{ fontSize: "1.2em", marginBottom: "8px" }}>
|
|
||||||
{otherUser.displayName}
|
|
||||||
</h1>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
marginBottom: 8,
|
|
||||||
color: vars.color.muted,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: 8,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TrophyIcon size={13} />
|
{getProfileImage(user)}
|
||||||
<span>
|
|
||||||
{otherUserUnlockedAchievementCount} /{" "}
|
|
||||||
{otherUserTotalAchievementCount}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
{formatDownloadProgress(
|
|
||||||
otherUserUnlockedAchievementCount /
|
|
||||||
otherUserTotalAchievementCount
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<progress
|
|
||||||
max={1}
|
|
||||||
value={
|
|
||||||
otherUserUnlockedAchievementCount / otherUserTotalAchievementCount
|
|
||||||
}
|
|
||||||
className={styles.achievementsProgressBar}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<h1 style={{ fontSize: "1.2em", marginBottom: "8px" }}>
|
<h1 style={{ marginBottom: "8px" }}>{user.displayName}</h1>
|
||||||
{userDetails?.displayName}
|
|
||||||
</h1>
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
width: "100%",
|
|
||||||
color: vars.color.muted,
|
color: vars.color.muted,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -207,7 +117,6 @@ function AchievementPanel({ user, otherUser }: AchievementPanelProps) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,18 +129,6 @@ function AchievementList({ user, otherUser }: AchievementListProps) {
|
||||||
|
|
||||||
const { userDetails } = useUserDetails();
|
const { userDetails } = useUserDetails();
|
||||||
|
|
||||||
const getProfileImage = (imageUrl: string | null | undefined) => {
|
|
||||||
return (
|
|
||||||
<div className={styles.profileAvatar}>
|
|
||||||
{imageUrl ? (
|
|
||||||
<img className={styles.profileAvatar} src={imageUrl} alt={"teste"} />
|
|
||||||
) : (
|
|
||||||
<PersonIcon size={24} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!otherUserAchievements || otherUserAchievements.length === 0) {
|
if (!otherUserAchievements || otherUserAchievements.length === 0) {
|
||||||
return (
|
return (
|
||||||
<ul className={styles.list}>
|
<ul className={styles.list}>
|
||||||
|
@ -271,7 +168,7 @@ function AchievementList({ user, otherUser }: AchievementListProps) {
|
||||||
<li
|
<li
|
||||||
key={index}
|
key={index}
|
||||||
className={styles.listItem}
|
className={styles.listItem}
|
||||||
style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr" }}
|
style={{ display: "grid", gridTemplateColumns: "3fr 1fr 1fr" }}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
@ -295,32 +192,46 @@ function AchievementList({ user, otherUser }: AchievementListProps) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div
|
||||||
|
title={
|
||||||
|
otherUserAchievement.unlockTime
|
||||||
|
? formatDateTime(otherUserAchievement.unlockTime)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
{otherUserAchievement.unlockTime ? (
|
{otherUserAchievement.unlockTime ? (
|
||||||
<div style={{ whiteSpace: "nowrap" }}>
|
<div
|
||||||
{getProfileImage(otherUser.profileImageUrl)}
|
style={{
|
||||||
<small>{t("unlocked_at")}</small>
|
whiteSpace: "nowrap",
|
||||||
<p>{formatDateTime(otherUserAchievement.unlockTime)}</p>
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CheckCircleIcon />
|
||||||
|
<small>{formatDateTime(otherUserAchievement.unlockTime)}</small>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<LockIcon />
|
<LockIcon />
|
||||||
<p>Não desbloqueada</p>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div
|
||||||
|
title={
|
||||||
|
userDetails?.subscription && achievements[index].unlockTime
|
||||||
|
? formatDateTime(achievements[index].unlockTime)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
{userDetails?.subscription && achievements[index].unlockTime ? (
|
{userDetails?.subscription && achievements[index].unlockTime ? (
|
||||||
<div style={{ whiteSpace: "nowrap" }}>
|
<div style={{ whiteSpace: "nowrap" }}>
|
||||||
{getProfileImage(user.profileImageUrl)}
|
<UnlockIcon />
|
||||||
<small>{t("unlocked_at")}</small>
|
|
||||||
<p>{formatDateTime(achievements[index].unlockTime)}</p>
|
<p>{formatDateTime(achievements[index].unlockTime)}</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<LockIcon />
|
<LockIcon />
|
||||||
<p>Não desbloqueada</p>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -334,7 +245,6 @@ export function AchievementsContent({ otherUser }: AchievementsContentProps) {
|
||||||
const heroRef = useRef<HTMLDivElement | null>(null);
|
const heroRef = useRef<HTMLDivElement | null>(null);
|
||||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||||
const [isHeaderStuck, setIsHeaderStuck] = useState(false);
|
const [isHeaderStuck, setIsHeaderStuck] = useState(false);
|
||||||
const [backdropOpactiy, setBackdropOpacity] = useState(1);
|
|
||||||
|
|
||||||
const { gameTitle, objectId, shop, achievements, gameColor, setGameColor } =
|
const { gameTitle, objectId, shop, achievements, gameColor, setGameColor } =
|
||||||
useContext(gameDetailsContext);
|
useContext(gameDetailsContext);
|
||||||
|
@ -380,11 +290,6 @@ export function AchievementsContent({ otherUser }: AchievementsContentProps) {
|
||||||
const heroHeight = heroRef.current?.clientHeight ?? styles.HERO_HEIGHT;
|
const heroHeight = heroRef.current?.clientHeight ?? styles.HERO_HEIGHT;
|
||||||
|
|
||||||
const scrollY = (event.target as HTMLDivElement).scrollTop;
|
const scrollY = (event.target as HTMLDivElement).scrollTop;
|
||||||
const opacity = Math.max(
|
|
||||||
0,
|
|
||||||
1 - scrollY / (heroHeight - HERO_ANIMATION_THRESHOLD)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (scrollY >= heroHeight && !isHeaderStuck) {
|
if (scrollY >= heroHeight && !isHeaderStuck) {
|
||||||
setIsHeaderStuck(true);
|
setIsHeaderStuck(true);
|
||||||
}
|
}
|
||||||
|
@ -392,8 +297,22 @@ export function AchievementsContent({ otherUser }: AchievementsContentProps) {
|
||||||
if (scrollY <= heroHeight && isHeaderStuck) {
|
if (scrollY <= heroHeight && isHeaderStuck) {
|
||||||
setIsHeaderStuck(false);
|
setIsHeaderStuck(false);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
setBackdropOpacity(opacity);
|
const getProfileImage = (user: UserInfo) => {
|
||||||
|
return (
|
||||||
|
<div className={styles.profileAvatarSmall}>
|
||||||
|
{user.profileImageUrl ? (
|
||||||
|
<img
|
||||||
|
className={styles.profileAvatarSmall}
|
||||||
|
src={user.profileImageUrl}
|
||||||
|
alt={user.displayName}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<PersonIcon size={24} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!objectId || !shop || !gameTitle || !userDetails) return null;
|
if (!objectId || !shop || !gameTitle || !userDetails) return null;
|
||||||
|
@ -402,6 +321,7 @@ export function AchievementsContent({ otherUser }: AchievementsContentProps) {
|
||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
<img
|
<img
|
||||||
src={steamUrlBuilder.libraryHero(objectId)}
|
src={steamUrlBuilder.libraryHero(objectId)}
|
||||||
|
style={{ display: "none" }}
|
||||||
alt={gameTitle}
|
alt={gameTitle}
|
||||||
className={styles.heroImage}
|
className={styles.heroImage}
|
||||||
onLoad={handleHeroLoad}
|
onLoad={handleHeroLoad}
|
||||||
|
@ -412,19 +332,14 @@ export function AchievementsContent({ otherUser }: AchievementsContentProps) {
|
||||||
onScroll={onScroll}
|
onScroll={onScroll}
|
||||||
className={styles.container}
|
className={styles.container}
|
||||||
>
|
>
|
||||||
<div ref={heroRef} className={styles.hero}>
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: gameColor,
|
display: "flex",
|
||||||
flex: 1,
|
flexDirection: "column",
|
||||||
opacity: Math.min(1, 1 - backdropOpactiy),
|
background: `linear-gradient(0deg, ${vars.color.darkBackground} 0%, ${gameColor} 100%)`,
|
||||||
}}
|
}}
|
||||||
/>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={styles.heroLogoBackdrop}
|
|
||||||
style={{ opacity: backdropOpactiy }}
|
|
||||||
>
|
>
|
||||||
|
<div ref={heroRef} className={styles.hero}>
|
||||||
<div className={styles.heroContent}>
|
<div className={styles.heroContent}>
|
||||||
<img
|
<img
|
||||||
src={steamUrlBuilder.logo(objectId)}
|
src={steamUrlBuilder.logo(objectId)}
|
||||||
|
@ -433,18 +348,50 @@ export function AchievementsContent({ otherUser }: AchievementsContentProps) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.panel({ stuck: isHeaderStuck })}>
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
gap: `${SPACING_UNIT * 2}px`,
|
||||||
|
padding: `${SPACING_UNIT * 2}px`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<AchievementPanel
|
<AchievementPanel
|
||||||
user={{
|
user={{
|
||||||
...userDetails,
|
...userDetails,
|
||||||
userId: userDetails.id,
|
userId: userDetails.id,
|
||||||
achievements: sortedAchievements,
|
achievements: sortedAchievements,
|
||||||
}}
|
}}
|
||||||
otherUser={otherUser}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{otherUser && <AchievementPanel user={otherUser} />}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{otherUser && (
|
||||||
|
<div className={styles.panel({ stuck: isHeaderStuck })}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "grid",
|
||||||
|
gridTemplateColumns: "3fr 1fr 1fr",
|
||||||
|
padding: `${SPACING_UNIT}px`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div></div>
|
||||||
|
<div>{getProfileImage(otherUser)}</div>
|
||||||
|
<div>
|
||||||
|
{getProfileImage({
|
||||||
|
...userDetails,
|
||||||
|
userId: userDetails.id,
|
||||||
|
achievements: sortedAchievements,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
|
|
@ -2,7 +2,8 @@ import { SPACING_UNIT, vars } from "../../theme.css";
|
||||||
import { style } from "@vanilla-extract/css";
|
import { style } from "@vanilla-extract/css";
|
||||||
import { recipe } from "@vanilla-extract/recipes";
|
import { recipe } from "@vanilla-extract/recipes";
|
||||||
|
|
||||||
export const HERO_HEIGHT = 300;
|
export const HERO_HEIGHT = 150;
|
||||||
|
export const LOGO_HEIGHT = 100;
|
||||||
|
|
||||||
export const wrapper = style({
|
export const wrapper = style({
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
@ -38,6 +39,7 @@ export const heroImage = style({
|
||||||
transition: "all ease 0.2s",
|
transition: "all ease 0.2s",
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
zIndex: "0",
|
zIndex: "0",
|
||||||
|
filter: "blur(5px)",
|
||||||
"@media": {
|
"@media": {
|
||||||
"(min-width: 1250px)": {
|
"(min-width: 1250px)": {
|
||||||
objectPosition: "center",
|
objectPosition: "center",
|
||||||
|
@ -53,11 +55,11 @@ export const heroContent = style({
|
||||||
width: "100%",
|
width: "100%",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
alignItems: "flex-end",
|
alignItems: "center",
|
||||||
});
|
});
|
||||||
|
|
||||||
export const gameLogo = style({
|
export const gameLogo = style({
|
||||||
width: 300,
|
height: LOGO_HEIGHT,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const container = style({
|
export const container = style({
|
||||||
|
@ -72,14 +74,10 @@ export const container = style({
|
||||||
export const panel = recipe({
|
export const panel = recipe({
|
||||||
base: {
|
base: {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "150px",
|
|
||||||
minHeight: "150px",
|
|
||||||
padding: `${SPACING_UNIT * 2}px`,
|
|
||||||
backgroundColor: vars.color.darkBackground,
|
backgroundColor: vars.color.darkBackground,
|
||||||
transition: "all ease 0.2s",
|
transition: "all ease 0.2s",
|
||||||
borderBottom: `solid 1px ${vars.color.border}`,
|
borderBottom: `solid 1px ${vars.color.border}`,
|
||||||
position: "sticky",
|
position: "sticky",
|
||||||
overflow: "hidden",
|
|
||||||
top: "0",
|
top: "0",
|
||||||
zIndex: "1",
|
zIndex: "1",
|
||||||
},
|
},
|
||||||
|
@ -149,7 +147,6 @@ export const achievementsProgressBar = style({
|
||||||
export const heroLogoBackdrop = style({
|
export const heroLogoBackdrop = style({
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
background: "linear-gradient(0deg, rgba(0, 0, 0, 0.3) 60%, transparent 100%)",
|
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
|
@ -184,6 +181,18 @@ export const listItemSkeleton = style({
|
||||||
});
|
});
|
||||||
|
|
||||||
export const profileAvatar = style({
|
export const profileAvatar = style({
|
||||||
|
height: "54px",
|
||||||
|
width: "54px",
|
||||||
|
borderRadius: "4px",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
backgroundColor: vars.color.background,
|
||||||
|
position: "relative",
|
||||||
|
objectFit: "cover",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const profileAvatarSmall = style({
|
||||||
height: "32px",
|
height: "32px",
|
||||||
width: "32px",
|
width: "32px",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue