Skip to content

Commit

Permalink
Merge pull request #37 from brionmario/feat-footer
Browse files Browse the repository at this point in the history
feat(react): add `Footer` component
  • Loading branch information
brionmario authored Feb 16, 2023
2 parents ba3f05e + 06b98d5 commit f666673
Show file tree
Hide file tree
Showing 9 changed files with 318 additions and 0 deletions.
5 changes: 5 additions & 0 deletions packages/react/.storybook/story-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export type Stories =
| 'Container'
| 'Divider'
| 'Drawer'
| 'Footer'
| 'Grid'
| 'Header'
| 'IconButton'
Expand All @@ -70,6 +71,7 @@ export type Stories =
| 'Tooltip'
| 'Typeset'
| 'Typography'
| 'UserDropdownMenu'
| 'Welcome';
export type StorybookConfig = Record<
Stories,
Expand Down Expand Up @@ -142,6 +144,9 @@ const StoryConfig: StorybookConfig = {
Drawer: {
hierarchy: `${StorybookCategories.Navigation}/Drawer`,
},
Footer: {
hierarchy: `${StorybookCategories.Navigation}/Footer`,
},
Grid: {
hierarchy: `${StorybookCategories.Layout}/Grid`,
},
Expand Down
89 changes: 89 additions & 0 deletions packages/react/src/components/Footer/Footer.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import {useArgs} from '@storybook/client-api';
import {ArgsTable, Source, Story, Canvas, Meta} from '@storybook/addon-docs';
import dedent from 'ts-dedent';
import StoryConfig from '../../../.storybook/story-config.ts';
import Footer from './Footer.tsx';

export const meta = {
component: Footer,
title: StoryConfig.Footer.hierarchy,
};

<Meta title={meta.title} component={meta.component} />

export const Template = args => {
const [runtimeArgs, updateArgs] = useArgs();
return <Footer {...args} />;
};

# Navbar

- [Overview](#overview)
- [Props](#props)
- [Usage](#usage)

## Overview

Footers display a set of links and a copyright at the bottom of the application.

<Canvas>
<Story
name="Overview"
args={{
copyright: <>&copy;&nbsp;{new Date().getFullYear()}, <span>WSO2 LLC.</span></>,
links: [
{
children: 'Terms of Use',
href: '/terms',
},
{
children: 'Privacy Policy',
href: '/privacy',
},
{
children: 'Support',
href: '/support',
},
],
}}
>
{Template.bind({})}
</Story>
</Canvas>

## Props

<ArgsTable story="Overview" />

## Usage

Import and use the `Footer` component in your components as follows.

<Source
language="jsx"
dark
format
code={dedent`
import Footer from '@oxygen-ui/react/Footer';\n
function Demo() {
return (
<Footer
copyright: <span>2023 WSO2 LLC.</span>,
links: [
{
children: 'Terms of Use',
href: '/terms',
},
{
children: 'Privacy Policy',
href: '/privacy',
},
{
children: 'Support',
href: '/support',
},
],
/>
);
}`}
/>
91 changes: 91 additions & 0 deletions packages/react/src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import {useMediaQuery} from '@mui/material';
import clsx from 'clsx';
import {FC, ReactElement, ReactNode} from 'react';
import {Theme, WithWrapperProps} from '../../models';
import {useTheme} from '../../theme/use-theme';
import {composeComponentDisplayName} from '../../utils';
import Box, {BoxProps} from '../Box';
import Container, {ContainerProps} from '../Container';
import Link, {LinkProps} from '../Link';
import Typography from '../Typography';
import './footer.scss';

export interface FooterProps extends BoxProps {
/**
* Copyright to display.
*/
copyright?: ReactNode;
/**
* Footer links.
*/
links?: LinkProps[];
/**
* Determine the max-width of the footer container.
*/
maxWidth?: ContainerProps['maxWidth'];
}

const COMPONENT_NAME: string = 'Footer';

const Footer: FC<FooterProps> & WithWrapperProps = (props: FooterProps): ReactElement => {
const {className, copyright, links, maxWidth, ...rest} = props;

const theme: Theme = useTheme();
const isMobile: boolean = useMediaQuery(theme.breakpoints.down(theme.breakpoints.values.sm));

const classes: string = clsx('oxygen-footer', {mobile: isMobile}, className);

return (
<Box component="footer" className={classes} {...rest}>
<Container disableGutters maxWidth={maxWidth} className="oxygen-footer-container">
{links !== undefined && Array.isArray(links) && links.length > 0 && (
<Box className="oxygen-footer-links" fontSize="body2.fontSize">
{links.map((link: LinkProps) => (
<Link
className="oxygen-footer-link"
underline="none"
target="_blank"
rel="noopener"
color="textSecondary"
{...link}
/>
))}
</Box>
)}
{copyright && (
<Box className="oxygen-footer-links">
<Box color="text.secondary">
<Typography className="oxygen-footer-copyright" display="inline" variant="body2">
{copyright}
</Typography>
</Box>
</Box>
)}
</Container>
</Box>
);
};

Footer.displayName = composeComponentDisplayName(COMPONENT_NAME);
Footer.muiName = COMPONENT_NAME;
Footer.defaultProps = {};

export default Footer;
32 changes: 32 additions & 0 deletions packages/react/src/components/Footer/__tests__/Footer.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import {render} from '@unit-testing';
import Footer from '../Footer';

describe('Footer', () => {
it('should render successfully', () => {
const {baseElement} = render(<Footer />);
expect(baseElement).toBeTruthy();
});

it('should match the snapshot', () => {
const {baseElement} = render(<Footer />);
expect(baseElement).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Footer should match the snapshot 1`] = `
<body>
<div>
<footer
class="oxygen-box oxygen-footer MuiBox-root css-0"
>
<div
class="MuiContainer-root MuiContainer-maxWidthLg MuiContainer-disableGutters oxygen-container oxygen-footer-container css-1p4tas-MuiContainer-root"
/>
</footer>
</div>
</body>
`;
54 changes: 54 additions & 0 deletions packages/react/src/components/Footer/footer.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

.oxygen-footer {
padding: 8px 16px;
margin-top: auto;
border-top: 1px solid var(--oxygen-palette-divider);
background: var(--oxygen-palette-customComponents-Footer-background);

.oxygen-footer-container {
display: flex;
justify-content: space-between;
align-content: center;
align-items: center;
flex-flow: row wrap;
}

&.mobile {
.oxygen-footer-container {
justify-content: center;
}
}

.oxygen-footer-links {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
flex-flow: row wrap;

.oxygen-footer-link {
margin-right: 8px;

&:not(:first-child) {
margin-left: 8px;
}
}
}
}
20 changes: 20 additions & 0 deletions packages/react/src/components/Footer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export {default} from './Footer';
export type {NavbarProps} from './Footer';
6 changes: 6 additions & 0 deletions packages/react/src/models/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import {CssVarsTheme, Theme as MuiTheme} from '@mui/material/styles';
declare module '@mui/material/styles' {
interface PaletteOptions {
customComponents: {
Footer: {
background: string;
};
Navbar: {
background: string;
};
Expand All @@ -37,6 +40,9 @@ declare module '@mui/material/styles' {
}
interface Palette {
customComponents: {
Footer: {
background: string;
};
Navbar: {
background: string;
};
Expand Down
6 changes: 6 additions & 0 deletions packages/react/src/theme/default-theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export const DEFAULT_THEME_OPTIONS: RecursivePartial<Theme> = {
dark: {
palette: {
customComponents: {
Footer: {
background: '#000000',
},
Navbar: {
background: '#262626',
},
Expand All @@ -44,6 +47,9 @@ export const DEFAULT_THEME_OPTIONS: RecursivePartial<Theme> = {
light: {
palette: {
customComponents: {
Footer: {
background: '#f7f8fb',
},
Navbar: {
background: '#fbfbfb',
},
Expand Down

0 comments on commit f666673

Please sign in to comment.