Skip to content

Commit 3665328

Browse files
authored
feat: Update card icon components for responsive design (#102)
* refactor: restructure Hero component layout to follow figma design * feat: update card icon components to use responsive sizes and improve layout for mobile * feat: add responsive size classes and utility functions for CardIcon component
1 parent 650c494 commit 3665328

7 files changed

Lines changed: 131 additions & 33 deletions

File tree

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { GradientIcon, type GradientIconType } from "../gradient-icon"
2-
import type { CardSize } from "./types"
2+
import type { ResponsiveCardSize } from "./types"
33
import { getIconSizeClasses } from "./utils"
44

5-
export function BasicCardMedia({ icon: Icon, size }: { icon: GradientIconType; size: CardSize }) {
5+
export function BasicCardMedia({ icon: Icon, size }: { icon: GradientIconType; size: ResponsiveCardSize }) {
66
return <GradientIcon icon={Icon} className={getIconSizeClasses(size)} />
77
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type { SizeClassMap } from "./types"
2+
3+
export const ICON_SIZE_CLASSES: SizeClassMap = {
4+
xs: "h-10 w-10",
5+
sm: "h-14 w-14",
6+
md: "h-32 w-32",
7+
lg: "h-44 w-44",
8+
}
9+
10+
export const CARD_PADDING_WITHOUT_DESCRIPTION: SizeClassMap = {
11+
xs: "p-3",
12+
sm: "px-8 py-4",
13+
md: "p-8",
14+
lg: "p-8",
15+
}
16+
17+
export const CARD_PADDING_WITH_DESCRIPTION: SizeClassMap = {
18+
xs: "p-8",
19+
sm: "p-8",
20+
md: "p-8",
21+
lg: "p-8",
22+
}
23+
24+
export const CONTENT_GAP_CLASSES: SizeClassMap = {
25+
xs: "gap-2",
26+
sm: "gap-2",
27+
md: "gap-6",
28+
lg: "gap-6",
29+
}
30+
31+
export const TITLE_SIZE_CLASSES: SizeClassMap = {
32+
xs: "typo-label-large",
33+
sm: "typo-headline-medium",
34+
md: "typo-headline-medium",
35+
lg: "typo-headline-medium",
36+
}

src/components/card-icon/description-card-media.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { cn } from "@/lib/utils"
22
import { GradientIcon, type GradientIconType } from "../gradient-icon"
3-
import type { CardSize } from "./types"
3+
import type { ResponsiveCardSize } from "./types"
44
import { getIconSizeClasses } from "./utils"
55

6-
export function DescriptionCardMedia({ icon: Icon, size }: { icon: GradientIconType; size: CardSize }) {
6+
export function DescriptionCardMedia({ icon: Icon, size }: { icon: GradientIconType; size: ResponsiveCardSize }) {
77
return (
88
<div className={cn("relative", getIconSizeClasses(size))}>
99
<GradientIcon icon={Icon} className="h-full w-full" />

src/components/card-icon/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { BasicCardMedia } from "./basic-card-media"
44
import { DescriptionCardMedia } from "./description-card-media"
55
import { CardHoverBackground } from "./hover-background"
66
import type { CardIconProps } from "./types"
7-
import { getCardPaddingClasses, getContentGapClasses } from "./utils"
7+
import { getCardPaddingClasses, getContentGapClasses, getTitleSizeClasses } from "./utils"
88

99
export function CardIcon(props: CardIconProps) {
1010
const { title, icon, size = "md", href, hoverEffect = false, className } = props
@@ -46,7 +46,8 @@ export function CardIcon(props: CardIconProps) {
4646
<div className={cn("flex flex-col", isDescriptionCard ? "gap-2 text-left" : "items-center text-center")}>
4747
<h3
4848
className={cn(
49-
"typo-headline-medium bg-linear-to-b from-blue-secondary to-blue-primary bg-clip-text text-transparent",
49+
getTitleSizeClasses(size),
50+
"bg-linear-to-b from-blue-secondary to-blue-primary bg-clip-text text-transparent",
5051
isDescriptionCard ? "text-left" : "text-center"
5152
)}
5253
>

src/components/card-icon/types.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
11
import type { GradientIconType } from "@/components/gradient-icon"
22

3-
export type CardSize = "sm" | "md" | "lg"
3+
export type CardSize = "xs" | "sm" | "md" | "lg"
4+
export type CardBreakpoint = "base" | "sm" | "md" | "lg"
5+
6+
export type SizeClassMap = Record<CardSize, string>
7+
8+
export type ResponsiveCardSizeConfig = {
9+
base: CardSize
10+
sm?: CardSize
11+
md?: CardSize
12+
lg?: CardSize
13+
}
14+
15+
export type ResponsiveCardSize = CardSize | ResponsiveCardSizeConfig
416

517
export type SharedCardProps = {
618
title: string
719
icon: GradientIconType
8-
size?: CardSize
20+
size?: ResponsiveCardSize
921
href?: string
1022
hoverEffect?: boolean
1123
className?: string
1224
}
1325

14-
export type CardWithDescriptionProps = SharedCardProps & {
15-
description: string
26+
export type CardIconProps = SharedCardProps & {
27+
description?: string
1628
}
17-
18-
export type CardIconProps = SharedCardProps | CardWithDescriptionProps

src/components/card-icon/utils.ts

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,63 @@
1-
import type { CardSize } from "./types"
1+
import {
2+
CARD_PADDING_WITH_DESCRIPTION,
3+
CARD_PADDING_WITHOUT_DESCRIPTION,
4+
CONTENT_GAP_CLASSES,
5+
ICON_SIZE_CLASSES,
6+
TITLE_SIZE_CLASSES,
7+
} from "./classes"
28

3-
export function getIconSizeClasses(size: CardSize) {
4-
if (size === "sm") return "h-14 w-14"
5-
if (size === "lg") return "h-44 w-44"
6-
return "h-32 w-32"
9+
import type { CardBreakpoint, ResponsiveCardSize, SizeClassMap } from "./types"
10+
11+
const BREAKPOINTS: CardBreakpoint[] = ["base", "sm", "md", "lg"]
12+
13+
const BREAKPOINT_PREFIX: Record<CardBreakpoint, string> = {
14+
base: "",
15+
sm: "sm:",
16+
md: "md:",
17+
lg: "lg:",
18+
}
19+
20+
function prefixClasses(prefix: string, value: string): string {
21+
return value
22+
.split(" ")
23+
.filter(Boolean)
24+
.map((token) => `${prefix}${token}`)
25+
.join(" ")
26+
}
27+
28+
function resolveResponsiveClasses(size: ResponsiveCardSize, classesBySize: SizeClassMap): string {
29+
if (typeof size === "string") {
30+
return classesBySize[size]
31+
}
32+
33+
return BREAKPOINTS.map((breakpoint) => {
34+
const currentSize = size[breakpoint]
35+
36+
if (!currentSize) {
37+
return ""
38+
}
39+
40+
return prefixClasses(BREAKPOINT_PREFIX[breakpoint], classesBySize[currentSize])
41+
})
42+
.filter(Boolean)
43+
.join(" ")
44+
}
45+
46+
export function getIconSizeClasses(size: ResponsiveCardSize) {
47+
return resolveResponsiveClasses(size, ICON_SIZE_CLASSES)
48+
}
49+
50+
export function getCardPaddingClasses(size: ResponsiveCardSize, hasDescription: boolean) {
51+
return resolveResponsiveClasses(
52+
size,
53+
hasDescription ? CARD_PADDING_WITH_DESCRIPTION : CARD_PADDING_WITHOUT_DESCRIPTION
54+
)
755
}
856

9-
export function getCardPaddingClasses(size: CardSize, hasDescription: boolean) {
10-
if (!hasDescription && size === "sm") return "px-8 py-4"
11-
return "p-8"
57+
export function getContentGapClasses(size: ResponsiveCardSize) {
58+
return resolveResponsiveClasses(size, CONTENT_GAP_CLASSES)
1259
}
1360

14-
export function getContentGapClasses(size: CardSize) {
15-
if (size === "sm") return "gap-2"
16-
return "gap-6"
61+
export function getTitleSizeClasses(size: ResponsiveCardSize) {
62+
return resolveResponsiveClasses(size, TITLE_SIZE_CLASSES)
1763
}

src/components/home/materials.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,37 +22,42 @@ const featuredCards = [
2222
] as const
2323

2424
const quickLinks = [
25-
{ title: "Dispense", icon: FiBook, size: "sm", href: "#" },
26-
{ title: "Esami", icon: FiFileText, size: "sm", href: "#" },
27-
{ title: "Appunti", icon: FiClipboard, size: "sm", href: "#" },
25+
{ title: "Dispense", icon: FiBook, size: { base: "xs", sm: "sm" }, href: "#" },
26+
{ title: "Esami", icon: FiFileText, size: { base: "xs", sm: "sm" }, href: "#" },
27+
{ title: "Appunti", icon: FiClipboard, size: { base: "xs", sm: "sm" }, href: "#" },
2828
] as const
2929

3030
export function Materials() {
3131
return (
32-
<section className="mx-auto flex max-w-500 flex-col-reverse gap-8 px-4 py-10 sm:px-8 sm:py-12 lg:gap-10 lg:px-12 xl:flex-row xl:items-start xl:gap-12 xl:px-16 2xl:gap-32 2xl:px-32">
33-
<div className="flex grow flex-col gap-5 lg:gap-6 xl:gap-8 xl:pt-12 2xl:pt-44">
34-
<div className="grid gap-12 md:grid-cols-2 2xl:gap-20">
32+
<section className="mx-auto flex max-w-400 flex-col-reverse gap-24 p-11 sm:px-20 sm:py-28 2xl:flex-row 2xl:items-start 2xl:gap-32">
33+
<div className="flex grow flex-col gap-5 sm:gap-6 2xl:gap-8 2xl:pt-44">
34+
<div className="grid gap-4 sm:grid-cols-2 sm:gap-12 2xl:gap-20">
35+
{/* TODO sotto sm usare le altre card fatte da Diubi */}
3536
{featuredCards.map((card) => (
3637
<CardIcon key={card.title} {...card} className="h-full" />
3738
))}
3839
</div>
3940

40-
<div className="grid gap-4 sm:grid-cols-2 sm:gap-12 lg:grid-cols-3 2xl:gap-20">
41+
<div className="grid grid-cols-3 gap-4 sm:gap-12 2xl:gap-20">
4142
{quickLinks.map((card) => (
4243
<CardIcon key={card.title} {...card} className="h-full" />
4344
))}
4445
</div>
4546
</div>
4647

47-
<div className="flex flex-col items-start gap-8 xl:justify-self-end">
48-
<h2 className="typo-display-large sm:typo-display-extralarge w-fit bg-linear-to-b from-text-primary to-text-secondary bg-clip-text py-4 text-transparent">
48+
<div className="flex flex-col items-center gap-8 text-center sm:ml-auto sm:items-start sm:text-start">
49+
<h2 className="typo-display-large sm:typo-display-extralarge bg-linear-to-b from-text-primary to-text-secondary bg-clip-text text-transparent sm:py-4">
4950
Materials
5051
</h2>
51-
<p className="typo-body-large max-w-lg">
52+
<p className="typo-body-large hidden max-w-lg sm:block">
5253
Il piu grande archivio didattico creato dagli studenti per gli studenti del Politecnico di Milano. Cerca tra
5354
migliaia di appunti, dispense, temi d'esame e molto altro. Carica i tuoi file per far crescere la community e
5455
trova tutto cio che ti serve, organizzato per corso di studi.
5556
</p>
57+
<p className="typo-body-large max-w-lg sm:hidden">
58+
Il più grande archivio didattico degli studenti del Politecnico. Trova appunti, dispense ed esami, oppure
59+
carica i tuoi file per far crescere la community.
60+
</p>
5661
<Button variant="primary" size="lg" className="w-fit">
5762
Scopri di piu
5863
<FiArrowUpRight />

0 commit comments

Comments
 (0)