Skip to content

Commit 9a99e61

Browse files
committed
Convert plugins MarketplaceFooter to use CSS modules
Demonstrate functional server-rendered CSS modules behavior
1 parent 8f5a28c commit 9a99e61

File tree

9 files changed

+138
-83
lines changed

9 files changed

+138
-83
lines changed

client/components/section/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ interface SectionProps {
88
subheader?: string | ReactElement;
99
children: ReactNode;
1010
dark?: boolean;
11+
className?: string;
1112
}
1213

1314
interface SectionContainerProps {
@@ -76,10 +77,10 @@ export const SectionHeaderContainer = styled.div< SectionHeaderProps >`
7677
const SectionContent = styled.div``;
7778

7879
const Section = ( props: SectionProps ) => {
79-
const { children, header, subheader, dark } = props;
80+
const { children, header, subheader, dark, className } = props;
8081
/* eslint-disable wpcalypso/jsx-classname-namespace */
8182
return (
82-
<SectionContainer dark={ dark }>
83+
<SectionContainer dark={ dark } className={ className }>
8384
<SectionHeaderContainer>
8485
<SectionHeader dark={ dark } className="wp-brand-font">
8586
{ header }
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @jest-environment jsdom
3+
*/
4+
import { render } from '@testing-library/react';
5+
import Section from '../index';
6+
7+
describe( 'Section', () => {
8+
it( 'applies additional className when provided', () => {
9+
const customClassName = 'custom-section-class';
10+
const { container } = render(
11+
<Section header="Test Header" className={ customClassName }>
12+
Test Content
13+
</Section>
14+
);
15+
16+
const sectionContainer = container.firstChild;
17+
expect( sectionContainer ).toHaveClass( customClassName );
18+
} );
19+
} );

client/declarations.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,13 @@ declare module 'is-my-json-valid' {
66
export default function ( schema: any, options?: any ): ( data: any ) => boolean;
77
export function filter( schema: any, options?: any ): any;
88
}
9+
10+
declare module '*.module.css' {
11+
const content: { [ className: string ]: string };
12+
export default content;
13+
}
14+
15+
declare module '*.module.scss' {
16+
const content: { [ className: string ]: string };
17+
export default content;
18+
}

client/my-sites/plugins/education-footer/index.tsx

Lines changed: 1 addition & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1-
import { Button } from '@automattic/components';
21
import { useOpenArticleInHelpCenter } from '@automattic/help-center/src/hooks';
32
import { useLocalizeUrl } from '@automattic/i18n-utils';
43
import styled from '@emotion/styled';
54
import { useI18n } from '@wordpress/react-i18n';
65
import { useCallback } from 'react';
7-
import FeatureItem from 'calypso/components/feature-item';
86
import LinkCard from 'calypso/components/link-card';
9-
import Section, { SectionContainer } from 'calypso/components/section';
10-
import { preventWidows } from 'calypso/lib/formatting';
11-
import { addQueryArgs } from 'calypso/lib/route';
127
import PluginsResultsHeader from 'calypso/my-sites/plugins/plugins-results-header';
138
import { useDispatch, useSelector } from 'calypso/state';
149
import { recordTracksEvent } from 'calypso/state/analytics/actions/record';
15-
import { isUserLoggedIn, getCurrentUserSiteCount } from 'calypso/state/current-user/selectors';
16-
import { getSectionName } from 'calypso/state/ui/selectors';
10+
import { isUserLoggedIn } from 'calypso/state/current-user/selectors';
1711

1812
const ThreeColumnContainer = styled.div`
1913
@media ( max-width: 660px ) {
@@ -72,32 +66,6 @@ const EducationFooterContainer = styled.div`
7266
}
7367
`;
7468

75-
const MarketplaceContainer = styled.div< { isloggedIn: boolean } >`
76-
--color-accent: var( --studio-blue-50 );
77-
--color-accent-60: var( --studio-blue-60 );
78-
margin-bottom: -32px;
79-
80-
.marketplace-cta {
81-
min-width: 122px;
82-
margin-bottom: 26px;
83-
84-
@media ( max-width: 660px ) {
85-
margin-left: 16px;
86-
margin-right: 16px;
87-
}
88-
}
89-
90-
${ ( { isloggedIn } ) =>
91-
! isloggedIn &&
92-
`${ SectionContainer } {
93-
padding-bottom: 32px;
94-
}` }
95-
96-
${ SectionContainer }::before {
97-
background-color: #f6f7f7;
98-
}
99-
`;
100-
10169
const CardText = styled.span< { color: string } >`
10270
color: ${ ( { color } ) => color };
10371
font-family: 'SF Pro Text', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto',
@@ -107,51 +75,6 @@ const CardText = styled.span< { color: string } >`
10775
line-height: 20px;
10876
`;
10977

110-
export const MarketplaceFooter = () => {
111-
const { __ } = useI18n();
112-
const isLoggedIn = useSelector( isUserLoggedIn );
113-
const currentUserSiteCount = useSelector( getCurrentUserSiteCount );
114-
const sectionName = useSelector( getSectionName );
115-
116-
const startUrl = addQueryArgs(
117-
{
118-
ref: sectionName + '-lp',
119-
},
120-
sectionName === 'plugins' ? '/start/business' : '/start'
121-
);
122-
123-
return (
124-
<MarketplaceContainer isloggedIn={ isLoggedIn }>
125-
<Section
126-
header={ preventWidows( __( 'You pick the plugin. We’ll take care of the rest.' ) ) }
127-
>
128-
{ ( ! isLoggedIn || currentUserSiteCount === 0 ) && (
129-
<Button className="is-primary marketplace-cta" href={ startUrl }>
130-
{ __( 'Get Started' ) }
131-
</Button>
132-
) }
133-
<ThreeColumnContainer>
134-
<FeatureItem header={ __( 'Fully managed' ) }>
135-
{ __(
136-
'Premium plugins are fully managed by the team at WordPress.com. No security patches. No update nags. It just works.'
137-
) }
138-
</FeatureItem>
139-
<FeatureItem header={ __( 'Thousands of plugins' ) }>
140-
{ __(
141-
'From WordPress.com premium plugins to thousands more community-authored plugins, we’ve got you covered.'
142-
) }
143-
</FeatureItem>
144-
<FeatureItem header={ __( 'Flexible pricing' ) }>
145-
{ __(
146-
'Pay yearly and save. Or keep it flexible with monthly premium plugin pricing. It’s entirely up to you.'
147-
) }
148-
</FeatureItem>
149-
</ThreeColumnContainer>
150-
</Section>
151-
</MarketplaceContainer>
152-
);
153-
};
154-
15578
const EducationFooter = () => {
15679
const { __ } = useI18n();
15780
const localizeUrl = useLocalizeUrl();
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { Button } from '@automattic/components';
2+
import { useI18n } from '@wordpress/react-i18n';
3+
import clsx from 'clsx';
4+
import FeatureItem from 'calypso/components/feature-item';
5+
import Section from 'calypso/components/section';
6+
import { preventWidows } from 'calypso/lib/formatting';
7+
import { addQueryArgs } from 'calypso/lib/route';
8+
import { useSelector } from 'calypso/state';
9+
import { isUserLoggedIn, getCurrentUserSiteCount } from 'calypso/state/current-user/selectors';
10+
import { getSectionName } from 'calypso/state/ui/selectors';
11+
import styles from './styles.module.css';
12+
13+
export const MarketplaceFooter = () => {
14+
const { __ } = useI18n();
15+
const isLoggedIn = useSelector( isUserLoggedIn );
16+
const currentUserSiteCount = useSelector( getCurrentUserSiteCount );
17+
const sectionName = useSelector( getSectionName );
18+
const classes = clsx( styles[ 'marketplace-footer' ], {
19+
[ styles[ 'is-logged-in' ] ]: isLoggedIn,
20+
} );
21+
22+
const startUrl = addQueryArgs(
23+
{
24+
ref: sectionName + '-lp',
25+
},
26+
sectionName === 'plugins' ? '/start/business' : '/start'
27+
);
28+
29+
return (
30+
<div className={ classes }>
31+
<Section
32+
header={ preventWidows( __( 'You pick the plugin. We’ll take care of the rest.' ) ) }
33+
className={ styles[ 'marketplace-footer__section' ] }
34+
>
35+
{ ( ! isLoggedIn || currentUserSiteCount === 0 ) && (
36+
<Button
37+
className={ `is-primary ${ styles[ 'marketplace-footer__cta' ] }` }
38+
href={ startUrl }
39+
>
40+
{ __( 'Get Started' ) }
41+
</Button>
42+
) }
43+
<div className={ styles[ 'marketplace-footer__three-column' ] }>
44+
<FeatureItem header={ __( 'Fully managed' ) }>
45+
{ __(
46+
'Premium plugins are fully managed by the team at WordPress.com. No security patches. No update nags. It just works.'
47+
) }
48+
</FeatureItem>
49+
<FeatureItem header={ __( 'Thousands of plugins' ) }>
50+
{ __(
51+
'From WordPress.com premium plugins to thousands more community-authored plugins, we’ve got you covered.'
52+
) }
53+
</FeatureItem>
54+
<FeatureItem header={ __( 'Flexible pricing' ) }>
55+
{ __(
56+
'Pay yearly and save. Or keep it flexible with monthly premium plugin pricing. It’s entirely up to you.'
57+
) }
58+
</FeatureItem>
59+
</div>
60+
</Section>
61+
</div>
62+
);
63+
};
64+
65+
export default MarketplaceFooter;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.marketplace-footer {
2+
--color-accent: var( --studio-blue-50 );
3+
--color-accent-60: var( --studio-blue-60 );
4+
margin-bottom: -32px;
5+
6+
& .marketplace-footer__section::before {
7+
background-color: #f6f7f7;
8+
}
9+
10+
&:not(.is-logged-in) .marketplace-footer__section {
11+
padding-bottom: 32px;
12+
}
13+
}
14+
15+
.marketplace-footer__cta {
16+
min-width: 122px;
17+
margin-bottom: 26px;
18+
}
19+
20+
@media ( max-width: 660px ) {
21+
.marketplace-footer__cta {
22+
margin-left: 16px;
23+
margin-right: 16px;
24+
}
25+
}
26+
27+
.marketplace-footer__three-column {
28+
display: flex;
29+
flex-wrap: wrap;
30+
justify-content: space-between;
31+
}
32+
33+
@media ( max-width: 660px ) {
34+
.marketplace-footer__three-column {
35+
padding: 0 16px;
36+
}
37+
}

client/my-sites/plugins/plans/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import PromoSection, { Props as PromoSectionProps } from 'calypso/components/pro
1414
import { Gridicon } from 'calypso/devdocs/design/playground-scope';
1515
import PageViewTracker from 'calypso/lib/analytics/page-view-tracker';
1616
import PlansFeaturesMain from 'calypso/my-sites/plans-features-main';
17-
import { MarketplaceFooter } from 'calypso/my-sites/plugins/education-footer';
17+
import MarketplaceFooter from 'calypso/my-sites/plugins/marketplace-footer';
1818
import { useDispatch, useSelector } from 'calypso/state';
1919
import { appendBreadcrumb } from 'calypso/state/breadcrumb/actions';
2020
import { getBreadcrumbs } from 'calypso/state/breadcrumb/selectors';

client/my-sites/plugins/plugin-details.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ import {
7777
isRequestingSites as checkRequestingSites,
7878
} from 'calypso/state/sites/selectors';
7979
import { getSelectedSite } from 'calypso/state/ui/selectors';
80-
import { MarketplaceFooter } from './education-footer';
80+
import MarketplaceFooter from './marketplace-footer';
8181
import NoPermissionsError from './no-permissions-error';
8282
import { usePluginIsMaintained } from './use-plugin-is-maintained';
8383

client/my-sites/plugins/plugins-browser/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import PageViewTracker from 'calypso/lib/analytics/page-view-tracker';
1313
import useScrollAboveElement from 'calypso/lib/use-scroll-above-element';
1414
import Categories from 'calypso/my-sites/plugins/categories';
1515
import { useCategories } from 'calypso/my-sites/plugins/categories/use-categories';
16-
import { MarketplaceFooter } from 'calypso/my-sites/plugins/education-footer';
16+
import MarketplaceFooter from 'calypso/my-sites/plugins/marketplace-footer';
1717
import NoPermissionsError from 'calypso/my-sites/plugins/no-permissions-error';
1818
import useIsVisible from 'calypso/my-sites/plugins/plugins-browser/use-is-visible';
1919
import SearchBoxHeader from 'calypso/my-sites/plugins/search-box-header';

0 commit comments

Comments
 (0)