New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create @primer/styled-octicons package #417
Conversation
To see if it was breaking tree shaking
This pull request is being automatically deployed with Vercel (learn more). 🔍 Inspect: https://vercel.com/primer/octicons/f0xn0lnx5 |
Honestly I don't think this is a hard requirement. If Octicons are always meant to be displayed inline-block we can leave it that way.
yes this would be nice to have. though if we wanted to have a default theme for these icons we'd have to have a dep on @primer/components which we might not want to do
yes 🚢 it!
I think just react and styled-components should be fine but not sure about styled-system |
Ok just looked through the code and it got me thinking more about the theme. Should we assume that folks are using this library inside of a |
@emplums I think styled-system has a default spacing scale. So |
@colebemis I can confirm I saw the same results as you with respect to tree-shaking. I played around with the package directly in my From this comment (webpack/webpack#9337 (comment)) it seems like maybe that's the best way to handle things anyway? I'm guessing since we're now executing a function call each icon (to compose it with system props), as opposed to just defining in the functions like in the However, it can use more of a "side-effects" approach which each icon is in its own module, perhaps? Feel free to ping me if you want to talk through some of this synchronously and I can walk you through what I tried. |
🎉 Bundling each icon individually fixed the tree-shaking issue! Thanks for your help, @dmarcey. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! ✨
Thanks for taking the time to get the tree-shaking working!
One thought I had for a future follow-up was to try to find a way to pull some of the common code out into a separate module that can be imported by each individual icon.
import { color, compose, space } from 'styled-system';
var sizeMap = {
small: 16,
medium: 32,
large: 64
};
export function getSvgProps(_ref) {
var ariaLabel = _ref['aria-label'],
className = _ref.className,
size = _ref.size,
verticalAlign = _ref.verticalAlign,
svgDataByHeight = _ref.svgDataByHeight;
var height = sizeMap[size] || size;
var naturalHeight = closestNaturalHeight(Object.keys(svgDataByHeight), height);
var naturalWidth = svgDataByHeight[naturalHeight].width;
var width = height * (naturalWidth / naturalHeight);
var path = svgDataByHeight[naturalHeight].path;
return {
'aria-hidden': ariaLabel ? 'false' : 'true',
'aria-label': ariaLabel,
role: 'img',
className: className,
viewBox: '0 0 ' + naturalWidth + ' ' + naturalHeight,
width: width,
height: height,
fill: 'currentColor',
style: {
display: 'inline-block',
userSelect: 'none',
verticalAlign: verticalAlign
},
dangerouslySetInnerHTML: { __html: path }
};
}
function closestNaturalHeight(naturalHeights, height) {
return naturalHeights.map(function (naturalHeight) {
return parseInt(naturalHeight, 10);
}).reduce(function (acc, naturalHeight) {
return naturalHeight <= height ? naturalHeight : acc;
}, naturalHeights[0]);
}
export var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}return target;
};
// eslint-disable-next-line import/no-namespace
export var COMMON = compose(space, color);
Those lines are duplicated across each *Icon.js
so when the consumer ends up bundling the package, they get a copy of those functions for each different type of icon they pull in - it looks like its about 500 bytes minified or so per icon. So making a change like this could save 10 KB for an app that uses 20 icons.
Just a suggestion for a follow-up, I think this is good to 🚢 as is!
## Install | ||
|
||
```shell | ||
npm install @primer/styled-octicons@canary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we recommend folks to install the canary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Until the v2
branch is merged, there won't actually be a @latest
version of the package. When the v2
branch is merged, we'll update the docs to remove @canary
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙌
Problem
We want to be able to style Octicons with system props like we style other Primer Components. The components in
@primer/octicons-react
, however, don't accept system props. So we created aStyledOcticon
component in Primer Components as a workaround. But the API for usingStyledOcticon
is clunky:Solution
What if we could pass system props directly to icon components?
This PR makes that possible. It adds a
@primer/styled-octicons
package that wraps the components in@primer/octicons-react
withCOMMON
system props.📝 Preview the docs
You can test out the package by installing:
After we merge this PR, we'll be able to deprecate
StyledOcticon
in Primer Components.Questions
display
prop?display
is part of theCOMMON
system props in Primer Components.@primer/octicons-react
because it uses inlines styles to setdisplay: inline-block
, which overrides thedisplay
prop. But how will we apply styles in@primer/octicons-react
without using inline styles or styled components?sx
prop?@primer/styled-octicons
for this package?react
andstyled-components
as peer dependencies. But shouldstyled-system
also be a peer dependency?TODO
@primer/octicons-react
but not for@primer/styled-octicons
.sx
propPart of primer/react#511