Skip to content

Commit

Permalink
feat: add environment to navbar switcher (#2857)
Browse files Browse the repository at this point in the history
* feat: add environment to navbar switcher

* refactor: improve env color check

* refactor: improve types and fix typo

* refactor: update color of caret icon
  • Loading branch information
massao committed Sep 9, 2024
1 parent e25956b commit 64d2a58
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 37 deletions.
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/components/navbar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@contentful/f36-skeleton": "^4.68.1",
"@contentful/f36-tokens": "^4.0.1",
"@contentful/f36-tooltip": "^4.68.1",
"@contentful/f36-typography": "5.0.0-alpha.1",
"@contentful/f36-utils": "^4.23.2",
"emotion": "^10.0.17"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function NavbarEnvVariant({
envVariant,
className,
}: NavbarEnvVariantProps) {
const color = envVariant === 'master' ? tokens.green600 : tokens.orange500;
const color = envVariant === 'master' ? tokens.green600 : tokens.gray600;

return isAlias ? (
<EnvironmentAliasIcon color={color} className={className} size="medium" />
Expand Down
110 changes: 87 additions & 23 deletions packages/components/navbar/src/NavbarSwitcher/NavbarSwitcher.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { type ReactNode } from 'react';
import React, { useMemo } from 'react';
import { getNavbarSwitcherStyles } from './NavbarSwitcher.styles';
import { Button } from '@contentful/f36-button';
import {
Expand All @@ -9,6 +9,10 @@ import {
} from '@contentful/f36-core';
import { cx } from 'emotion';
import { NavbarEnvVariant } from './NavbarEnvVariant';
import { NavbarSwitcherSkeleton } from './NavbarSwitcherSkeleton';
import { CaretRightIcon } from '@contentful/f36-icons';
import { Text } from '@contentful/f36-typography';
import tokens from '@contentful/f36-tokens';

type TruncateOptions = {
/**
Expand All @@ -23,7 +27,7 @@ type TruncateOptions = {
end?: number;
};

function splitSpaceName(
function splitString(
string: string,
{
start: startLength = 5,
Expand All @@ -41,35 +45,94 @@ function splitSpaceName(
return [start, remainder, end];
}

type NavbarSwitcherOwnProps = CommonProps & {
children: ReactNode;
isCircle?: boolean;
envVariant?: 'master' | 'non-master';
isAlias?: boolean;
ariaLabel?: string;
};
type NavbarLoadingProps =
| {
isLoading?: true;
environment?: never;
space?: never;
}
| {
isLoading?: false;
environment?: string;
space?: string;
};

type NavbarSwitcherOwnProps = CommonProps &
NavbarLoadingProps & {
isCircle?: boolean;
envVariant?: 'master' | 'non-master';
isAlias?: boolean;
ariaLabel?: string;
};

export type NavbarSwitcherProps = PropsWithHTMLElement<
NavbarSwitcherOwnProps,
'button'
>;

type SwitcherLabelEnvVariantProps =
| {
type: 'environment';
envVariant?: 'master' | 'non-master';
}
| {
type: 'space';
envVariant?: never;
};

type SwitcherLabelProps = SwitcherLabelEnvVariantProps & {
value: React.ReactNode;
styles: ReturnType<typeof getNavbarSwitcherStyles>;
type: 'space' | 'environment';
envVariant?: 'master' | 'non-master';
};

const SwitcherLabel = ({
value,
styles,
envVariant,
type,
}: SwitcherLabelProps) => {
const [start, middle, end] =
typeof value === 'string' ? splitString(value) : [];
const envColor = useMemo(() => {
const isEnv = type === 'environment';
const isMaster = envVariant === 'master';
if (isEnv && isMaster) {
return 'green600';
}
return 'gray600';
}, [type, envVariant]);

return start !== undefined ? (
<Text fontColor={envColor}>
<span>{start}</span>
{middle && (
<span className={styles.switcherSpaceNameTruncation}>{middle}</span>
)}
{end && <span>{end}</span>}
</Text>
) : (
<Text fontColor={envColor}>{value}</Text>
);
};

function _NavbarSwitcher(
props: ExpandProps<NavbarSwitcherProps>,
ref: React.Ref<HTMLButtonElement>,
) {
const {
children,
className,
envVariant,
isAlias,
testId = 'cf-ui-navbar-switcher',
ariaLabel = 'Space and Environment Navigation',
space,
environment,
isLoading,
...otherProps
} = props;
const styles = getNavbarSwitcherStyles();
const [start, middle, end] =
typeof children === 'string' ? splitSpaceName(children) : [];

return (
<Button
Expand All @@ -94,18 +157,19 @@ function _NavbarSwitcher(
className={styles.switcherSpaceName}
flexDirection="row"
>
{start !== undefined ? (
<>
<span>{start}</span>
{middle && (
<span className={styles.switcherSpaceNameTruncation}>
{middle}
</span>
)}
{end && <span>{end}</span>}
</>
{isLoading ? (
<NavbarSwitcherSkeleton estimatedWidth={148} />
) : (
children
<Flex gap={tokens.spacing2Xs} alignItems="center">
<SwitcherLabel type="space" value={space} styles={styles} />
<CaretRightIcon size="tiny" color={tokens.gray500} />
<SwitcherLabel
envVariant={envVariant}
type="environment"
value={environment}
styles={styles}
/>
</Flex>
)}
</Flex>
</Button>
Expand Down
36 changes: 23 additions & 13 deletions packages/components/navbar/stories/Navbar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@ export default {
} as Meta;

const Switcher = ({
children = 'Our super long space name',
space = 'Our super long space name',
environment = 'master',
isAlias = false,
envVariant = 'master',
}: Partial<NavbarSwitcherProps>) => (
<Navbar.Switcher isAlias={isAlias} envVariant={envVariant}>
{children}
</Navbar.Switcher>
<Navbar.Switcher
isAlias={isAlias}
envVariant={envVariant}
space={space}
environment={environment}
/>
);

const Account = ({
Expand Down Expand Up @@ -121,7 +125,7 @@ const MainItems = () => {

export const Basic: Story<{ initials?: string; avatar?: string }> = (args) => {
return (
<div style={{ width: '900px' }}>
<div style={{ minWidth: '900px' }}>
<Navbar
mainNavigation={<MainItems />}
switcher={<Switcher />}
Expand Down Expand Up @@ -163,7 +167,7 @@ export const WithInitialsAvatar: Story<{
avatar?: string;
}> = (args) => {
return (
<div style={{ width: '900px' }}>
<div style={{ minWidth: '900px' }}>
<Navbar
switcher={<Switcher />}
account={<Account {...args} />}
Expand All @@ -179,7 +183,7 @@ WithInitialsAvatar.args = {

export const WithFallbackAvatar: Story<{}> = (args) => {
return (
<div style={{ width: '900px' }}>
<div style={{ minWidth: '900px' }}>
<Navbar
switcher={<Switcher />}
account={<Account {...args} />}
Expand All @@ -195,7 +199,7 @@ export const WithShortSpaceName = () => {
return (
<Navbar
mainNavigation={<MainItems />}
switcher={<Switcher>Space</Switcher>}
switcher={<Switcher space="Space" />}
account={<Account />}
/>
);
Expand Down Expand Up @@ -422,7 +426,7 @@ export const WithDifferentEnvironments: Story<{
avatar?: string;
}> = (args) => {
return (
<Flex flexDirection="column" gap="spacingL" style={{ width: '900px' }}>
<Flex flexDirection="column" gap="spacingL" style={{ minWidth: '900px' }}>
<Flex flexDirection="column">
<SectionHeading as="h3" marginBottom="spacingS">
Master
Expand All @@ -444,7 +448,13 @@ export const WithDifferentEnvironments: Story<{
<Navbar
mobileNavigation={<MobileMenu />}
mainNavigation={<MainItems />}
switcher={<Switcher envVariant="non-master">development</Switcher>}
switcher={
<Switcher
envVariant="non-master"
space="development"
environment="development"
/>
}
account={<Account {...args} />}
/>
</Flex>
Expand All @@ -470,7 +480,7 @@ export const WithDifferentEnvironments: Story<{
<Navbar
mobileNavigation={<MobileMenu />}
mainNavigation={<MainItems />}
switcher={<Switcher isAlias envVariant="non-master"></Switcher>}
switcher={<Switcher isAlias envVariant="non-master" />}
account={<Account {...args} />}
/>
</Flex>
Expand All @@ -489,7 +499,7 @@ export const WithAccountNotification: Story<{
avatar?: string;
}> = (args) => {
return (
<Flex flexDirection="column" gap="spacingL" style={{ width: '900px' }}>
<Flex flexDirection="column" gap="spacingL" style={{ minWidth: '900px' }}>
<Flex flexDirection="column">
<SectionHeading as="h3" marginBottom="spacingS">
Warning
Expand Down Expand Up @@ -548,7 +558,7 @@ export const LoadingSkeleton: Story<{}> = () => {
<Navbar
mobileNavigation={<MobileMenu />}
account={<Navbar.AccountSkeleton ariaLabel="Loading account" />}
switcher={<Navbar.SwitcherSkeleton estimatedWidth={148} />}
switcher={<Navbar.Switcher isLoading />}
mainNavigation={
<>
<Navbar.ItemSkeleton estimatedWidth={100} />
Expand Down

0 comments on commit 64d2a58

Please sign in to comment.