Let's make our app a bit visually pleasing by adding some images. The perfect place to do this is in the TaskListEmptyState
component.
Download the following image and put it at ssets/no-tasks-light.png
.
Modify your plugin to add an assets
property like the in the code below:
Basically, we're telling BlueBase that the said image has an ID NoTasks
and where to find it. Now we can just reference this image by this ID and BlueBase will take care of loading and rendering it across formats.
Modify the ComponentState
node in the TaskListEmptyState
component and add a prop imageSource="NoTasks"
as shown in the code below:
Now when you refresh the app, you should see an image in the empty state.
Sometimes we need a different variant of an image for dark mode. Don't worry, we have got you covered here as well.
Download the following image and put it at: assets/no-tasks-dark.png
.
Now, modify the assets property in the plugin to match the following:
Try refreshing your app. You'll see different images will be rendered in light mode and dark mode.
Basically, you can define a different image with the same ID (NoTasks
in this example) for all of the following scenarios:
NoTasks
Default version
NoTasks_dark
Dark mode version
NoTasks_light
Light mode verion
NoTasks_desktop
Desktop Screen Size version
NoTasks_mobile
Mobile Screen Size version
NoTasks_desktop_dark
Desktop Screen Size version on Dark mode
NoTasks_mobile_dark
Mobile Screen Size version on Dark mode
NoTasks_desktop_light
Desktop Screen Size version on Light mode
NoTasks_mobile_light
Mobile Screen Size version on Light mode
BlueBase was built from the ground up with theming in mind. It is an extensive topic and we encourage you to read the Themes section of the docs.
Just to see a bit of a demo, we will customise the styles of our custom component from app configurations.
You remember creating the ToDoAppIcon
component in Chapter 1.3:
Explanation:
Line 2: We import 2 hooks from BlueBase core: useStyles
and useTheme
.
Line 6: We define the interface of the stylesheet for the component.
Line 13: Add the styles
property as an optional prop.
Line 18: We access the currently active theme from the useTheme
hook.
Line 20: Extract the final styles from the useStyles
hook. This hook takes 3 params:
Name of the component. We can use this name in our themes to override the styles of this component.
Input props of the component. These may contain the styles
prop, as well as any other prop that is needed. Note that these props are also passed on to the defaultStyles
prop if it's a function.
The default styles. These are the base styles that may be overwritten by theme overrides. This param may be an object (of the interface defined at Line 6), or a function that returns this object.
Line 35 & 39: We use the styles in our component.
Let's see how we can customize the appearance of this component from our app configs.
Create a prop in the configs by key theme.overrides
. The value of this property is a theme object. Here you can override a theme's styles.
In the example below, we are basically telling BlueBase to override the styles of the ToDoAppIcon
component in light
mode.
Note that the value of configs['theme.overrides'].light.components.ToDoAppIcon
is an object that matches the ToDoAppIconStyles
interface.
Now when you run your app, you will notice the app icon color is purple in light
mode, and not red.
Now that we have created our plugin that adds the Tasks functionality to our app, let's see if we can make it configurable.
There are "configurable", we mean 2 things:
A developer that is using this plugin, can configure it via the configs
prop.
An end-user can configure the feature through the "Settings" UI.
We will attempt to do both these things in this chapter. For this example, we will make the number of items our Task List loads per page.
Let's go back to our TaskList component from Chapter 4.2.
Change Line 32 from:
To:
Basically, rather than having a hardcoded number in the code, we extract it from config with key 'tasks.itemsPerPage'
. We utilize the useConfig
hook for this purpose, that is imported from the @bluebase/core
package.
Note that the useConfig
hook has the same API as the useState
hook in the react
library.
This should be your final code now:
Now that we are using the config, we also need to define its default value. Add the defaultConfigs
object to your plugin as shown in the code below:
Now run your app and inspect. You will observe that BlueBase has successfully loaded the default config, which has been passed onto the GraphqlList
component.
Now comes the fun part. Let's override this value from our app's configs:
Run your app again. You will observe that the value in the configs
was loaded and preferred over the defaultConfigs
.
Now, let's see how we can allow the end-user to customize the value too.
Let's create a form that will allow the user to input a value, and update the config when he presses the submit button.
For this purpose, we will use the JsonForm
component from the @bluebase/plugin-json-schema-components
.
The props of JsonForm
component are very similar to the GraphqlJsonForm
that we have previously usesd.
This is because the GraphqlJsonForm
too uses JsonForm
internally.
JsonForm
component is built using the formik library.
Add the index file to export the component.
Now we want to create a screen for "Tasks" in the Settings app. Luckily the Settings app allows this to be done via bluebase.plugin.setting-app.pages
filter.
This filter inputs an array of screens in the settings app, all we have to do is to append our own screen configs and return the array. Create a new file and copy the following code:
Note that in Line 22 till 27 we define the "Task Settings" panel and use the TaskSettingsForm
component that we created in the previous step.
Let's add this filter to the plugin (See Line 13):
Run the app and go to the settings section. You will see the "Tasks" settings page is added.
When you use and submit the form, you will observe that it will update the config to achieve the desired result:
Internationalisation is a big part of modern apps. BlueBase has built-in support for translations and right-to-left (RTL) text support.
Go you the Settings app, and select a language. If the language needs RTL, BlueBase will change orientation automatically.
Changing content direction on native requires app to be restarted.
You can add support for any language you desire. Here are the steps on how to do this:
We support English and Urdu languages by default. If you need to add support for any other language just pass them to the locale.options
object in your configs file, where the key of the object is the language code, and value is the language name.
Next, we have to create a dictionary, that the system can refer to when attempting to translate a string. The dictionary is an object where where original string is the key, and the translated version is the value.
The way to do it is, we create a function that takes a dictionary as input, and we return that dictionary by appending our own translations to it. This is because the translations feature in BlueBase is built upon its Filters feature.
The filter key for format to add translations is: bluebase.intl.messages.${language_code}
. So for french language it would be bluebase.intl.messages.fr
.
When we have all our language filters setup, we just need to add them to the filters
object in the plugin.
While we attempt to give built in conversion support for our official plugins, you may still need to do one additional step to convert your string to the current locale.
We'll take example of our TaskListEmptyState
component. When you select a language different than English, you will note that the text is still not translated. Let's change that.
Go to your component and change to code to the following:
You will note that:
Line 2: We import useIntl
hook from @bluebase/core
.
Line 9: We extract the __
function from the useIntl()
hook.
Line 15-17: We use the __
function to translate strings.
That's all! Since we have already provided translations to these strings in previous step, when you refresh the app you will now observe the text to be converted.