The best way to handle font-face
likethemammal opened this issue · comments
I'm writing a styled open-sourcable react component. I'd like to use react-primitives to layout and style the whole thing, and there arent many issues I can think of when it comes to using StyleSheet for everything over relying on css, but one comes to mind for this project.
The component will need a custom font as part of it's styling. I know the web and react native each have their own ways of importing custom fonts and setting what fontFamily
s are available. But this is such a lightweight component, and it really isnt dependent on react native. I'm basically trying to come up with a way to base64 include the font and set font-face
for all platforms.
Is this something that would fall under the .[platform].js
pattern, where the .web.js
file would be an injectable font-face stylesheet, and the react native file would have it's equivalent? Or is this something StyleSheet could handle? Or is this a situation where I'd just have to instruct in my documentation to include a font-face stylesheet when using the component for web, and follow the traditional react-native custom font importing instructions for the native platforms?
I'm trying to avoid that moment of
"Hey, thanks for installing this package. Now figure out how to include this font to make it look right"
I don't think this is something that should be handled by StyleSheet
, as that should just be a dependency on React Native, React Native Web, etc. Fonts act as globals pretty much on React Native (since they need to be linked from the respective native projects).
For web, Web Font Loader may be a nice way to help standardise font family usage instead of font-face
, and with its async capabilities, could be used together with React's Suspense API.
This could be handled with a util function that wraps <Text>
and has a fontFamily
prop, that resolves to the web/iOS/Android font family name.
Some pseudo-code:
components/common/Text.jsx
import { Text as _Text, Platform } from 'react-primitives';
const fonts = {
Roboto: {
default: 'Roboto',
android: 'Roboto Medium',
},
'Droid Sans': {
default: 'Droid Sans',
ios: 'SF Pro', // Example override to show we could resolve completely different fonts for platforms
}
};
// TODO: Add some kind of platform-specific fontWeight handling with fontFamily
const Text = ({ fontFamily = 'SF Pro Text', style, children, ...props }) => {
const resolvedFontFamily = fonts[fontFamily] && fonts[fontFamily][Platform.OS] || fontFamily;
return (
<_Text style={{ fontFamily: resolvedFontFamily, ...style }} {...props}>
{children}
</_Text>
);