feat: swap panel component (#51687)

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
Muhammed Mustafa
2023-10-14 01:52:53 +03:00
committed by GitHub
parent d2ab338c35
commit 87cea98d52
15 changed files with 68 additions and 119 deletions
@@ -1,10 +1,10 @@
import { Panel, Button } from '@freecodecamp/react-bootstrap';
import { Button } from '@freecodecamp/react-bootstrap';
import type { RouteComponentProps } from '@reach/router';
import React from 'react';
import Helmet from 'react-helmet';
import { useTranslation } from 'react-i18next';
import { Container, Panel } from '@freecodecamp/ui';
import { Container } from '@freecodecamp/ui';
import envData from '../../config/env.json';
import { Spacer } from '../components/helpers';
import FullWidthRow from '../components/helpers/full-width-row';
@@ -28,7 +28,7 @@ function ShowUnsubscribed({
<main>
<FullWidthRow>
<Spacer size='large' />
<Panel bsStyle='primary' className='text-center'>
<Panel variant='primary' className='text-center'>
<Spacer size='medium' />
<h2 data-playwright-test-label='main-heading'>
{t('misc.unsubscribed')}
+3 -6
View File
@@ -1,5 +1,4 @@
import {
Panel,
FormControl,
FormGroup,
ControlLabel,
@@ -11,7 +10,7 @@ import type { TFunction } from 'i18next';
import { Trans, withTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { Col, Row } from '@freecodecamp/ui';
import { Col, Row, Panel } from '@freecodecamp/ui';
import Login from '../components/Header/components/login';
@@ -84,11 +83,9 @@ function ShowUser({
<main>
<FullWidthRow>
<Spacer size='large' />
<Panel bsStyle='info' className='text-center'>
<Panel variant='primary' className='text-center'>
<Panel.Heading>
<Panel.Title componentClass='h3'>
{t('report.sign-in')}
</Panel.Title>
<Panel.Title>{t('report.sign-in')}</Panel.Title>
</Panel.Heading>
<Panel.Body className='text-center'>
<Spacer size='large' />
@@ -1,7 +1,8 @@
import { Panel } from '@freecodecamp/react-bootstrap';
import Prism from 'prismjs';
import React from 'react';
import { ChallengeFile } from '../../redux/prop-types';
import { Panel } from '@freecodecamp/ui';
import type { ChallengeFile } from '../../redux/prop-types';
type Props = {
challengeFiles: Solution[] | null;
@@ -25,7 +26,7 @@ function SolutionViewer({ challengeFiles, solution }: Props): JSX.Element {
return (
<>
{solutions.map(({ fileKey, ext, contents }) => (
<Panel bsStyle='primary' className='solution-viewer' key={fileKey}>
<Panel variant='primary' className='solution-viewer' key={fileKey}>
<Panel.Heading>{ext.toUpperCase()}</Panel.Heading>
<Panel.Body>
<pre>
-19
View File
@@ -470,11 +470,6 @@ code {
white-space: break-spaces;
}
.panel {
border-radius: 0;
background-color: transparent;
}
.help-block em {
font-size: 0.8rem;
}
@@ -519,10 +514,6 @@ hr {
color: var(--quaternary-color);
}
.panel-default > .panel-heading {
background-color: transparent;
}
.challenge-output span {
font-size: 1rem;
}
@@ -544,12 +535,6 @@ pre {
border-radius: 0;
}
.panel-primary > .panel-heading {
background-color: transparent;
border-color: var(--primary-color);
color: var(--primary-color);
}
.solution-viewer,
.solution-viewer pre {
margin-bottom: 0;
@@ -593,10 +578,6 @@ pre {
border-color: var(--tertiary-color);
}
.panel-primary {
border-color: var(--primary-color);
}
blockquote footer,
blockquote small,
blockquote .small {
@@ -8,7 +8,7 @@ exports[`<Honesty /> <Honesty /> snapshot when isHonest is false: Honesty 1`] =
settings.headings.honesty
</SectionHeader>
<FullWidthRow>
<Uncontrolled(Panel)
<d
className="honesty-panel"
>
<p>
@@ -42,7 +42,7 @@ exports[`<Honesty /> <Honesty /> snapshot when isHonest is false: Honesty 1`] =
</a>
</Trans>
</p>
</Uncontrolled(Panel)>
</d>
<Button
active={false}
aria-disabled={false}
@@ -66,7 +66,7 @@ exports[`<Honesty /> <Honesty /> snapshot when isHonest is true: HonestyAccepted
settings.headings.honesty
</SectionHeader>
<FullWidthRow>
<Uncontrolled(Panel)
<d
className="honesty-panel"
>
<p>
@@ -100,7 +100,7 @@ exports[`<Honesty /> <Honesty /> snapshot when isHonest is true: HonestyAccepted
</a>
</Trans>
</p>
</Uncontrolled(Panel)>
</d>
<Button
active={false}
aria-disabled={true}
@@ -10,18 +10,6 @@
background-color: var(--danger-background);
border-color: var(--danger-background);
}
.danger-zone .panel-heading {
color: var(--danger-color);
background-color: var(--danger-background);
border-radius: 0;
border: none;
}
.danger-zone .panel-danger {
border-color: var(--danger-background);
}
.danger-zone p {
color: var(--danger-color);
}
@@ -1,10 +1,11 @@
import { Button, Panel } from '@freecodecamp/react-bootstrap';
import { Button } from '@freecodecamp/react-bootstrap';
import React, { useState } from 'react';
import type { TFunction } from 'i18next';
import { withTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import type { Dispatch } from 'redux';
import { Panel } from '@freecodecamp/ui';
import { deleteAccount, resetProgress } from '../../redux/settings/actions';
import { FullWidthRow, Spacer } from '../helpers';
@@ -44,7 +45,7 @@ function DangerZone({ deleteAccount, resetProgress, t }: DangerZoneProps) {
return (
<FullWidthRow className='danger-zone text-center'>
<Panel bsStyle='danger' id='danger-zone'>
<Panel variant='danger' id='danger-zone'>
<Panel.Heading>{t('settings.danger.heading')}</Panel.Heading>
<Spacer size='medium' />
<p>{t('settings.danger.be-careful')}</p>
+2 -1
View File
@@ -1,6 +1,7 @@
import { Button, Panel } from '@freecodecamp/react-bootstrap';
import { Button } from '@freecodecamp/react-bootstrap';
import React from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { Panel } from '@freecodecamp/ui';
import { FullWidthRow } from '../helpers';
import SectionHeader from './section-header';
@@ -1,7 +1,3 @@
.user-panel {
border-color: var(--highlight-background);
}
.btn-info {
background-color: var(--highlight-color);
color: var(--highlight-background);
@@ -15,17 +11,6 @@
border-color: var(--highlight-background);
}
.user-token .panel-heading {
color: var(--highlight-color);
background-color: var(--highlight-background);
border-radius: 0;
border: none;
}
.user-token .panel-info {
border-color: var(--highlight-background);
}
.user-token p {
color: var(--highlight-color);
}
@@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { Button, Panel } from '@freecodecamp/react-bootstrap';
import { Button } from '@freecodecamp/react-bootstrap';
import React, { Component } from 'react';
import type { TFunction } from 'i18next';
import { withTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { Panel } from '@freecodecamp/ui';
import { deleteUserToken } from '../../redux/actions';
import { FullWidthRow, Spacer } from '../helpers';
@@ -32,7 +32,7 @@ class UserToken extends Component<UserTokenProps> {
return (
<div data-cy='user-token' className='user-token text-center'>
<FullWidthRow>
<Panel className='user-panel'>
<Panel variant='info'>
<Panel.Heading>{t('user-token.title')}</Panel.Heading>
<Spacer size='medium' />
<p>{t('user-token.delete-p1')}</p>
+1
View File
@@ -4,6 +4,7 @@ export { Alert, type AlertProps } from './alert';
export { CloseButton } from './close-button';
// export { Image } from './image';
export { Table } from './table';
export { Panel } from './panel';
// export { ToggleButton } from './toggle-button';
export { Dropdown } from './drop-down';
export { MenuItem } from './drop-down/menu-item';
@@ -7,12 +7,12 @@ const story = {
component: Panel,
parameters: {
controls: {
include: ['className', 'bsStyle']
include: ['className', 'variant']
}
},
argType: {
className: { control: { type: 'text' } },
bsStyle: { option: ['primary', 'danger', 'info', undefined] }
variant: { option: ['primary', 'danger', 'info', undefined] }
}
};
@@ -37,19 +37,19 @@ Default.args = {
export const Primary = Template.bind({});
Primary.args = {
children: <Child />,
bsStyle: 'primary'
variant: 'primary'
};
export const Info = Template.bind({});
Info.args = {
children: <Child />,
bsStyle: 'info'
variant: 'info'
};
export const Danger = Template.bind({});
Danger.args = {
children: <Child />,
bsStyle: 'danger'
variant: 'danger'
};
export default story;
+2 -2
View File
@@ -11,14 +11,14 @@ describe('<Panel />', () => {
});
it('PanelHead should inherit bsStyle', () => {
render(
<Panel role='article' bsStyle='primary'>
<Panel role='article' variant='primary'>
<Panel.Heading>Test</Panel.Heading>
<Panel.Body>TestBody</Panel.Body>
</Panel>
);
expect(screen.getByRole('article')).toBeInTheDocument();
expect(screen.getByText('Test')).toHaveClass(
'border-b-1 border-solid border-foreground-primary text-foreground-primary'
'outline-[1px] outline outline-foreground-primary text-foreground-primary px-3.5 py-2.5'
);
expect(screen.getByText('TestBody')).toBeInTheDocument();
});
+37 -43
View File
@@ -2,34 +2,30 @@ import React, { createContext, useContext } from 'react';
import { PanelProps } from './types';
type PanelContextProps = Pick<PanelProps, 'bsStyle'>;
type PanelContextProps = Pick<PanelProps, 'variant'>;
const PanelContext = createContext<PanelContextProps>({});
const styles = 'border-1 border-solid shadow-sm mb-6';
const defaultBorder = 'border-background-tertiary';
const primaryBorder = 'border-foreground-primary';
const dangerBorder = 'border-foreground-danger';
const infoBorder = 'border-foreground-info';
const defaultHeadingStyle =
'border-b-1 border-solid border-background-tertiary';
const primaryHeadingStyle =
'border-b-1 border-solid border-foreground-primary text-foreground-primary';
const infoHeadingStyle = 'text-background-info bg-foreground-info';
const dangerHeadingStyle = 'text-background-danger bg-foreground-danger';
const headingPadding = 'px-2.5 py-3.5 ';
const border = {
primary: 'border-foreground-primary',
danger: 'border-foreground-danger',
info: 'border-foreground-info'
};
let bsStyleClass = defaultBorder;
let headingStyles = headingPadding + defaultHeadingStyle;
const heading = {
primary:
'outline-[1px] outline outline-foreground-primary text-foreground-primary',
danger: 'bg-foreground-danger text-background-danger',
info: 'bg-foreground-info text-background-info'
};
const Body = ({
children,
props
}: {
children?: React.ReactNode;
props?: React.ComponentProps<'div'>;
}): JSX.Element => {
className,
...props
}: React.ComponentProps<'div'>): JSX.Element => {
const classes = [className, 'p-3.5'].join(' ');
return (
<div className='p-3.5' {...props}>
<div className={classes} {...props}>
{children}
</div>
);
@@ -37,18 +33,18 @@ const Body = ({
export const Heading = ({
children,
props
}: {
children?: React.ReactNode;
props?: React.ComponentProps<'div'>;
}): JSX.Element => {
const { bsStyle } = useContext(PanelContext);
if (bsStyle === 'primary') headingStyles = primaryHeadingStyle;
else if (bsStyle === 'danger') headingStyles = dangerHeadingStyle;
else if (bsStyle === 'info') headingStyles = infoHeadingStyle;
className,
...props
}: React.ComponentProps<'div'>): JSX.Element => {
const { variant } = useContext(PanelContext);
const headingStyles = variant
? heading[variant]
: 'outline outline-[1px] outline-background-tertiary';
const classes = [className, headingStyles, 'px-3.5 py-2.5'].join(' ');
return (
<div className={headingStyles} {...props}>
<div className={classes} {...props}>
{children}
</div>
);
@@ -56,11 +52,8 @@ export const Heading = ({
export const Title = ({
children,
props
}: {
children?: React.ReactNode;
props?: React.ComponentProps<'h3'>;
}): JSX.Element => {
...props
}: React.ComponentProps<'h3'>): JSX.Element => {
return (
<h3 className='text-inherit mb-0 text-xl' {...props}>
{children}
@@ -71,17 +64,18 @@ export const Title = ({
export const Panel = ({
children,
className,
bsStyle,
variant,
...restProps
}: PanelProps): JSX.Element => {
if (bsStyle === 'primary') bsStyleClass = primaryBorder;
else if (bsStyle === 'danger') bsStyleClass = dangerBorder;
else if (bsStyle === 'info') bsStyleClass = infoBorder;
const panelClassed = [styles, bsStyleClass, className].join(' ');
const variantClass = variant ? border[variant] : 'border-background-tertiary';
const panelClassed = [
'border-1 border-solid shadow-sm mb-6',
variantClass,
className
].join(' ');
return (
<PanelContext.Provider value={{ bsStyle }}>
<PanelContext.Provider value={{ variant }}>
<div className={panelClassed} {...restProps}>
{children}
</div>
+1 -1
View File
@@ -1,5 +1,5 @@
import React from 'react';
export interface PanelProps extends React.HTMLAttributes<HTMLDivElement> {
bsStyle?: 'primary' | 'info' | 'danger';
variant?: 'primary' | 'info' | 'danger';
}