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
<Select>
docsThe <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
<DatePicker>
docsThe <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";
Modal
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 sinceheader
is now optionalfromBottom
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:
- 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} />;
- 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
<Breakpoint>
docsWe 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
<Bifrost>
docsRemoved 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.
Nav
Color mode picker
Color mode picker example
The hideTheme
prop has been removed since <Nav>
no longer renders a color
mode picker.
Collapsible sidebar
Sidebar is no longer collapsible by default. Pass your own state to sideProps
.
Input
<Input>
docsAll 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" });
}
useDateTimeFormatter()
hook<FormatDate>
componentButton 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
- New CSS Variables
--bf-radius-none
= 0px--bf-radius-xs
= 4px--bf-radius-s
= 8px--bf-radius
or--bf-radius-m
= 12px--bf-radius-l
= 16px--bf-radius-xl
= 24px--bf-radius-full
= 9999px
- New Corresponding CSS helper classes
.bf-radius-xs
applies 4pxborder-radius
.bf-radius-s
applies 8pxborder-radius
.bf-radius
or.bf-radius-m
applies 12pxborder-radius
.bf-radius-l
applies 16pxborder-radius
.bf-radius-xl
applies 24pxborder-radius
.bf-radius-full
applies 9999pxborder-radius
- Old border radius classes and variable
- Deprecated
--bfl-border-radius
(use--bf-radius-xs
instead) - Deprecated
.bfl-border-radius
and.bf-border-radius
(use.bf-radius-xs
instead)
- Deprecated
bfl
CSS prefix
Almost all bifrost class names and CSS variable names are prefixed with bf-
,
with a few exceptions:
bfc-*
for colorsbfs*
for spacingbfl-*
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 name | New name |
---|---|
bfl-border | bf-border |
--bfl-border | --bf-border |
bfl-padding | bf-padding |
--bfl-box-padding | --bf-box-padding |
bfl-page-padding | bf-page-padding |
--bfl-page-padding | --bf-page-padding |
bfl-autocol | bf-autocol |
--bfl-autocol-width | --bf-autocol-width |
--bfl-autocol-gap | --bf-autocol-gap |