Skip to content

Commit

Permalink
refactor svg icons
Browse files Browse the repository at this point in the history
  • Loading branch information
jabranr committed May 9, 2020
1 parent d5e4960 commit 72d4df1
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 93 deletions.
10 changes: 3 additions & 7 deletions src/components/layout.js
Expand Up @@ -3,13 +3,9 @@ import { useLocation, Link } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import cookie from 'js-cookie';

import style from './style.module.scss';
import SvgIcons from './svg-icons';

const PlusIcon = ({ width = 16, height = 16, ...attrs }) => (
<svg width={width} height={height} viewBox={`0 0 ${width * 2} ${height * 2}`} fill="currentColor" {...attrs}>
<path d="M21 8l-5 5-5-5-3 3 5 5-5 5 3 3 5-5 5 5 3-3-5-5 5-5z" />
</svg>
);
import style from './style.module.scss';

const Layout = ({ title, description, canonical, children }) => {
const location = useLocation();
Expand Down Expand Up @@ -63,7 +59,7 @@ const Layout = ({ title, description, canonical, children }) => {
{location.pathname !== '/add-data' && (
<nav className={style.nav}>
<Link to="/add-data" className={style['nav-item']}>
<PlusIcon className={style['plus-icon']} />
<SvgIcons name="plus" width={16} height={16} viewBox="0 0 32 32" className={style['plus-icon']} />
Add
</Link>
</nav>
Expand Down
91 changes: 21 additions & 70 deletions src/components/organisation/index.js
@@ -1,71 +1,10 @@
import React, { memo, useState, useRef } from 'react';

import FormattedString from '../formatted-string';

import style from './style.module.scss';
import { pushDataLayer } from '../../util';
import SvgIcons from '../svg-icons';

const PhoneIcon = ({ width = 16, height = 16, ...attrs }) => (
<svg width={width} height={height} viewBox={`0 0 ${width * 2} ${height * 2}`} fill="currentColor" {...attrs}>
<path d="M22 20c-2 2-2 4-4 4s-4-2-6-4-4-4-4-6 2-2 4-4-4-8-6-8-6 6-6 6c0 4 4.11 12.11 8 16s12 8 16 8c0 0 6-4 6-6s-6-8-8-6z" />
</svg>
);

const WebIcon = ({ width = 16, height = 18, ...attrs }) => {
if (width !== height) {
attrs.viewBox = `0 0 ${width * 2} ${height * 2}`;
}

return (
<svg width={width} height={height} fill="currentColor" {...attrs}>
<path d="M15 2C6.716 2 0 8.716 0 17c0 8.284 6.716 15 15 15 8.284 0 15-6.716 15-15 0-8.284-6.716-15-15-15zm8.487 20a23.85 23.85 0 00.493-4h3.982a12.87 12.87 0 01-.958 4h-3.517zM6.513 12a23.85 23.85 0 00-.493 4H2.038a12.87 12.87 0 01.958-4h3.517zm14.926 0c.3 1.28.48 2.62.54 4H16v-4h5.439zM16 10V4.146c.456.132.908.355 1.35.668.832.585 1.626 1.487 2.299 2.608.465.776.867 1.638 1.203 2.578H16zm-5.649-2.578c.673-1.12 1.467-2.023 2.298-2.609A4.563 4.563 0 0114 4.146V10H9.148a14.48 14.48 0 011.203-2.578zM14 12v4H8.021c.06-1.38.24-2.72.54-4H14zM2.997 22a12.87 12.87 0 01-.96-4H6.02a23.85 23.85 0 00.493 4H2.997zm5.024-4H14v4H8.561c-.3-1.28-.48-2.62-.54-4zM14 24v5.854a4.566 4.566 0 01-1.35-.667c-.832-.586-1.626-1.488-2.299-2.61A14.48 14.48 0 019.148 24H14zm5.649 2.578c-.673 1.12-1.467 2.023-2.298 2.609a4.565 4.565 0 01-1.351.667V24h4.852c-.336.94-.738 1.802-1.203 2.578zM16 22v-4h5.979c-.06 1.38-.24 2.72-.54 4H16zm7.98-6a23.85 23.85 0 00-.493-4h3.517a12.87 12.87 0 01.958 4H23.98zm1.978-6h-2.997c-.582-1.836-1.387-3.447-2.353-4.732a12.962 12.962 0 013.584 2.54A13.032 13.032 0 0125.958 10zM5.808 7.808a12.963 12.963 0 013.584-2.54C8.425 6.553 7.622 8.164 7.04 10H4.042a13.032 13.032 0 011.766-2.192zM4.042 24h2.997c.582 1.836 1.387 3.447 2.353 4.732a12.96 12.96 0 01-3.584-2.54A13.029 13.029 0 014.042 24zm20.15 2.192a12.962 12.962 0 01-3.584 2.54c.966-1.285 1.77-2.896 2.353-4.732h2.997a13.032 13.032 0 01-1.766 2.192z" />
</svg>
);
};

const LocationIcon = ({ size = 14, ...attrs }) => (
<svg width={size} height={size} viewBox="0 0 1024 1024" fill="currentColor" {...attrs}>
<path d="M512 0C335.268 0 192 143.268 192 320c0 320 320 704 320 704s320-384 320-704C832 143.268 688.73 0 512 0zm0 512c-106.04 0-192-85.96-192-192s85.96-192 192-192 192 85.96 192 192-85.96 192-192 192z" />
</svg>
);

const FacebookIcon = ({ size = 16, ...attrs }) => (
<svg width={size} height={size} fill="currentColor" {...attrs}>
<path d="M29 0H3C1.35 0 0 1.35 0 3v26c0 1.65 1.35 3 3 3h13V18h-4v-4h4v-2c0-3.306 2.694-6 6-6h4v4h-4c-1.1 0-2 .9-2 2v2h6l-1 4h-5v14h9c1.65 0 3-1.35 3-3V3c0-1.65-1.35-3-3-3z" />
</svg>
);

const TwitterIcon = ({ size = 16, ...attrs }) => (
<svg width={size} height={size} fill="currentColor" {...attrs}>
<path d="M32 7.075a12.948 12.948 0 01-3.769 1.031 6.602 6.602 0 002.888-3.631c-1.269.75-2.675 1.3-4.169 1.594A6.565 6.565 0 0022.156 4a6.562 6.562 0 00-6.562 6.563c0 .512.056 1.012.169 1.493A18.633 18.633 0 012.23 5.194a6.564 6.564 0 00-.887 3.3 6.555 6.555 0 002.918 5.462 6.572 6.572 0 01-2.975-.818v.08a6.566 6.566 0 005.27 6.438 6.576 6.576 0 01-2.97.113A6.586 6.586 0 009.72 24.33a13.167 13.167 0 01-8.157 2.813c-.53 0-1.05-.031-1.568-.094A18.57 18.57 0 0010.062 30c12.075 0 18.682-10.006 18.682-18.681 0-.288-.007-.569-.019-.85A13.215 13.215 0 0032 7.075z" />
</svg>
);

const ChevronDownIcon = ({ width = 18, height = 16, ...attrs }) => {
if (width !== height) {
attrs.viewBox = `0 0 ${width * 2} ${height * 2}`;
}

return (
<svg width={width} height={height} fill="currentColor" {...attrs}>
<path d="M32 16c0-8.837-7.163-16-16-16S0 7.163 0 16s7.163 16 16 16 16-7.163 16-16zM3 16C3 8.82 8.82 3 16 3s13 5.82 13 13-5.82 13-13 13S3 23.18 3 16z" />
<path d="M9.914 11.086l-2.828 2.828L16 22.828l8.914-8.914-2.828-2.828L16 17.172z" />
</svg>
);
};

const ChevronUpIcon = ({ width = 18, height = 16, ...attrs }) => {
if (width !== height) {
attrs.viewBox = `0 0 ${width * 2} ${height * 2}`;
}

return (
<svg width={width} height={height} fill="currentColor" {...attrs}>
<path d="M0 16c0 8.837 7.163 16 16 16s16-7.163 16-16S24.837 0 16 0 0 7.163 0 16zm29 0c0 7.18-5.82 13-13 13S3 23.18 3 16 8.82 3 16 3s13 5.82 13 13z" />
<path d="M22.086 20.914l2.828-2.828L16 9.172l-8.914 8.914 2.828 2.828L16 14.828z" />
</svg>
);
};
import style from './style.module.scss';

const isInViewport = function (elem, stickyHeaderOffset = 100) {
const bounding = elem.getBoundingClientRect();
Expand Down Expand Up @@ -104,7 +43,7 @@ const Organisation = ({ org }) => {
<h3 className={style.name}>{org.name}</h3>
{Boolean(org.areasCovered.length) && (
<div className={style['areas-covered']}>
<LocationIcon />
<SvgIcons name="location" width={14} height={14} viewBox="0 0 1024 1024" />
<div>
{org.areasCovered.map((areaCovered) => (
<a
Expand Down Expand Up @@ -150,9 +89,9 @@ const Organisation = ({ org }) => {
}}
>
{/[0-9-+ ]/.test(org.donation) ? (
<PhoneIcon className={style['cta-icon']} />
<SvgIcons name="phone" width={16} height={16} viewBox="0 0 32 32" className={style['cta-icon']} />
) : (
<WebIcon className={style['cta-icon']} />
<SvgIcons name="web" width={16} height={18} viewBox="0 0 32 36" className={style['cta-icon']} />
)}{' '}
Make a donation
</FormattedString>
Expand Down Expand Up @@ -213,7 +152,7 @@ const Organisation = ({ org }) => {
});
}}
>
<FacebookIcon size={20} viewBox="0 0 32 32" className={style.facebook} />
<SvgIcons name="facebook" width={20} height={20} viewBox="0 0 32 32" className={style.facebook} />
</FormattedString>
)}
{Boolean(twitter) && (
Expand All @@ -228,7 +167,7 @@ const Organisation = ({ org }) => {
});
}}
>
<TwitterIcon size={20} viewBox="0 0 32 32" className={style.twitter} />
<SvgIcons name="twitter" width={20} height={20} viewBox="0 0 32 32" className={style.twitter} />
</FormattedString>
)}
<button
Expand Down Expand Up @@ -264,12 +203,24 @@ const Organisation = ({ org }) => {
>
{isDetailedView ? (
<>
<ChevronUpIcon className={style['more-details-icon']} />
<SvgIcons
name="chevronUp"
width={18}
height={16}
viewBox="0 0 36 32"
className={style['more-details-icon']}
/>
Less details
</>
) : (
<>
<ChevronDownIcon className={style['more-details-icon']} />
<SvgIcons
name="chevronDown"
width={18}
height={16}
viewBox="0 0 36 32"
className={style['more-details-icon']}
/>
More details
</>
)}
Expand Down
35 changes: 35 additions & 0 deletions src/components/svg-icons.js
@@ -0,0 +1,35 @@
import React, { memo } from 'react';
import { isArray } from 'lodash-es';

// prettier-ignore
const icons = {
plus: 'M21 8l-5 5-5-5-3 3 5 5-5 5 3 3 5-5 5 5 3-3-5-5 5-5z',
tick:
'M19.414 27.414l10-10a2 2 0 000-2.828l-10-10a2 2 0 00-2.828 2.828L23.172 14H4a2 2 0 000 4h19.172l-6.586 6.586c-.39.39-.586.902-.586 1.414s.195 1.024.586 1.414a2 2 0 002.828 0z',
search:
'M31.008 27.231l-7.58-6.447c-.783-.705-1.621-1.028-2.298-.997A11.952 11.952 0 0024 12c0-6.627-5.373-12-12-12S0 5.373 0 12s5.373 12 12 12c2.972 0 5.69-1.08 7.787-2.87-.032.677.292 1.515.997 2.298l6.447 7.58c1.104 1.227 2.907 1.33 4.007.23s.997-2.903-.23-4.007zM12 20a8 8 0 110-16 8 8 0 010 16z',
phone:
'M22 20c-2 2-2 4-4 4s-4-2-6-4-4-4-4-6 2-2 4-4-4-8-6-8-6 6-6 6c0 4 4.11 12.11 8 16s12 8 16 8c0 0 6-4 6-6s-6-8-8-6z',
web:
'M15 2C6.716 2 0 8.716 0 17c0 8.284 6.716 15 15 15 8.284 0 15-6.716 15-15 0-8.284-6.716-15-15-15zm8.487 20a23.85 23.85 0 00.493-4h3.982a12.87 12.87 0 01-.958 4h-3.517zM6.513 12a23.85 23.85 0 00-.493 4H2.038a12.87 12.87 0 01.958-4h3.517zm14.926 0c.3 1.28.48 2.62.54 4H16v-4h5.439zM16 10V4.146c.456.132.908.355 1.35.668.832.585 1.626 1.487 2.299 2.608.465.776.867 1.638 1.203 2.578H16zm-5.649-2.578c.673-1.12 1.467-2.023 2.298-2.609A4.563 4.563 0 0114 4.146V10H9.148a14.48 14.48 0 011.203-2.578zM14 12v4H8.021c.06-1.38.24-2.72.54-4H14zM2.997 22a12.87 12.87 0 01-.96-4H6.02a23.85 23.85 0 00.493 4H2.997zm5.024-4H14v4H8.561c-.3-1.28-.48-2.62-.54-4zM14 24v5.854a4.566 4.566 0 01-1.35-.667c-.832-.586-1.626-1.488-2.299-2.61A14.48 14.48 0 019.148 24H14zm5.649 2.578c-.673 1.12-1.467 2.023-2.298 2.609a4.565 4.565 0 01-1.351.667V24h4.852c-.336.94-.738 1.802-1.203 2.578zM16 22v-4h5.979c-.06 1.38-.24 2.72-.54 4H16zm7.98-6a23.85 23.85 0 00-.493-4h3.517a12.87 12.87 0 01.958 4H23.98zm1.978-6h-2.997c-.582-1.836-1.387-3.447-2.353-4.732a12.962 12.962 0 013.584 2.54A13.032 13.032 0 0125.958 10zM5.808 7.808a12.963 12.963 0 013.584-2.54C8.425 6.553 7.622 8.164 7.04 10H4.042a13.032 13.032 0 011.766-2.192zM4.042 24h2.997c.582 1.836 1.387 3.447 2.353 4.732a12.96 12.96 0 01-3.584-2.54A13.029 13.029 0 014.042 24zm20.15 2.192a12.962 12.962 0 01-3.584 2.54c.966-1.285 1.77-2.896 2.353-4.732h2.997a13.032 13.032 0 01-1.766 2.192z',
location:
'M512 0C335.268 0 192 143.268 192 320c0 320 320 704 320 704s320-384 320-704C832 143.268 688.73 0 512 0zm0 512c-106.04 0-192-85.96-192-192s85.96-192 192-192 192 85.96 192 192-85.96 192-192 192z',
facebook:
'M29 0H3C1.35 0 0 1.35 0 3v26c0 1.65 1.35 3 3 3h13V18h-4v-4h4v-2c0-3.306 2.694-6 6-6h4v4h-4c-1.1 0-2 .9-2 2v2h6l-1 4h-5v14h9c1.65 0 3-1.35 3-3V3c0-1.65-1.35-3-3-3z',
twitter:
'M32 7.075a12.948 12.948 0 01-3.769 1.031 6.602 6.602 0 002.888-3.631c-1.269.75-2.675 1.3-4.169 1.594A6.565 6.565 0 0022.156 4a6.562 6.562 0 00-6.562 6.563c0 .512.056 1.012.169 1.493A18.633 18.633 0 012.23 5.194a6.564 6.564 0 00-.887 3.3 6.555 6.555 0 002.918 5.462 6.572 6.572 0 01-2.975-.818v.08a6.566 6.566 0 005.27 6.438 6.576 6.576 0 01-2.97.113A6.586 6.586 0 009.72 24.33a13.167 13.167 0 01-8.157 2.813c-.53 0-1.05-.031-1.568-.094A18.57 18.57 0 0010.062 30c12.075 0 18.682-10.006 18.682-18.681 0-.288-.007-.569-.019-.85A13.215 13.215 0 0032 7.075z',
chevronDown: ["M32 16c0-8.837-7.163-16-16-16S0 7.163 0 16s7.163 16 16 16 16-7.163 16-16zM3 16C3 8.82 8.82 3 16 3s13 5.82 13 13-5.82 13-13 13S3 23.18 3 16z", "M9.914 11.086l-2.828 2.828L16 22.828l8.914-8.914-2.828-2.828L16 17.172z"],
chevronUp: ["M0 16c0 8.837 7.163 16 16 16s16-7.163 16-16S24.837 0 16 0 0 7.163 0 16zm29 0c0 7.18-5.82 13-13 13S3 23.18 3 16 8.82 3 16 3s13 5.82 13 13z", "M22.086 20.914l2.828-2.828L16 9.172l-8.914 8.914 2.828 2.828L16 14.828z"]
};

const SvgIcons = ({ name, width, height, ...attrs }) => {
const paths = icons[name];

return (
<svg width={width} height={height} fill="currentColor" {...attrs}>
{isArray(paths) ? paths.map((path) => <path d={path} />) : <path d={paths} />}
</svg>
);
};

export default memo(SvgIcons);
9 changes: 2 additions & 7 deletions src/pages/country.js
Expand Up @@ -9,17 +9,12 @@ import FormattedString from '../components/formatted-string';
import useSummary from '../store/summary-hook';
import config from '../config';
import { pushDataLayer } from '../util';
import SvgIcons from '../components/svg-icons';

import style from './country.module.scss';

const { APP_HOSTNAME, APP_BASEPATH } = config();

export const TickIcon = ({ width = 16, height = 14, ...attrs }) => (
<svg width={width} height={height} viewBox={`0 0 ${width * 2} ${height * 2}`} fill="currentColor" {...attrs}>
<path d="M19.414 27.414l10-10a2 2 0 000-2.828l-10-10a2 2 0 00-2.828 2.828L23.172 14H4a2 2 0 000 4h19.172l-6.586 6.586c-.39.39-.586.902-.586 1.414s.195 1.024.586 1.414a2 2 0 002.828 0z" />
</svg>
);

const CountryPage = ({ slug }) => {
const location = useLocation();
const [summary] = useSummary();
Expand Down Expand Up @@ -107,7 +102,7 @@ const CountryPage = ({ slug }) => {
<h2 className="heading">Other resources</h2>
{waysToHelp.links.map((link) => (
<div key={link} className={style.link}>
<TickIcon className={style['tick-icon']} />
<SvgIcons name="tick" width={16} height={14} viewBox="0 0 32 28" className={style['tick-icon']} />
<FormattedString key={link} href={link}>
{link}
</FormattedString>
Expand Down
12 changes: 3 additions & 9 deletions src/pages/index.js
Expand Up @@ -4,17 +4,11 @@ import classNames from 'classnames';
import Layout from '../components/layout';
import countries from '../assets/data';
import CountryCard from '../components/country-card';
import { TickIcon } from './country';
import SvgIcons from '../components/svg-icons';

import style from './style.module.scss';
import { Link } from 'react-router-dom';

const SearchIcon = ({ width = 18, height = 18, ...attrs }) => (
<svg width={width} height={height} viewBox={`0 0 ${width * 2} ${height * 2}`} fill="currentColor" {...attrs}>
<path d="M31.008 27.231l-7.58-6.447c-.783-.705-1.621-1.028-2.298-.997A11.952 11.952 0 0024 12c0-6.627-5.373-12-12-12S0 5.373 0 12s5.373 12 12 12c2.972 0 5.69-1.08 7.787-2.87-.032.677.292 1.515.997 2.298l6.447 7.58c1.104 1.227 2.907 1.33 4.007.23s.997-2.903-.23-4.007zM12 20a8 8 0 110-16 8 8 0 010 16z" />
</svg>
);

const HomePage = () => {
const searchRef = useRef();
const imagesRef = useRef([]);
Expand Down Expand Up @@ -63,15 +57,15 @@ const HomePage = () => {
setFilteredCountries(newList);
}}
/>
<SearchIcon className={style['search-icon']} />
<SvgIcons name="search" width={18} height={18} viewBox="0 0 36 36" className={style['search-icon']} />
</div>
{Boolean(filteredCountries.length) && (
<>
<p className={style['result-indicator']}>Search result</p>
<ul className={style['search-result']}>
{filteredCountries.map((c, i) => (
<li className={classNames(style['result-item'], { [style['even-item']]: i % 2 !== 0 })} key={c.slug}>
<TickIcon />
<SvgIcons name="tick" width={16} height={14} viewBox="0 0 32 28" />
<Link
className={style['result-link']}
to={`/${c.slug}?utm_source=search&utm_keyword=${searchRef.current.value}`}
Expand Down

0 comments on commit 72d4df1

Please sign in to comment.