-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add internal news carousel for news and announcements page #744
Changes from 22 commits
dfd2ad8
e3cecb4
bd02b3d
03cdf50
728db43
66672cc
ba3009e
c657ce9
a902eff
077e442
e403e9c
b6520be
444466a
aa417ab
afd2d18
684bc33
c958f99
823e7b4
9b1914c
67fd32b
e037e7a
4de79e5
39cde4b
fd8bf16
dd943d4
034b37f
82989b8
4d98c22
ff84f0e
679c517
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,42 @@ | ||
export const cmsPortalNewsArticlesMock = [ | ||
{ | ||
__typename: 'Article', | ||
id: 'cl3buldda0247riyt6h85cpgc', | ||
id: 'id1', | ||
slug: 'announcing-the-dev-blog', | ||
title: 'Announcing the dev blog', | ||
preview: 'This is the preview text!', | ||
publishedDate: '2022-05-18T17:18:40.802Z', | ||
labels: [], | ||
}, | ||
{ | ||
__typename: 'Article', | ||
id: 'cl3bpuzvq0885i6ytzr2oumu9', | ||
id: 'id2', | ||
slug: 'welcome-and-overview', | ||
title: 'Welcome and Overview', | ||
preview: | ||
'The USSF/CTIO team has been busy in 2021! This year, we’ve conducted more than 40 one-on-one interviews with Guardians (and have surveyed dozens more) in order to custom create a portal that best serves your needs.', | ||
publishedDate: '2022-05-18T15:06:00.056Z', | ||
labels: [], | ||
}, | ||
{ | ||
__typename: 'Article', | ||
id: 'cl3bpu9pm0725i6yto1qd5swv', | ||
id: 'id3', | ||
slug: 'version-300-released', | ||
title: 'Version 3.0.0 released!', | ||
preview: | ||
'This release removes the beta gate and officially marks the launch of the new USSF portal!', | ||
publishedDate: '2022-05-18T15:05:27.289Z', | ||
labels: [], | ||
}, | ||
{ | ||
__typename: 'Article', | ||
id: 'cl3bprjlw0561i6ytphwqi3tb', | ||
id: 'id4', | ||
slug: 'version-285-released-includes-mvp-search-experience-and-a-way-to-filter-the-news', | ||
title: | ||
'Version 2.8.5 released! Includes MVP search experience and a way to filter the news.', | ||
preview: | ||
'Vestibulum in turpis vitae arcu tincidunt maximus sit amet suscipit justo. Morbi lobortis posuere mollis. Suspendisse egestas egestas sapien eu blandit. In euismod suscipit nisi, eget vulputate tellus. Cras vel nisi nec urna facilisis luctus. Phasellus vel sagittis lacus. Ut dapibus ipsum arcu, nec semper ipsum malesuada in. Aliquam et lectus pharetra, gravida eros suscipit, tincidunt libero. Fusce vel ultrices tellus, vel pulvinar diam. Vestibulum pharetra vehicula lacinia.', | ||
publishedDate: '2022-05-18T15:03:24.089Z', | ||
labels: [], | ||
}, | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
@import 'styles/uswdsDependencies'; | ||
@import 'styles/sfds/sfdsDependencies'; | ||
|
||
.carouselContainer { | ||
display: flex !important; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. might not need the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it! Yeah there is a good chance that I just forgot to remove this. |
||
flex-direction: row; | ||
align-items: center; | ||
justify-content: center; | ||
width: 100%; | ||
height: 100%; | ||
background-color: #161f2f; | ||
border-radius: 4px; | ||
|
||
.dots { | ||
button.newsCarouselEllipse { | ||
width: 16.17px; | ||
height: 16px; | ||
border-radius: 50px; | ||
background: $theme-spacebase-lightest; | ||
} | ||
|
||
button::before { | ||
color: transparent !important; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above -- the |
||
} | ||
} | ||
|
||
> :global(.slick-dots | ||
li.slick-active | ||
div.news-carousel-container | ||
button::before) { | ||
color: transparent !important; | ||
background: #112548; | ||
width: 16.17px; | ||
height: 16px; | ||
border-radius: 50px; | ||
} | ||
} | ||
|
||
.carouselArrow { | ||
&:hover { | ||
cursor: pointer; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import React from 'react' | ||
import { Meta } from '@storybook/react' | ||
import NewsCarousel from './NewsCarousel' | ||
import { ArticleListItemRecord } from 'types' | ||
|
||
export default { | ||
title: 'Components/NewsCarousel', | ||
component: NewsCarousel, | ||
decorators: [ | ||
(Story) => ( | ||
<div className="sfds"> | ||
<Story /> | ||
</div> | ||
), | ||
], | ||
} as Meta | ||
|
||
const mockArticles: ArticleListItemRecord[] = [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO for future: Another opportunity to store/reuse data in |
||
{ | ||
id: '1', | ||
title: 'My Thing!', | ||
labels: [ | ||
{ | ||
id: 'label1', | ||
name: 'A Label', | ||
type: 'Source', | ||
}, | ||
], | ||
publishedDate: 'Aug 03, 2022', | ||
preview: "It's a thing", | ||
}, | ||
{ | ||
id: '2', | ||
title: 'Next USSF town hall happening 1 MAY 2022, at 1300 GMT', | ||
labels: [ | ||
{ | ||
id: 'label2', | ||
name: 'Super Cool Label', | ||
type: 'Audience', | ||
}, | ||
], | ||
publishedDate: 'Aug 03, 2022', | ||
preview: | ||
'The second Inspector General Independent Racial Disparity Review focused on gender and ethnicity, and included additional racial groups (Hispanics, Latinos, Asians, American Indians, Alaska Natives, Native Hawaiians and other Pacific Islanders). It also referenced and compared data from the prior report on racial disparity, involving Black/African American Airmen and Guardians.', | ||
}, | ||
] | ||
|
||
export const DefaultNewsCarousel = () => ( | ||
<NewsCarousel articles={mockArticles} /> | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* @jest-environment jsdom | ||
*/ | ||
|
||
import { fireEvent, render, screen } from '@testing-library/react' | ||
import React from 'react' | ||
import { cmsPortalNewsArticlesMock } from '../../__fixtures__/data/cmsPortalNewsArticles' | ||
import '../../__mocks__/mockMatchMedia' | ||
import NewsCarousel from './NewsCarousel' | ||
|
||
describe('NewsCarousel component', () => { | ||
it('renders the component with mock articles', () => { | ||
render(<NewsCarousel articles={cmsPortalNewsArticlesMock} />) | ||
|
||
// Slider component in react-slick clones each item in the carousel, | ||
// so a length of 2 is accurate | ||
expect(screen.getAllByText('Announcing the dev blog')).toHaveLength(2) | ||
|
||
fireEvent.click(screen.getByTestId('slick-next')) | ||
jcbcapps marked this conversation as resolved.
Show resolved
Hide resolved
|
||
expect(screen.getAllByText('Welcome and Overview')).toHaveLength(2) | ||
|
||
fireEvent.click(screen.getByTestId('slick-prev')) | ||
expect(screen.getAllByText('Announcing the dev blog')).toHaveLength(2) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import React, { useRef } from 'react' | ||
import Slider from 'react-slick' | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||
import styles from './NewsCarousel.module.scss' | ||
import NewsCarouselItem from 'components/NewsCarouselItem/NewsCarouselItem' | ||
import 'slick-carousel/slick/slick.css' | ||
import 'slick-carousel/slick/slick-theme.css' | ||
import { ArticleListItemRecord } from 'types' | ||
|
||
const CustomEllipse = ({ onClick }: any) => { | ||
return ( | ||
<div className="news-carousel-container"> | ||
<button | ||
onClick={onClick} | ||
type="button" | ||
title="slide" | ||
className={styles.newsCarouselEllipse} | ||
/> | ||
</div> | ||
) | ||
} | ||
|
||
const NewsCarousel = ({ articles }: { articles: ArticleListItemRecord[] }) => { | ||
const sliderRef = useRef<Slider>(null) | ||
|
||
const settings = { | ||
dots: true, | ||
accessibility: true, | ||
adaptiveHeight: true, | ||
infinite: true, | ||
speed: 500, | ||
slidesToShow: 1, | ||
slidesToScroll: 1, | ||
arrows: false, | ||
dotsClass: `slick-dots ${styles.dots}`, | ||
appendDots: (dots: React.ReactNode) => { | ||
return ( | ||
<div | ||
style={{ | ||
bottom: '-40px', | ||
display: 'flex', | ||
justifyContent: 'space-between', | ||
alignItems: 'center', | ||
paddingLeft: '8rem', | ||
paddingRight: '8rem', | ||
}}> | ||
<div className={styles.carouselArrow}> | ||
<FontAwesomeIcon | ||
size="lg" | ||
icon="angle-left" | ||
data-testid="slick-prev" | ||
onClick={() => { | ||
if (sliderRef.current) { | ||
return sliderRef.current.slickPrev() | ||
} | ||
}} | ||
/> | ||
</div> | ||
<ul | ||
style={{ | ||
margin: '0px', | ||
paddingLeft: '0px', | ||
}}> | ||
{' '} | ||
{dots}{' '} | ||
</ul> | ||
<div className={styles.carouselArrow}> | ||
<FontAwesomeIcon | ||
size="lg" | ||
icon="angle-right" | ||
data-testid="slick-next" | ||
onClick={() => { | ||
if (sliderRef.current) { | ||
return sliderRef.current.slickNext() | ||
} | ||
}} | ||
/> | ||
</div> | ||
</div> | ||
) | ||
}, | ||
customPaging: () => <CustomEllipse />, | ||
} | ||
|
||
return ( | ||
<Slider ref={sliderRef} className={styles.carouselContainer} {...settings}> | ||
{articles.map((article: ArticleListItemRecord, index: number) => { | ||
return <NewsCarouselItem key={index} article={article} /> | ||
})} | ||
</Slider> | ||
) | ||
} | ||
|
||
export default NewsCarousel |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
@import 'styles/uswdsDependencies'; | ||
@import 'styles/sfds/sfdsDependencies'; | ||
|
||
.carouselImage { | ||
margin: 0; | ||
} | ||
|
||
.imageContainer { | ||
@media screen and (max-width: 1024px) { | ||
display: flex; | ||
justify-content: center; | ||
width: 100%; | ||
} | ||
} | ||
|
||
.gridContainer { | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
|
||
@media screen and (max-width: 1024px) { | ||
padding-top: 0.5rem; | ||
padding-bottom: 1.25rem; | ||
} | ||
|
||
.textContainer { | ||
color: $white; | ||
width: 100%; | ||
padding-left: 2.5rem; | ||
padding-right: 2.5rem; | ||
|
||
@media screen and (max-width: 768px) { | ||
padding-top: 0; | ||
} | ||
} | ||
|
||
.articleTitle { | ||
margin-bottom: 0; | ||
margin-top: 0; | ||
} | ||
|
||
.articlePreview { | ||
padding-bottom: 2rem; | ||
|
||
@media screen and (max-width: 1440px) { | ||
padding-bottom: 0.5rem; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
q: can you remind me why we needed to change these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh it was just something I thought would be helpful. I've noticed in other mock data in the repo, we're using just basic ids (ex: 1, test1) so I just thought I'd make it less complicated. I copy/pasted the data from a query I did against my local cms, and I just thought all that long text is a pain to look at. Just thinking ahead to if anyone ever needs to differentiate between items in the array via the id or something it would just be quicker/easier to look at.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gotcha -- i think overall we can definitely improve our mock data and should align on some styles, like what should be as close to the format of prod data (the previous id) and what can be simplified (the current id). for a future eng sync, maybe! cc @gidjin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aligning on some standards of when to pick a production format vs not. I could go either way here so probably worth us talking it out a little bit or just agreeing to one. Would / Could the library you were looking at for seed data help in this situation as well?