Skip to content

Commit

Permalink
✨ feat: added scrollable option to header and footer components
Browse files Browse the repository at this point in the history
  • Loading branch information
e1en0r committed Nov 7, 2024
1 parent 745a367 commit 1404bfd
Show file tree
Hide file tree
Showing 11 changed files with 291 additions and 28 deletions.
16 changes: 15 additions & 1 deletion src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { cx } from '@emotion/css';
import React from 'react';
import { SequentialVariant, ThemeProps } from '../../types';
import { useAccessibility } from '../../context/Accessibility/useAccessibility';
import { useThemeId } from '../../context/Theme';
import styles from './styles/Footer.module.css';

Expand All @@ -11,6 +12,10 @@ export type FooterProps = React.HTMLAttributes<HTMLDivElement> &
className?: string;
full?: boolean;
style?: React.CSSProperties;
/** When used with the scrollable flag the footer will overflow horizontally instead of wrapping */
nowrap?: boolean;
scrollable?: boolean;
scrollbar?: 'xsmall' | 'small' | 'medium';
transparent?: boolean;
variant?: SequentialVariant;
volume?: 'quiet';
Expand All @@ -27,6 +32,9 @@ export function Footer({
className,
contrast = false,
full = false,
nowrap = false,
scrollable = false,
scrollbar = 'small',
themeId: initThemeId,
transparent = false,
unthemed = false,
Expand All @@ -35,22 +43,28 @@ export function Footer({
...props
}: FooterProps): JSX.Element {
const themeId = useThemeId(initThemeId);
const accessible = useAccessibility();
const variant = contrast ? 'contrast' : initVariant;

const classes = cx(
styles.footer,
bordered && styles['footer--bordered'],
bordered === 'pseudo' && styles['footer--bordered-pseudo'],
full && styles['footer--full'],
nowrap && styles['footer--nowrap'],
scrollable && styles['footer--scrollable'],
scrollbar && styles[`footer--${scrollbar}-scrollbar`],
!unthemed && themeId && styles[`footer--${themeId}`],
!unthemed && variant && styles[`footer--${variant}`],
transparent && styles['footer--transparent'],
volume && styles[`footer--${volume}`],
accessible && styles['is-accessible'],
className,
);

return (
<div className={classes} {...props}>
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
<div className={classes} tabIndex={scrollable ? 0 : undefined} {...props}>
{children}
</div>
);
Expand Down
29 changes: 23 additions & 6 deletions src/components/Footer/StyledFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,34 @@ import styled from '@emotion/styled';
import React from 'react';
import { Footer, FooterProps } from './Footer';

export type StyledFooterProps = Omit<FooterProps, 'contrast' | 'themeId'> & {
export type StyledFooterProps = Omit<FooterProps, 'contrast'> & {
backgroundColor?: string;
borderColor?: string;
focusedOutlineColor?: string;
scrollbarColor?: string;
textColor?: string;
height?: number | string;
/** Allow the footer to fall back to the normal theme */
themed?: boolean;
};

const BaseStyledFooter = styled(Footer, {
shouldForwardProp: (prop: string) => !['borderColor', 'backgroundColor', 'textColor', 'height'].includes(prop),
shouldForwardProp: (prop: string) =>
!['borderColor', 'backgroundColor', 'focusedOutlineColor', 'scrollbarThumbColor', 'textColor', 'height'].includes(
prop,
),
})<StyledFooterProps>`
${({ backgroundColor }) => backgroundColor && `--footer-background-color: ${backgroundColor};`}
${({ borderColor }) => borderColor && `--footer-border-color: ${borderColor};`}
${({ textColor }) => textColor && `--footer-text-color: ${textColor};`}
${({ backgroundColor, unthemed }) =>
backgroundColor && `--footer-background-color: ${backgroundColor}${unthemed ? '' : ' !important'};`}
${({ borderColor, unthemed }) =>
borderColor && `--footer-border-color: ${borderColor}${unthemed ? '' : ' !important'};`}
${({ focusedOutlineColor, unthemed }) =>
focusedOutlineColor && `--footer-focused-outline-color: ${focusedOutlineColor}${unthemed ? '' : ' !important'};`}
${({ scrollbarColor, unthemed }) =>
scrollbarColor && `--footer-scrollbar-thumb-color: ${scrollbarColor}${unthemed ? '' : ' !important'};`}
${({ textColor, unthemed }) => textColor && `--footer-text-color: ${textColor}${unthemed ? '' : ' !important'};`}
${({ height }) => height !== undefined && `height: ${Number.isNaN(Number(height)) ? height : `${height}px`};`}
`;

Expand All @@ -24,6 +39,8 @@ const BaseStyledFooter = styled(Footer, {
* and background colors, and an optional custom
* height.
*/
export const StyledFooter = (props: StyledFooterProps) => <BaseStyledFooter {...props} unthemed />;
export const StyledFooter = ({ themed, ...props }: StyledFooterProps) => (
<BaseStyledFooter {...props} unthemed={!themed} />
);

StyledFooter.displayName = 'StyledFooter';
37 changes: 37 additions & 0 deletions src/components/Footer/stories/Footer.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,26 @@ export default {
type: 'text',
},
},
nowrap: {
table: {
category: 'Appearance',
},
},
full: {
table: {
category: 'Appearance',
},
},
scrollable: {
table: {
category: 'Appearance',
},
},
scrollbar: {
table: {
category: 'Appearance',
},
},
transparent: {
table: {
category: 'Appearance',
Expand Down Expand Up @@ -162,3 +177,25 @@ TertiaryVariant.args = {
bordered: true,
variant: 'tertiary',
};

export const Scrollable = Template.bind({});
Scrollable.args = {
...defaultArgs,
children: (
<React.Fragment>
<div>Superlongword</div>
<div>Superlongword</div>
<div>Superlongword</div>
<div>Superlongword</div>
<div>Superlongword</div>
<div>Superlongword</div>
<div>Superlongword</div>
<div>Superlongword</div>
<div>Superlongword</div>
<div>Superlongword</div>
</React.Fragment>
),
nowrap: true,
scrollable: true,
scrollbar: 'small',
};
28 changes: 27 additions & 1 deletion src/components/Footer/stories/StyledFooter.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,32 @@ export default {
category: 'Styled',
},
},
focusedOutlineColor: {
table: {
category: 'Styled',
},
},
scrollbarColor: {
table: {
category: 'Styled',
},
},
textColor: {
table: {
category: 'Styled',
},
},
footerColor: {
themed: {
table: {
category: 'Styled',
},
},

themeId: {
table: {
category: 'Uncommon',
},
},
...argTypes,
},
parameters: {
Expand Down Expand Up @@ -77,6 +93,7 @@ const defaultArgs = {
borderColor: '#393a61',
textColor: '#fff',
height: 50,
themed: false,
variant: undefined,
};

Expand All @@ -85,6 +102,15 @@ Default.args = {
...defaultArgs,
};

export const Themed = Template.bind({});
Themed.storyName = 'Inherit theme';
Themed.args = {
bordered: true,
height: 50,
variant: 'primary',
themed: true,
};

/*
Default.parameters = {
jest: ['StyledFooter.test.js', 'Footer.test.js'],
Expand Down
59 changes: 47 additions & 12 deletions src/components/Footer/styles/Footer.module.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import '../../../styles/common/mixins/addScrollbar.css';

.footer {
align-items: center;
background-color: var(--footer-background-color);
Expand All @@ -10,6 +12,10 @@
width: 100%;
}

.footer--nowrap {
flex-wrap: nowrap;
}

/**
* 1. Use a pseudo element rather than a border so that
* it doesn't add height to the box element.
Expand All @@ -35,6 +41,10 @@
.footer--primary {
@mixin themed .footer {
--footer-border-color: $theme-primary-palette-border-color;
--footer-focused-outline-color: $theme-primary-palette-text-color;
--footer-scrollbar-thumb-color: $theme-primary-scrollbar-thumb-color;
--footer-background-color: $theme-primary-palette-background-color;
--footer-text-color: $theme-primary-palette-text-color;

&.footer--quiet {
--footer-border-color: $theme-primary-palette-quiet-border-color;
Expand All @@ -43,15 +53,16 @@
&.footer--transparent {
background-color: transparent;
}

background-color: $theme-primary-palette-background-color;
color: $theme-primary-palette-text-color;
}
}

.footer--secondary {
@mixin themed .footer {
--footer-border-color: $theme-secondary-palette-border-color;
--footer-focused-outline-color: $theme-secondary-palette-text-color;
--footer-scrollbar-thumb-color: $theme-primary-scrollbar-thumb-color;
--footer-background-color: $theme-secondary-palette-background-color;
--footer-text-color: $theme-secondary-palette-text-color;

&.footer--quiet {
--footer-border-color: $theme-secondary-palette-quiet-border-color;
Expand All @@ -60,15 +71,16 @@
&.footer--transparent {
background-color: transparent;
}

background-color: $theme-secondary-palette-background-color;
color: $theme-secondary-palette-text-color;
}
}

.footer--tertiary {
@mixin themed .footer {
--footer-border-color: $theme-tertiary-palette-border-color;
--footer-focused-outline-color: $theme-tertiary-palette-text-color;
--footer-scrollbar-thumb-color: $theme-primary-scrollbar-thumb-color;
--footer-background-color: $theme-tertiary-palette-background-color;
--footer-textcolor: $theme-tertiary-palette-text-color;

&.footer--quiet {
--footer-border-color: $theme-tertiary-palette-quiet-border-color;
Expand All @@ -77,15 +89,16 @@
&.footer--transparent {
background-color: transparent;
}

background-color: $theme-tertiary-palette-background-color;
color: $theme-tertiary-palette-text-color;
}
}

.footer--contrast {
@mixin themed .footer {
--footer-border-color: $theme-contrast-palette-border-color;
--footer-focused-outline-color: $theme-contrast-palette-text-color;
--footer-scrollbar-thumb-color: $theme-contrast-scrollbar-thumb-color;
--footer-background-color: var(--phork-contrast-color, $theme-contrast-palette-background-color);
--footer-text-color: $theme-contrast-palette-text-color;

&.footer--quiet {
--footer-border-color: $theme-contrast-palette-quiet-border-color;
Expand All @@ -94,13 +107,35 @@
&.footer--transparent {
background-color: transparent;
}

background-color: var(--phork-contrast-color, $theme-contrast-palette-background-color);
color: $theme-contrast-palette-text-color;
}
}

.footer--full {
height: 100%;
width: 100%;
}

.footer--scrollable {
&.footer--medium-scrollbar {
@mixin addScrollbar var(--footer-scrollbar-thumb-color);
}

&.footer--small-scrollbar {
@mixin addSmallScrollbar var(--footer-scrollbar-thumb-color);
}

&.footer--xsmall-scrollbar {
@mixin addXSmallScrollbar var(--footer-scrollbar-thumb-color);
}

&:focus {
outline: none;
}

&.is-accessible:focus {
outline: 1px solid var(--footer-focused-outline-color);
outline-offset: -1px;
}

overflow: auto;
}
1 change: 1 addition & 0 deletions src/components/Form/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './Checkbox';
export * from './Fieldset';
export * from './Formbox';
export * from './Label';
export * from './LabelWrapper';
export * from './Notification';
Expand Down
Loading

0 comments on commit 1404bfd

Please sign in to comment.