Skip to main content
/
/
/
/
Upgrade to Bifrost 4.0

Upgrade to Bifrost 4.0

This migration guide should help you upgrade @intility/bifrost-react from 3.x to 4.x. If you're currently on 2.x (or older) please see upgrade to 3 first.

React component changes

Select

Updated <Select> docs

The <Select> component has been moved to a new package. If you need it, install the package:

npm install @intility/bifrost-react-select
npm install @intility/bifrost-react-select

and update your imports:

// old import { Select } from "@intility/bifrost-react"; // removed in 4.0 // new import Select from "@intility/bifrost-react-select";
// old import { Select } from "@intility/bifrost-react"; // removed in 4.0 // new import Select from "@intility/bifrost-react-select";

DatePicker

Updated <DatePicker> docs

The <DatePicker> component has been moved to a new package. If you need it, install the package:

npm install @intility/bifrost-react-datepicker
npm install @intility/bifrost-react-datepicker

Then import the CSS (once, globally in your app):

import "@intility/bifrost-react-datepicker/datepicker.css";
import "@intility/bifrost-react-datepicker/datepicker.css";

and update your imports (in each file you use the DatePicker):

// old import { DatePicker } from "@intility/bifrost-react"; // removed in 4.0 // new import DatePicker from "@intility/bifrost-react-datepicker";
// old import { DatePicker } from "@intility/bifrost-react"; // removed in 4.0 // new import DatePicker from "@intility/bifrost-react-datepicker";

We've rewritten our <Modal> component from scratch, and no longer rely on the react-modal dependency.

Removed Modal.Footer

As part of the cleanup, <Modal.Footer> has been removed. You can get a similar result using the new <Inline> component. Depending on your layout and css you may need to adjust some spacing.

// old <Modal.Footer> <Button>Right-aligned button</Button> </Modal.Footer> // new <Inline> <Inline.Separator /> <Button>Right-aligned button</Button> </Inline>
// old <Modal.Footer> <Button>Right-aligned button</Button> </Modal.Footer> // new <Inline> <Inline.Separator /> <Button>Right-aligned button</Button> </Inline>

Removed props

  • noHeader removed since header is now optional
  • fromBottom removed (use a <Drawer>)
  • icon removed (use an <Icon>)
  • overlayClassName removed (className now applies to outermost element)
  • center removed since modal is no longer rendered fullscreen for mobile

In addition, all of the props previously forwarded to react-modal will no longer work, please contact us if you're missing some functionality.

new noCloseOnOverlayClick and noCloseOnEsc props

// old <Modal shouldCloseOnOverlayClick={false} shouldCloseOnEsc={false} /> // new <Modal noCloseOnOverlayClick noCloseOnEsc />
// old <Modal shouldCloseOnOverlayClick={false} shouldCloseOnEsc={false} /> // new <Modal noCloseOnOverlayClick noCloseOnEsc />

fromBottom moved to Drawer

The fromBottom prop has been removed from <Modal>, instead you can use <Drawer position='bottom'>:

// old <Modal fromBottom /> // new <Drawer position='bottom' />
// old <Modal fromBottom /> // new <Drawer position='bottom' />

No Modal.setAppElement

Since we now use the browser-native <dialog> element under the hood, it's accessible out of the box and if you previously used the setAppElement method you can safely remove it:

// just remove this line, if you have it present in your app Modal.setAppElement(rootElement);
// just remove this line, if you have it present in your app Modal.setAppElement(rootElement);

Overflow

If you have content that might overflow the <Modal> container (like a <Select>), the new Modal might create an unwanted scrollbar. See the overflow section in the Modal docs for solutions. This should be fixed in latest versions of select and datepicker packages.

SlideDown

We've rewritten our <SlideDown> component from scratch, and no longer rely on the react-animate-height dependency.

No code changes should be needed, unless:

  1. you rely on one of the props provided by the react-animate-height from the old implementation (if so, install and use that instead).
// closedHeight prop removed in 4.0 import { SlideDown } from "@intility/bifrost-react"; <SlideDown open={booleanState} closedHeight={26} />; // instead, you can use AnimateHeight directly instead import AnimateHeight from "react-animate-height"; <AnimateHeight height={booleanState ? "auto" : 26} />;
// closedHeight prop removed in 4.0 import { SlideDown } from "@intility/bifrost-react"; <SlideDown open={booleanState} closedHeight={26} />; // instead, you can use AnimateHeight directly instead import AnimateHeight from "react-animate-height"; <AnimateHeight height={booleanState ? "auto" : 26} />;
  1. you have some padding directly on the <SlideDown> element, move the padding to a child element instead:
// old <SlideDown open={booleanState} style={{ padding: "16px" }}> <p>Will not be hidden properly :(</p> </SlideDown> // new <SlideDown open={booleanState}> <div style={{ padding: "16px" }}> <p>Ahh, that's much better</p> </div> </SlideDown>
// old <SlideDown open={booleanState} style={{ padding: "16px" }}> <p>Will not be hidden properly :(</p> </SlideDown> // new <SlideDown open={booleanState}> <div style={{ padding: "16px" }}> <p>Ahh, that's much better</p> </div> </SlideDown>

Button

The default value for the type prop is now "button" (previously "submit").

If the <Button> is not part of a <form>, this change should not affect you, and for most cases this is the desired behavior.

However, if you're using a bifrost <Button> inside a <form> (listening to the onSubmit event), and want it to submit the form, you now need to explicitly set <Button type="submit">:

// old <form onSubmit={handleSubmit}> <Button>Will no longer submit the form</Button> </form> // new <form onSubmit={handleSubmit}> <Button type="submit">Submit the form</Button> </form>
// old <form onSubmit={handleSubmit}> <Button>Will no longer submit the form</Button> </form> // new <form onSubmit={handleSubmit}> <Button type="submit">Submit the form</Button> </form>

Breakpoint

We generally recommend using breakpoint css classes instead of this component, but if you are using it, it should still work, but 4.0 introduces a <div> wrapper , so make sure it still looks right in your app.

If your design doesn't work with the extra element (for instance in a css grid), use the CSS classes instead.

// old <Breakpoint from="small"> <div>my grid item</div> </Breakpoint> // new <div className="from-small">my grid item</div>
// old <Breakpoint from="small"> <div>my grid item</div> </Breakpoint> // new <div className="from-small">my grid item</div>

Accordion

Restyled slightly, state indicator icon now placed to the left for variant="styled".

This should work fine in 99% of cases, but if you've got some custom CSS it might not work the same any more (try removing your custom CSS and see if it looks better without).

Bifrost

Removed the onThemeChange prop and deprecated theme. We recommend you don't use this component to control the color mode, and if you need to force a color mode, simply set a class on the root <html> element.

Color mode picker

Color mode picker example

The hideTheme prop has been removed since <Nav> no longer renders a color mode picker.

Collapsible sidebar

Collapsible sidebar

Sidebar is no longer collapsible by default. Pass your own state to sideProps.

Input

Updated <Input> docs

All form inputs have been restyled to "outline" styling, therefore we have removed variant prop from <Input> (since all it did was apply outline styling).

Checkbox and CheckboxCard

The internal DOM structure and CSS for our <Checkbox> and <CheckboxCard> components have been quite convoluted since the styling relied on the <input> state, and without :has() it's been impossible to write CSS selectors that target parent (or previous sibling) elements.

The browser support is now good enough that we've been able to simplify our CSS and DOM structure for checkboxes, and removed the need for us to generate an id internally.

The design and usage should stay the same, but if you have any customized checkbox styling, there could be unforeseen side-effects.

Package changes

Components are updated to work with React Server Components out of the box.

We've restructured our internal folder structure and modernized the package.json.

ES module only

We've dropped support for CommonJS (require()), always use ES module (import or import()) syntax instead.

Deep imports

Deep import paths should be significantly simpler now:

// old import Nav from "@intility/bifrost-react/dist/navigation/Nav"; import Accordion from "@intility/bifrost-react/dist/interactive/Accordion"; import "@intility/bifrost-react/dist/bifrost-app.css"; // new import Nav from "@intility/bifrost-react/Nav"; import Accordion from "@intility/bifrost-react/Accordion"; import "@intility/bifrost-react/bifrost-app.css";
// old import Nav from "@intility/bifrost-react/dist/navigation/Nav"; import Accordion from "@intility/bifrost-react/dist/interactive/Accordion"; import "@intility/bifrost-react/dist/bifrost-app.css"; // new import Nav from "@intility/bifrost-react/Nav"; import Accordion from "@intility/bifrost-react/Accordion"; import "@intility/bifrost-react/bifrost-app.css";

Replaced icons

All previously bundled icons have been removed, and replaced with free alternatives or custom equivalents. For the most part it shouldn't matter much, but if you use <Message> for instance, you may prefer to use font awesome pro icons over the new default icons (font awesome solid).

import { faCircleInfo } from '@fortawesome/pro-regular-svg-icons' <Message icon={faCircleInfo} ... />
import { faCircleInfo } from '@fortawesome/pro-regular-svg-icons' <Message icon={faCircleInfo} ... />

Typography margins removed

Figma designs usually have no margins on elements like headings, paragraphs and lists, instead using gap inside autolayout (roughly equivalent to grid or flexbox in CSS), resulting in developers needing to manually remove the bifrost-applied margins with bifrost 3.x.

To make it easier to implement new designs going forward, we have removed the margin from the following CSS classes in 4.x:

// old <h4 className="bf-h4" style={{margin: 0}}>Heading without margin</h4> // new <h4 className="bf-h4">Heading without margin</h4>
// old <h4 className="bf-h4" style={{margin: 0}}>Heading without margin</h4> // new <h4 className="bf-h4">Heading without margin</h4>

.bf-content mostly unchanged

Since the .bf-content is meant for using on a wrapper around html content you don't control, it will still apply margins as it always has.

We have, however, lowered the specificity for selectors, so it should be easier to override the bifrost styling with your custom CSS.

New .bf-elements wrapper

Since it gets tiresome to apply the classnames to all headings etc, you can use the new .bf-elements which does the same as .bf-content but without the margins!

// old <div className="bf-content"> <h4 style={{margin: 0}}>Heading without margin</h4> </div> // new <div className="bf-elements"> <h4>Heading without margin</h4> </div>
// old <div className="bf-content"> <h4 style={{margin: 0}}>Heading without margin</h4> </div> // new <div className="bf-elements"> <h4>Heading without margin</h4> </div>

Re-apply margin

If you want to keep the margin on a heading (or paragraph etc.) you can either use the .bf-content class, or apply a margin yourself.

// old <h4 className="bf-h4">Heading with margin</h4> // new <h4 className="bf-h4" style={{ marginBlock: '1rem' }}>Heading with margin</h4> // or <div className="bf-content"> <h4>Heading with margin</h4> </div>
// old <h4 className="bf-h4">Heading with margin</h4> // new <h4 className="bf-h4" style={{ marginBlock: '1rem' }}>Heading with margin</h4> // or <div className="bf-content"> <h4>Heading with margin</h4> </div>

Deprecated

useTheme hook

Deprecated the useTheme() hook, and its setTheme method has been removed. Prefer to set classes on root element instead.

dateFormat and timeFormat functions

The dateFormat() and timeFormat() functions have proven to be troublesome when hydrating since server might format differently (server in different timezone than client, for instance), and will probably be removed in a future version.

Instead, we are introducing a new useDateTimeFormatter() hook that will respect current bifrost locale.

// old import { dateFormat } from "@intility/bifrost-react"; function MyComponent() { return "Date is " + dateFormat(new Date()); } // new import useDateTimeFormatter from "@intility/bifrost-react/hooks/useDateTimeFormatter"; function MyComponent() { const dateTimeFormatter = useDateTimeFormatter(); return "Date is " + dateTimeFormatter({ date: new Date(), show: "date" }); }
// old import { dateFormat } from "@intility/bifrost-react"; function MyComponent() { return "Date is " + dateFormat(new Date()); } // new import useDateTimeFormatter from "@intility/bifrost-react/hooks/useDateTimeFormatter"; function MyComponent() { const dateTimeFormatter = useDateTimeFormatter(); return "Date is " + dateTimeFormatter({ date: new Date(), show: "date" }); }

Button icon prop

The icon and rightIcon props for <Button> have been deprecated. Use a nested <Icon> instead:

// old <Button icon={faHome}>Left icon</Button> <Button icon={faHome} rightIcon>Right icon</Button> // new <Button><Icon icon={faHome} /> Left icon</Button> <Button>Right icon <Icon icon={faHome} /></Button>
// old <Button icon={faHome}>Left icon</Button> <Button icon={faHome} rightIcon>Right icon</Button> // new <Button><Icon icon={faHome} /> Left icon</Button> <Button>Right icon <Icon icon={faHome} /></Button>

Depending on your design, you might find the marginLeft/marginRight props on <Icon> useful to get the positioning just right.

Border radius

Bifrost 4.0 introduces new standard values for border-radius

bfl CSS prefix

Almost all bifrost class names and CSS variable names are prefixed with bf-, with a few exceptions:

  • bfc-* for colors
  • bfs* for spacing
  • bfl-* for layout

What constitutes "layout" can be confusing, so we're planning on dropping bfl-* in a future release, and started deprecating some variables and classes in 4.0:

Old nameNew name
bfl-borderbf-border
--bfl-border--bf-border
bfl-paddingbf-padding
--bfl-box-padding--bf-box-padding
bfl-page-paddingbf-page-padding
--bfl-page-padding--bf-page-padding
bfl-autocolbf-autocol
--bfl-autocol-width--bf-autocol-width
--bfl-autocol-gap--bf-autocol-gap