Custom Themes for Flatfile Portal
Theming gives you independent control over the look and feel of Flatfile Portal. With this, you can adjust both a global styles and individual components within the importer, as well as control the CSS pseudo-class :hover on buttons.
How it works
Portal Theming is one of the optional settings within the FlatfileImporter Options. For simplicity's sake, the below code example shows only the global setting, and then we will expand out a bit more on each specific area and what can be customized.
import FlatfileImporter from "@flatfile/adapter";
const importer = new FlatfileImporter("license_key", {
type: "Theming Demo Imports",
fields: [
{ key: "name", label: "Name" },
{ key: "email", label: "Email" },
],
theme: {
global: {
backgroundColor: "#212327",
textColor: "#c2c3c3",
primaryTextColor: "#c2c3c3",
secondaryTextColor: "#c2c3c3",
successColor: "#c2c3c3",
warningColor: "#c2c3c3",
fontFamily: "font",
},
// other keys below
},
});
As mentioned above, the theme
key is an options key within the Portal Options. This key is an object with keys that reference specific areas of the importer. Below you will see each key and how to work with it in more depth.
global
The global
key is a generic and easy-to-use key for giving a very general/global styling or even some defaults to then override in more specific keys. Some of these keys work very similarly to Portal Theme's predecessor, styleOverrides
. So if you previously used that, some of these will look familiar. The options available in the global
key are:
backgroundColor
- This will control the general background color of the importer. Note that this does not control the main manual input and review tables during the process, but those can now be controlled as well.textColor
- This sets a default text color for the importer. Much like with thebackgroundColor
setting, this does not apply to the manual input and review tables, but that too can be controlled in another setting below.primaryTextColor
- This will get slightly more specific than the previoustextColor
key.secondaryTextColor
- This too is a more specific styling that thetextColor
key.successColor
- This controls some specific UI elements like certain buttons, icons and some text.warningColor
- LikesuccessColor
, this controls some specific UI elements like certain buttons, icons and some text.fontFamily
- This allows for you to set the custom font within the theme. Please note that you must also import the fonts in the integrations setting
buttons
The buttons
key allows for control of the buttons within the importer. This key also allows for the use of the :hover
pseudo-class for styling buttons in a deeper manner. All buttons have the ability to use backgroundColor
, color
, padding
, border
, fontSize
, borderRadius
and ":hover"
. With these options in mind, there are a few different button options for styling as follows:
primary
- Controls the primary buttons within the importer.secondary
- Controls the secondary buttons within the importer.tertiary
- Controls the tertiary buttons within the importer.success
- Controls the success, confirm match, etc buttons that by default end up green.headerMatchYes
- Controls the 'Yes' button in the header matching screen.headerMatchNo
- Controls the 'No' button in the header matching screen.
As an example for these, and to keep the code cleaner and DRYer, the theme will reference the following button styling objects.
const primaryButton = {
backgroundColor: "#00c6ff",
color: "#002d3d",
border: "1px solid #00c6ff",
padding: "6px 16px",
fontSize: "15px",
borderRadius: "8px",
":hover": {
backgroundColor: "#0D93BA",
border: "1px solid #0D93BA",
},
};
const secondaryButton = {
backgroundColor: "transparent",
color: "#00c6ff",
border: "1px solid #00c6ff",
padding: "6px 16px",
fontSize: "15px",
borderRadius: "8px",
":hover": {
backgroundColor: "#00c6ff",
border: "1px solid #00c6ff",
color: "#002d3d",
},
};
const tertiaryButton = {
backgroundColor: "#DE781F",
color: "#002d3d",
border: "1px solid #002d3d",
padding: "6px 16px",
fontSize: "15px",
borderRadius: "8px",
":hover": {
backgroundColor: "transparent",
border: "1px solid #DE781F",
color: "#DE781F",
},
};
And here's what this might look like when being used.
theme: {
buttons: {
primary: primaryButton,
secondary: secondaryButton,
tertiary: tertiaryButton,
success: primaryButton,
headerMatchYes: {
...primaryButton,
padding: "6px 40px"
},
headerMatchNo: {
...secondaryButton,
padding: "6px 40px"
}
}
}
The remainder of the keys below will all use a root
option. This option will control the base styling of the area of the specific section. This will allow for control of backgroundColor
, border
, borderRadius
and padding
while the more specific options within each key will control fontWeight
, fontSize
and color
.
progressBar
The progressBar
allows for the styling of the progress indicator section (sometimes called breadcrumbs) in the top right that indicates which stage of the import process you have completed, are currently on and are still to come. Here are the options for this key:
root
- controls the base stylings for the section.current
- Controls the styling of the current step.complete
- Controls the styling of the completed steps.incomplete
- Controls the styling of the incomplete steps.
theme: {
progressBar: {
root: {
backgroundColor: "grey",
borderRadius: "4px",
border: "1px solid white",
padding: "20px"
},
current: {
color: "blue",
fontSize: "24px",
fontWeight: "600"
},
complete: {
color: "green"
},
incomplete: {
color: "yellow"
}
}
}
header
This key controls the styling for anything above the tables in the importer outside of specific items like the above progressBar
or dropzone
pieces which have their own styling. Here are the available options for use:
root
- Controls the base stylings for the section.title
- Controls the header title text in the upper left. This text will by default say "Bulk add" and whatever you set your importtype
to or will match the value provided in thetitle
configuration option.closeButton
- Controls the styling of the button to close the importer in the top right corner. This styling will allow for the same use of the":hover"
option in thebuttons
key above.
theme: {
header: {
root: {
backgroundColor: "#171a1d"
},
title: {
color: "white"
},
closeButton: {
color: "white",
":hover": {
color: "yellow"
}
}
}
}
footer
This key controls the root stylings of the bottom of the importer. The only option available to use here is the root
key.
root
- Controls the base stylings for the section.
theme: {
footer: {
root: {
backgroundColor: "#171a1d";
}
}
}
dropzone
This key allows for the control of the dropzone section that appears when the importer first opens. Note that the button inside this section is controlled by the buttons for the importer and not in this section. Here are the available options:
root
- Controls the base stylings for the section.content
- Controls the bubble that defaults with dotted lines. This section will use the same styling options asroot
but will control a different section of the dropzone.fileTypes
- Controls the styling for the content on the right paragraph.accepted
- Conrtols the styling for the content on the left paragraph.
theme: {
dropzone: {
root: {
backgroundColor: "#171a1d"
},
content: {
backgroundColor: "#171a1d",
border: "none",
borderRadius: "20px",
padding: "40px 60px"
},
fileTypes: {
border: "none",
color: "yellow"
},
accepted: {
color: "yellow"
}
}
}
manualInput
This key will control the styling for the manual input table that appears when the importer is initially loaded. Keep in mind that if diasbleManualInput: true
is in your settings, this key is unneccesary as this table will never display. Here are the available options:
root
- Controls the base stylings for the section.title
- Controls the base stylings and the text styling for the section right above the actual manual input table. By default, this section will say "...or just manually enter your data here:"table
- Controls the table elements with additional nested options for table specific elements such asth
,td
, etc.
theme: {
manualInput: {
root: {
padding: "20px"
},
title: {
margin: "0",
padding: "16px 30px",
backgroundColor: "#4c5057",
borderRadius: "20px 20px 0 0",
fontSize: "14px",
fontWeight: "400"
},
table: {
th: {
backgroundColor: "#2c3135",
color: "#6a7c87",
borderColor: "#2c3135"
},
td: {
color: "black"
}
}
}
}
headerMatch
This controls styling on the header matching phase of the import process. Here are the available keys:
root
- Controls the base stylings for the section.content
- Controls the text content of everything on the left side of this stage and anything not inside a table element.icon
- Controls the arrow icon fill color. Its only available option is thefill
key.table
- Controls the tables within this stage. It uses a very similar format to the above manual input table where its nested options are that of table elements such asth
,td
, etc.
theme: {
headerMatch: {
root: {
backgroundColor: "#171a1d"
},
content: {
fontSize: "14px"
},
icon: {
fill: "yellow"
},
table: {
th: {
backgroundColor: "#212327",
color: "#6a7c87",
borderColor: "#212327"
},
td: {
color: "black"
}
}
}
}
columnMatch
This key controls the elements in the column matching/mapping stage of the importer.
root
- Controls the base stylings for the entire section.content
- Controls the text color within the data preview part of the table (left side) and the background/base/root of each field's card.rule
- Controls the text color of the right side of each card.autoMatchRule
- This is a nested object that is associated only with field content on the right that informs the user a field has been matched. You can useroot
,field
,description
andicon
to control different aspect of the line that will tell you that the data in the card has been match to a certain field.
theme: {
columnMatch: {
root: {
backgroundColor: "orange"
},
content: {
backgroundColor: "white",
color: "blue"
},
rule: {
color: "red"
},
autoMatchRule: {
root: {
backgroundColor: "grey"
},
field: {
color: "purple"
},
description: {
color: "green"
},
icon: {
fill: "pink"
}
}
}
}
dialog
This key controls the styling of the dialog boxes that will pop up for confirmations and input from users during the import flow. The keys available for use are:
root
- Controls the base stylings for the section.content
- Controls the styling of content in the top part of the dialogs.footer
- Controls the styling of the content on the bottom of the dialogs.overlayColor
- Controls the color for the overlay around the dialogs.
theme: {
dialog: {
root: {
backgroundColor: "#2c3135",
borderRadius: "20px",
border: "none"
},
content: {
fontSize: "16px",
fontWeight: "500",
border: "none",
padding: "30px 30px 15px"
},
footer: {
backgroundColor: "orange",
border: "none",
padding: "15px 30px 30px"
},
overlayColor: "rgba(34,139,34,0.5)"
}
}
dataSource
When giving a datasource other than a csv file (xls for example) there is a dialogue that will go through the individual sheets and has its own flow. This key controls the styling for that dialogue. Here are the available options:
root
- Controls the base stylings for the section.title
- Controls the styling for the title of the dialog.subtitle
- Controls the styling for the subtitle for the dialogue (for xls this will say "select sheet").step
- Controls the styling for the steps/progress indicators for the dialog.footer
- Controls the footer section of the dialog.
theme: {
dataSource: {
root: {
color: "yellow"
},
title: {
fontSize: "17px",
textAlign: "left"
},
subtitle: {
fontSize: "15px",
textAlign: "left",
fontWeight: "400"
},
step: {
margin: "0",
padding: "0 0 0 16px"
},
footer: {
color: "yellow"
}
},
}
loader
When the importer is initially loading, there is a loading indicator that will appear. This key styles that indicator and its container.
root
- Controls the base stylings for the section.overlayColor
- Controls the color of the overlay that surrounds the dialog container.
theme: {
loader: {
root: {
backgroundColor: "#1B3D46",
color: "#c2c3c3"
},
overlayColor: "rgba(0,0,0,0.5)"
},
}
iterator
root
- Controls the base stylings for the section.overlayColor
- Controls the color of the overlay that surrounds the iterator.
theme: {
iterator: {
root: {
backgroundColor: "#1B3D46",
color: "#c2c3c3"
},
overlayColor: "rgba(0,0,0,0.5)"
}
}
Here is a full snippet of all of the pieces from above.
theme: {
global: {
backgroundColor: "#212327",
textColor: "#c2c3c3",
primaryTextColor: "#c2c3c3",
secondaryTextColor: "#c2c3c3",
successColor: "#c2c3c3",
warningColor: "#c2c3c3",
fontFamily: "font"
},
buttons: {
primary: primaryButton,
secondary: secondaryButton,
tertiary: tertiaryButton,
success: primaryButton,
headerMatchYes: {
...primaryButton,
padding: "6px 40px"
},
headerMatchNo: {
...secondaryButton,
padding: "6px 40px"
}
},
progressBar: {
root: {
backgroundColor: "grey",
borderRadius: "4px",
border: "1px solid white",
padding: "20px"
},
current: {
color: "blue",
fontSize: "24px",
fontWeight: "600"
},
complete: {
color: "green"
},
incomplete: {
color: "yellow"
}
},
header: {
root: {
backgroundColor: "#171a1d"
},
title: {
color: "white"
},
closeButton: {
color: "white",
":hover": {
color: "yellow"
}
}
},
footer: {
root: {
backgroundColor: "#171a1d"
}
},
dropzone: {
root: {
backgroundColor: "#171a1d"
},
content: {
backgroundColor: "#171a1d",
border: "none",
borderRadius: "20px",
padding: "40px 60px"
},
fileTypes: {
border: "none",
color: "yellow"
},
accepted: {
color: "yellow"
}
},
manualInput: {
root: {
padding: "20px"
},
title: {
margin: "0",
padding: "16px 30px",
backgroundColor: "#4c5057",
borderRadius: "20px 20px 0 0",
fontSize: "14px",
fontWeight: "400"
},
table: {
th: {
backgroundColor: "#2c3135",
color: "#6a7c87",
borderColor: "#2c3135"
},
td: {
color: "black"
}
}
},
headerMatch: {
root: {
backgroundColor: "#171a1d"
},
content: {
fontSize: "14px"
},
icon: {
fill: "yellow"
},
table: {
th: {
backgroundColor: "#212327",
color: "#6a7c87",
borderColor: "#212327"
},
td: {
color: "black"
}
}
},
columnMatch: {
root: {
backgroundColor: "orange"
},
content: {
backgroundColor: "white",
color: "blue"
},
rule: {
color: "red"
},
autoMatchRule: {
root: {
backgroundColor: "grey"
},
field: {
color: "purple"
},
description: {
color: "green"
},
icon: {
fill: "pink"
}
}
},
dialog: {
root: {
backgroundColor: "#2c3135",
borderRadius: "20px",
border: "none"
},
content: {
fontSize: "16px",
fontWeight: "500",
border: "none",
padding: "30px 30px 15px"
},
footer: {
backgroundColor: "orange",
border: "none",
padding: "15px 30px 30px"
},
overlayColor: "rgba(34,139,34,0.5)"
},
dataSource: {
root: {
color: "yellow"
},
title: {
fontSize: "17px",
textAlign: "left"
},
subtitle: {
fontSize: "15px",
textAlign: "left",
fontWeight: "400"
},
step: {
margin: "0",
padding: "0 0 0 16px"
},
footer: {
color: "yellow"
}
},
loader: {
root: {
backgroundColor: "#1B3D46",
color: "#c2c3c3"
},
overlayColor: "rgba(0,0,0,0.5)"
},
iterator: {
root: {
backgroundColor: "#1B3D46",
color: "#c2c3c3"
},
overlayColor: "rgba(0,0,0,0.5)"
}
}
Should I remove my styleOverrides if I plan to start using Portal Theming?
We recommend that if you want to use this newer Portal Theme that you should remove the styleOverrides
setting all together. While it technically won't hurt anything if you leave them in, if you use both settings, anything in styleOverrides
will be ignored/disabled. This means that even if you aren't technically overriding some of the same pieces of the importer, the default styles would be in place over what you have in the styleOverrides
setting.