Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 27 additions & 9 deletions src/Components/portfolio/PortfolioCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type PortfolioCoverImageProps = {
alt: string;
className: string;
cover: string;
objectPosition?: string;
priority?: boolean;
responsiveCover?: ResponsivePortfolioCover;
sizes: string;
Expand All @@ -27,6 +28,7 @@ export function PortfolioCoverImage({
alt,
className,
cover,
objectPosition,
priority = false,
responsiveCover,
sizes,
Expand All @@ -38,6 +40,9 @@ export function PortfolioCoverImage({
className={className}
loading={priority ? "eager" : "lazy"}
decoding="async"
{...(objectPosition === undefined
? {}
: { style: { objectPosition } })}
{...(priority ? { fetchpriority: "high" } : {})}
{...(responsiveCover === undefined
? {}
Expand Down Expand Up @@ -72,10 +77,13 @@ interface PortfolioCardProps {
desc: string;
details: ReactNode;
expanded: boolean;
fullBleed?: boolean;
headingLevel?: "h2" | "h3";
disclaimer?: string;
objectPosition?: string;
priority?: boolean;
responsiveCover?: ResponsivePortfolioCover;
sizes?: string;
status?: string;
tags: string;
title: string;
Expand All @@ -87,10 +95,13 @@ export default function PortfolioCard({
desc,
details,
expanded,
fullBleed = false,
headingLevel = "h3",
disclaimer,
objectPosition,
priority = false,
responsiveCover,
sizes = "(min-width: 1280px) 457px, (min-width: 768px) calc(41.67vw - 76px), calc(100vw - 88px)",
status,
tags,
title,
Expand All @@ -101,32 +112,39 @@ export default function PortfolioCard({
return (
<motion.div
data-nojs-visible
className={`border border-gray-200 rounded-2xl shadow-sm bg-white ${expanded || status ? "" : "md:h-[280px] md:overflow-hidden"}`}
className={`border border-gray-200 rounded-2xl shadow-sm bg-white ${expanded ? "" : "lg:h-[360px]"}`}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.45 }}
viewport={{ once: true }}
>
<div className="flex flex-col md:flex-row">
<div className="md:w-5/12">
<div className="w-full aspect-[16/9] p-5 md:p-7 rounded-2xl bg-white overflow-hidden flex items-center justify-center">
<div className="flex flex-col md:flex-row lg:h-full">
<div className="md:w-5/12 lg:h-full">
<div
className={`flex aspect-[16/9] w-full items-center justify-center overflow-hidden rounded-2xl bg-white lg:h-full lg:aspect-auto ${
fullBleed ? "" : "p-5 md:p-7"
}`}
>
<PortfolioCoverImage
cover={cover}
alt=""
className={`w-full h-full object-center rounded-xl ${
className={`w-full h-full object-center ${
fullBleed ? "" : "rounded-xl"
} ${
coverFit === "cover" ? "object-cover" : "object-contain"
}`}
{...(objectPosition === undefined ? {} : { objectPosition })}
priority={priority}
sizes="(min-width: 1280px) 457px, (min-width: 768px) calc(41.67vw - 76px), calc(100vw - 88px)"
sizes={sizes}
{...(responsiveCover === undefined
? {}
: { responsiveCover })}
/>
</div>
</div>
<div className="md:w-7/12 p-6">
<div className="p-6 md:w-7/12 lg:flex lg:h-full lg:flex-col">
{status && (
<p className="mb-2 inline-flex rounded-full bg-blue-50 px-3 py-1 text-xs font-semibold text-blue-800">
<p className="mb-2 inline-flex self-start rounded-full bg-blue-50 px-3 py-1 text-xs font-semibold text-blue-800">
{status}
</p>
)}
Expand All @@ -140,7 +158,7 @@ export default function PortfolioCard({
</p>
)}
<p className="mt-3 text-sm text-gray-600">• {tags}</p>
<div className="mt-4 flex items-center gap-4 flex-wrap">
<div className="mt-4 flex flex-wrap items-center gap-4 lg:mt-auto lg:pt-4">
{actions}
</div>
{details}
Expand Down
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions src/data/portfolio/cases/lemBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,19 @@ import lemBox768Avif from "../../../assets/lem-box/lem-box-768.avif";
import lemBox768Webp from "../../../assets/lem-box/lem-box-768.webp";
import lemBox1200Avif from "../../../assets/lem-box/lem-box-1200.avif";
import lemBox1200Webp from "../../../assets/lem-box/lem-box-1200.webp";
import lemBoxPortfolioCover from "../../../assets/portfolio/lem-box/lem-box-portfolio-cover.jpg";
import lemBoxPortfolioCover480Avif from "../../../assets/portfolio/lem-box/lem-box-portfolio-cover-480.avif";
import lemBoxPortfolioCover480Webp from "../../../assets/portfolio/lem-box/lem-box-portfolio-cover-480.webp";
import lemBoxPortfolioCover768Avif from "../../../assets/portfolio/lem-box/lem-box-portfolio-cover-768.avif";
import lemBoxPortfolioCover768Webp from "../../../assets/portfolio/lem-box/lem-box-portfolio-cover-768.webp";
import lemBoxPortfolioCover1200Avif from "../../../assets/portfolio/lem-box/lem-box-portfolio-cover-1200.avif";
import lemBoxPortfolioCover1200Webp from "../../../assets/portfolio/lem-box/lem-box-portfolio-cover-1200.webp";
import lemBoxPortfolioCover1600Avif from "../../../assets/portfolio/lem-box/lem-box-portfolio-cover-1600.avif";
import lemBoxPortfolioCover1600Webp from "../../../assets/portfolio/lem-box/lem-box-portfolio-cover-1600.webp";
import {
definePortfolioCase,
type Localized,
type PortfolioCardCover,
type PortfolioAction,
type ResponsivePortfolioCover,
} from "../types";
Expand All @@ -29,6 +39,33 @@ const lemBoxResponsiveCover = {
},
} as const satisfies ResponsivePortfolioCover;

const lemBoxPortfolioCardCover = {
cover: lemBoxPortfolioCover,
fullBleed: true,
objectPosition: "center 55%",
sizes:
"(min-width: 1280px) 513px, (min-width: 768px) calc(41.67vw - 21px), calc(100vw - 50px)",
responsiveCover: {
width: 1920,
height: 1440,
fit: "cover",
sources: {
avif: [
{ src: lemBoxPortfolioCover480Avif, width: 480 },
{ src: lemBoxPortfolioCover768Avif, width: 768 },
{ src: lemBoxPortfolioCover1200Avif, width: 1200 },
{ src: lemBoxPortfolioCover1600Avif, width: 1600 },
],
webp: [
{ src: lemBoxPortfolioCover480Webp, width: 480 },
{ src: lemBoxPortfolioCover768Webp, width: 768 },
{ src: lemBoxPortfolioCover1200Webp, width: 1200 },
{ src: lemBoxPortfolioCover1600Webp, width: 1600 },
],
},
},
} as const satisfies PortfolioCardCover;

const stack = [
"Next.js",
"React",
Expand Down Expand Up @@ -156,6 +193,7 @@ export const lemBoxCase = definePortfolioCase({
category: "systems",
cover: "/img/lem-box-cover.png",
responsiveCover: lemBoxResponsiveCover,
portfolioCardCover: lemBoxPortfolioCardCover,
actions: lemBoxPublicLinks,
content: {
es: {
Expand Down
9 changes: 9 additions & 0 deletions src/data/portfolio/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ export type ResponsivePortfolioCover = {
};
};

export type PortfolioCardCover = {
cover: string;
fullBleed: boolean;
objectPosition?: string;
responsiveCover: ResponsivePortfolioCover;
sizes: string;
};

export function getPortfolioCoverFit(
responsiveCover: ResponsivePortfolioCover | undefined,
): PortfolioCoverFit {
Expand All @@ -143,6 +151,7 @@ type PortfolioCaseDefinitionBase<
category: ProjectCategory;
cover: string;
responsiveCover?: ResponsivePortfolioCover;
portfolioCardCover?: PortfolioCardCover;
actions: readonly PortfolioAction[];
content: Localized<Content>;
home?: {
Expand Down
22 changes: 19 additions & 3 deletions src/pages/PortfolioPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ export default function PortfolioPage() {
const content = portfolioCase.content[language];
const detailsId = `portfolio-details-${portfolioCase.key}`;
const caseStudy = portfolioCase.caseStudy;
const portfolioCardCover = portfolioCase.portfolioCardCover;
const cardCover = portfolioCardCover?.cover ?? portfolioCase.cover;
const cardResponsiveCover =
portfolioCardCover?.responsiveCover ?? portfolioCase.responsiveCover;
const detailsExpanded =
caseStudy === undefined &&
content.details !== undefined &&
Expand Down Expand Up @@ -171,7 +175,7 @@ export default function PortfolioPage() {
</>
)
}
cover={portfolioCase.cover}
cover={cardCover}
desc={content.description}
details={
detailsExpanded && content.details !== undefined ? (
Expand All @@ -186,13 +190,25 @@ export default function PortfolioPage() {
) : null
}
expanded={detailsExpanded}
{...(portfolioCardCover === undefined
? {}
: {
fullBleed: portfolioCardCover.fullBleed,
sizes: portfolioCardCover.sizes,
...(portfolioCardCover.objectPosition === undefined
? {}
: {
objectPosition:
portfolioCardCover.objectPosition,
}),
})}
headingLevel="h2"
priority={portfolioIndex === 0}
tags={content.tags.join(" · ")}
title={content.title}
{...(portfolioCase.responsiveCover === undefined
{...(cardResponsiveCover === undefined
? {}
: { responsiveCover: portfolioCase.responsiveCover })}
: { responsiveCover: cardResponsiveCover })}
{...(content.status === undefined
? {}
: { status: content.status })}
Expand Down
2 changes: 1 addition & 1 deletion src/test/NoJsVisibility.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const approvedFiles = {
},
"src/Components/portfolio/PortfolioCard.tsx": {
baselineHash:
"82db7710efc1da9799d2b53bc96eb15009f3f5da39aee86f84e3bec56983ecf8",
"c74bed74086dabd4988f143a677732349715168e106af4f6bcddc9d3bf615369",
markers: 1,
},
} as const;
Expand Down
Loading
Loading