Migrating from Fannypack#

If you are migrating from Fannypack, there are quite a few notable breaking changes. This guide aims to help you migrate to Bumbag. If you feel like there is anything missing from this guide, feel free to raise a pull request.

Upgrading incrementally#

It's recommended to upgrade to Bumbag incrementally, meaning that Fannypack and Bumbag will co-exist until Bumbag takes over.

If you wish to upgrade incrementally, you can install the bumbag package:

npm install bumbag

And then, set up Bumbag in your app base:

// Bumbag
import { Provider as BumbagProvider } from 'bumbag';
// Fannypack
import { ThemeProvider } from 'fannypack';
const oldTheme = { ... };
const newTheme = { ... };
const App = () => (
<ThemeProvider theme={oldTheme}>
<BumbagProvider theme={newTheme}>
Hello world!
</BumbagProvider>
</ThemeProvider>
);

Then you can start incrementally migrating your components like so:

- import { Box } from 'fannypack';
+ import { Box } from 'bumbag';
import { Button } from 'fannypack';
function Example() {
return (
<Box>
<Button>Hello world!</Button>
</Box>
)
}

Breaking changes#

General: ThemeProvider to Provider#

We have renamed the <ThemeProvider> component to <Provider>.

See more...

v4
import { ThemeProvider } from 'fannypack';
const App = () => (
<ThemeProvider>
Hello world!
</ThemeProvider>
);
v5
import { Provider } from 'bumbag';
const App = () => (
<Provider>
Hello world!
</Provider>
);

Theming: .base to .styles.base#

We have renamed the base attribute in the global theme to styles.base.

v4
const theme = {
Box: {
base: {
backgroundColor: 'red'
}
}
}
v5
const theme = {
Box: {
styles: {
base: {
backgroundColor: 'red'
}
}
}
}

See more...

Theming: No more support for inline functions in the css attribute.#

We have removed support for inline functions within the css attribute. You will now have to retrieve props by converting the attribute to a function.

v4
const theme = {
Box: {
base: css`
color: ${palette('primary')};
${props => props.error && css`
background-color: red;
`}
`
}
}
v5
const theme = {
Box: {
styles: {
base: props => css`
color: ${palette('primary')(props)};
${props.error && css`
background-color: red;
`}
`
}
}
}

Theming: layout.<viewport>Breakpoint to breakpoints.<viewport>#

We have moved where breakpoints are defined in the global theme.

v4

In v4, they were placed under the layout attribute.

const theme = {
layout: {
mobileBreakpoint: 480,
tabletBreakpoint: 768,
desktopBreakpoint: 1024,
widescreenBreakpoint: 1200,
fullHDBreakpoint: 1440,
}
};
v5

Now they are placed under a dedicated breakpoints attribute.

const theme = {
breakpoints: {
mobile: 480,
tablet: 768,
desktop: 1024,
widescreen: 1200,
fullHD: 1440
}
};

See more...

Theming: layout.gapFactor to Columns.defaultProps.spacing#

The gapFactor attribute was only used for the Columns component. So we renamed it to a spacing prop to put on the Columns component.

v4
const theme = {
layout: {
gapFactor: '1rem'
}
};
v5
const theme = {
Columns: {
defaultProps: {
spacing: 'major-2'
}
}
};

Theming: layout.<minor|major>Unit to spacing.<minor|major>Unit#

The layout.minorUnit and layout.majorUnit attributes are renamed to spacing.minorUnit and spacing.majorUnit

v4
const theme = {
layout: {
minorUnit: 4,
majorUnit: 8
}
};
v5
const theme = {
spacing: {
minorUnit: 4,
majorUnit: 8
}
};

Theming: global.fontFamily to fonts.default#

We have moved the global.fontFamily attribute to fonts.default

v4
const theme = {
global: {
fontFamily: "'Lato', system-ui, sans-serif"
}
}
v5
const theme = {
fonts: {
default: "'Lato', system-ui, sans-serif"
}
}

Theming: Removed webFontLoader#

Web Font Loader was removed in favour of direct Google Font imports with font swapping.

v4

Previously, web font loader was used to import Google Fonts.

const theme = {
global: {
fontFamily: "'Lato', system-ui, sans-serif",
fallbackFontFamily: "system-ui, sans-serif"
},
webFontLoader: {
google: {
families: ['Lato:400,700,900']
}
}
}
v5

Now, you import the font(s) directly from Google Fonts.

Click here to see a list of Google Fonts

const theme = {
fonts: {
importUrls: ['https://fonts.googleapis.com/css2?family=Lato:wght@400;700;900&display=swap'],
default: "'Lato', system-ui, sans-serif"
}
}

Box: hiddenBreakpoint to <Hide>#

The hiddenBreakpoint prop on components has been converted to a <Hide> component.

v4
<Box hiddenBreakpoint="tablet">Hidden below tablet</Box>
v5
<Hide below="tablet">Hidden below tablet</Hide>

Box: showBreakpoint to <Show>#

The showBreakpoint prop on components has been converted to a <Show> component.

v4
<Box showBreakpoint="tablet">Shown above tablet</Box>
v5
<Show above="tablet">Shown above tablet</Show>

LayoutSet: LayoutSet to Stack#

The LayoutSet component has been renamed to Stack.

<LayoutSet>
<Box>Evenly</Box>
<Box>Spaced</Box>
<Box>Components</Box>
</LayoutSet>
v5
<Stack>
<Box>Evenly</Box>
<Box>Spaced</Box>
<Box>Components</Box>
</Stack>

Pane: Removed <Pane>#

We have removed Pane in v5.

If you still want borders, then use the border attribute on box.

If you still want shadow, then use the altitude attribute on box.

If you still want border radius, then use the borderRadius attribute on box.

v4
<Pane border="shadow">Hello world</Pane>
v5
<Box altitude="100" borderRadius="default">Hello world</Box>

Alert: Removed hasTint#

We have removed the hasTint prop on the Alert component in favour of variant.

v4
<Alert hasTint type="danger">Hello world</Alert>
v5
<Alert variant="tint" type="danger">Hello world</Alert>

Avatar: kind to variant#

We have renamed the kind prop to variant

v4
<Avatar kind="circle">
v5
<Avatar variant="circle">

Badge: isAbsolute to isAttached#

v4
<Badge isAbsolute>1</Badge>
v5
<Badge isAttached>1</Badge>

Breadcrumb: Breadcrumb.Step to Breadcrumb.Item#

The Breadcrumb.Step component was renamed to Breadcrumb.Item.

If you have been using links in your breadcrumbs, you will also have to create separate Breadcrumb.Link components.

v4
<Breadcrumb>
<Breadcrumb.Step href="#">Home</Breadcrumb.Step>
<Breadcrumb.Step href="#">Business</Breadcrumb.Step>
<Breadcrumb.Step href="#" isCurrent>Staff members</Breadcrumb.Step>
</Breadcrumb>
v5
<Breadcrumb>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Business</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Item isCurrent>
<Breadcrumb.Link href="#">Staff Members</Breadcrumb.Link>
</Breadcrumb.Item>
</Breadcrumb>

Button: kind to variant#

The kind prop has been renamed to variant.

v4
<Button kind="outlined" palette="primary">Hello world</Button>
v5
<Button variant="outlined" palette="primary">Hello world</Button>

Button Theme: Removed Button.interactive#

The Button.interactive theme key has been removed in favour of pseudo based keys.

v4
const theme = {
Button: {
interactive: css`
&:focus {
...
}
&:hover {
...
}
&:hover:active {
...
}
`
}
}
v5
const theme = {
Button: {
focus: css`
...
`,
hover: css`
...
`,
hoveractive: css`
...
`
}
}

CalloutOverlay: Removed CalloutOverlay#

Removed CalloutOverlay in favor of Callout.Overlay and the Overlay utility.

v4
<Overlay.Container>
{overlay => (
<Box>
<Button use={Overlay.Toggle} {...overlay}>
Click me
</Button>
<CalloutOverlay
title="This is a title"
{...overlay}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, ultrices
eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur lectus
augue sit amet justo.
</CalloutOverlay>
</Box>
)}
</Overlay.Container>
v5
<Overlay.State>
<Overlay.Disclosure use={Button}>Open callout</Overlay.Disclosure>
<Callout.Overlay title="This is a title">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, ultrices
eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur lectus
augue sit amet justo.
</Callout.Overlay>
</Overlay.State>

Card: elevation to altitude#

The elevation prop has been renamed to altitude.

v4
<Card elevation="100">
v5
<Card altitude="100">

Card: headerActions to headerAddon#

The headerActions prop has been renamed to headerAddon.

v4
<Card headerActions={...}>
v5
<Card headerAddon={...}>

HighlightedCode: Moved to bumbag-addon-highlighted-code#

We have moved the HighlightedCode component to bumbag-addon-highlighted-code to save some bundle size.

v4
import { HighlightedCode } from 'fannypack';
v5
// First, install the package
npm install bumbag-addon-highlighted-code
// Then, import it accordingly
import { HighlightedCode } from 'bumbag-addon-highlighted-code';

Column: Moved to Columns.Column#

We have moved the Column component to a sub-component of Columns.

v4
<Column>
v5
<Columns.Column>

DialogModal: Removed DialogModal#

Removed DialogModal in favor of Dialog.Modal and the Modal utility.

v4
<Modal.Container>
{modal => (
<Box>
<Button use={Modal.Show} {...modal}>
Click me
</Button>
<DialogModal {...modal}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue,
ultrices eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum
consectetur lectus augue sit amet justo.
</DialogModal>
</Box>
)}
</Modal.Container>
v5
<Modal.State>
<Modal.Disclosure use={Button}>Open dialog</Modal.Disclosure>
<Dialog.Modal title="This is a title">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, ultrices
eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur lectus
augue sit amet justo.
</Dialog.Modal>
</Modal.State>

Divider: Removed content#

We have removed the content prop on Divider.

Divider: isVertical to orientation#

We have repurposed the isVertical prop to orientation.

v4
<Divider isVertical />
v5
<Divider orientation="vertical" />

FieldSet: Renamed to FieldStack#

v4
<FieldSet>
v5
<FieldStack>

FieldSet: isHorizontal to orientation#

v4
<FieldSet isHorizontal />
v5
<FieldStack orientation="horizontal" />

FieldWrapper: tooltipTrigger to tooltipTriggerComponent#

We have renamed the tooltipTrigger prop to tooltipTriggerComponent

v4
<FieldWrapper tooltipTrigger={<Button size="small">Tooltip</Button>} />
v5
<FieldWrapper tooltipTriggerComponent={<Button size="small">Tooltip</Button>} />

Group: isVertical to orientation#

We have renamed the isVertical prop to orientation.

v4
<Group isVertical />
v5
<Group orientation="vertical" />

Group: verticalAt to verticalBelow#

We have renamed the verticalAt prop to verticalBelow.

v4
<Group verticalAt="desktop" />
v5
<Group verticalBelow="desktop" />

Hidden: Removed Hidden#

We have removed the Hidden utility in favour of the Disclosure utility.

v4
<Hidden.Container>
{hidden => (
<Box>
<Button use={Hidden.Toggle} {...hidden}>Toggle</Button>
<Hidden {...hidden}>
Hello world
</Hidden>
</Box>
)}
</Hidden.Container>
v5
<Disclosure.State>
<Disclosure>Toggle</Disclosure>
<Disclosure.Content>Hello world</Disclosure.Content>
</Disclosure.State>

Icon: size to fontSize#

The size prop has been renamed to fontSize.

v4
<Icon size="400">
v5
<Icon fontSize="400">

List: isVertical to orientation#

We have renamed the isVertical prop to orientation.

v4
<List isVertical>
v5
<List orientation="vertical">

Markdown: Moved to bumbag-addon-markdown#

We have moved the Markdown component to bumbag-addon-markdown to save some bundle size.

v4
import { Markdown } from 'fannypack';
v5
// First, install the package
npm install bumbag-addon-markdown
// Then, import it accordingly
import { Markdown } from 'bumbag-addon-markdown';

Modal: Modal.Container to Modal.State#

We have repurposed the Modal.Container utility to Modal.State.

v4
<Modal.Container>
{({ isVisible, show, hide, toggle, ... })} => (...)
</Modal.Container>
v5
<Modal.State>
{({ visible, show, hide, toggle, ... })} => (...)
</Modal.State>

Overlay: Overlay.Container to Overlay.State#

We have repurposed the Overlay.Container utility to Overlay.State.

v4
<Overlay.Container>
{({ isVisible, show, hide, toggle, ... })} => (...)
</Overlay.Container>
v5
<Overlay.State>
{({ visible, show, hide, toggle, ... })} => (...)
</Overlay.State>

PageContent: Page.Content to PageContent#

We have renamed the Page.Content component to PageContent.

v4
<Page.Content>
v5
<PageContent>

PageWithSidebar: Page.WithSidebar to PageWithSidebar#

We have renamed the Page.WithSidebar component to PageWithSidebar.

v4
<Page.WithSidebar>
v5
<PageWithSidebar>

PageWithSidebar: sidebarContent to sidebar#

v4
<Page.WithSidebar sidebarContent={...}>
v5
<PageWithSidebar sidebar={...}>

Popover: Popover to Popover.State & Popover#

We have repurposed the Popover component to use Popover.State along with a Popover.Disclosure component.

The Popover component no longer handles it's state internally.

v4
<Popover content={<Text>What was the best thing that happened to you today?</Text>}>
<Button>Open Popover</Button>
</Popover>
v5
<Popover.State>
<Popover.Disclosure use={Button}>Open Popover</Popover.Disclosure>
<Popover>
What was the best thing that happened to you today?
</Popover>
</Popover.State>

Rating: maxRating to maxValue#

We have renamed the maxRating prop to maxValue.

v4
<Rating maxRating={10}>
v5
<Rating maxValue={10}>

Rating: onRate to onChange#

We have renamed the onRate prop to onChange.

v4
<Rating onRate={() => {}}>
v5
<Rating onChange={() => {}}>

SelectMenu: useTags to hasTags#

We have renamed the useTags prop to hasTags.

v4
<SelectMenu useTags>
v5
<SelectMenu hasTags>

SelectMenu: loadQuery to loadVariables#

v4
<SelectMenu loadQuery={{ key: 'value' }}>
v5
<SelectMenu loadVariables={{ key: 'value' }}>

SelectMenu: data to variables#

Inside the loadOptions prop, the data attribute has been renamed to variables.

v4
<SelectMenu loadOptions={({ searchText, page, data }) => ...}>
v5
<SelectMenu loadOptions={({ searchText, page, variables }) => ...}>

SelectMenu: isSearchable to hasSearch#

The isSearchable prop has been renamed to hasSearch.

v4
<SelectMenu isSearchable>
v5
<SelectMenu hasSearch>

Set: isVertical to orientation#

The isVertical prop has been renamed to orientation.

v4
<Set isVertical>
v5
<Set orientation="vertical">

Sidebar: Sidebar to Drawer#

The Sidebar utility has been renamed to Drawer.

Sidebar.Container has also been renamed to Drawer.State.

v4
<Sidebar.Container>
{sidebar => (
<Box>
<Button use={Sidebar.Show} {...sidebar}>
Toggle
</Button>
<Sidebar {...sidebar}>
This is a side drawer
</Sidebar>
</Box>
)}
</Sidebar.Container>
v5
<Drawer.State>
<Drawer.Disclosure>Toggle</Drawer.Disclosure>
<Drawer>
This is a side drawer
</Drawer>
</Drawer.State>

Tabs: Tabs.Container to Tabs#

The Tabs.Container component has been repurposed to Tabs.

v4
<Tabs.Container>
{tabs => (
...
)}
</Tabs.Container>
v5
<Tabs>
...
</Tabs>

Tabs: Tabs to Tabs.List#

v4
<Tabs.Container>
{tabs => (
<Tabs>
<Tabs.Tab tab="dogs" {...tabs}>
Dogs
</Tabs.Tab>
<Tabs.Tab tab="cats" {...tabs}>
Cats
</Tabs.Tab>
<Tabs.Tab tab="parrots" {...tabs}>
Parrots
</Tabs.Tab>
</Tabs>
)}
</Tabs.Container>
v5
<Tabs selectedId="tab1">
<Tabs.List>
<Tabs.Tab tabId="tab1">Dogs</Tabs.Tab>
<Tabs.Tab tabId="tab2">Cats</Tabs.Tab>
<Tabs.Tab tabId="tab3">Parrots</Tabs.Tab>
</Tabs.List>
</Tabs>

Tabs: type to variant#

The type prop has been renamed to variant

v4
<Tabs type="boxed">
v5
<Tabs.List variant="boxed">

Tabs.Panel: tab to tabId#

The tab prop has been renamed to tabId

v4
<Tabs.Panel tab="cats">
v5
<Tabs.Panel tabId="cats">

Tabs.Tab: tab to tabId#

The tab prop has been renamed to tabId

v4
<Tabs.Tab tab="cats">
v5
<Tabs.Tab tabId="cats">

Tag: kind to variant#

The kind prop has been renamed to variant

v4
<Tag variant="outlined">
v5
<Tag variant="outlined">

Toast: Now requires a ToastManager#

The Toast component now requires a ToastManager to render the toasts.

import { Provider, ToastManager } from 'bumbag';
const App = () => (
<Provider theme={theme}>
// ... your app
<ToastManager />
</Provider>
);

Toast: Toast.Container & withToasts to useToasts#

v4
<Toast.Container>
{toasts => (
<Button
onClick={() => toasts.success({ title: 'Message sent' })}
>
Add toast
</Button>
)}
</Toast.Container>
v5
function Example() {
const toasts = useToasts();
return (
<Button
onClick={() => toasts.success({ title: 'Message sent' })}
>
Add toast
</Button>
)
}

Tooltip: Now wraps over children#

The Tooltip component now wraps over it's children.

v4
<Button>
Hover on me
<Tooltip>Hello world!</Tooltip>
</Button>
v5
<Tooltip content="Hello world">
<Button>Hover on me</Button>
</Tooltip>
On this page
Copyright © 2021 Jake Moxey