Skip to content

Platform specific styles inside StyleSheet #254

@svbutko

Description

@svbutko

Introduction

Current implementation of theming doesn't allow developers to assign theme-dependant changes inside StyleSheet

Details

React Native has a built-in support for theming which is a great addition itself but at the moment it only gives developers information about what theme device has currently and based on this, developer can decide what styles to use in components which can be done different ways, but it always brings to something similar to this:

render() {
    const colorScheme = Appearance.getColorScheme();

    return (
        <View style={colorScheme === "dark" ? darkStyles.container : lightStyles.container}>
            {children}
        </View>
    );
}

const lightStyles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: Colors.white,
    },
});

const darkStyles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: Colors.backgroundDark,
    },
});

So now in order to have different styles working, a developer needs to manually check current theme and apply the styles, and in case if user has a lot of components it creates a lot of clutter and separates the styles by different constants (dark, light).

Besides, styles could have a lot of properties and in order to avoid copying and pasting them, one need to create one more constant style (i.e. commonStyles) and merge it with dark and light ones.

To “avoid” (mitigate) this comparison and “improve” merging, something like this can be done:



    getThemeStyle(lightStyles, darkStyles) {
        return Appearance.getColorScheme() == "light" ? lightStyles : darkStyles;
    }

    render() {
        const styles = getThemeStyle(lightStyles, darkStyles);

        return (
            <View style={styles.container}>
                {children}
            </View>
        );
    }

const commonStyles = StyleSheet.create({
    container: {
        flex: 1,
    },
});

const lightStyles = StyleSheet.create({
    container: {
        ...commonStyles.container,
        backgroundColor: Colors.white,
    },
});

const darkStyles = StyleSheet.create({
    container: {
        ...commonStyles.container,
        backgroundColor: Colors.backgroundDark,
    },
});

What if instead creating separate styles and merging them, and in most of the cases get rid of Appearance.getColorScheme() == “light" comparison, developers could define their theme styles inside StyleSheet.create similar way we have platform dependant code using Platform.select?

So that it could look something like this:

const styles = StyleSheet.create({
    container: {
        flex: 1,
        ...Appearance.select({
            dark: {
                backgroundColor: Colors.backgroundDark
            },
            light: {
                backgroundColor: Colors.white,
            },
        }),
    },
});

Discussion points

  • Implement a similar to Platform.select mechanism to have theme-dependant selection inside StyleSheet style

Metadata

Metadata

Assignees

No one assigned

    Labels

    🗣 DiscussionThis label identifies an ongoing discussion on a subject

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions