akveo / react-native-ui-kitten

:boom: React Native UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode
https://akveo.github.io/react-native-ui-kitten/
MIT License
10.36k stars 958 forks source link

How do I load dynamic custom mapping for font sizes? #1618

Open lyqht opened 2 years ago

lyqht commented 2 years ago

💬 Question

Hello there, recently I faced an issue due to native font scaling setting on my mobile app.

Screenshot 2022-04-30 at 1 40 07 AM

On the left, it is default font size on iOS simulator. On the right it is the 'Largest' font setting set by user on their mobile.

Hence, I was thinking of using react-native's fontScale to check this setting and then set the font sizes according in a custom mapping. This is an example metro.config.js that I understood from the docs.

const evaConfig = {
  evaPackage: '@eva-design/eva',
  customMappingPath: './src/constants/evaMapping.json',
};

module.exports = MetroConfig.create(evaConfig, {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false,
      },
    }),
  },
});

However, with this approach, I cannot check the fontScale on run time and override the font-size values accordingly. Is there another workaround to this problem?

Thank you!

UI Kitten and Eva version

    "@eva-design/eva": "2.1.1",
    "@ui-kitten/components": "5.1.2",
    "@ui-kitten/eva-icons": "5.1.2",
    "@ui-kitten/metro-config": "5.1.2",
swizes commented 2 years ago

I can verify that there is no workaround for this use case and it makes whole usage of UI Kitten a bit obselete. I can't make paddings, margins, radius sizes etc. responsive with using eva metro config

flexbox commented 2 years ago

I can't make paddings, margins, radius sizes etc. responsive with using eva metro config

But you can use another library for that 😄

I am successfully using https://github.com/Shopify/restyle to tackle these issues in colocation with KittenUI

Here is an example of my ThemeProvider.tsx

import React from "react";
import {
  ApplicationProvider as KittenProvider,
  IconRegistry,
} from "@ui-kitten/components";
import { EvaIconsPack } from "@ui-kitten/eva-icons";
import merge from "lodash/merge";
import * as eva from "@eva-design/eva";
import { ThemeProvider as RestyleProvider } from "@shopify/restyle";

import { ThemeContext } from "./ThemeContext";
import type { ProvidersProps } from "./Providers";

import { default as mapping } from "~/constants/app-mapping-theme.json";
import { default as kittenTheme } from "~/constants/app-theme.json";
import restyleTheme from "~/constants/theme";

export const ThemeProvider = ({ children }: ProvidersProps) => {
  const [theme, setTheme] = React.useState("light");

  const toggleTheme = () => {
    const nextTheme = theme === "light" ? "dark" : "light";
    setTheme(nextTheme);
  };

  return (
    <>
      <IconRegistry icons={EvaIconsPack} />
      <ThemeContext.Provider value={{ theme, toggleTheme }}>
        <KittenProvider
          {...eva}
          customMapping={merge(eva.mapping, mapping)}
          theme={{ ...eva.light, ...kittenTheme }}
        >
          <RestyleProvider theme={restyleTheme}>{children}</RestyleProvider>
        </KittenProvider>
      </ThemeContext.Provider>
    </>
  );
};
swizes commented 2 years ago

I can't make paddings, margins, radius sizes etc. responsive with using eva metro config

But you can use another library for that 😄

I am successfully using https://github.com/Shopify/restyle to tackle these issues in colocation with KittenUI

Here is an example of my ThemeProvider.tsx

import React from "react";
import {
  ApplicationProvider as KittenProvider,
  IconRegistry,
} from "@ui-kitten/components";
import { EvaIconsPack } from "@ui-kitten/eva-icons";
import merge from "lodash/merge";
import * as eva from "@eva-design/eva";
import { ThemeProvider as RestyleProvider } from "@shopify/restyle";

import { ThemeContext } from "./ThemeContext";
import type { ProvidersProps } from "./Providers";

import { default as mapping } from "~/constants/app-mapping-theme.json";
import { default as kittenTheme } from "~/constants/app-theme.json";
import restyleTheme from "~/constants/theme";

export const ThemeProvider = ({ children }: ProvidersProps) => {
  const [theme, setTheme] = React.useState("light");

  const toggleTheme = () => {
    const nextTheme = theme === "light" ? "dark" : "light";
    setTheme(nextTheme);
  };

  return (
    <>
      <IconRegistry icons={EvaIconsPack} />
      <ThemeContext.Provider value={{ theme, toggleTheme }}>
        <KittenProvider
          {...eva}
          customMapping={merge(eva.mapping, mapping)}
          theme={{ ...eva.light, ...kittenTheme }}
        >
          <RestyleProvider theme={restyleTheme}>{children}</RestyleProvider>
        </KittenProvider>
      </ThemeContext.Provider>
    </>
  );
};
  • KittenUI control all components
  • restyle for all things related to layout, positions, padding, margin, responsive

You can't use customMapping in "KittenProvider" if you are using @ui-kitten/metro-config. The issue is about using @ui-kitten/metro-config and applying a custom mapping with dynamic values based on screen dimensions. Since you apply mapping during build, it is not possible to make it responsive.

The question is how do you make the fontSize of UIKitten Text component with category H1 responsive?. Do you set the fontSize in style object with help of restyle or do you just use the default value in your mapping.json file

valinaga commented 2 years ago

I think you can still be able to do it with restyle, however need to ignore ui-kitten text mapping and use restyle variants instead. That's because the restyle theme is a .js file instead of ui-kitten which is a json one. You can take inspiration from here on how to add dynamic style in restyle theme. Hope this helps.

swizes commented 2 years ago

This requires to apply "restyle" to all components (Input,Text,Button,Select etc.) and it defeats the purpose of using an UI Kit. But thank you for the suggestion and i will definitely look into restyle, it might help me while I am building my own basic ui boilerplate code.

vinodsptharsha commented 1 year ago

There is a hack solution for this using custom mappings. Register the font sizes as per the requirement like below, "text-heading-1-font-size": 32, "text-heading-1-font-size-large": 36, "text-heading-1-font-size-small": 28,

Then in the Text component mappings under variantGroups->category add new category "s1": { "default": false }, "s1l": { "default": false }, "s1s": { "default": false },

Then under appearances -> variant groups add your new category variant like the one below, "s1": { "fontSize": "text-subtitle-1-font-size", "fontWeight": "text-subtitle-1-font-weight", "fontFamily": "text-subtitle-1-font-family" }, "s1l": { "fontSize": "text-subtitle-1-font-size-large", "fontWeight": "text-subtitle-1-font-weight", "fontFamily": "text-subtitle-1-font-family" }, "s1s": { "fontSize": "text-subtitle-1-font-size-large", "fontWeight": "text-subtitle-1-font-weight", "fontFamily": "text-subtitle-1-font-family" },

Then dynamically call <Text category={s1${var}} >Hello</Text> where var can be empty or l or s.