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:
// Bumbagimport { Provider as BumbagProvider } from 'bumbag';// Fannypackimport { 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>
.
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'}}}}
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}};
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><CalloutOverlaytitle="This is a title"{...overlay}>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, ultriceseget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur lectusaugue 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, ultriceseget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur lectusaugue 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 packagenpm install bumbag-addon-highlighted-code// Then, import it accordinglyimport { 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, vestibulumconsectetur 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, ultriceseget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur lectusaugue 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 packagenpm install bumbag-addon-markdown// Then, import it accordinglyimport { 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 => (<ButtononClick={() => toasts.success({ title: 'Message sent' })}>Add toast</Button>)}</Toast.Container>
v5
function Example() {const toasts = useToasts();return (<ButtononClick={() => 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>