Skip to content

Commit

Permalink
fix(Nav): add .card-header-* only if nested in card header (#5720)
Browse files Browse the repository at this point in the history
Rename CardContext to CardHeaderContext since it's only used for CardHeaders
  • Loading branch information
kyletsang committed Mar 16, 2021
1 parent 82fa40d commit 793e857
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 42 deletions.
38 changes: 14 additions & 24 deletions src/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import classNames from 'classnames';
import * as React from 'react';
import { useMemo } from 'react';
import PropTypes from 'prop-types';

import { useBootstrapPrefix } from './ThemeProvider';
import createWithBsPrefix from './createWithBsPrefix';
import divWithClassName from './divWithClassName';
import CardContext from './CardContext';
import CardImg from './CardImg';
import CardHeader from './CardHeader';
import { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers';
import { Color, Variant } from './types';

Expand All @@ -22,7 +21,6 @@ const CardSubtitle = createWithBsPrefix('card-subtitle', {
});
const CardLink = createWithBsPrefix('card-link', { Component: 'a' });
const CardText = createWithBsPrefix('card-text', { Component: 'p' });
const CardHeader = createWithBsPrefix('card-header');
const CardFooter = createWithBsPrefix('card-footer');
const CardImgOverlay = createWithBsPrefix('card-img-overlay');

Expand Down Expand Up @@ -95,29 +93,21 @@ const Card: BsPrefixRefForwardingComponent<'div', CardProps> = React.forwardRef<
ref,
) => {
const prefix = useBootstrapPrefix(bsPrefix, 'card');
const cardContext = useMemo(
() => ({
cardHeaderBsPrefix: `${prefix}-header`,
}),
[prefix],
);

return (
<CardContext.Provider value={cardContext}>
<Component
ref={ref}
{...props}
className={classNames(
className,
prefix,
bg && `bg-${bg}`,
text && `text-${text}`,
border && `border-${border}`,
)}
>
{body ? <CardBody>{children}</CardBody> : children}
</Component>
</CardContext.Provider>
<Component
ref={ref}
{...props}
className={classNames(
className,
prefix,
bg && `bg-${bg}`,
text && `text-${text}`,
border && `border-${border}`,
)}
>
{body ? <CardBody>{children}</CardBody> : children}
</Component>
);
},
);
Expand Down
10 changes: 0 additions & 10 deletions src/CardContext.tsx

This file was deleted.

60 changes: 60 additions & 0 deletions src/CardHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import classNames from 'classnames';
import * as React from 'react';
import { useMemo } from 'react';
import PropTypes from 'prop-types';

import { useBootstrapPrefix } from './ThemeProvider';
import CardHeaderContext from './CardHeaderContext';
import { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers';

export interface CardHeaderProps
extends BsPrefixProps,
React.HTMLAttributes<HTMLElement> {}

const propTypes = {
/**
* @default 'card-header'
*/
bsPrefix: PropTypes.string,

as: PropTypes.elementType,
};

const CardHeader: BsPrefixRefForwardingComponent<
'div',
CardHeaderProps
> = React.forwardRef<HTMLElement, CardHeaderProps>(
(
{
bsPrefix,
className,
// Need to define the default "as" during prop destructuring to be compatible with styled-components github.com/react-bootstrap/react-bootstrap/issues/3595
as: Component = 'div',
...props
},
ref,
) => {
const prefix = useBootstrapPrefix(bsPrefix, 'card-header');
const contextValue = useMemo(
() => ({
cardHeaderBsPrefix: prefix,
}),
[prefix],
);

return (
<CardHeaderContext.Provider value={contextValue}>
<Component
ref={ref}
{...props}
className={classNames(className, prefix)}
/>
</CardHeaderContext.Provider>
);
},
);

CardHeader.displayName = 'CardHeader';
CardHeader.propTypes = propTypes;

export default CardHeader;
10 changes: 10 additions & 0 deletions src/CardHeaderContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as React from 'react';

interface CardHeaderContextValue {
cardHeaderBsPrefix: string;
}

const context = React.createContext<CardHeaderContextValue | null>(null);
context.displayName = 'CardHeaderContext';

export default context;
8 changes: 4 additions & 4 deletions src/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useUncontrolled } from 'uncontrollable';

import { useBootstrapPrefix } from './ThemeProvider';
import NavbarContext from './NavbarContext';
import CardContext from './CardContext';
import CardHeaderContext from './CardHeaderContext';
import AbstractNav from './AbstractNav';
import NavItem from './NavItem';
import NavLink from './NavLink';
Expand Down Expand Up @@ -133,13 +133,13 @@ const Nav: BsPrefixRefForwardingComponent<'div', NavProps> = React.forwardRef<
let isNavbar = false;

const navbarContext = useContext(NavbarContext);
const cardContext = useContext(CardContext);
const cardHeaderContext = useContext(CardHeaderContext);

if (navbarContext) {
navbarBsPrefix = navbarContext.bsPrefix;
isNavbar = navbar == null ? true : navbar;
} else if (cardContext) {
({ cardHeaderBsPrefix } = cardContext);
} else if (cardHeaderContext) {
({ cardHeaderBsPrefix } = cardHeaderContext);
}

return (
Expand Down
8 changes: 4 additions & 4 deletions test/NavSpec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { mount } from 'enzyme';
import Card from '../src/Card';
import CardHeader from '../src/CardHeader';
import Nav from '../src/Nav';
import Navbar from '../src/Navbar';
import NavDropdown from '../src/NavDropdown';
Expand Down Expand Up @@ -73,14 +73,14 @@ describe('<Nav>', () => {
).assertSingle('div.navbar-nav');
});

it('should be card aware', () => {
it('should be card header aware', () => {
mount(
<Card>
<CardHeader>
<Nav variant="pills">
<Nav.Link eventKey={1}>Pill 1 content</Nav.Link>
<Nav.Link eventKey={2}>Pill 2 content</Nav.Link>
</Nav>
</Card>,
</CardHeader>,
).assertSingle('div.card-header-pills');
});

Expand Down
24 changes: 24 additions & 0 deletions www/src/pages/components/cards.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,14 @@ Use `Row`'s [grid column](/layout/grid/#row-layout-col-sizing) props to control

<ComponentApi metadata={props.data.Card} />
<ComponentApi metadata={props.data.CardBody} exportedBy={props.data.Card} />
<ComponentApi metadata={props.data.CardFooter} exportedBy={props.data.Card} />
<ComponentApi metadata={props.data.CardHeader} exportedBy={props.data.Card} />
<ComponentApi metadata={props.data.CardImg} exportedBy={props.data.Card} />
<ComponentApi metadata={props.data.CardImgOverlay} exportedBy={props.data.Card} />
<ComponentApi metadata={props.data.CardLink} exportedBy={props.data.Card} />
<ComponentApi metadata={props.data.CardSubtitle} exportedBy={props.data.Card} />
<ComponentApi metadata={props.data.CardText} exportedBy={props.data.Card} />
<ComponentApi metadata={props.data.CardTitle} exportedBy={props.data.Card} />

<ComponentApi metadata={props.data.CardGroup} />
<ComponentApi metadata={props.data.CardColumns} />
Expand All @@ -159,12 +165,30 @@ export const query = graphql`
CardBody: componentMetadata(displayName: { eq: "CardBody" }) {
...ComponentApi_metadata
}
CardFooter: componentMetadata(displayName: { eq: "CardFooter" }) {
...ComponentApi_metadata
}
CardHeader: componentMetadata(displayName: { eq: "CardHeader" }) {
...ComponentApi_metadata
}
CardImg: componentMetadata(displayName: { eq: "CardImg" }) {
...ComponentApi_metadata
}
CardImgOverlay: componentMetadata(displayName: { eq: "CardImgOverlay" }) {
...ComponentApi_metadata
}
CardLink: componentMetadata(displayName: { eq: "CardLink" }) {
...ComponentApi_metadata
}
CardSubtitle: componentMetadata(displayName: { eq: "CardSubtitle" }) {
...ComponentApi_metadata
}
CardText: componentMetadata(displayName: { eq: "CardText" }) {
...ComponentApi_metadata
}
CardTitle: componentMetadata(displayName: { eq: "CardTitle" }) {
...ComponentApi_metadata
}
CardGroup: componentMetadata(displayName: { eq: "CardGroup" }) {
...ComponentApi_metadata
}
Expand Down

0 comments on commit 793e857

Please sign in to comment.