#ClimateEmergency

Migration Guide

Migrate to v2.85.0

Separator compact

DEPRECATED Separator’s compact prop, displaying a Separator in its compact form will become the default in an upcoming major GDS version. To future-proof things, i.e. to avoid having no spacing before and after the separator line, the newly added spacing prop can and should already be set on all Separators that have no compact prop.

There are two possible values for the spacing prop. First and foremost, REGULAR will add a 6px margin before and after the Separator. However, when Separator is used to create a divider line inside a Card or Modal, we want to INHERIT the spacing from whatever is set on the Card or Modal. Doing results in 10px in a Card with medium padding, 32px in Card with large padding, and 16px inside a Modal.

So the migration strategy depends on where and how Separator is used. Given that the aforementioned Card/Modal divider line is an ability that has only been added recently, it is safe to assume that REGULAR spacing will be needed in almost all cases. A notable exception is the protrude prop that has also been added only recently: When protrude is set and compact isn’t, a Separator’s spacing should most definitely be INHERIT.

jsx// old: compact not set (or set to false)
<Separator />

// new (most cases): 6px spacing
<Separator spacing={Separator.SPACING.REGULAR} />
// new (exception): 10px/32px/16px spacing
<Separator spacing={Separator.SPACING.INHERIT} />

Contrary, wherever compact is set, there is no need to future-proof things, but at the same time no change is possible, so for now the prop needs to be kept.

jsx// old: compact is true
<Separator compact />

// new: same as before, DO NOT CHANGE
<Separator compact />

Migrate to v2.74.0

Using old Button in DropdownToggle has been deprecated. This has several aspects.

  • useNewButton prop should be set to true for now, until it is removed altogether.
  • color prop should not be used anymore. Use variant instead.
  • size prop should no longer be set to SIZE.LARGE. The NewButton supports SMALL and MEDIUM sizes and so will the DropdownToggle.
jsx// old
<DropdownToggle
  color={DropdownToggle.COLOR.PRIMARY}
  size={DropdownToggle.SIZE.LARGE}
>
  …
</DropdownToggle>

// new
<DropdownToggle
  variant={DropdownToggle.VARIANT.PRIMARY}
  size={DropdownToggle.SIZE.MEDIUM}
  useNewButton
>
  …
</DropdownToggle>

ClearableButton with old Button

Using old Button in ClearableButton has been deprecated. This means:

  • useNewButton prop should be set to true for now, until it is removed altogether.
  • size prop should no longer be set to SIZE.LARGE. The NewButton supports SMALL and MEDIUM sizes and so will the ClearableButton.
jsx// old
<ClearableButton
  size={ClearableButton.SIZE.LARGE}
  …
>
  …
</ClearableButton>

// new
<ClearableButton
  size={ClearableButton.SIZE.MEDIUM}
  useNewButton
  …
>
  …
</ClearableButton>

Migrate to v2.64.0

SnackbarItem message

SnackbarItem’s message prop being optional has been DEPRECATED, it will become mandatory in an upcoming major GDS version.

Currently, the text to be announced in screen readers is retrieved by parsing SnackbarItem’s children, which may lead to undesirable results. To ensure proper spoken text, said text must be provided:

jsx// old
<SnackbarItem variant={…}>
    Text and more.
</SnackbarItem>

// new
<SnackbarItem variant={…} message="Text">
    Text and more.
</SnackbarItem>

Migrate to v2.55.0

Table Wrapper

A Table’s ability to provide its own wrapper – which adds a thin border line around the table when placed inside a padded Card – has been DEPRECATED.

The ability will be removed in an upcoming major GDS version, Tables that require a border line around them need to be wrapped inside an unpadded Card. In other words, a nested Card wraps the Table inside the already present Card:

jsx// old
<Card>
    ...
    <Table>...table content...</Table>
    ...
</Card>

// new
<Card>
    ...
    <Card padded={false}>
        <Table>...table content...</Table>
    </Card>
    ...
</Card>

See Playroom example for more details.

Migrate to v2.49.0

InfoCardHeader with ContactInfo

While ContactInfo inside a CardHeader with variant INFO sees continued support, for most purposes it is beneficial to switch to ProductInfo instead, because ProductInfo is more versatile and lets you set all the information – that previously had to be split up into individual paragraphs – directly. Both the old and the improved version shown below produce the same result visually.

jsx// old
<CardHeader variant={CardHeader.VARIANT.INFO} alignment={…}>
    <Paragraph>
      <ContactInfo
          avatar={<Avatar icon={…} color={…} />}
          alias="Transaction title"
      />
    </Paragraph>
    <Paragraph>
        <Inline small>Transaction subtitle (Optional)</Inline>
    </Paragraph>
    <Paragraph>
        <Amount value="12345" currency={…} />
    </Paragraph>
</CardHeader>

// improved
<CardHeader variant={CardHeader.VARIANT.INFO} alignment={…}>
    <Paragraph>
        <ProductInfo
            avatar={<Avatar icon={…} color={…} />}
            alias="Transaction title"
            productNumber="Transaction subtitle (Optional)"
            amount={<Amount value="12345" currency={…} />}
        />
    </Paragraph>
</CardHeader>

In order to know whether to migrate or not, you should ask yourself if the CardHeader resembles “a contact” or “a product”, and choose ContactInfo/ProductInfo accordingly. Or simply migrate all cases that result in fewer paragraphs.

HINT Depending on your use case, it may be required to set the ProductInfo’s verbosity level to REGULAR; in this case you have to provide all the labels (aliasLabel, productNumberLabel, etc.) for each line of visible text too.

Migrate to v2.44.0

Horizontal-/VerticalFunctionCard

DEPRECATED VerticalFunctionCard, use FunctionCard instead

The new FunctionCard component without horizontal prop must be used as a VerticalFunctionCard replacement. However, the way “body” content gets sent in may need an update.

If VerticalFunctionCard either used buttonsText and no children, or both buttonsText and children, the new FunctionCard component can be used as a 1 to 1 replacement. If on the other hand VerticalFunctionCard solely used children, content now needs to be sent via buttonsText. The latter is also true for Function Information Cards, which happen to be vertical FunctionCards with some heading style tweaks, and no indicator.

jsx// --- children only, now via buttonsText ---

// old:
<VerticalFunctionCard  {...props}>{children}</VerticalFunctionCard>
// new:
<FunctionCard {...props} buttonText={children} />

// --- and the two easy other cases for comparison ---

// old:
<VerticalFunctionCard {...props} buttonText={buttonsText} />
// new:
<FunctionCard {...props} buttonText={buttonsText} />

// old:
<VerticalFunctionCard {...props} buttonText={buttonsText}>{children}</VerticalFunctionCard>
// new:
<FunctionCard {...props} buttonText={buttonsText}>{children}</FunctionCard>

DEPRECATED HorizontalFunctionCard, use FunctionCard with horizontal instead

The new FunctionCard component with horizontal prop is a 1 to 1 replacement for HorizontalFunctionCard.

jsx// old:
<HorizontalFunctionCard {...props}>{children}</HorizontalFunctionCard>
// new:
<FunctionCard {...props} horizontal>{children}</FunctionCard>

DEPRECATED HorizontalFunctionCardGroup, use CardGroup or Group instead

The new horizontal FunctionCard no longer needs a dedicated HorizontalFunctionCardGroup wrapper, it can be placed in a regular CardGroup. In the unlikely event you have a standalone horizontal FunctionCard (i.e. without any siblings) on grey background, you can even put it in a plain Group.

jsx// --- any content that actually needs "grouping", i.e. at least 2 cards ---

// old:
<HorizontalFunctionCardGroup>
  <HorizontalFunctionCard {...props}>{children}</HorizontalFunctionCard>
  <HorizontalFunctionCard {...props}>{children}</HorizontalFunctionCard>
</HorizontalFunctionCardGroup>
// new:
<CardGroup>
  <FunctionCard {...props} horizontal>{children}</FunctionCard>
  <FunctionCard {...props} horizontal>{children}</FunctionCard>
</CardGroup>

// --- single/standalone horizontal FunctionCard ---

// old:
<HorizontalFunctionCardGroup>
  <HorizontalFunctionCard {...props}>{children}</HorizontalFunctionCard>
</HorizontalFunctionCardGroup>
// new:
<Group>
  <FunctionCard {...props} horizontal>{children}</FunctionCard>
</Group>

Migrate to v2.43.0

ProductCard size

BREAKING removed ProductCard size, please use variant instead.

Former size valueNew variant value
SMALL (default)PLUGIN (default)
MEDIUMTEASER
LARGELARGE_TEASER

Migrate to v2.40.0

ActivatedPluginCard

DEPRECATED ActivatedPluginCard, please use ProductCard instead.

Can be used as a 1 to 1 replacement, with two key differences:

  • ActivatedPluginCard’s color prop must be mapped to ProductCard’s colorValue prop, and not the color prop (which also exists).
  • ActivatedPluginCard’s buttonsText prop must be mapped to ProductCard’s price prop, and you are only allowed to send inline content, a wrapper paragraph is created automatically.

Stripe pluginColor

BREAKING Removed pluginColor prop, use colorValue instead

jsx// old:
<StripeHeader
  pluginColor="#eeeeee"
  …
/>

// new:
<StripeHeader
  colorValue="#eeeeee"
  …
/>

Migrate to v2.24.0

Dual currency OverviewCard

BREAKING Removed extraAmountsConverted prop, use extraAmounts with structured objects

jsx// old:
<OverviewCard
  mainAmount={<OverviewCardAmount … />}
  mainAmountConverted={<OverviewCardAmount … />}
  extraAmounts={[<OverviewCardAmount … />]}
  extraAmountsConverted={[<OverviewCardAmount … />]}
  …
/>

// new:
<OverviewCard
  mainAmount={<OverviewCardAmount … />}
  mainAmountConverted={<OverviewCardAmount … />}
  extraAmounts={[
    {
        original: <OverviewCardAmount … />,
        converted: <OverviewCardAmount … />,
    }
  ]}
  …
/>

Migrate to v2.19.0

Button unstyled .g-button-avatar

DEPRECATED the need to set unstyled and .g-button-avatar when Button contains an Avatar in its children, those props may now be omitted.

jsx// old:
<Button unstyled className="g-button-avatar" icon={Button.ICON.CAMERA} aria-label="Button Label">
  <Avatar icon={Avatar.ICON.USER} />
</Button>

// new:
<Button icon={Button.ICON.CAMERA} aria-label="Button Label">
  <Avatar icon={Avatar.ICON.USER} />
</Button>

Migrate to v2.17.0

Transaction date without Moment.js

DEPRECATED usage of Moment.js in Transaction.date. Unfortunately, this also means, that all format strings will have to be updated, as date-fns uses Unicode Tokens, which is the accepted new standard for date formatting tokens.

jsx// old:
<Transaction
    date={moment('2022-03-24')}
    dateFormat="DD.MM.YYYY"
    largeDateFormat="D MMM [escaped]"
    largeDateFormatYear="YYYY"
/>

// new:
<Transaction
    date={new Date('2022-03-24')}
    dateFormat="dd.MM.yyyy"
    largeDateFormat="d MMM 'escaped'"
    largeDateFormatYear="yyyy"
/>

Please note, that should you decide to migrate to use JavaScript Dates instead of Moment.js, that globally defined formats in LanguageProvider will have to be migrated as well. Here’s a list of the affected keys:

  • format.date
  • format.isoDate
  • format.screenreaderDate
  • transaction.format.date
  • transaction.format.largeDate
  • transaction.format.largeDateYear

Migrate to v2.12.0

TransactionMenu

With the introduction of TransactionMenu, support for an overlay with buttons as used in Order list transactions has been deprecated. TransactionMenu uses MenuDropdown internally and will forward all props to it.

jsx// old:
<TransactionGroup columns={{ overlay: { show: true } }}>
    <Transaction
        title="Shows an overlay on hover"
        overlay={
            <ButtonGroup buttonSize={ButtonGroup.BUTTON_SIZE.SMALL}>
                <Button variant={Button.VARIANT.SECONDARY} onClick={() => {}}>Sign</Button>
                <Button variant={Button.VARIANT.SECONDARY}>Edit</Button>
                <Button variant={Button.VARIANT.SECONDARY}>Delete</Button>
            </ButtonGroup>
        }
    />
</TransactionGroup>

// new:
<TransactionGroup columns={{ menu: { show: true } }}>
    <Transaction
        title="Shows a menu with actions"
        menu={
            <TransactionMenu
                {...DropdownMenuProps}
                toggleLabel="Actions"
                items={[
                    { value: 'sign', label: 'Sign', onClick: () => {} },
                    { value: 'edit', label: 'Edit' },
                    { value: 'delete', label: 'Delete' },
                ]}
            />
        }
    />
</TransactionGroup>

PrimaryNavigationDropdownToggle

BREAKING PrimaryNavigationDropdownToggle has been removed, as PrimaryNavigationButton now comes with a showDropdownIndicator, which makes the toggle obsolete.

PrimaryNavigationDropdownToggle made sure that the icon of a navigation item is always the downward-facing caret. With this release, the dropdown indicator is a separate thing, which means icon and a dropdown indicator at the same time become possible. Essentially, we now support all combinations of navigation item content (icon, label, pill, dropdown indicator).

Consequently, this change enables us to add a dropdown indicator to icon-only buttons, but for now we continue the old way for aesthetic reasons. Therefore, this is no 1:1 migration, i.e. not all occurances of PrimaryNavigationDropdownToggle will be turned into PrimaryNavigationButton with showDropdownIndicator={true}.

Navigation items that have a visible label should be migrated like this:

jsx// old:
<PrimaryNavigationDropdownToggle>
  Your Products
</PrimaryNavigationDropdownToggle>

// new:
<PrimaryNavigationButton showDropdownIndicator>
  Your Products
</PrimaryNavigationButton>

In contrast, for items that only show the icon, use PrimaryNavigationButton without showDropdownIndicator:

jsx// old:
<PrimaryNavigationDropdownToggle
  hiddenLabel={PrimaryNavigationButton.HIDDEN_LABEL.ALWAYS}
  icon={PrimaryNavigationButton.ICON.COMMENT}
>
  Your Messages
</PrimaryNavigationDropdownToggle>

// new:
<PrimaryNavigationButton
  hiddenLabel={PrimaryNavigationButton.HIDDEN_LABEL.ALWAYS}
  icon={PrimaryNavigationButton.ICON.COMMENT}
>
  Your Messages
</PrimaryNavigationButton>

Needless to say, navigation items that are already using PrimaryNavigationButton – i.e. those that do not open a dropdown – need no migration, as showDropdownIndicator defaults to false.

Bottom line, PrimaryNavigationDropdownToggle usually resides in Dropdown’s renderToggle, migrate all occurances to PrimaryNavigationButton with/without dropdown indicator.

jsx// new - with PrimaryNavigationDropdownToggle already replaced:
<Dropdown
  renderToggle={() => (
    <PrimaryNavigationButton showDropdownIndicator={!isIconOnlyButton}>
      Your Products
    </PrimaryNavigationButton>
  )}
>
  {/* dropdown content */}
</Dropdown>

Migrate to v2.11.0

Avatar hoverIcon

DEPRECATED all hoverIcon* props, hence the scenarios shown in the example code marked as “old” should be migrated to the new format, where the Avatar is wrapped in an unstyled Button with an icon and the modifier .g-button-avatar applied. The Button’s icon replaces Avatar’s hoverIcon, and no tabIndex should be needed anymore.

jsx// old - without button, but something (e.g. a Dropdown) that had a tabIndex:
<Dropdown
  tabIndex={0}
  renderToggle={<Avatar icon={Avatar.ICON.USER} hoverIcon={Button.ICON.CAMERA} />}
>
  {children}
</Dropdown>

// old - without button, the Avatar itself had a tabIndex:
<Avatar icon={Avatar.ICON.USER} hoverIcon={Button.ICON.CAMERA} tabIndex={0} />

// old - already with unstyled button, but only a `.g-button-rounded` modifier class:
<Button unstyled className="g-button-rounded" aria-label="Button Label">
  <Avatar icon={Avatar.ICON.USER} hoverIcon={Button.ICON.CAMERA} />
</Button>

// new:
<Button unstyled className="g-button-avatar" icon={Button.ICON.CAMERA} aria-label="Button Label">
  <Avatar icon={Avatar.ICON.USER} />
</Button>

Amount in ProductSelect/RecipientSelect

DEPRECATED amount data in the items’ product data in ProductSelect and RecipientSelect in favour of an actual Amount element:

jsx// old:
<ProductSelect
    items={[
        ...items,
        {
            label: 'Product',
            value: 'product',
            product: {
                ...productData,
                amount: {
                    value: '123456',
                    currency: 'EUR',
                    color: Amount.COLOR.POSITIVE,
                }
            }
        }
    ]}
/>

// new:
<ProductSelect
    items={[
        ...items,
        {
            label: 'Product',
            value: 'product',
            product: {
                ...productData,
                amount: <Amount value="123456" currency="EUR" color={Amount.COLOR.POSITIVE} />
            }
        }
    ]}
/>

Migrate to v2.9.0

While Transaction components are still in BETA status, the changes this time are quite significant, so we tried to deprecate as much as possible. Here’s a quick overview of what has changed:

  • visual update in list and detail (date column, indicators under amounts, improved padding, alignment of Retail, Pro and Business)
  • one customisable Transaction component instead of two variants
  • alignment of prop, column and language key names
  • full control over visibility of all columns in TransactionGroup and TransactionDetail
  • direct usage of Avatar instead of icon and imageUrl
  • new dedicated alert column

Transaction

To streamline the usage of Transaction/TransactionDetail and enable various different configurations, the special variants AccountTransaction and OrderTransaction got deprecated in favour of a single Transaction component. Please refer to the following table to see how the props translate. The props of TransactionDetail are similarly affected by this change.

DEPRECATED propNew prop
*Transaction.iconTransaction.avatar
*Transaction.imageUrlTransaction.avatar
*Transaction.renderTypeTransaction.renderAvatar
*Transaction.bigDateFormatUpperTransaction.largeDateFormat
*Transaction.bigDateFormatLowerTransaction.largeDateFormat
*Transaction.bigDateFormatYearTransaction.largeDateFormatYear
AcountTransaction.descriptionTransaction.info
AcountTransaction.noteTransaction.info
AcountTransaction.categoriesTransaction.badges
OrderTransaction.statusesTransaction.badges
jsx// old:
<AccountTransaction
    description="Description"
    note="Note"
    categories={["Improvements & furniture", "Home"]}
    icon={AccountTransaction.ICON.BUILDING_SAVINGS}
    bigDateFormatUpper="D"
    bigDateFormatLower="MMM"
    bigDateFormatYear="YYYY"
    renderType={({ children, icon, imageUrl }) => children }
/>
<OrderTransaction
    statuses={["Open"]}
    imageUrl="path-to-asset"
/>

// new:
<Transaction
    info="Description or Note"
    badges={[
        <Badge key="1" variant={BADGE.VARIANT.CATEGORY} text="Improvements & furniture" />
        <Badge key="2" variant={BADGE.VARIANT.CATEGORY} text="Home" />
    ]}
    avatar={<Avatar icon={Avatar.ICON.BUILDING_SAVINGS} />}
    largeDateFormat="D MMM"
    largeDateFormatYear="YYYY"
    renderAvatar={({ children, avatar }) => children }
/>
<Transaction
    info="Description or Note"
    badges={[
        <Badge key="1" variant={BADGE.VARIANT.TODO} text="Open" />
    ]}
    avatar={<Avatar imageUrl="path-to-asset" />}
/>

TransactionGroup

To further align the APIs of Transaction components, column names and language string keys have been aligned with their respective prop in Transaction:

Old TransactionGroupNew TransactionGroupBREAKING New LanguageProvider key
columns.typecolumns.avatartransaction.header.avatar
columns.descriptioncolumns.infotransaction.header.info
columns.actionscolumns.overlaytransaction.header.overlay
columns.detailscolumns.detailtransaction.header.detail

Furthermore, it is now possible to control all individual columns through a show property in the respective column. Similar to that, showInDetail can be used to control visibility of individual columnns inside the TransactionDetail.

By default, TransactionGroup uses the following default configuration:

jsxconst COLUMN_DEFAULTS = {
  selectable: { show: false, showInDetail: false },
  date: { show: true, showInDetail: true },
  avatar: { show: true, showInDetail: true },
  title: { show: true, showInDetail: true },
  amount: { show: true, showInDetail: true },
  indicators: { show: true, showInDetail: true },
  info: { show: true, showInDetail: true },
  misc: { show: false, showInDetail: false },
  badges: { show: true, showInDetail: false },
  alert: { show: false, showInDetail: false },
  overlay: { show: false, showInDetail: false },
  detail: { show: true, showInDetail: false },
};

To further illustrate the changes mentioned above, here’s a stripped down example a TransactionGroup component:

jsx// old:
<TransactionGroup
    selectable
    showDate={false}
    showType={false}
    columns={{
        selectable: { label: 'Select transaction' },
        date: { label: 'Date' },
        type: { label: 'Type' },
        description: { label: 'Description' },
        actions: { label: 'Actions' },
        details: { label: 'Transaction details' },
    }}
>
    ... Transactions
</TransactionGroup>

// new:
<TransactionGroup
    columns={{
        selectable: { show: true, label: 'Select transaction' },
        date: { show: false, label: 'Date' },
        avatar: { show: false, label: 'Type' },
        info: { label: 'Description' },
        detail: { label: 'Transaction detail' },
    }}
>
    ... Transactions
</TransactionGroup>

Migrate to v2.0.0-beta.48

TransactionGroup columns

With the added support of sortable Transactions through TransactionGroup we’ve added the ability to customize the columns of the underlying table, this also includes their label, so the abstraction of those labels into dateLabel and the like are no longer necessary. Labels provided through LanguageProvider strings are unaffected by this change.

jsx// old:
<TransactionGroup
  dateLabel="Date"
  badgesLabel="Status"
>
  ... Transactions
</TransactionGroup>

// new:
<TransactionGroup
  columns={{
    date: { label: 'Date' },
    badges: { label: 'Date' },
  }}
>
  ... Transactions
</TransactionGroup>

Each label translates into its own column like follows:

DEPRECATED keyNew key
dateLabelcolumns.date.label
typeLabelcolumns.type.label
titleLabelcolumns.title.label
amountLabelcolumns.amount.label
indicatorsLabelcolumns.indicators.label
badgesLabelcolumns.badges.label
descriptionLabelcolumns.description.label
miscLabelcolumns.misc.label
actionsLabelcolumns.actions.label
detailsLabelcolumns.details.label
selectableLabelcolumns.selectable.label

Migrate to v2.0.0-beta.37

CardHeader

  • Update LargeCardHeader (see below).
  • Update <InfoCardHeader /> to <CardHeader variant={CardHeader.VARIANT.INFO} />.
jsx// old:
<LargeCardHeader
  left={left}
  right={right}
>
  Title
</LargeCardHeader>

// new:
<StripeHeader
  left={left}
  right={right}
  center={
    <StripeTitle>Title</StripeTitle>
  }
/>

Meter

BREAKING The Meter component has lost three abilities, and two things have changed:

  1. It no longer handles min > max ranges.
  2. It no longer has a tooltip property.
  3. It no longer has a description property.
  4. The misspelt auxillaryValue was changed to auxilaryValue, but this is also misspelt, as it should be auxiliaryValue, which is why is was changed to auxValue.
  5. The label now shows the uncapped value.

Removal of min > max support

With this change, minmax applies. Most likely there is no “countdown meter” out there, because the implementation had bugs. Instead of fixing them, this feature has been removed, as the range boundaries can easily be flipped (recalculated) before sending them to Meter.

Removal of tooltip

The tooltip property is not needed, as Meter can simply be wrapped inside an actual Tooltip. This comes with the additional benefit of all Tooltip properties being usable.

jsx<Tooltip tag="div" content="You have saved 60% of the required amount.">
  <Meter value={60} />
</Tooltip>

Removal of description

Setting the now removed description property resulted in an aria-label on the Meter, which does not work on <span> elements in most screen readers. So do not replace it with aria-label, instead augment it with VisuallyHidden text.

There are two scenarios where you do not need a description: 1. Meter is wrapped inside a self-explanatory Tooltip; and 2. Meter has enough text before/after it which covers the explanation. For everything else, supplementary text is needed to replace what previously went in description, like shown below.

jsx// add a description that is announced instead of the Meter value
<Meter value={60} aria-hidden /><VisuallyHidden>You have saved 60% of the required amount.</VisuallyHidden>

// add a description to Meter without hiding it's value
<VisuallyHidden>You have saved </VisuallyHidden><Meter value={60} /><VisuallyHidden> of the required amount.</VisuallyHidden>

Fixed typo in auxiliary value

Change all auxillaryValue to auxValue.

Change in label behaviour

If you use Meter with a value ouside the min/max range, the length of the bar is determined by the capped value, but the contained text is now holding the uncapped value.

jsx// As `max` defaults to 100, this will now show 110% instead of 100%
<Meter value={110} showLabel />
// 👉 output: <span class="g-meter…>110%</span>

// If you *really* need the old behaviour, use either
<Meter value={110} showLabel label="100%" />
// or alternatively recalculate and send in the capped value
<Meter value={100} showLabel />
// But! Most likely you wanted the uncapped value anyway, so now
// you can remove any `label="110%"` you had to add previously.

Migrate to v2.0.0-beta.31

New buttons

BREAKING The Button component no longer has an iconLabel for icon-only buttons, specifying a label now works identical for all kinds of buttons, i.e. label only, icon only, and label with icon. To hide the label, set hiddenLabel to Button.HIDDEN_LABEL.ALWAYS. (In most cases, you also want to set fullWidth to Button.FULL_WIDTH.NEVER at the same time.)

jsx// to get an icon-only (primary) button

<Button
  icon={Button.ICON.DELETE}
  fullWidth={Button.FULL_WIDTH.NEVER}
  hiddenLabel={Button.HIDDEN_LABEL.ALWAYS}
>
  Mandatory label
</Button>

Migrate to v2.0.0-beta-29

The DropdownToggle component now supports replacing its internal button for the new one:

jsx// old button accepts a `color` prop

<DropdownToggle
  color={DropdownToggle.COLOR.PRIMARY}
  size={DropdownToggle.SIZE.SMALL}
>
  Dropdown toggle old button
</DropdownToggle>

// new button accepts a `variant` prop when `useNewButton` is true

<DropdownToggle
  variant={DropdownToggle.VARIANT.TERTIARY}
  size={DropdownToggle.SIZE.SMALL}
  useNewButton
>
  Dropdown toggle new button
</DropdownToggle>

Migrate to v2.0.0-beta.25

New buttons

A new Button component is introduced to replace the various button components (these are deprecated but will stay available until GDS v3).

The components can be replaced as follows:

OldNew
<PrimaryButton /><Button variant={Button.VARIANT.PRIMARY} />
<SecondaryButton /><Button variant={Button.VARIANT.SECONDARY} />
<DangerButton /><Button variant={Button.VARIANT.DANGER} />
<TransparentButton /><Button variant={Button.VARIANT.SECONDARY} /> placed in a container with .g-inverted className
<PrimaryIconButton icon={PrimaryIconButton.ICON.*} /><Button variant={Button.VARIANT.TERTIARY} icon={Button.ICON.*} />
<SecondaryIconButton icon={SecondaryIconButton.ICON.*} /><Button variant={Button.VARIANT.SECONDARY} icon={Button.ICON.*} />
<SecondaryIconButton outline={false} icon={SecondaryIconButton.ICON.*} /><Button variant={Button.VARIANT.TERTIARY} icon={Button.ICON.*} />
<TransparentIconButton icon={TransparentIconButton.ICON.*} /><Button variant={Button.VARIANT.SECONDARY} icon={Button.ICON.*} /> placed in a container with .g-inverted className
<PrimaryLinkButton href="" /><Button variant={Button.VARIANT.TERTIARY} href="" />
<SecondaryLinkButton href="" /><Button variant={Button.VARIANT.TERTIARY} href="" />
<UIButton /><Button variant={Button.VARIANT.TERTIARY} />
<SegmentedButton /><Button /> in a <ButtonGroup segmented />

ButtonGroup requires a little adjustment based on whether it contains the old or the new buttons.

The following button components remain to be used: ClearableButton, CollapsibleButton, DropdownActionButton, FileListButton, OverviewCardButton, StripeActionButton, ToggleButton.

Migrate to v2.0.0-color.9

Breaking changes

  • Replace George Pro colour PRO with G_PRO.
  • Replace $color-g-emerald with $color-forest, same applies to colour classes .g-bg-g-emerald and .g-fg-g-emerald.
  • Replace $color-g-fog with $color-stone, same applies to colour classes .g-bg-g-fog and .g-fg-g-fog.

Deprecation summary

No immediate action required.

  • All existing colour values have automatically mapped to the new reduced George colour palette. For details see old colour variables.
    • Colour variables ($color-g-*) and their helper classes (.g-bg-g-*/.g-fg-g-*) have been deprecated. Switch to the new $color-* variables and .g-bg-*/.g-fg-* helper classes.
    • CI colours (Erste Group colours) have been deprecated, use new colours according to the mapping.
    • UI colours (Primary, Secondary, Grey, Active, Green, Red, Orange and Yellow) have been deprecated, use new colours according to the mapping.

Migrate to v2.0.0-beta.17

We’ve removed all the deprecations from last major release.

Amount

  • Update <Amount value={…} useSuperscript={false} /> to <Amount value={…} superscript={Amount.SUPERSCRIPT.DISABLED} />
  • Update <Amount value={…} forceSuperscript> to <Amount value={…} superscript={Amount.SUPERSCRIPT.FORCED} />

Button

  • StoreButton was removed, use PrimaryButton instead.

Card

  • Update CardFooters which have set an amount or a button
    • Update <CardFooter amount={amount}>{label}</CardFooter> to <CardFooter label={label} amount={amount} />
    • Update <CardFooter action={button}>{label}</CardFooter> to <CardFooter label={label} action={button} />
  • Update TransactionGroupFooters which have set an amount or a button
    • Update <TransactionGroupFooter amount={amount}>{label}</TransactionGroupFooter> to <TransactionGroupFooter label={label} amount={amount} />
    • Update <TransactionGroupFooter action={button}>{label}</TransactionGroupFooter> to <TransactionGroupFooter label={label} action={button} />
  • Update LargeCardHeaders

Before

jsx<LargeCardHeader
    backUrl={url}
    backText={text}
    backOnClick={onClick}
/>

After

jsx<LargeCardHeader left={
    <UIButton href={url} onClick={onClick}>{text}</UIButton>
} />

Before

jsx<LargeCardHeader
    buttonIcon={icon}
    buttonText={text}
    buttonOnClick={onClick}
    buttonClassName={className}
/>

After

jsx<LargeCardHeader right={
    <TransparentIconButton icon={icon} className={className} onClick={onClick}>{text}</TransparentIconButton>
} />

You can also use TransparentButton

Form

  • Update <FormField noLayout/> to <FormField variant={FormField.VARIANT.NO_LAYOUT} />

Select

Before

jsx<ProductSelect items={[{ color: itemColor, … }]} />`

After

jsx<ProductSelect items={[{ product: { color: itemColor, … }, … }]} />

Before

jsx<RecipientSelect contactItems={[{ color: itemColor, … }]} />

After

jsx<ProductSelect contactItems={[{ product: { color: itemColor, … }, … }]} />

Migrate to v2.0.0-beta.15

LanguageProvider strings structure change

With a growing collection of components using strings the flat structure needed an upgrade. LanguageProvider now supports a deep object as strings. See the following table and code examples on how to migrate your app.

DEPRECATED keyNew key
actionstransaction.header.actions
additionalInformationtransaction.header.misc
amounttransaction.header.amount
browseFilesinput.file.browse
categoriesOrStatetransaction.header.badges
closecommon.close
collapsecommon.collapse
datetransaction.header.date
dateButtoninput.date.button
deleteinput.file.delete
descriptiontransaction.header.description
detailstransaction.header.details
dragFilesinput.file.drag
dropFilesinput.file.drop
expandcommon.expand
helpcommon.help
indicatorstransaction.header.indicators
loadingspinner.message
optionalform.label.optional
selectabletransaction.header.selectable
selectAllinput.select.selectAll
selectAllProductsinput.productSelect.selectAll
selectedItemsinput.select.selectedItems
selectedProductsinput.productSelect.selectedItems
stepperLabelstepper.compactInfo
titletransaction.header.title
typetransaction.header.type
uploadinginput.file.uploading

Before:

jsxconst strings = {
  actions: 'Actions',
  additionalInformation: 'Additional information',
  amount: 'Amount',
  browseFiles: 'Browse Files',
  categoriesOrState: 'Categories/State',
  close: 'Close',
  collapse: 'Collapse',
  date: 'Date',
  dateButton: 'Choose a date',
  delete: 'Delete',
  description: 'Description',
  details: 'Details',
  dragFiles: 'Drag files here to upload or',
  dropFiles: 'Drop files here',
  expand: 'Expand',
  help: 'Help',
  indicators: 'Indicators',
  loading: 'Loading...',
  optional: 'Optional',
  selectable: 'Select',
  selectedItems: 'Selected multiple items',
  selectedProducts: 'Selected multiple products',
  selectAll: 'All items',
  selectAllProducts: 'All products',
  stepperLabel: 'Step {{currentStep}} of {{totalSteps}} – {{currentStepLabel}}',
  title: 'Title',
  type: 'Type',
  uploading: 'Uploading...',
};

return (
  <LanguageProvider locale="en" strings={strings}>
    {children}
  </LanguageProvider>
);

After:

jsxconst strings = {
  common: {
    close: 'Close',
    collapse: 'Collapse',
    expand: 'Expand',
    help: 'Help',
  },
  form: {
    label: {
      optional: 'Optional',
    },
  },
  input: {
    date: {
      button: 'Choose a date',
    },
    file: {
      browse: 'Browse files',
      delete: 'Delete',
      drag: 'Drag files here to upload or',
      drop: 'Drop files here',
      uploading: 'Uploading...',
    },
    select: {
      selectAll: 'All items',
      selectedItems: 'Selected multiple items',
    },
    productSelect: {
      selectAll: 'All products',
      selectedItems: 'Selected multiple products',
    },
  },
  spinner: {
    message: 'Loading...',
  },
  stepper: {
    compactInfo: 'Step {{currentStep}} of {{totalSteps}} – {{currentStepLabel}}',
  },
  transaction: {
    header: {
      date: 'Date',
      title: 'Title',
      description: 'Description',
      amount: 'Amount',
      type: 'Type',
      badges: 'Categories/State',
      indicators: 'Indicators',
      misc: 'Additional information',
      actions: 'Actions',
      details: 'Details',
      selectable: 'Select',
    },
  },
};

return (
  <LanguageProvider locale="en" strings={strings}>
    {children}
  </LanguageProvider>
);

Migrate to v2.0.0-beta.12

ContactInfo

  • Replace useGroupIcon prop with icon={ContactInfo.ICON.GROUP}

Snackbar enums

  • Update <SnackbarItem type={SnackbarItem.TYPE.X} /> to <SnackbarItem variant={SnackbarItem.VARIANT.X} />

Stripe

  • Replace stickyOffsets prop with stickyOffset

Migrate to v2.0.0-beta.8

Misc enums

  • Update <Badge type={Badge.TYPE.X} /> to <Badge variant={Badge.VARIANT.X} />
  • Update <Pill type={Pill.TYPE.X} /> to <Pill variant={Pill.VARIANT.X} />

New default in FormField

  • The default label position for large FormFields has changed. To keep the previous behaviour, update <FormField variant={FormField.VARIANT.LARGE} /> to <FormField variant={FormField.VARIANT.LARGE} labelPosition={FormField.LABEL_POSITION.INSIDE} />

Migrate to v2.0.0-beta.6

Render props

All internal usages of render props throughout GDS have been standardized to use a single argument with properties instead of an unnamed argument list. Most components are unaffected by this, but if you are using one of the following props you need to adapt their signature as follows:

Component(s)PropSignature change
All Select componentsrenderToggle(selection)({ selection })
All Select componentsrenderSelection(selection)({ selection })
All Select componentsrenderSelectableItemDecorator(item)({ item })
Select, ProductSelect, MenuDropdownrenderItem(item)({ item })
FilteredSelect, RecipientSelectrenderItem(item, search)({ item, search })
MenuDropdownrenderItemsContainer(children)({ children })
SelectableItemrenderDecorator(value)({ value })
TableRowrender(cells, props)({ cells, props })
TableCellrender(children, props)({ children, props })

Alert enums

  • Update <Alert type={Alert.TYPE.X} /> to <Alert variant={Alert.VARIANT.X} />
  • Update <CollapsibleAlert type={CollapsibleAlert.TYPE.X} /> to <CollapsibleAlert variant={CollapsibleAlert.VARIANT.X} />
  • Update <ModalAlert type={ModalAlert.TYPE.X} /> to <ModalAlert variant={ModalAlert.VARIANT.X} />

EmptyState/StatusInfo & enums

  • Update <EmptyState type={EmptyState.TYPE.X} /> to <StatusInfo variant={StatusInfo.VARIANT.X} />
  • Update g-empty* classes to g-status-info* if used directly in your code

Migrate to v2.0.0-beta.4

LabeledList enums

A selection of boolean props have been reorganised into enums:

  • replace compact prop with variant={LabeledList.VARIANT.COMPACT}
  • replace separated={false} prop with variant={LabeledList.VARIANT.PLAIN}
  • replace striped prop with variant={LabeledList.VARIANT.STRIPED}
  • replace alignRight prop with alignment={LabeledList.ALIGNMENT.RIGHT}
  • replace smallLabels prop with labelSize={LabeledList.LABEL_SIZE.SMALL}

Open/close handlers renaming

4 event handlers have been globally renamed to better reflect the underlying mechanic. The migration is straightforward (the order of operations is recommended):

  • change onOpen prop to onBeforeOpen
  • change onOpened prop to onOpen
  • change onClose prop to onBeforeClose
  • change onClosed prop to onClose

Affected components: Alert, CollapsibleAlert, CTAAlert, InputAlert, ModalAlert, Collapsible, Dropdown, ColorDropdown, MenuDropdown, FormField, Handover, DateInput, DateRangeInput, FileInput, HashtagInput, Modal, SecondaryNavigation, AmountDropdown, SegmentedMenu, FilteredSelect, ProductSelect, RecipientSelect, Snackbar, SnackbarItem, StripeNavigation, StripeHeader, CollapsibleTableRow, and AccountTransaction.

Migrate to v2.0.0-beta.0

Importing styles

With version 2.0, GDS component’s CSS has been removed from the JS bundle. Please import it in your project straight after gds-main.min.css or gds-store.min.css respectively

A minified version of this can be imported from here: @george-labs.com/design-system/dist/gds-components.min.css

So styles.scss might end up looking something like this:

scss@import '~@george-labs.com/design-system/dist/bootstrap.min.css';
@import '~@george-labs.com/design-system/dist/gds-main.min.css';
@import '~@george-labs.com/design-system/dist/gds-components.min.css';

Bootstrap 4.5

With version 2.0, GDS has updated its Bootstrap dependency to 4.5. A lot has changed since v4.0-alpha.6, so please refer to external migration guides to update your classes accordingly:

Notable changes in GDS components:

Col push and pull aren’t supported in Bootstrap anymore. Please use offset if you want to shift a column and order if you want to order it differently from how they appear in the markup.

InputGroup styles have changed significantly, and require specific classes to work seamlessly. GDS tries to apply those classes automatically, but if you wrap our components you might run into problems. Please add a static property to your wrapper so that GDS knows how to deal with that addon.

jsxconst SelectWrapper = ({ ...rest }) => <Select {...rest} />;

SelectWrapper.wrapsComponent = Select;

Currently supported addons:

  • Text
  • Button components
  • Select components

Small Paragraphs

To add a paragraph with smaller text to George Web, the inline HTML element small has been used, which then was rendered as a paragraph with margins and a decreased font size. This has been wrong for two reasons. For starters, <small> is not a block-level but an inline element, and should be placed inside a proper block-level parent, usually a paragraph. And more importantly, <small> is the wrong element to begin with. According to MDN,

the HTML <small> element represents side-comments and small print, like copyright and legal text, independent of its styled presentation.

Starting with GDS 2.0, all occurrences of <small> need to be replaced with Paragraphs that have a .g-small modifier class added. There might be cases where the <small> element should be kept for semantic reasons, but chances on that are slim to nil. Legal text usually comes preformatted from the Copywriter’s CMS. That said, even if such cases exist, they still need to be wrapped in the aforementioned way.

Toggle

Toggle components have been turned into inline elements. To reinstate the former behaviour, ToggleIcon, ToggleImage and most likely also ToggleButton need to be wrapped inside e.g. a paragraph. As ToggleIcons and ToggleImages mainly come in groups of two or three, this is especially important on tier XS, where they are displayed vertically: If you do not wrap each one inside a paragraph, they end up not having enough margin between them. Other parent elements may also work, whatever makes sense semantically.

The newly introduced ToggleBadge should be inline anyway, so you may not need to add any parent element, but better cross-check.

Avatar

PunchedImage has been renamed to Avatar and its style has been updated. All functionalities remain the same as before.

GDS Styles

PunchedImage (old)Avatar (new)
.g-punched.g-avatar
.g-punched-content.g-avatar-content
.g-punched-image.g-avatar-image
.g-punched-icon.g-avatar-icon
.g-punched-hover.g-avatar-hover
.g-punched-badge.g-avatar-badge

Alert variants

CTAAlert and InputAlert components are deprecated in favour of using a new size prop in the Alert component. Migration is straightforward:

  • change <CTAAlert {...rest} /> to <Alert size={Alert.SIZE.LARGE} {...rest} />
  • change <InputAlert {...rest} /> to <Alert size={Alert.SIZE.SMALL} {...rest} />

Migrate to v1.0.0-beta.2

Removal of deprecated features

GDS Styles

RemovedAlternative
.g-product-info-data .g-amount.g-product-info-horizontal .g-product-info-display (see documentation)
.g-product-info-amount-right(requires same solution as .g-product-info-data .g-amount, see above)

Deprecated features

GDS Components

DeprecatedAlternative
ProductInfo.amountRightno longer possible for vertical ProductInfos, and automatically happening when ProductInfo.horizontal is set

Migrate to v1.0.0-beta.0

While it took some time to merge George Styleguide and George Components into George Design System, it shouldn’t be much of an effort for you to migrate to our newest release.

NPM package

Now that George Styleguide (george-styleguide) and George Components (george-components) are provided via a single NPM package (@george-labs.com/design-system) all imports in your project need to be changed to use the new repository.

There’s two things that need to be done now:

  • Delete both george-styleguide and george-components dependencies
  • Add @george-labs.com/design-system as a dependency
bashnpm add @george-labs.com/design-system

GDS Styles

All assets and SASS files still live in the same folder than before, so only the dependency name needs to be changed, the path should stay the same, except for the following theme files:

Old themeNew theme
sass/george-bs4-theme.scsssass/gds-main.scss
sass/george-store-theme.scsssass/gds-store.scss
sass/george-sanity-theme.scsssass/gds-sanity.scss

Before:

scss@import '~george-styleguide/sass/common';
@import '~george-styleguide/sass/george-bs4-theme';
@import '~george-styleguide/assets/fonts/styleguide/styleguide.css';
// ...

After:

scss@import '~@george-labs.com/design-system/sass/common';
@import '~@george-labs.com/design-system/sass/gds-main';
@import '~@george-labs.com/design-system/assets/fonts/styleguide/styleguide.css';
// ...

GDS Components

The GDS JS module exports all components exactly the same way than before, so a search/replace over george-components should be enough. Typescript type definitions should work out of the box as well.

Before:

jsximport { Card } from 'george-components';
// ...

After:

jsximport { Card } from '@george-labs.com/design-system';
// ...

Renamed assets

Assets renamed to use gds prefix. The following include paths need to be adjusted:

  • /assets/george-icons.svgBREAKING removed
  • /assets/george-icons-new.svg/assets/gds-icons.svg
  • /assets/george-loading.svg/assets/gds-loading.svg

Bootstrap, Compiled CSS and Autoprefixer

As of GDS 1.0.0, SASS files won’t be using vendor prefixes anymore. They will be added automatically by Autoprefixer in combination with a browserlist entry in our package.json file on build.

What this means:

  • SASS files shouldn’t be imported directly anymore if they are expected to be vendor-prefixed
  • Instead we provide a compiled CSS version (including sourcmap files) of the theme in the dist folder
  • Variables, functions and mixins can still be used without any repercussions by importing sass/common
  • Should it be necessary to import the SASS files somehow, they would have to be vendor-prefixed the build process of your project
Theme (unprefixed)Compiled CSS (prefixed)
sass/gds-main.scssdist/gds-main.css
sass/gds-store.scssdist/gds-store.css
sass/gds-sanity.scssdist/gds-sanity.css

In addition to that, we now also provide a stripped down, compiled version of Bootstrap. This file is already namespaced with .g-bootstrap.

Before:

scss.g-bootstrap {
  @import '../../../../node_modules/george-styleguide/node_modules/bootstrap/scss/bootstrap';
  // 🤷‍♂️
}

After:

scss@import '~@george-labs.com/design-system/dist/bootstrap.css';
// ... or the SASS version (without prefixes) ...
@import '~@george-labs.com/design-system/sass/bootstrap';

Removal of deprecated features

GDS Styles

RemovedAlternative
.g-dropdown-product-simple.g-dropdown-product (see documentation)
.g-dropdown-account-simple.g-dropdown-product (see documentation)
.g-alert-danger.g-alert-error (see documentation)

GDS Components

RemovedAlternative
Alert.TYPE.DANGERAlert.TYPE.ERROR
Icon.nameIcon.icon
PunchedImage.iconHoverPunchedImage.hoverIcon
PunchedImage.iconBadgePunchedImage.badgeIcon
AmountInput.amountObjectAmountInput.value, AmountInput.precision, AmountInput.currency
AmountInput.onInputBlurAmountInput.onBlur, AmountInput.onFormat, AmountInput.onInput
AmountInput.onInputFocusAmountInput.onFocus
Badge.variationBadge.type
Pill.variationPill.type
MoneyFormatterAmount
formatMoneyformatAmount