#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>

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';

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">

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>
Copyright © 2020 Jake Moxey