Skip to content

Commit

Permalink
feat: APP-322 terassos project filters UI (#2487)
Browse files Browse the repository at this point in the history
  • Loading branch information
wgardiner authored Oct 15, 2024
1 parent 9a5fb65 commit b883f3e
Show file tree
Hide file tree
Showing 19 changed files with 648 additions and 5 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ module.exports = {
'borderRight',
'borderBottom',
'borderRadius',
'boxShadow',
'flexFlow',
'transition',
'transform',
Expand Down
2 changes: 1 addition & 1 deletion web-components/src/components/icons/icons.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default {
component: ArrowDownIcon,
};

function LabeledIcon(props: {
export function LabeledIcon(props: {
icon: React.ReactElement;
label: string;
}): JSX.Element {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { inactiveFill, inactiveStroke } from './ColombiaRegionIcon.constants';

export default function RegionPath({
pathData,
fill,
stroke,
}: {
pathData: string;
fill?: string;
stroke?: string;
}) {
fill = fill ?? inactiveFill;
stroke = stroke ?? inactiveStroke;

return (
<path
d={pathData}
fill={fill}
stroke={stroke}
strokeWidth="0.2"
strokeLinejoin="round"
/>
);
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import SvgIcon from '@mui/material/SvgIcon';
import classNames from 'classnames';

import { sxToArray } from '../../../../utils/mui/sxToArray';
import {
activeFill,
activeStroke,
regionPaths,
selectedFill,
selectedStroke,
} from './ColombiaRegionIcon.constants';
import RegionPath from './ColombiaRegionIcon.RegionPath';
import { RegionIndicatorIconProps } from './ColombiaRegionIcon.types';

export default function RegionIndicatorIcon({
region,
sx,
isSelected = false,
className,
...props
}: RegionIndicatorIconProps): JSX.Element {
const activeRegionPath = Object.entries(regionPaths).filter(
([key, _]) => key === region,
)[0][1];
const otherRegionPaths = Object.entries(regionPaths)
.filter(([key, _]) => key !== region)
.map(([_, value]) => value);
return (
<SvgIcon
sx={sx}
className={classNames('mr-1 w-[30px] h-[30px]', className)}
width="30"
height="30"
viewBox="0 0 30 30"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g clipPath="url(#clip0_1479_22775)">
{otherRegionPaths.map((path: string, index: number) => (
<RegionPath key={index} pathData={path} />
))}
<RegionPath
pathData={activeRegionPath}
fill={isSelected ? selectedFill : activeFill}
stroke={isSelected ? selectedStroke : activeStroke}
/>
</g>
<defs>
<clipPath id="clip0_1479_22775">
<rect width="30" height="30" fill="white" />
</clipPath>
</defs>
</SvgIcon>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { SvgIconProps } from '@mui/material/SvgIcon';

export interface RegionPaths {
PACIFIC: string;
ORINOCO: string;
CARIBBEAN: string;
AMAZON: string;
ANDEAN: string;
}

export type Region = 'PACIFIC' | 'ORINOCO' | 'CARIBBEAN' | 'AMAZON' | 'ANDEAN';

export interface RegionIndicatorIconProps extends SvgIconProps {
region: Region;
isSelected?: boolean;
className?: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './ColombiaRegionIcon';
21 changes: 21 additions & 0 deletions web-components/src/components/icons/terassos/ComplianceBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Box } from '@mui/material';

export default function ComplianceBadge() {
return (
<Box
display="flex"
alignItems="center"
justifyContent="center"
width="24px"
height="24px"
padding="3px"
borderRadius="50%"
fontSize="12px"
className="rounded-full ml-2 border border-dashed border-sc-surface-stroke bg-sc-icon-standard-background"
fontWeight={700}
// eslint-disable-next-line lingui/no-unlocalized-strings
>
ha.
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import { Grid } from '@mui/material';
import { Meta } from '@storybook/react';

import { LabeledIcon } from '../icons.stories';
import RegionIndicatorIcon from './ColombiaRegionIcon/ColombiaRegionIcon';

export default {
title: 'Terassos/Icons',
component: RegionIndicatorIcon,
} as Meta;

export const allIcons = (): JSX.Element => (
<Grid container gap={4}>
<LabeledIcon
label="Pacific"
icon={
<RegionIndicatorIcon region="PACIFIC" className="w-[60px] h-[60px]" />
}
/>
<LabeledIcon
label="Orinoco"
icon={
<RegionIndicatorIcon region="ORINOCO" className="w-[60px] h-[60px]" />
}
/>
<LabeledIcon
label="Caribbean"
icon={
<RegionIndicatorIcon region="CARIBBEAN" className="w-[60px] h-[60px]" />
}
/>
<LabeledIcon
label="Amazon"
icon={
<RegionIndicatorIcon region="AMAZON" className="w-[60px] h-[60px]" />
}
/>
<LabeledIcon
label="Andean"
icon={
<RegionIndicatorIcon region="ANDEAN" className="w-[60px] h-[60px]" />
}
/>
<LabeledIcon
label="Andean (selected)"
icon={
<RegionIndicatorIcon
region="ANDEAN"
className="w-[60px] h-[60px]"
isSelected={true}
/>
}
/>
</Grid>
);
28 changes: 28 additions & 0 deletions web-components/src/components/icons/utils/SvgColorOverride.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useMemo } from 'react';
import { SvgIcon, SxProps } from '@mui/material';

export default function SvgThemeWrapper({
src,
sx,
color,
}: {
src: string;
sx?: SxProps;
color: string;
}) {
const maskId = useMemo(() => `mask_${Math.random()}`, []);
return (
<SvgIcon sx={sx}>
<mask id={maskId}>
<image
href={src}
// filter: 'brightness(10)' is used to make the image full intensity for the mask
style={{ filter: 'brightness(10)' }}
height="100%"
width="100%"
/>
</mask>
<rect mask={`url(#${maskId})`} width="100%" height="100%" fill={color} />
</SvgIcon>
);
}
25 changes: 25 additions & 0 deletions web-components/src/components/icons/utils/SvgWithSelectedColor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { SxProps } from '@mui/system';

import SvgColorOverride from './SvgColorOverride';

export default function SvgWithIsSelectedColor({
src,
sx,
isSelected = false,
unselectedColor,
selectedColor,
}: {
src: string;
sx?: SxProps;
isSelected?: boolean;
unselectedColor: string;
selectedColor: string;
}) {
return (
<SvgColorOverride
src={src}
sx={sx}
color={isSelected ? selectedColor : unselectedColor}
/>
);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { isValidElement } from 'react';
import { Box, SxProps } from '@mui/material';

import { Theme } from '../../../theme/muiTheme';
import { sxToArray } from '../../../utils/mui/sxToArray';
import { ProjectTagType } from './ProjectTag.types';
import { isImageType, ProjectTagType } from './ProjectTag.types';

export interface Props {
tag: ProjectTagType;
sx?: SxProps<Theme>;
onClick?: () => void;
}

const ProjectTag = ({ tag, sx = [] }: Props): JSX.Element => {
const ProjectTag = ({ tag, sx = [], onClick }: Props): JSX.Element => {
const { icon, name } = tag;

return (
Expand All @@ -27,8 +29,9 @@ const ProjectTag = ({ tag, sx = [] }: Props): JSX.Element => {
},
...sxToArray(sx),
]}
onClick={onClick}
>
{icon.src && (
{isImageType(icon) && (
<Box
component="img"
src={icon.src}
Expand All @@ -40,6 +43,7 @@ const ProjectTag = ({ tag, sx = [] }: Props): JSX.Element => {
}}
/>
)}
{isValidElement(icon) && icon}
<Box sx={{ fontWeight: 700, fontSize: { xs: 12, sm: 14 } }}>{name}</Box>
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { ImageType } from '../../../types/shared/imageType';

export type ProjectTagType = {
icon: ImageType;
icon: ImageType | JSX.Element;
name: string;
};

export function isImageType(icon: ImageType | JSX.Element): icon is ImageType {
return (icon as ImageType).src !== undefined;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { cloneElement } from 'react';

import { ProjectTag } from '../../molecules/ProjectTag/ProjectTag';

interface TagFilterProps {
icon: JSX.Element;
name: string;
isSelected: boolean;
onClick?: () => void;
}

const tagSx = {
cursor: 'pointer',
boxShadow:
'0px 2px 2px 0px var(--tag-filter-outer-shadow, rgba(0, 0, 0, 0.20))',
'&:hover': {
filter: 'brightness(0.9)',
},
};

export default function TagFilter({
icon,
name,
isSelected,
onClick,
}: TagFilterProps) {
// add isSelected prop to icon
const iconWithProps = cloneElement(icon, { isSelected });
return (
<ProjectTag
sx={tagSx}
tag={{
name,
icon: iconWithProps,
}}
onClick={onClick}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Box, FormControlLabel } from '@mui/material';
import Checkbox from 'web-components/src/components/inputs/new/CheckBox/Checkbox';

export default function CheckboxFilter({
icon,
name,
isSelected,
onChange,
}: {
icon: JSX.Element;
name: string;
isSelected: boolean;
onChange?: () => void;
}) {
return (
<FormControlLabel
control={<Checkbox checked={isSelected} onChange={onChange} />}
label={
<Box display="flex" flexWrap="nowrap" alignItems="center">
{name}
{icon}
</Box>
}
sx={{ mb: 2 }}
/>
);
}
Loading

0 comments on commit b883f3e

Please sign in to comment.