gluestack-ui
gluestack-ui copied to clipboard
[Android] Heading fontFamily
Description
On Android the FontFamily of the Heading Component is not applied correctly
CodeSandbox/Snack link
No response
Steps to reproduce
If i install gluestack and eject theme and use expo font to load a font to apply it to the heading - the font doesnt get applied on android.
Works fine on ios.
Workaround with <Text fontFamily="$heading"></Text> work on android as well.
theme-provider.tsx
const { theme } = useThemeColorMode();
const [loaded, error] = useFonts({
Manrope_400Regular,
Manrope_500Medium,
Manrope_800ExtraBold,
});
if (error) {
throw new Error("Failed to load fonts");
}
if (!loaded) {
return null;
}
return (
<GluestackUIProvider config={config} colorMode={theme}>
<PushNotificationsProvider>
<AuthProvider>
<SplashScreenProvider>
<IntroProvider>
<NavigationProvider />
</IntroProvider>
</SplashScreenProvider>
</AuthProvider>
</PushNotificationsProvider>
<StatusBar style={theme === "dark" ? "light" : "dark"} />
</GluestackUIProvider>
);
};
config
import { AnimationResolver } from "@gluestack-style/animation-resolver";
import { MotionAnimationDriver } from "@gluestack-style/legend-motion-animation-driver";
import { createComponents, createConfig } from "@gluestack-style/react";
import * as componentsTheme from "./theme";
const colors = {
primary: {
light: "#188939",
main: "#0F5824",
dark: "#0B3D19",
contrast: "#FFFFFF",
},
secondary: {
light: "#ECF7DC",
main: "#ECF7DC",
dark: "#AFCC85",
contrast: "#0F5824",
},
backgroundLight: {
light: "#FFFFFF",
main: "#F5F5F5",
dark: "#D3D3D3",
contrast: "#2C3931",
},
textLight: {
light: "#4E6556",
main: "#3C4E42",
dark: "#2C3931",
contrast: "#FFFFFF",
},
infoLight: {
light: "#E0F4FF",
main: "#8AC6E7",
dark: "#135175",
contrast: "#001A2A",
},
warningLight: {
light: "#FFD057",
main: "#BE8D10",
dark: "#825E00",
contrast: "#292210",
},
successLight: {
light: "#94E592",
main: "#466246",
dark: "#324532",
contrast: "#061A06",
},
errorLight: {
light: "#FF9A9A",
main: "#6F3131",
dark: "#491E1E",
contrast: "#2B0F0F",
},
primaryDark: {
light: "#CDFF7E",
main: "#ACED45",
dark: "#88BB38",
contrast: "#13311C",
},
secondaryDark: {
light: "#000",
main: "#111706",
dark: "#0C1004",
contrast: "#ACED45",
},
textDark: {
light: "#8A8A8A",
main: "#DBDBDB",
dark: "#FFFFFF",
contrast: "#fff",
},
backgroundDark: {
light: "#232924",
main: "#161D17",
dark: "#0C0C0C",
contrast: "#fff",
},
infoDark: {
light: "#051925",
main: "#135175",
dark: "#186998",
contrast: "#DEEEF7",
},
warningDark: {
light: "#292210",
main: "#825E00",
dark: "#BE8D10",
contrast: "#FFD057",
},
successDark: {
light: "#081D08",
main: "#324532",
dark: "#466246",
contrast: "#99D698",
},
errorDark: {
light: "#2B0F0F",
main: "#491E1E",
dark: "#6F3131",
contrast: "#FF9A9A",
},
};
export const gluestackUIConfig = createConfig({
aliases: {
bg: "backgroundColor",
bgColor: "backgroundColor",
h: "height",
w: "width",
p: "padding",
px: "paddingHorizontal",
py: "paddingVertical",
pt: "paddingTop",
pb: "paddingBottom",
pr: "paddingRight",
pl: "paddingLeft",
m: "margin",
mx: "marginHorizontal",
my: "marginVertical",
mt: "marginTop",
mb: "marginBottom",
mr: "marginRight",
ml: "marginLeft",
rounded: "borderRadius",
} as const,
tokens: {
colors: {
primary0: colors.primary.contrast,
primary50: colors.primary.light,
primary100: colors.primary.light,
primary200: colors.primary.light,
primary300: colors.primary.light,
primary400: colors.primary.main,
primary500: colors.primary.main,
primary600: colors.primary.main,
primary700: colors.primary.dark,
primary800: colors.primary.dark,
primary900: colors.primary.dark,
primary950: colors.primary.dark,
primaryDark0: colors.primaryDark.contrast,
primaryDark50: colors.primaryDark.light,
primaryDark100: colors.primaryDark.light,
primaryDark200: colors.primaryDark.light,
primaryDark300: colors.primaryDark.light,
primaryDark400: colors.primaryDark.main,
primaryDark500: colors.primaryDark.main,
primaryDark600: colors.primaryDark.main,
primaryDark700: colors.primaryDark.dark,
primaryDark800: colors.primaryDark.dark,
primaryDark900: colors.primaryDark.dark,
primaryDark950: colors.primaryDark.dark,
secondary0: colors.secondary.contrast,
secondary50: colors.secondary.light,
secondary100: colors.secondary.light,
secondary200: colors.secondary.light,
secondary300: colors.secondary.light,
secondary400: colors.secondary.main,
secondary500: colors.secondary.main,
secondary600: colors.secondary.main,
secondary700: colors.secondary.dark,
secondary800: colors.secondary.dark,
secondary900: colors.secondary.dark,
secondary950: colors.secondary.dark,
secondaryDark0: colors.secondaryDark.contrast,
secondaryDark50: colors.secondaryDark.light,
secondaryDark100: colors.secondaryDark.light,
secondaryDark200: colors.secondaryDark.light,
secondaryDark300: colors.secondaryDark.light,
secondaryDark400: colors.secondaryDark.main,
secondaryDark500: colors.secondaryDark.main,
secondaryDark600: colors.secondaryDark.main,
secondaryDark700: colors.secondaryDark.dark,
secondaryDark800: colors.secondaryDark.dark,
secondaryDark900: colors.secondaryDark.dark,
secondaryDark950: colors.secondaryDark.dark,
textLight0: colors.textLight.contrast,
textLight50: colors.textLight.light,
textLight100: colors.textLight.light,
textLight200: colors.textLight.light,
textLight300: colors.textLight.light,
textLight400: colors.textLight.main,
textLight500: colors.textLight.main,
textLight600: colors.textLight.main,
textLight700: colors.textLight.dark,
textLight800: colors.textLight.dark,
textLight900: colors.textLight.dark,
textLight950: colors.textLight.dark,
textDark0: colors.textDark.contrast,
textDark50: colors.textDark.light,
textDark100: colors.textDark.light,
textDark200: colors.textDark.light,
textDark300: colors.textDark.light,
textDark400: colors.textDark.main,
textDark500: colors.textDark.main,
textDark600: colors.textDark.main,
textDark700: colors.textDark.dark,
textDark800: colors.textDark.dark,
textDark900: colors.textDark.dark,
textDark950: colors.textDark.dark,
borderDark0: "#FCFCFC",
borderDark50: "#F5F5F5",
borderDark100: "#E5E5E5",
borderDark200: "#DBDBDB",
borderDark300: "#D4D4D4",
borderDark400: "#A3A3A3",
borderDark500: "#8C8C8C",
borderDark600: "#737373",
borderDark700: "#525252",
borderDark800: "#404040",
borderDark900: "#262626",
borderDark950: "#171717",
borderLight0: "#FCFCFC",
borderLight50: "#F5F5F5",
borderLight100: "#E5E5E5",
borderLight200: "#DBDBDB",
borderLight300: "#D4D4D4",
borderLight400: "#A3A3A3",
borderLight500: "#8C8C8C",
borderLight600: "#737373",
borderLight700: "#525252",
borderLight800: "#404040",
borderLight900: "#262626",
borderLight950: "#171717",
backgroundDark0: "#FFFFFF",
backgroundDark50: "#232924",
backgroundDark100: "#232924",
backgroundDark200: "#232924",
backgroundDark300: "#232924",
backgroundDark400: "#161D17",
backgroundDark500: "#161D17",
backgroundDark600: "#161D17",
backgroundDark700: "#0C0C0C",
backgroundDark800: "#0C0C0C",
backgroundDark900: "#0C0C0C",
backgroundDark950: "#0C0C0C",
backgroundLight0: colors.backgroundLight.contrast,
backgroundLight50: colors.backgroundLight.light,
backgroundLight100: colors.backgroundLight.light,
backgroundLight200: colors.backgroundLight.light,
backgroundLight300: colors.backgroundLight.light,
backgroundLight400: colors.backgroundLight.main,
backgroundLight500: colors.backgroundLight.main,
backgroundLight600: colors.backgroundLight.main,
backgroundLight700: colors.backgroundLight.dark,
backgroundLight800: colors.backgroundLight.dark,
backgroundLight900: colors.backgroundLight.dark,
backgroundLight950: colors.backgroundLight.dark,
error0: colors.errorLight.contrast,
error50: colors.errorLight.light,
error100: colors.errorLight.light,
error200: colors.errorLight.light,
error300: colors.errorLight.light,
error400: colors.errorLight.main,
error500: colors.errorLight.main,
error600: colors.errorLight.main,
error700: colors.errorLight.dark,
error800: colors.errorLight.dark,
error900: colors.errorLight.dark,
error950: colors.errorLight.dark,
success0: colors.successLight.contrast,
success50: colors.successLight.light,
success100: colors.successLight.light,
success200: colors.successLight.light,
success300: colors.successLight.light,
success400: colors.successLight.main,
success500: colors.successLight.main,
success600: colors.successLight.main,
success700: colors.successLight.dark,
success800: colors.successLight.dark,
success900: colors.successLight.dark,
success950: colors.successLight.dark,
warning0: colors.warningLight.contrast,
warning50: colors.warningLight.light,
warning100: colors.warningLight.light,
warning200: colors.warningLight.light,
warning300: colors.warningLight.light,
warning400: colors.warningLight.main,
warning500: colors.warningLight.main,
warning600: colors.warningLight.main,
warning700: colors.warningLight.dark,
warning800: colors.warningLight.dark,
warning900: colors.warningLight.dark,
info0: colors.infoLight.contrast,
info50: colors.infoLight.light,
info100: colors.infoLight.light,
info200: colors.infoLight.light,
info300: colors.infoLight.light,
info400: colors.infoLight.main,
info500: colors.infoLight.main,
info600: colors.infoLight.main,
info700: colors.infoLight.dark,
info800: colors.infoLight.dark,
info900: colors.infoLight.dark,
errorDark0: colors.errorDark.contrast,
errorDark50: colors.errorDark.light,
errorDark100: colors.errorDark.light,
errorDark200: colors.errorDark.light,
errorDark300: colors.errorDark.light,
errorDark400: colors.errorDark.main,
errorDark500: colors.errorDark.main,
errorDark600: colors.errorDark.main,
errorDark700: colors.errorDark.dark,
errorDark800: colors.errorDark.dark,
errorDark900: colors.errorDark.dark,
errorDark950: colors.errorLight.dark,
successDark0: colors.successDark.contrast,
successDark50: colors.successDark.light,
successDark100: colors.successDark.light,
successDark200: colors.successDark.light,
successDark300: colors.successDark.light,
successDark400: colors.successDark.main,
successDark500: colors.successDark.main,
successDark600: colors.successDark.main,
successDark700: colors.successDark.dark,
successDark800: colors.successDark.dark,
successDark900: colors.successDark.dark,
successDark950: colors.successDark.dark,
warningDark0: colors.warningDark.contrast,
warningDark50: colors.warningDark.light,
warningDark100: colors.warningDark.light,
warningDark200: colors.warningDark.light,
warningDark300: colors.warningDark.light,
warningDark400: colors.warningDark.main,
warningDark500: colors.warningDark.main,
warningDark600: colors.warningDark.main,
warningDark700: colors.warningDark.dark,
warningDark800: colors.warningDark.dark,
warningDark900: colors.warningDark.dark,
infoDark0: colors.infoDark.contrast,
infoDark50: colors.infoDark.light,
infoDark100: colors.infoDark.light,
infoDark200: colors.infoDark.light,
infoDark300: colors.infoDark.light,
infoDark400: colors.infoDark.main,
infoDark500: colors.infoDark.main,
infoDark600: colors.infoDark.main,
infoDark700: colors.infoDark.dark,
infoDark800: colors.infoDark.dark,
infoDark900: colors.infoDark.dark,
backgroundLightError: "#491E1E",
backgroundDarkError: "#FE8383",
backgroundLightWarning: "#6A4B2E",
backgroundDarkWarning: "#FFC691",
backgroundLightSuccess: "#324532",
backgroundDarkSuccess: "#99D698",
backgroundLightInfo: "#135175",
backgroundDarkInfo: "#DEEEF7",
backgroundLightMuted: "#F6F6F7",
backgroundDarkMuted: "#252526",
white: "#FFFFFF",
black: "#000000",
},
space: {
px: "1px",
"0": 0,
"0.5": 2,
"1": 4,
"1.5": 6,
"2": 8,
"2.5": 10,
"3": 12,
"3.5": 14,
"4": 16,
"4.5": 18,
"5": 20,
"6": 24,
"7": 28,
"8": 32,
"9": 36,
"10": 40,
"11": 44,
"12": 48,
"16": 64,
"20": 80,
"24": 96,
"32": 128,
"40": 160,
"48": 192,
"56": 224,
"64": 256,
"72": 288,
"80": 320,
"96": 384,
"1/2": "50%",
"1/3": "33.333%",
"2/3": "66.666%",
"1/4": "25%",
"2/4": "50%",
"3/4": "75%",
"1/5": "20%",
"2/5": "40%",
"3/5": "60%",
"4/5": "80%",
"1/6": "16.666%",
"2/6": "33.333%",
"3/6": "50%",
"4/6": "66.666%",
"5/6": "83.333%",
full: "100%",
},
borderWidths: {
"0": 0,
"1": 1,
"2": 2,
"4": 4,
"8": 8,
},
radii: {
none: 0,
xs: 2,
sm: 4,
md: 6,
lg: 8,
xl: 12,
"2xl": 16,
"3xl": 24,
full: 9999,
},
breakpoints: {
base: 0,
sm: 480,
md: 768,
lg: 992,
xl: 1280,
},
mediaQueries: {
base: "@media screen and (min-width: 0)",
xs: "@media screen and (min-width: 400px)",
sm: "@media screen and (min-width: 480px)",
md: "@media screen and (min-width: 768px)",
lg: "@media screen and (min-width: 992px)",
xl: "@media screen and (min-width: 1280px)",
},
letterSpacings: {
xs: -0.4,
sm: -0.2,
md: 0,
lg: 0.2,
xl: 0.4,
"2xl": 1.6,
},
lineHeights: {
"2xs": 16,
xs: 18,
sm: 20,
md: 22,
lg: 24,
xl: 28,
"2xl": 32,
"3xl": 40,
"4xl": 48,
"5xl": 56,
"6xl": 72,
"7xl": 90,
},
fontWeights: {
hairline: "300",
thin: "400",
light: "400",
normal: "500",
medium: "500",
semibold: "800",
bold: "800",
extrabold: "800",
black: "800",
extraBlack: "800",
},
fonts: {
heading: "Manrope_800ExtraBold",
body: "Manrope_500Medium",
mono: "Manrope_400Regular",
},
fontSizes: {
"2xs": 10,
xs: 10,
sm: 12,
md: 14,
lg: 16,
xl: 18,
"2xl": 24,
"3xl": 30,
"4xl": 36,
"5xl": 48,
"6xl": 60,
"7xl": 72,
"8xl": 96,
"9xl": 128,
},
opacity: {
0: 0,
5: 0.05,
10: 0.1,
20: 0.2,
25: 0.25,
30: 0.3,
40: 0.4,
50: 0.5,
60: 0.6,
70: 0.7,
75: 0.75,
80: 0.8,
90: 0.9,
95: 0.95,
100: 1,
},
} as const,
globalStyle: {
variants: {
hardShadow: {
"1": {
shadowColor: "$backgroundLight900",
shadowOffset: {
width: -2,
height: 2,
},
shadowRadius: 8,
shadowOpacity: 0.5,
elevation: 10,
},
"2": {
shadowColor: "$backgroundLight900",
shadowOffset: {
width: 0,
height: 3,
},
shadowRadius: 8,
shadowOpacity: 0.5,
elevation: 10,
},
"3": {
shadowColor: "$backgroundLight900",
shadowOffset: {
width: 2,
height: 2,
},
shadowRadius: 8,
shadowOpacity: 0.5,
elevation: 10,
},
"4": {
shadowColor: "$backgroundLight900",
shadowOffset: {
width: 0,
height: -3,
},
shadowRadius: 8,
shadowOpacity: 0.5,
elevation: 10,
},
// this 5th version is only for toast shadow
// temporary
"5": {
shadowColor: "$backgroundLight900",
shadowOffset: {
width: 0,
height: 3,
},
shadowRadius: 8,
shadowOpacity: 0.2,
elevation: 10,
},
},
softShadow: {
"1": {
shadowColor: "$primary500",
shadowOffset: {
width: 0,
height: 4,
},
shadowRadius: 10,
shadowOpacity: 0.5,
_android: {
shadowColor: "$primary500",
elevation: 10,
shadowOpacity: 0.5,
},
_dark: {
shadowColor: "$black",
shadowOffset: {
width: 0,
height: 4,
},
shadowRadius: 10,
shadowOpacity: 0.5,
_android: {
shadowColor: "$black",
elevation: 10,
shadowOpacity: 0.5,
},
},
},
"2": {
shadowColor: "$backgroundLight500",
shadowOffset: {
width: 0,
height: 4,
},
shadowRadius: 10,
shadowOpacity: 0.3,
_android: {
shadowColor: "$backgroundLight500",
elevation: 10,
shadowOpacity: 0.3,
},
_dark: {
shadowColor: "$backgroundDark500",
shadowOffset: {
width: 0,
height: 4,
},
shadowRadius: 10,
shadowOpacity: 0.5,
_android: {
shadowColor: "$backgroundDark500",
elevation: 10,
shadowOpacity: 0.5,
},
},
},
"3": {
shadowColor: "$textLight500",
shadowOffset: {
width: 0,
height: 4,
},
shadowRadius: 12,
shadowOpacity: 0.15,
_android: {
shadowColor: "$textLight500",
elevation: 4,
shadowOpacity: 0.15,
},
},
"4": {
shadowColor: "$backgroundLight900",
shadowOffset: {
width: 0,
height: 0,
},
shadowRadius: 40,
shadowOpacity: 0.1,
elevation: 10,
_android: {
shadowColor: "$backgroundLight500",
elevation: 20,
shadowOpacity: 0.2,
},
},
},
},
},
plugins: [new AnimationResolver(MotionAnimationDriver)],
});
type Config = typeof gluestackUIConfig; // Assuming `config` is defined elsewhere
type Components = typeof componentsConfig;
export const componentsConfig = createComponents(componentsTheme);
export type { UIConfig, UIComponents } from "@gluestack-ui/themed";
export interface IConfig {}
export interface IComponents {}
declare module "@gluestack-ui/themed" {
interface UIConfig extends Omit<Config, keyof IConfig>, IConfig {}
interface UIComponents
extends Omit<Components, keyof IComponents>,
IComponents {}
}
// Extend the internal styled config
declare module "@gluestack-style/react" {
interface ICustomConfig extends Config {}
}
export const config = {
...gluestackUIConfig,
components: componentsConfig,
};
gluestack-ui Version
1.1.18
Platform
- [X] Expo
- [ ] React Native CLI
- [ ] Next
- [ ] Web
- [X] Android
- [ ] iOS
Other Platform
No response
Additional Information
No response
it is somehow related to the fontWeight, if i apply fontWeight 400 the font is loaded correctly
Hey @borstessi, Thanks for reporting issue. We will have a look.
Just here to report that we have the same issue. Applying fontWeight: 400 on config fixes the issue.
I have a similar issue. I am working in Android and Expo. Despite I have imported the fonts using UseFont in the expo and changed the tokens the fonts are not applied to the global theme.
import { config as defaultConfig } from "@gluestack-ui/config";
import { createConfig } from "@gluestack-ui/themed";
export const themeConfig = createConfig({
...defaultConfig,
tokens: {
...defaultConfig.tokens,
fontSizes: {
...defaultConfig.tokens.fontSizes,
newFontSize: 90,
},
fonts: {
heading: 'Futura-Bold',
body: 'Futura-Medium',
mono: 'Futura-Book',
},
colors: {
...defaultConfig.tokens.colors,
primary0: "#E5F1FB",
primary50: "#e2ebff",
primary100: "#b2c3ff",
primary200: "#809bff",
primary300: "#4e72fe",
primary400: "#204afd",
primary500: "#0b32e4",
primary600: "#0426b2",
primary700: "#001b80",
primary800: "#001871",
primary900: "#00051f",
primary950: "#000711",
brandPrimary: '#001871',
brandSecondary: '#007aff',
brandInfo: '#C0E7F7',
brandSuccess: '#4DD298',
brandDanger: '#F58BA0',
brandWarning: '#FA8202',
brandDark: '#000',
brandLight: '#a9a9a9',
}
}
});
When I do this the font is not applied,
<Text style={{ alignSelf: "center", marginTop: 500}}>Styling! :D Hooray!</Text>
The only way it works is forcing the font in each component like this.
<Text style={{fontFamily: "Futura-Bold", alignSelf: "center", marginTop: 500}}>Styling! :D Hooray!</Text>
I am using
"@gluestack-style/react": "^1.0.52",
"@gluestack-ui/config": "^1.1.16",
"@gluestack-ui/themed": "^1.1.22",
"expo": "~50.0.14",
"expo-font": "~11.10.3",
Same issue, setting fontWeight to 400 seems to fix I guess the fontWeight's don't actually do anything
Hi hi can anyone show where you add the fontweight: 400 code? I dded in my config file but the font on android still doesnt change
I am having same issue, loading any custom font from google or local. font colors/sizes does not works. any solution or bug fix?
I have the same issue, in my project I have both expo-google-fonts and local ones: on iOS everything's ok, on Android it only works but with several issue by adding the FontResolver so it seems it isn't a real solution
@Viraj-10 I believe this is still present in gluestack-ui v2.
If in my tailwind config I have custom: ["Poppins_400Regular"], and I use a heading with <Heading className="font-custom">{title}</Heading>, it will not work unless I add the font-normal or font-medium classes such as <Heading className="font-normal font-custom">{title}</Heading> and now it'll work, but again that's just for an hardcoded font with a predefined weight.
In the tailwind config, custom: ["Poppins", "sans-serif"] or custom: ["Poppins"] will not work.
I've been having issues with gluestack-ui with the fonts since the very beginning, even in v1. It'd be nice if someone could look into this and have a good in-depth documentation and one of the example apps using a custom font as the default font for everything.