Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Commit

Permalink
Feature/cor 959/dynamic icons (#4361)
Browse files Browse the repository at this point in the history
* Get an icon dynamically

* feat: make dynamic icon work including typings

* fix: code cleanup

* feat: extend type info in icon build

* feat: add eye icon

Co-authored-by: VWSCoronaDashboard18 <[email protected]>
Co-authored-by: VWSCoronaDashboard24 <[email protected]>
  • Loading branch information
3 people committed Aug 18, 2022
1 parent 0b05b3a commit a5c39fd
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 7 deletions.
38 changes: 38 additions & 0 deletions packages/app/src/components/get-icon-by-name.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as allIcons from '@corona-dashboard/icons';
import { iconName2filename, IconProps } from '@corona-dashboard/icons';
import React from 'react';
import { isDefined } from 'ts-is-present';
import { assert } from '~/utils/assert';

type IconName = keyof typeof iconName2filename;
type IconCollection = Record<IconName, React.ComponentType>;

interface DynamicIconProps extends IconProps {
name: IconName;
}

/**
* Returns an icon component by the name of the icon
* Throws when requested component was not found
*/
function getIconByName(name: IconName) {
const icons: IconCollection = allIcons;
const DynamicIcon = icons[name];

assert(
isDefined(DynamicIcon),
`[${getIconByName.name}] Icon with name "${name}" does not exist`
);

return DynamicIcon;
}

/**
* Renders an icon component by the name of the icon
*/
function DynamicIcon({ name, ...otherProps }: DynamicIconProps) {
const Icon = getIconByName(name);
return <Icon {...otherProps} />;
}

export default DynamicIcon;
4 changes: 4 additions & 0 deletions packages/app/src/pages/nieuw-actueel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ArticleList, TopicalSectionHeader } from '~/domain/topical';
import { isPresent } from 'ts-is-present';
import { Search } from '~/domain/topical/components/search';
import { Languages, SiteText } from '~/locale';
import DynamicIcon from '~/components/get-icon-by-name';
import {
createGetStaticProps,
StaticProps,
Expand Down Expand Up @@ -62,6 +63,9 @@ const Home = (props: StaticProps<typeof getStaticProps>) => {
pt={{ _: 3, md: 5 }}
px={{ _: 3, sm: 4 }}
>
<Box py={4}>
<DynamicIcon name={selectedTopicalData.themes[0].icon} />
</Box>
<Box py={4}>
<Search title={textShared.secties.search.title.nl} />
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@ import { PatchEvent, set, unset } from 'part:@sanity/form-builder/patch-event';
import React, { forwardRef, useCallback, useState } from 'react';
import { isDefined } from 'ts-is-present';

const filename2IconName = Object.keys(iconName2filename).reduce((aggr, key) => {
aggr[iconName2filename[key]] = key;
return aggr;
}, {} as Record<string, string>);
const allIconsToFilename: Record<string, string> = iconName2filename;

const filename2IconName = Object.keys(allIconsToFilename).reduce(
(aggr, key) => {
aggr[allIconsToFilename[key]] = key;
return aggr;
},
{} as Record<string, string>
);

export type KpiIconKey = keyof typeof allIcons;

Expand Down Expand Up @@ -83,11 +88,14 @@ export const KpiIconInput = forwardRef((props: any, ref: any) => {
key={id}
direction="column"
align="center"
onClick={() => onChangeIcon(iconName2filename[id])}
onClick={() => onChangeIcon(allIconsToFilename[id])}
title={id}
>
<GridIcon width="35" height="35" color="black" />
<Radio checked={value === iconName2filename[id]} readOnly />
<Radio
checked={value === allIconsToFilename[id]}
readOnly
/>
</Flex>
))}

Expand Down
5 changes: 4 additions & 1 deletion packages/icons/bin/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,12 @@ const attrsToString = (attrs) => {
};

const lookup = icons.sort().map((x) => `${pascalcase(x)}: '${x}.svg'`);
const iconNames = icons.sort().map((x) => `'${pascalcase(x)}'`);

const iconName2filename = [
'export const iconName2filename: Record<string, string> = {',
`export type IconName = ${iconNames.join(' | ')};`,
'',
'export const iconName2filename: Record<IconName, string> = {',
]
.concat(lookup.join(','))
.concat(['}', '']);
Expand Down
1 change: 1 addition & 0 deletions packages/icons/src/svg/eye.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a5c39fd

Please sign in to comment.