Skip to content

Commit

Permalink
Feat(web-react): Add minimalistic footer demo #DS-1574
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelklibani committed Dec 12, 2024
1 parent 3c86457 commit 33fc104
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 14 deletions.
18 changes: 14 additions & 4 deletions packages/web-react/src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,26 @@

import classNames from 'classnames';
import React from 'react';
import { BackgroundColors } from '../../constants';
import { useStyleProps } from '../../hooks';
import { SpiritFooterProps } from '../../types';
import { PADDING_BOTTOM, PADDING_TOP } from './constants';
import { useFooterStyleProps } from './useFooterStyleProps';

const Footer = (props: SpiritFooterProps): JSX.Element => {
const { children, ...restProps } = props;
const defaultStyleProps: Partial<SpiritFooterProps> = {
backgroundColor: BackgroundColors.SECONDARY,
paddingBottom: PADDING_BOTTOM,
paddingTop: PADDING_TOP,
};

const Footer = (props: SpiritFooterProps) => {
const propsWithDefaults = { ...defaultStyleProps, ...props };
const { children, backgroundColor, paddingBottom, paddingTop, ...restProps } = propsWithDefaults;
const { classProps } = useFooterStyleProps({ backgroundColor, paddingBottom, paddingTop });
const { styleProps, props: otherProps } = useStyleProps(restProps);
const footerClasses = 'bg-secondary pt-1400 pb-1200';

return (
<footer {...styleProps} {...otherProps} className={classNames(footerClasses, styleProps.className)}>
<footer {...styleProps} {...otherProps} className={classNames(classProps, styleProps.className)}>
{children}
</footer>
);
Expand Down
20 changes: 18 additions & 2 deletions packages/web-react/src/components/Footer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The Footer supports several ready-to-use building blocks:
This is how all supported building blocks of the Footer build up the complete composition:

```jsx
<Footer UNSAFE_className="bg-secondary pt-1400 pb-1200">
<Footer>
<Container>
{/* Grid with navigation links */}
{/* Grid with product logo, social media links and language switch */}
Expand Down Expand Up @@ -137,7 +137,7 @@ This section is optional and consists of a [Flex][flex] layout with secondary li
## Full Example

```jsx
<Footer UNSAFE_className="bg-secondary pt-1400 pb-1200">
<Footer>
<Container>
{/* Grid with navigation links */}
<Grid cols={{ mobile: 1, tablet: 2, desktop: 4 }} spacing="space-1000">
Expand Down Expand Up @@ -252,11 +252,27 @@ This section is optional and consists of a [Flex][flex] layout with secondary li
</Footer>
```

### API

| Name | Type | Default | Required | Description |
| ----------------- | ---------------------------------------------------------- | ------------ | -------- | ----------------------------------------------- |
| `backgroundColor` | [Background Color dictionary][dictionary-background-color] | `secondary` || Sets the background color of the footer |
| `paddingBottom` | `SpaceToken` | `space-1400` || Defines the padding at the bottom of the footer |
| `paddingTop` | `SpaceToken` | `space-1200` || Defines the padding at the top of the footer |

On top of the API options, the components accept [additional attributes][readme-additional-attributes].
If you need more control over the styling of a component, you can use [style props][readme-style-props]
and [escape hatches][readme-escape-hatches].

[buttonlink]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/ButtonLink/README.md
[dictionary-background-color]: https://github.com/lmc-eu/spirit-design-system/blob/main/docs/DICTIONARIES.md#color
[divider]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/Divider/README.md
[flex]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/Flex/README.md
[grid]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/Grid/README.md
[product-logo]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/ProductLogo/README.md
[readme-additional-attributes]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#additional-attributes
[readme-escape-hatches]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#escape-hatches
[readme-style-props]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#style-props
[readme-style-props]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/README.md#style-props
[select]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/Select/README.md
[stack]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/Stack/README.md
17 changes: 17 additions & 0 deletions packages/web-react/src/components/Footer/__tests__/Footer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import '@testing-library/jest-dom';
import { restPropsTest } from '../../../../tests/providerTests/restPropsTest';
import { stylePropsTest } from '../../../../tests/providerTests/stylePropsTest';
import { BackgroundColors } from '../../../constants';
import Footer from '../Footer';

describe('Footer', () => {
Expand All @@ -15,4 +16,20 @@ describe('Footer', () => {

expect(screen.getByRole('contentinfo')).toHaveTextContent('Hello World');
});

it.each([Object.values(BackgroundColors)])('should have background %s color', (color) => {
render(<Footer backgroundColor={color}>Hello World</Footer>);

expect(screen.getByRole('contentinfo')).toHaveClass(`bg-${color}`);
});

it('should have correct correct utility class paddings', () => {
render(
<Footer paddingTop="space-1000" paddingBottom="space-1100">
Hello World
</Footer>,
);

expect(screen.getByRole('contentinfo')).toHaveClass('pt-1000 pb-1100');
});
});
2 changes: 2 additions & 0 deletions packages/web-react/src/components/Footer/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const PADDING_BOTTOM = 'space-1200';
export const PADDING_TOP = 'space-1400';
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ const FooterDefault = () => {
elementType="ul"
direction={{ mobile: 'column', tablet: 'row' }}
alignmentX={{ mobile: 'stretch', tablet: 'center' }}
spacing={{ mobile: 'space-600', tablet: 'space-900' }}
spacingX={{ mobile: 'space-600', tablet: 'space-900' }}
isWrapping
>
<li>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from 'react';
import { Container } from '../../Container';
import { Flex } from '../../Flex';
import { Grid, GridItem } from '../../Grid';
import { Link } from '../../Link';
import { ProductLogo } from '../../ProductLogo';
import { defaultSvgLogo } from '../../ProductLogo/demo/ProductLogoDefault';
import { Select } from '../../Select';
import Footer from '../Footer';

const FooterMinimalistic = () => {
return (
<Footer paddingBottom="space-900" paddingTop="space-900">
<Container>
{/* Grid with product logo, social media links and language switch */}
<Grid
cols={{ mobile: 1, desktop: 12 }}
alignmentX={{ mobile: 'center', desktop: 'stretch' }}
alignmentY="center"
spacingY="space-1100"
>
{/* Product logo */}
<GridItem columnStart={{ desktop: 1 }} columnEnd={{ desktop: 4 }}>
<div className="text-desktop-left">
<Link href="https://www.example.com">
<ProductLogo>{defaultSvgLogo}</ProductLogo>
</Link>
</div>
</GridItem>

{/* Flex with secondary links */}
<GridItem columnStart={{ desktop: 4 }} columnEnd={{ desktop: 10 }}>
<nav className="text-center" aria-label="Secondary links">
<Flex
elementType="ul"
direction={{ mobile: 'column', tablet: 'row' }}
alignmentX={{ mobile: 'stretch', tablet: 'center' }}
spacingX={{ mobile: 'space-600', tablet: 'space-900' }}
isWrapping
>
<li>
<Link href="https://www.example.com" color="secondary">
Legal notice
</Link>
</li>
<li>
<Link href="https://www.example.com" color="secondary">
Terms of service
</Link>
</li>
<li>
<Link href="https://www.example.com" color="secondary">
Privacy policy
</Link>
</li>
<li>
<Link href="https://www.example.com" color="secondary">
Manage cookies
</Link>
</li>
</Flex>
</nav>
</GridItem>

{/* Language switch */}
<GridItem columnStart={{ desktop: 11 }} columnEnd={{ desktop: 13 }}>
<div className="text-desktop-right">
<Select id="select-language" name="selectLanguage" label="Language" isLabelHidden isFluid>
<option value="en">English</option>
<option value="cs">Čeština</option>
</Select>
</div>
</GridItem>
</Grid>
</Container>
</Footer>
);
};

export default FooterMinimalistic;
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import FooterLinkFactory from './FooterLinkFactory';

const FooterNested = () => {
return (
<Footer UNSAFE_className="bg-secondary pt-1400 pb-1200">
<Footer>
<Container>
{/* Grid with navigation links */}
<Grid cols={{ mobile: 1, tablet: 2, desktop: 6 }} spacing="space-1000">
Expand Down Expand Up @@ -121,7 +121,7 @@ const FooterNested = () => {
elementType="ul"
direction={{ mobile: 'column', tablet: 'row' }}
alignmentX={{ mobile: 'stretch', tablet: 'center' }}
spacing={{ mobile: 'space-600', tablet: 'space-900' }}
spacingX={{ mobile: 'space-600', tablet: 'space-900' }}
isWrapping
>
<li>
Expand Down
4 changes: 4 additions & 0 deletions packages/web-react/src/components/Footer/demo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import ReactDOM from 'react-dom/client';
import DocsSection from '../../../../docs/DocsSections';
import { IconsProvider } from '../../../context';
import FooterDefault from './FooterDefault';
import FooterMinimalistic from './FooterMinimalistic';
import FooterNested from './FooterNested';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
Expand All @@ -19,6 +20,9 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<DocsSection title="Nested Link Blocks, Logo Only" stackAlignment="stretch" container="heading-only">
<FooterNested />
</DocsSection>
<DocsSection title="Minimalistic" stackAlignment="stretch" container="heading-only">
<FooterMinimalistic />
</DocsSection>
</IconsProvider>
</React.StrictMode>,
);
2 changes: 1 addition & 1 deletion packages/web-react/src/components/Footer/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{{> web-react/demo}}
{{> web-react/demo title="Footer" parentPageName="Components"}}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Markdown } from '@storybook/blocks';
import type { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import { BackgroundColors } from '../../../constants';
import { Container } from '../../Container';
import { PADDING_BOTTOM, PADDING_TOP } from '../constants';
import Footer from '../Footer';
import ReadMe from '../README.md';
import { Footer } from '..';

const meta: Meta<typeof Footer> = {
title: 'Components/Footer',
Expand All @@ -17,9 +19,31 @@ const meta: Meta<typeof Footer> = {
children: {
control: 'object',
},
backgroundColor: {
control: 'select',
options: [...Object.values(BackgroundColors)],
table: {
defaultValue: { summary: BackgroundColors.SECONDARY },
},
},
paddingBottom: {
control: 'text',
table: {
defaultValue: { summary: 'space-1200' },
},
},
paddingTop: {
control: 'text',
table: {
defaultValue: { summary: 'space-1400' },
},
},
},
args: {
children: <Container>Footer content</Container>,
backgroundColor: BackgroundColors.SECONDARY,
paddingBottom: PADDING_BOTTOM,
paddingTop: PADDING_TOP,
},
};

Expand All @@ -28,5 +52,5 @@ type Story = StoryObj<typeof Footer>;

export const Playground: Story = {
name: 'Footer',
render: (args) => <Footer UNSAFE_className="bg-secondary pt-1400 pb-1200" {...args} />,
render: (args) => <Footer {...args} />,
};
24 changes: 24 additions & 0 deletions packages/web-react/src/components/Footer/useFooterStyleProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import classNames from 'classnames';
import { SpiritFooterProps } from '../../types';

export interface UseFooterStyleProps {
classProps: string;
}

export function useFooterStyleProps(props: Partial<SpiritFooterProps>): UseFooterStyleProps {
const { backgroundColor, paddingBottom, paddingTop } = props;

const footerBackgroundColor = backgroundColor ? `bg-${backgroundColor}` : '';
const footerPaddingBottom = paddingBottom ? paddingBottom.replace('space-', 'pb-') : '';
const footerPaddingTop = paddingTop ? paddingTop.replace('space-', 'pt-') : '';

const classProps = classNames({
[footerBackgroundColor]: backgroundColor,
[footerPaddingBottom]: paddingBottom,
[footerPaddingTop]: paddingTop,
});

return {
classProps,
};
}
10 changes: 8 additions & 2 deletions packages/web-react/src/types/footer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import { ChildrenProps, StyleProps, TransferProps } from './shared';
import { BackgroundColorsDictionaryType, ChildrenProps, SpaceToken, StyleProps, TransferProps } from './shared';

export interface SpiritFooterProps extends ChildrenProps, StyleProps, TransferProps {}
export interface FooterStyleProps {
paddingTop?: SpaceToken;
paddingBottom?: SpaceToken;
backgroundColor?: BackgroundColorsDictionaryType;
}

export interface SpiritFooterProps extends FooterStyleProps, ChildrenProps, StyleProps, TransferProps {}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 33fc104

Please sign in to comment.