Skip to content

Commit

Permalink
fix: resolved layout issues with the HeroArticle component
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-crowell committed Jun 20, 2024
1 parent 8cb3672 commit 6eed823
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 17 deletions.
83 changes: 66 additions & 17 deletions packages/ui/src/components/HeroArticles/HeroArticles.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
import { clsx } from '@do-ob/core';
import { HeroArticlesProps } from './data/HeroArticlesProps';
import { Button, Card, CardFooter, Image } from '@nextui-org/react';
import { Button, Image, Link } from '@nextui-org/react';
// import { configUI } from '@do-ob/ui/config';

function truncateToWordBoundary(text: string, maxLength = 120): string {

// If the text is already within the limit, return it as is
if (text.length <= maxLength) {
return text;
}

// Find the last space within the allowed range
const trimmedText = text.slice(0, maxLength);
const lastSpaceIndex = trimmedText.lastIndexOf(' ');

// If no space is found, we should still cut off the string at maxLength
if (lastSpaceIndex === -1) {
return trimmedText;
}

// Otherwise, return the string truncated at the last space
return trimmedText.slice(0, lastSpaceIndex);
}

export type HeroVariant = 'standard' | 'prompt';

export function HeroArticles({
Expand All @@ -14,42 +34,71 @@ export function HeroArticles({
const {
className,
articles,
radius,
imageNode,
} = props;

let roundedClass = '';
switch (radius) {
case 'sm':
roundedClass = 'rounded-small';
break;
case 'md':
roundedClass = 'rounded-medium';
break;
case 'lg':
roundedClass = 'rounded-large';
break;
case 'none':
roundedClass = 'rounded-none';
break;
default:
roundedClass = 'rounded-medium';
break;
}

return (
<section
aria-label="Introduction"
className={clsx('grid grid-cols-1 items-center gap-8 md:grid-cols-2', className)}
aria-label="Latest Articles"
className={clsx('grid grid-cols-1 items-center gap-8 lg:grid-cols-2', className)}
>
{articles.slice(0, 3).map((article, index) => (
<Card
{articles.map((article, index) => (
<Link
key={article.title}
className={clsx('group relative w-full cursor-pointer border-none', index === 0 && 'md:col-span-2')}
radius="lg"
href={article.url}
aria-label="Read More"
className={clsx('group relative block w-full cursor-pointer overflow-hidden border-none hover:opacity-100', index === 0 && 'lg:col-span-2', roundedClass)}
>
<Image
as={imageNode}
width={2048}
height={1365}
className="aspect-video h-auto w-full object-cover transition-transform duration-1000 ease-in-out group-hover:scale-105"
className="aspect-[3/2] h-auto w-full object-cover"
radius={radius}
src={article.image}
/>
<CardFooter className="absolute top-2 z-20 ml-2 flex w-3/5 flex-col items-start gap-8 overflow-hidden px-8 py-4">
<article className="float-left flex flex-col items-center justify-center gap-8">
<h1 className={clsx(index === 0 ? 'text-5xl' : 'text-2xl', 'font-bold tracking-tight text-white')}>{article.title}</h1>
<div className={clsx(index === 0 ? 'w-11/12 lg:w-4/5' : 'w-11/12','absolute top-2 z-20 ml-2 flex flex-col items-start gap-4 overflow-hidden px-8 py-4 lg:gap-6')}>
<article className="float-left flex flex-col items-start justify-center gap-4 lg:gap-6">
<h1 className={clsx(index === 0 ? 'text-3xl lg:text-5xl' : 'text-3xl lg:text-3xl', 'font-bold tracking-tight text-white drop-shadow-[0_0_2px_rgba(0,0,0,1)]')}>{article.title}</h1>
{index === 0 ? (
<h2 className={clsx(index === 0 ? 'text-base lg:text-2xl' : 'text-base lg:text-lg', 'hidden text-white/60 drop-shadow-[0_0_2px_rgba(0,0,0,1)] lg:inline')}>{truncateToWordBoundary(article.subtitle) + ' ...'}</h2>
) : null}
</article>
<Button
size={index === 0 ? 'lg' : 'md'}
size="lg"
color="primary"
variant="solid"
className={clsx(index === 0 && 'text-lg', 'font-bold')}
variant="ghost"
radius={radius}
tabIndex={-1}
className={clsx(index === 0 && 'lg:text-lg', 'bg-black/30 font-bold group-hover:bg-primary group-hover:text-primary-foreground group-focus:bg-primary group-focus:text-primary-foreground')}
>
Read More
</Button>
</CardFooter>
</div>

<div className="absolute left-0 top-0 z-10 size-full bg-gradient-to-br from-black/80 from-20% to-transparent to-60%" />
<div className="absolute left-0 top-0 z-10 size-full bg-black/40 transition-opacity group-hover:opacity-0" />
</Card>
<div className="absolute left-0 top-0 z-10 size-full bg-black/40 transition-opacity group-hover:opacity-0 group-focus:opacity-0" />
</Link>
))}

</section>
Expand Down
11 changes: 11 additions & 0 deletions packages/ui/src/components/HeroArticles/data/HeroArticlesProps.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* A hero aritcle.
*/
Expand Down Expand Up @@ -34,6 +35,16 @@ export interface HeroArticlesProps {
*/
className?: string;

/**
* The image node to use.
*/
imageNode?: React.ElementType<any>;

/**
* Radius of images
*/
radius?: 'none' | 'sm' | 'md' | 'lg';

/**
* Custom classes for slots
*/
Expand Down
7 changes: 7 additions & 0 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ const config: Config = {
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}',
'./packages/ui/src/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
aspectRatio: {
'photo': '3 / 2',
},
}
},
plugins: [
nextui(),
tailwindTypography,
Expand Down

0 comments on commit 6eed823

Please sign in to comment.