Commit c96e60c3 authored by Lyza Danger Gardner's avatar Lyza Danger Gardner

Add icons and allow inline display of SvgIcons

parent 8b82b294
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true" focusable="false" class="Icon Icon--email"><g fill-rule="evenodd"><rect fill="none" stroke="none" x="0" y="0" width="16" height="16"></rect><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 3v10h14V3H1zm0 0l7 6 7-6H1z"></path></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true" focusable="false" class="Icon Icon--social-facebook"><g fill-rule="evenodd"><rect fill="none" stroke="none" x="0" y="0" width="16" height="16"></rect><path fill="currentColor" stroke="none" d="M15.999 8.049c0-4.445-3.582-8.049-8-8.049S0 3.604 0 8.049C0 12.066 2.925 15.396 6.75 16v-5.624H4.717V8.049H6.75V6.276c0-2.018 1.195-3.132 3.022-3.132.875 0 1.79.157 1.79.157v1.981h-1.008c-.994 0-1.304.62-1.304 1.257v1.51h2.219l-.355 2.327H9.25V16c3.825-.604 6.75-3.934 6.75-7.951z"></path></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true" focusable="false" class="Icon Icon--share"><g fill-rule="evenodd"><rect fill="none" stroke="none" x="0" y="0" width="16" height="16"></rect><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 11V2m7 8v5H1v-5m3-5l4-4 4 4"></path></g></svg>
<path fill="currentColor" fill-rule="nonzero" d="M16 1.656v3.5c0 .587-.721.874-1.138.464l-.992-.977-6.764 6.66a.674.674 0 0 1-.943 0l-.629-.62a.649.649 0 0 1 0-.927l6.765-6.66-.992-.976c-.419-.412-.122-1.12.471-1.12h3.555c.369 0 .667.294.667.656zm-4.694 6.749c.42-.414 1.138-.121 1.138.464v4.819c0 .724-.597 1.312-1.333 1.312H1.333A1.323 1.323 0 0 1 0 13.687V4.063C0 3.338.597 2.75 1.333 2.75h8.223c.593 0 .89.707.47 1.12l-.444.438a.772.772 0 0 1-.47.192H1.777v8.75h8.889V9.306c0-.15.087-.358.195-.464l.444-.437z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" aria-hidden="true" focusable="false" class="Icon Icon--social-twitter"><g fill-rule="evenodd"><rect fill="none" stroke="none" x="0" y="0" width="16" height="16"></rect><path fill="currentColor" stroke="none" d="M15.969 3.049c-.59.259-1.22.436-1.884.516a3.305 3.305 0 0 0 1.442-1.815c-.634.37-1.336.64-2.084.79a3.28 3.28 0 0 0-5.59 2.988 9.29 9.29 0 0 1-6.76-3.418A3.214 3.214 0 0 0 .65 3.76c0 1.14.58 2.142 1.459 2.73a3.27 3.27 0 0 1-1.485-.41v.04a3.282 3.282 0 0 0 2.63 3.218 3.33 3.33 0 0 1-1.474.057 3.291 3.291 0 0 0 3.069 2.278A6.578 6.578 0 0 1 .78 13.076c-.26 0-.52-.015-.78-.044a9.33 9.33 0 0 0 5.038 1.472c6.036 0 9.332-4.997 9.332-9.323 0-.14 0-.28-.01-.42.64-.46 1.2-1.04 1.64-1.7l-.031-.012z"></path></g></svg>
'use strict'; 'use strict';
const classnames = require('classnames');
const { createElement } = require('preact'); const { createElement } = require('preact');
const { useLayoutEffect, useRef } = require('preact/hooks'); const { useLayoutEffect, useRef } = require('preact/hooks');
const propTypes = require('prop-types'); const propTypes = require('prop-types');
...@@ -12,7 +13,9 @@ const icons = { ...@@ -12,7 +13,9 @@ const icons = {
'expand-menu': require('../../images/icons/expand-menu.svg'), 'expand-menu': require('../../images/icons/expand-menu.svg'),
copy: require('../../images/icons/copy.svg'), copy: require('../../images/icons/copy.svg'),
cursor: require('../../images/icons/cursor.svg'), cursor: require('../../images/icons/cursor.svg'),
email: require('../../images/icons/email.svg'),
external: require('../../images/icons/external.svg'), external: require('../../images/icons/external.svg'),
facebook: require('../../images/icons/facebook.svg'),
groups: require('../../images/icons/groups.svg'), groups: require('../../images/icons/groups.svg'),
help: require('../../images/icons/help.svg'), help: require('../../images/icons/help.svg'),
leave: require('../../images/icons/leave.svg'), leave: require('../../images/icons/leave.svg'),
...@@ -21,6 +24,7 @@ const icons = { ...@@ -21,6 +24,7 @@ const icons = {
public: require('../../images/icons/public.svg'), public: require('../../images/icons/public.svg'),
refresh: require('../../images/icons/refresh.svg'), refresh: require('../../images/icons/refresh.svg'),
share: require('../../images/icons/share.svg'), share: require('../../images/icons/share.svg'),
twitter: require('../../images/icons/twitter.svg'),
}; };
/** /**
...@@ -30,7 +34,7 @@ const icons = { ...@@ -30,7 +34,7 @@ const icons = {
* This matches the way we do icons on the website, see * This matches the way we do icons on the website, see
* https://github.com/hypothesis/h/pull/3675 * https://github.com/hypothesis/h/pull/3675
*/ */
function SvgIcon({ name, className = '' }) { function SvgIcon({ name, className = '', inline = false }) {
if (!icons[name]) { if (!icons[name]) {
throw new Error(`Unknown icon ${name}`); throw new Error(`Unknown icon ${name}`);
} }
...@@ -48,7 +52,11 @@ function SvgIcon({ name, className = '' }) { ...@@ -48,7 +52,11 @@ function SvgIcon({ name, className = '' }) {
]); ]);
return ( return (
<span className="svg-icon" dangerouslySetInnerHTML={markup} ref={element} /> <span
className={classnames('svg-icon', { 'svg-icon--inline': inline })}
dangerouslySetInnerHTML={markup}
ref={element}
/>
); );
} }
...@@ -58,6 +66,9 @@ SvgIcon.propTypes = { ...@@ -58,6 +66,9 @@ SvgIcon.propTypes = {
/** A CSS class to apply to the `<svg>` element. */ /** A CSS class to apply to the `<svg>` element. */
className: propTypes.string, className: propTypes.string,
/** Apply a style allowing for inline display of icon wrapper */
inline: propTypes.bool,
}; };
module.exports = SvgIcon; module.exports = SvgIcon;
...@@ -43,4 +43,20 @@ describe('SvgIcon', () => { ...@@ -43,4 +43,20 @@ describe('SvgIcon', () => {
const svg = container.querySelector('svg'); const svg = container.querySelector('svg');
assert.equal(svg.getAttribute('class'), 'thing__icon'); assert.equal(svg.getAttribute('class'), 'thing__icon');
}); });
it('sets a default class on the wrapper element', () => {
const container = document.createElement('div');
render(<SvgIcon name="expand-menu" />, container);
const wrapper = container.querySelector('span');
assert.isTrue(wrapper.classList.contains('svg-icon'));
assert.isFalse(wrapper.classList.contains('svg-icon--inline'));
});
it('appends an inline class to wrapper if `inline` prop is `true`', () => {
const container = document.createElement('div');
render(<SvgIcon name="expand-menu" inline={true} />, container);
const wrapper = container.querySelector('span');
assert.isTrue(wrapper.classList.contains('svg-icon'));
assert.isTrue(wrapper.classList.contains('svg-icon--inline'));
});
}); });
/* Make the wrapper element's size match the contained `svg` element */ /* Make the wrapper element's size match the contained `svg` element */
.svg-icon { .svg-icon {
display: flex; display: flex;
&--inline {
display: inline;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment