diff --git a/components/common/Card.js b/components/common/Card.tsx
similarity index 51%
rename from components/common/Card.js
rename to components/common/Card.tsx
index 924e7764..044bec57 100644
--- a/components/common/Card.js
+++ b/components/common/Card.tsx
@@ -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';
@@ -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;
@@ -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 (
+
+ {imageUrl && }
+
+ );
+ }
+ if (imageType === 'bitmapIcon') {
+ return (
+
+ {imageUrl && }
+
+ );
+ }
+ if (imageType === 'image' && imageUrl) {
+ return (
+
+
+
+ );
+ }
+ return null;
+ };
+
return (
- {/* TODO: maybe animate transition */}
- {imageUrl && (
-
-
-
- )}
+
{children}
);
};
-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;
diff --git a/components/contentblocks/CategoryListBlock.tsx b/components/contentblocks/CategoryListBlock.tsx
index e63fa813..45a5c0f0 100644
--- a/components/contentblocks/CategoryListBlock.tsx
+++ b/components/contentblocks/CategoryListBlock.tsx
@@ -27,6 +27,12 @@ const CATEGORY_FRAGMENT = gql`
...MultiUseImageFragment
}
color
+ iconSvgUrl
+ iconImage {
+ rendition(size: "400x400", crop: false) {
+ src
+ }
+ }
categoryPage {
title
urlPath
@@ -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;
@@ -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 (
@@ -175,13 +223,10 @@ const CategoryListBlock = (props: CategoryListBlockProps) => {