Skip to content

Commit

Permalink
Use icons in lieu category image
Browse files Browse the repository at this point in the history
  • Loading branch information
terotik committed Oct 11, 2023
1 parent 21a245f commit 624cf74
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 39 deletions.
105 changes: 73 additions & 32 deletions components/common/Card.js → components/common/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import SVG from 'react-inlinesvg';
import { Card as BSCard, CardBody } from 'reactstrap';
import styled from 'styled-components';
import { transparentize } from 'polished';
Expand Down Expand Up @@ -50,14 +49,24 @@ const StyledCard = styled(BSCard)`
}
`;

const ImgArea = styled.div`
const ImgArea = styled.div<{ colorEffect?: string }>`
height: 9rem;
position: relative;
display: flex;
align-items: center;
justify-content: center;
background-color: ${(props) => props.colorEffect};
border-bottom: ${(props) => (props.colorEffect ? '6px' : '0')} solid
${(props) => props.colorEffect};
@media (min-width: ${(props) => props.theme.breakpointMd}) {
height: 8rem;
}
`;

const ImgBg = styled.div`
const ImgBg = styled.div<{ background: string; imageAlign: string }>`
height: 9rem;
flex: 1 1 100%;
background-image: url(${(props) => props.background});
background-position: ${(props) => props.imageAlign};
background-size: cover;
Expand All @@ -67,51 +76,83 @@ const ImgBg = styled.div`
}
`;

const Card = (props) => {
const SvgIcon = styled(SVG)`
position: absolute;
right: ${(props) => props.theme.spaces.s050};
top: ${(props) => props.theme.spaces.s050};
width: ${(props) => props.theme.spaces.s300};
fill: white;
`;

const BitmapIcon = styled.div<{ imageSrc: string }>`
width: ${(props) => props.theme.spaces.s800};
height: ${(props) => props.theme.spaces.s800};
background-image: url(${(props) => props.imageSrc || 'none'});
background-size: cover;
background-position: center center;
`;

interface CardProps {
imageUrl?: string;
imageAlign?: string;
imageType?: 'svgIcon' | 'bitmapIcon' | 'image';
colorEffect?: string;
negative?: boolean;
customColor?: string;
children: React.ReactNode;
outline?: boolean;
}

const Card = (props: CardProps) => {
const {
imageUrl,
colorEffect,
imageAlign,
imageAlign = 'center center',
imageType = 'image',
negative,
customColor,
children,
outline,
} = props;

/*
Support svgIcon, bitmapIcon, image as cards main image
*/
const ImageComponent = () => {
if (imageType === 'svgIcon') {
return (
<ImgArea colorEffect={colorEffect}>
{imageUrl && <SvgIcon src={imageUrl} />}
</ImgArea>
);
}
if (imageType === 'bitmapIcon') {
return (
<ImgArea colorEffect={colorEffect}>
{imageUrl && <BitmapIcon imageSrc={imageUrl} />}
</ImgArea>
);
}
if (imageType === 'image' && imageUrl) {
return (
<ImgArea colorEffect={colorEffect}>
<ImgBg background={imageUrl} imageAlign={imageAlign} />
</ImgArea>
);
}
return null;
};

return (
<StyledCard
className={`${negative && 'negative'} ${outline && 'outline'}`}
customcolor={customColor}
data-testid='card'
data-testid="card"
>
{/* TODO: maybe animate transition */}
{imageUrl && (
<ImgArea colorEffect={colorEffect}>
<ImgBg data-testid='image-bg' background={imageUrl} imageAlign={imageAlign} />
</ImgArea>
)}
<ImageComponent />
<CardBody>{children}</CardBody>
</StyledCard>
);
};

Card.defaultProps = {
imageUrl: '',
imageAlign: 'center',
colorEffect: undefined,
negative: false,
customColor: '',
outline: false,
};

Card.propTypes = {
imageUrl: PropTypes.string,
imageAlign: PropTypes.string,
colorEffect: PropTypes.string,
negative: PropTypes.bool,
customColor: PropTypes.string,
children: PropTypes.element.isRequired,
outline: PropTypes.bool,
};

export default Card;
59 changes: 52 additions & 7 deletions components/contentblocks/CategoryListBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ const CATEGORY_FRAGMENT = gql`
...MultiUseImageFragment
}
color
iconSvgUrl
iconImage {
rendition(size: "400x400", crop: false) {
src
}
}
categoryPage {
title
urlPath
Expand Down Expand Up @@ -122,6 +128,12 @@ export type CategoryListBlockCategory = {
id: string;
image?: MultiUseImageFragmentFragment | null;
color?: string | null;
iconSvgUrl?: string | null;
iconImage?: {
rendition: {
src: string;
};
};
identifier: string;
name: string;
shortDescription?: string;
Expand Down Expand Up @@ -153,6 +165,42 @@ const CategoryListBlock = (props: CategoryListBlockProps) => {
categories = fallbackCategories,
} = props;

/*
Determine what image to use on category card
If category has no own image but has icon use icon on colored bg
If category has no own image and no icon use fallback image
If category has own image use that
*/
type CardImageType = (category: CategoryListBlockCategory) => {
type: 'image' | 'svgIcon' | 'bitmapIcon';
src: string | undefined;
alignment: string;
};

const getCardImage: CardImageType = (category) => {
const categryImageSrc = category.image?.small?.src;

if (!categryImageSrc && category.iconSvgUrl) {
return {
type: 'svgIcon',
src: category.iconSvgUrl,
alignment: 'center',
};
}
if (!categryImageSrc && category.iconImage) {
return {
type: 'bitmapIcon',
src: category.iconImage?.rendition?.src,
alignment: 'center',
};
} else
return {
type: 'image',
src: categryImageSrc || fallbackImage?.small?.src,
alignment: getBgImageAlignment(category.image || fallbackImage),
};
};

return (
<CategoryListSection id={id}>
<Container>
Expand All @@ -175,13 +223,10 @@ const CategoryListBlock = (props: CategoryListBlockProps) => {
<Link href={cat.categoryPage.urlPath}>
<a className="card-wrapper">
<Card
imageUrl={
cat.image?.small?.src || fallbackImage?.small?.src
}
imageAlign={getBgImageAlignment(
cat.image || fallbackImage
)}
colorEffect={cat.color}
imageUrl={getCardImage(cat).src}
imageAlign={getCardImage(cat).alignment}
imageType={getCardImage(cat).type}
colorEffect={cat.color ?? undefined}
>
<div>
<CardHeader className="card-title">
Expand Down

0 comments on commit 624cf74

Please sign in to comment.