Skip to content

Commit

Permalink
feat: allow Container render without a max width
Browse files Browse the repository at this point in the history
  • Loading branch information
rpenido committed Sep 5, 2024
1 parent 4b63a24 commit 4a206ae
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 61 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import { render } from '@testing-library/react';
import Container from '.';
import Container, { type ContainerSize } from '.';

const getClassNames = (container) => container.className.split(' ');
const getClassNames = (container: HTMLElement) => container.className.split(' ');

describe('<Container />', () => {
it('displays children', () => {
Expand All @@ -12,32 +12,38 @@ describe('<Container />', () => {

it('adds the .container-fluid class', () => {
const { container } = render(<Container>Content</Container>);
const containerElement = container.firstChild;
const containerElement = container.firstChild as HTMLElement;
expect(getClassNames(containerElement)).toContain('container-fluid');
});

it('adds the .container class', () => {
const { container } = render(<Container fluid={false}>Content</Container>);
const containerElement = container.firstChild;
expect(getClassNames(containerElement)).toContain('container');
const containerElement = container.firstChild as HTMLElement;
expect(getClassNames(containerElement!)).toContain('container');
expect(getClassNames(containerElement)).not.toContain('container-fluid');
});

['xs', 'sm', 'md', 'lg', 'xl'].forEach((size) => {
['xs', 'sm', 'md', 'lg', 'xl'].forEach((size: ContainerSize) => {
it(`adds the .container-mw-${size} class`, () => {
const { container } = render(<Container size={size}>Content</Container>);
const containerElement = container.firstChild;
const containerElement = container.firstChild as HTMLElement;
expect(getClassNames(containerElement)).toContain(`container-mw-${size}`);
});
});

it('does not add a size class when size is not specified', () => {
const { container } = render(<Container>Content</Container>);
const containerElement = container.firstChild as HTMLElement;
expect(getClassNames(containerElement)).toEqual(['container-fluid']);
});

it('preserves custom class names', () => {
const { container } = render(
<Container className="custom-class" size="md">
Content
</Container>,
);
const containerElement = container.firstChild;
const containerElement = container.firstChild as HTMLElement;
expect(getClassNames(containerElement)).toContain('container-mw-md');
expect(getClassNames(containerElement)).toContain('container-fluid');
expect(getClassNames(containerElement)).toContain('custom-class');
Expand Down
4 changes: 4 additions & 0 deletions src/Container/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ The base container to contain, pad, and center content in the viewport. This com
```jsx live
<div style={{ overflowX: 'auto' }}>
<div style={{ width: '1500px', border: 'solid 3px red' }}>
<Container size="full" className="bg-danger-300 my-4">
The content in this container don't have a max width
</Container>
<Container size="xl" className="bg-danger-300 my-4">
The content in this container won't exceed the extra large width.
</Container>
Expand Down
49 changes: 0 additions & 49 deletions src/Container/index.jsx

This file was deleted.

66 changes: 66 additions & 0 deletions src/Container/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* eslint-disable react/require-default-props */
import React from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import RBContainer, { type ContainerProps as RBContainerProps } from 'react-bootstrap/Container';

import type { ComponentWithAsProp } from '../utils/types/bootstrap';

enum ContainerSizeClass {
xs = 'container-mw-xs',
sm = 'container-mw-sm',
md = 'container-mw-md',
lg = 'container-mw-lg',
xl = 'container-mw-xl',
}

export type ContainerSize = keyof typeof ContainerSizeClass;

interface ContainerProps extends RBContainerProps {
size?: ContainerSize;
}

type ContainerType = ComponentWithAsProp<'div', ContainerProps> & { Deprecated?: any };

const Container: ContainerType = React.forwardRef<HTMLDivElement, ContainerProps>(({
size,
children,
...props
}, ref) => (
<RBContainer
bsPrefix="container"
fluid
{...props}
ref={ref}
className={classNames(
props.className,
size && ContainerSizeClass[size],
)}
>
{children}
</RBContainer>
));

Container.propTypes = {
...RBContainer.propTypes,
/** Override the base element */
as: PropTypes.elementType,
/** Specifies the contents of the container */
children: PropTypes.node,
/** Fill all available space at any breakpoint */
fluid: PropTypes.bool,
/** Set the maximum width for the container */
size: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl', undefined]),
/** Overrides underlying component base CSS class name */
bsPrefix: PropTypes.string,
};

Container.defaultProps = {
as: 'div',
children: undefined,
fluid: true,
size: undefined,
bsPrefix: 'container',
};

export default Container;
2 changes: 1 addition & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { default as Bubble } from './Bubble';
export { default as Button, ButtonGroup, ButtonToolbar } from './Button';
export { default as Chip, CHIP_PGN_CLASS } from './Chip';
export { default as ChipCarousel } from './ChipCarousel';
export { default as Container, ContainerSize } from './Container';
export { default as Hyperlink, HYPER_LINK_EXTERNAL_LINK_ALT_TEXT, HYPER_LINK_EXTERNAL_LINK_TITLE } from './Hyperlink';
export { default as Icon } from './Icon';
export { default as IconButton, IconButtonWithTooltip } from './IconButton';
Expand Down Expand Up @@ -41,7 +42,6 @@ export const
export const CheckBox: any; // from './CheckBox';
export const CheckBoxGroup: any; // from './CheckBoxGroup';
export const CloseButton: any; // from './CloseButton';
export const Container: any; // from './Container';
export const Layout: any, Col: any, Row: any; // from './Layout';
export const Collapse: any; // from './Collapse';
export const Collapsible: any; // from './Collapsible';
Expand Down
6 changes: 3 additions & 3 deletions www/src/context/SettingsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { createContext, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Helmet } from 'react-helmet';
import { IntlProvider } from 'react-intl';
import { messages } from '~paragon-react';
import { messages, type ContainerSize } from '~paragon-react';

import { THEMES, DEFAULT_THEME } from '../../theme-config';
import { SETTINGS_EVENTS, sendUserAnalyticsEvent } from '../../segment-events';
Expand All @@ -12,7 +12,7 @@ export interface IDefaultValue {
theme?: string,
direction?: string,
language?: string,
containerWidth?: string,
containerWidth?: ContainerSize,
},
theme?: string,
handleSettingsChange: Function,
Expand All @@ -35,7 +35,7 @@ function SettingsContextProvider({ children }) {
theme: DEFAULT_THEME,
direction: 'ltr',
language: 'en',
containerWidth: 'md',
containerWidth: 'md' as ContainerSize,
});
const [showSettings, setShowSettings] = useState(false);

Expand Down

0 comments on commit 4a206ae

Please sign in to comment.