Skip to content

Commit 848d387

Browse files
authored
Add footer variants (#564)
Add a base Footer component with Website and Application variants. ## Changes - Adds a base Footer component that accepts any content - Renames existing footer to WebsiteFooter - Adds two-column ApplicationFooter variant that accepts any content in the left column and a list of links in the right - Updates styling of back to top button - Pulls in latest footer styles from cf.gov - Adds jump link styling on footer links
1 parent 648f939 commit 848d387

9 files changed

Lines changed: 280 additions & 139 deletions

File tree

src/assets/styles/_shared.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,6 @@ pre,
6363
// Override DS wrapper match-content width to 1170px content with 30px gutters.
6464
.wrapper--match-content {
6565
@include respond-to-min($bp-sm-min) {
66-
max-width: $grid-wrapper-width - ($grid-gutter-width * 2);
66+
max-width: $grid-wrapper-width - ($grid-gutter-width * 2) !important;
6767
}
6868
}
Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import { JSX } from 'react';
22
/* eslint-disable jsx-a11y/anchor-is-valid */
3-
import { Icon } from '../Icon/icon';
4-
3+
import Link from '../Link/link';
54
export const BackToTop = (): JSX.Element => (
6-
<a
7-
className='a-btn a-btn--secondary o-footer__top-button'
8-
data-gtm_ignore='true'
9-
data-js-hook='behavior_return-to-top'
10-
href='#'
11-
>
12-
Back to top
13-
<Icon name='arrow-up' isPresentational />
14-
</a>
5+
<Link label="Back to top"
6+
isButton
7+
className='a-btn--secondary a-btn--full-on-xs o-footer__top-button u-show-on-mobile u-mb45'
8+
data-gtm_ignore='true'
9+
data-js-hook='behavior_return-to-top'
10+
data-testid='back-to-top'
11+
href='#'
12+
iconRight='arrow-up'/>
1513
);

src/components/Footer/footer-cf-gov.tsx

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { JSX } from 'react';
22
import { Icon } from '../Icon/icon';
3-
import Footer from './footer';
3+
import Link from '../Link/link';
4+
import {WebsiteFooter} from './footer';
45

56
interface FootCfGovProperties {
67
cfLink?: string;
@@ -140,30 +141,25 @@ export const FooterCfGov = ({
140141
];
141142

142143
const linksCol3 = [
143-
<a key='usa-gov' className='a-link a-link--icon' href='https://usa.gov/'>
144-
<span className='a-link__text'>USA.gov</span>&nbsp;
145-
<Icon
146-
ariaLabel='External link'
147-
name='external-link'
148-
alt='External link'
149-
/>
150-
</a>,
151-
<a
144+
<Link
145+
key='usa-gov'
146+
href='https://usa.gov/'
147+
label='USA.gov'
148+
iconRight='external-link'/>,
149+
<Link
152150
key='inspector'
153-
className='a-link a-link--icon'
154151
href='https://oig.federalreserve.gov/'
155-
>
156-
<span className='a-link__text'>Office of Inspector General</span>&nbsp;
157-
<Icon
158-
ariaLabel='External link'
159-
name='external-link'
160-
alt='External link'
161-
/>
162-
</a>,
152+
label='Office of Inspector General'
153+
iconRight='external-link'/>,
154+
<Link
155+
key='archive'
156+
href='https://archive-it.org/organizations/2800'
157+
label='Public Archive'
158+
iconRight='external-link'/>
163159
];
164160

165161
return (
166-
<Footer
162+
<WebsiteFooter
167163
{...properties}
168164
className={className}
169165
navLinks={navLinks}

src/components/Footer/footer-links.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ export const NavLinks = ({ children }: WrapperProperties): JSXElement => {
1616
if (isEmptyArray(children)) return null;
1717

1818
return (
19-
<List className='o-footer__nav-list m-list--links m-list--horizontal'>
20-
<ListItemBuilder itemClassname='m-list__link'>{children}</ListItemBuilder>
19+
<List className='o-footer__nav-list m-list'>
20+
<ListItemBuilder itemClassname='m-list__link a-link--jump'>{children}</ListItemBuilder>
2121
</List>
2222
);
2323
};
@@ -51,11 +51,12 @@ export const FooterLinksColumn = ({
5151

5252
return (
5353
<div className='o-footer__col'>
54-
<List className='o-footer__list'>
55-
<ListItemBuilder itemClassname='m-list__link'>
54+
<List className='o-footer__list m-list'>
55+
<ListItemBuilder itemClassname='m-list__link a-link--jump'>
5656
{children}
5757
</ListItemBuilder>
5858
</List>
5959
</div>
6060
);
6161
};
62+

src/components/Footer/footer.scss

Lines changed: 104 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
@use 'sass:math';
12
@use '/src/assets/styles/variables.scss' as *;
23
@use '@cfpb/cfpb-design-system/src/elements/abstracts' as *;
34
@use '@cfpb/cfpb-design-system/src/utilities' as *;
45
@use '@cfpb/cfpb-design-system/src/components/cfpb-typography/mixins' as *;
5-
@use 'sass:math';
66

77
// https://github.com/cfpb/consumerfinance.gov/blob/main/cfgov/unprocessed/css/organisms/footer.scss
88

@@ -21,81 +21,139 @@
2121
- cfgov-organisms
2222
*/
2323

24+
@mixin u-upper-hover-line() {
25+
position: absolute;
26+
top: -1px;
27+
content: '';
28+
display: block;
29+
height: 1px;
30+
width: 100%;
31+
border-top: 1px solid currentcolor;
32+
}
33+
2434
.o-footer {
2535
// Adding an extra 5px to the top to account for the absolute positioned
2636
// social media icons.
27-
padding-top: math.div(50px, $base-font-size-px) + em;
37+
padding-top: math.div($grid-gutter-width * 1.5, $base-font-size-px) + rem;
2838

2939
// There is a 10px margin-bottom on the last .o-footer__list li's, plus the
3040
// 50px bottom padding = 60px of total padding at the bottom of the footer.
31-
padding-bottom: math.div(50px, $base-font-size-px) + em;
41+
padding-bottom: math.div($grid-gutter-width * 2, $base-font-size-px) + rem;
3242
border-top: 5px solid var(--green);
3343
background: var(--gray-5);
3444

45+
// Mobile only.
46+
@include respond-to-max($bp-xs-max) {
47+
// Tighten top spacing on mobile.
48+
padding-top: math.div($grid-gutter-width, $base-font-size-px) + rem;
49+
50+
.m-list__link {
51+
display: block;
52+
box-sizing: border-box;
53+
padding-top: math.div(10px, $base-font-size-px) + rem;
54+
padding-bottom: math.div(10px, $base-font-size-px) + rem;
55+
border-top-width: 1px;
56+
border-bottom-width: 1px;
57+
58+
.a-link__text {
59+
border-bottom: none;
60+
}
61+
}
62+
63+
// Handle the borders of jump links that are adjacent in a list.
64+
.o-footer-middle-right .m-list__link:hover::before {
65+
@include u-upper-hover-line;
66+
}
67+
68+
li:has(.m-list__link) + li:has(.m-list__link) {
69+
.m-list__link {
70+
position: relative;
71+
border-top: none;
72+
}
73+
74+
.m-list__link:hover::before {
75+
@include u-upper-hover-line;
76+
}
77+
}
78+
}
79+
3580
&__nav-list {
81+
padding-left: 0;
82+
list-style-type: none;
83+
3684
.m-list__link {
85+
margin-left: 0;
3786
font-size: math.div(18px, $base-font-size-px) + em;
3887

3988
@include u-link-colors(var(--black));
4089

90+
// Tablet and above.
4191
@include respond-to-min($bp-sm-min) {
4292
margin-right: 1em;
4393

4494
@include u-link-hover-border;
4595
}
4696

97+
// Desktop and above.
4798
@include respond-to-min($bp-med-min) {
4899
margin-right: math.div($grid-gutter-width, 22px) + em;
49-
font-size: math.div(20px, $base-font-size-px) + em;
50100
}
51101
}
52102

53103
.m-list__link.m-list__link--disabled {
54104
border-bottom: 1px dotted;
55105

106+
// Desktop and above.
56107
@include respond-to-min($bp-med-min) {
57108
@include u-link-no-border;
58109
}
59110
}
60111
}
61112

62113
&__list {
114+
padding-left: 0;
115+
list-style-type: none;
116+
63117
.m-list__link {
118+
margin-left: 0;
119+
64120
@include u-link-colors(var(--gray-dark));
65121
}
66122
}
67123

124+
// Mobile only.
125+
@include respond-to-max($bp-xs-max) {
126+
// This is essentially .m-list--links.
127+
&__nav-list .m-list__item,
128+
&__list .m-list__item {
129+
margin-bottom: 0;
130+
}
131+
}
132+
68133
&__pre {
69134
position: relative;
70-
margin-bottom: math.div(45px, $base-font-size-px) + em;
71-
72-
.o-footer__top-button {
73-
display: block;
74-
width: 100%;
75-
text-align: center;
76-
77-
// There's a standard margin between the top
78-
// of the footer and the links. The button comes between
79-
// that margin in the wireframes.
80-
margin: -2em auto 2em;
81-
}
135+
margin-bottom: math.div($grid-gutter-width, $base-font-size-px) + em;
82136

83137
.o-footer__nav-list {
84138
margin-bottom: 0;
85139
}
86140

141+
// Tablet and above.
87142
@include respond-to-min($bp-sm-min) {
88143
padding-bottom: math.div($grid-gutter-width, $base-font-size-px) + em;
89-
margin-bottom: math.div($grid-gutter-width, $base-font-size-px) + em;
90-
91144
border-bottom: 1px solid var(--gray-40);
92145

93-
.o-footer__top-button {
94-
display: none;
95-
}
96-
97146
.o-footer__nav-list {
147+
padding-left: 0;
148+
list-style-type: none;
149+
98150
.m-list__item {
151+
margin-left: 0;
152+
display: inline-block;
153+
154+
// Assuming a natural space of 4px between inline block items
155+
// then the space between would be 8px (4px natural + 4px added).
156+
margin-right: math.div(4px, $base-font-size-px) + em;
99157
margin-bottom: 0;
100158
}
101159
}
@@ -115,8 +173,9 @@
115173
margin: 0;
116174
}
117175

118-
/* Fix doubled border in mobile view */
176+
// Mobile only.
119177
@include respond-to-max($bp-xs-max) {
178+
// Fix doubled border in mobile view.
120179
.o-footer__col:nth-child(n + 2) {
121180
.o-footer__list {
122181
.m-list__item .m-list__link {
@@ -126,7 +185,9 @@
126185
}
127186
}
128187

188+
// Tablet and above.
129189
@include respond-to-min($bp-sm-min) {
190+
130191
@include u-grid-column(8);
131192
border-right: 1px solid var(--gray-40);
132193
border-left: 0;
@@ -138,7 +199,8 @@
138199
padding-right: math.div(
139200
math.div($grid-gutter-width, 2),
140201
$base-font-size-px
141-
) + em;
202+
) +
203+
em;
142204
}
143205
}
144206

@@ -151,15 +213,20 @@
151213
}
152214

153215
&__middle-right {
154-
/* Fix doubled border in mobile view */
216+
// Mobile only.
155217
@include respond-to-max($bp-xs-max) {
218+
// Fix missing top line hover.
219+
position: relative;
220+
221+
// Fix doubled border in mobile view.
156222
.o-footer__list {
157223
.m-list__item .m-list__link {
158224
border-top-width: 0;
159225
}
160226
}
161227
}
162228

229+
// Tablet and above.
163230
@include respond-to-min($bp-sm-min) {
164231
@include u-grid-column(4);
165232

@@ -178,8 +245,9 @@
178245
}
179246

180247
&__post {
181-
margin-top: math.div($grid-gutter-width, $base-font-size-px) + em;
248+
margin-top: math.div($grid-gutter-width * 1.5, $base-font-size-px) + em;
182249

250+
// Tablet and above.
183251
@include respond-to-min($bp-sm-min) {
184252
padding-top: math.div($grid-gutter-width, $base-font-size-px) + em;
185253
border-top: 1px solid var(--gray-40);
@@ -191,27 +259,19 @@
191259
margin: 0;
192260
}
193261
}
194-
}
195-
196-
/* topdoc
197-
name: EOF
198-
eof: true
199-
*/
200262

201-
.o-footer .cf-icon-svg--external-link {
202-
margin-left: 3px;
203-
}
263+
// Layout classes for the ApplicationFooter
264+
&__content {
265+
display: grid;
266+
gap: math.div($grid-gutter-width, $base-font-size-px) + em;
204267

205-
@media (max-width: $bp-sm-min - 1) {
206-
.o-footer {
207-
.m-list__link,
208-
.o-footer-post,
209-
.m-social-media {
210-
padding-left: $space-sm;
211-
}
268+
@include respond-to-min($bp-sm-min) {
269+
gap: math.div($grid-gutter-width * 2, $base-font-size-px) + em;;
270+
grid-template-columns: 2fr 1fr;
212271

213-
.o-footer__top-button {
214-
width: 95%;
272+
.o-footer__right-column {
273+
text-align: right;
274+
}
215275
}
216276
}
217277
}

0 commit comments

Comments
 (0)