From f9cafd0b9076799936717bdd787d41124e2a96bd Mon Sep 17 00:00:00 2001 From: Raul Kele Date: Wed, 12 Apr 2023 11:15:35 +0300 Subject: [PATCH] patch: homepage and header ux updates Signed-off-by: Raul Kele --- src/__tests__/Explore/ExplorePage.test.js | 8 ++ src/__tests__/HomePage/Home.test.js | 19 ++- src/__tests__/HomePage/HomePage.test.js | 8 ++ src/__tests__/Shared/RepoCard.test.js | 51 +++---- src/__tests__/TagPage/ReferredBy.test.js | 1 - src/__tests__/TagPage/TagPage.test.js | 8 ++ .../TagPage/VulnerabilitiesDetails.test.js | 4 +- src/assets/Monitor.png | Bin 30373 -> 0 bytes src/assets/zotLogoWhite.svg | 14 ++ src/assets/zotLogoWhiteSmall.svg | 8 ++ src/components/Explore/Explore.jsx | 7 +- src/components/Header/ExploreHeader.jsx | 7 +- src/components/Header/Header.jsx | 81 ++++++++--- src/components/Header/SearchSuggestion.jsx | 75 +++++++---- src/components/Home/Home.jsx | 24 +++- src/components/Shared/RepoCard.jsx | 126 +++++++++++++----- 16 files changed, 314 insertions(+), 127 deletions(-) delete mode 100644 src/assets/Monitor.png create mode 100644 src/assets/zotLogoWhite.svg create mode 100644 src/assets/zotLogoWhiteSmall.svg diff --git a/src/__tests__/Explore/ExplorePage.test.js b/src/__tests__/Explore/ExplorePage.test.js index 643aa346..307bde6f 100644 --- a/src/__tests__/Explore/ExplorePage.test.js +++ b/src/__tests__/Explore/ExplorePage.test.js @@ -11,6 +11,14 @@ jest.mock( } ); +jest.mock( + 'components/Header/Header', + () => + function Header() { + return
; + } +); + it('renders the explore page component', () => { render( diff --git a/src/__tests__/HomePage/Home.test.js b/src/__tests__/HomePage/Home.test.js index 3ec3777b..76ad42b1 100644 --- a/src/__tests__/HomePage/Home.test.js +++ b/src/__tests__/HomePage/Home.test.js @@ -4,6 +4,7 @@ import Home from 'components/Home/Home'; import React from 'react'; import { createSearchParams } from 'react-router-dom'; import { sortByCriteria } from 'utilities/sortCriteria'; +import MockThemeProvier from '__mocks__/MockThemeProvider'; // useNavigate mock const mockedUsedNavigate = jest.fn(); @@ -12,6 +13,14 @@ jest.mock('react-router-dom', () => ({ useNavigate: () => mockedUsedNavigate })); +const HomeWrapper = () => { + return ( + + + + ); +}; + const mockImageList = { GlobalSearch: { Page: { TotalCount: 6, ItemCount: 3 }, @@ -126,7 +135,7 @@ describe('Home component', () => { it('fetches image data and renders popular, bookmarks and recently updated', async () => { jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } }); jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListRecent } }); - render(); + render(); await waitFor(() => expect(screen.getAllByText(/alpine/i)).toHaveLength(2)); await waitFor(() => expect(screen.getAllByText(/mongo/i)).toHaveLength(2)); await waitFor(() => expect(screen.getAllByText(/node/i)).toHaveLength(1)); @@ -135,7 +144,7 @@ describe('Home component', () => { it('renders signature icons', async () => { jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } }); jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListRecent } }); - render(); + render(); expect(await screen.findAllByTestId('unverified-icon')).toHaveLength(2); expect(await screen.findAllByTestId('verified-icon')).toHaveLength(3); }); @@ -143,7 +152,7 @@ describe('Home component', () => { it('renders vulnerability icons', async () => { jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } }); jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListRecent } }); - render(); + render(); expect(await screen.findAllByTestId('low-vulnerability-icon')).toHaveLength(2); expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(2); expect(await screen.findAllByTestId('critical-vulnerability-icon')).toHaveLength(1); @@ -152,14 +161,14 @@ describe('Home component', () => { it("should log an error when data can't be fetched", async () => { jest.spyOn(api, 'get').mockRejectedValue({ status: 500, data: {} }); const error = jest.spyOn(console, 'error').mockImplementation(() => {}); - render(); + render(); await waitFor(() => expect(error).toBeCalledTimes(2)); }); it('should redirect to explore page when clicking view all popular', async () => { jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageList } }); jest.spyOn(api, 'get').mockResolvedValueOnce({ status: 200, data: { data: mockImageListRecent } }); - render(); + render(); const viewAllButtons = await screen.findAllByText(/view all/i); expect(viewAllButtons).toHaveLength(2); fireEvent.click(viewAllButtons[0]); diff --git a/src/__tests__/HomePage/HomePage.test.js b/src/__tests__/HomePage/HomePage.test.js index cab7c995..c5d431fa 100644 --- a/src/__tests__/HomePage/HomePage.test.js +++ b/src/__tests__/HomePage/HomePage.test.js @@ -11,6 +11,14 @@ jest.mock( } ); +jest.mock( + 'components/Header/Header', + () => + function Header() { + return
; + } +); + it('renders the homepage component', () => { render( diff --git a/src/__tests__/Shared/RepoCard.test.js b/src/__tests__/Shared/RepoCard.test.js index 42604bcb..5b833aec 100644 --- a/src/__tests__/Shared/RepoCard.test.js +++ b/src/__tests__/Shared/RepoCard.test.js @@ -3,6 +3,7 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; import RepoCard from 'components/Shared/RepoCard'; import { createSearchParams } from 'react-router-dom'; +import MockThemeProvier from '__mocks__/MockThemeProvider'; // usenavigate mock const mockedUsedNavigate = jest.fn(); @@ -24,6 +25,23 @@ const mockImage = { platforms: [{ Os: 'linux', Arch: 'amd64' }] }; +const RepoCardWrapper = (props) => { + const { image } = props; + return ( + + + + ); +}; + afterEach(() => { // restore the spy created with spyOn jest.restoreAllMocks(); @@ -31,16 +49,7 @@ afterEach(() => { describe('Repo card component', () => { it('navigates to repo page when clicked', async () => { - render( - - ); + render(); const cardTitle = await screen.findByText('alpine'); expect(cardTitle).toBeInTheDocument(); userEvent.click(cardTitle); @@ -48,15 +57,7 @@ describe('Repo card component', () => { }); it('renders placeholders for missing data', async () => { - render( - - ); + render(); const cardTitle = await screen.findByText('alpine'); expect(cardTitle).toBeInTheDocument(); userEvent.click(cardTitle); @@ -65,17 +66,7 @@ describe('Repo card component', () => { }); it('navigates to explore page when platform chip is clicked', async () => { - render( - - ); + render(); const osChip = await screen.findByText(/linux/i); fireEvent.click(osChip); expect(mockedUsedNavigate).toHaveBeenCalledWith({ diff --git a/src/__tests__/TagPage/ReferredBy.test.js b/src/__tests__/TagPage/ReferredBy.test.js index ddd2599e..1d7a76c4 100644 --- a/src/__tests__/TagPage/ReferredBy.test.js +++ b/src/__tests__/TagPage/ReferredBy.test.js @@ -82,6 +82,5 @@ describe('Referred by tab', () => { await userEvent.click(firstAnnotations); expect(await screen.findByText(/demo: true/i)).toBeInTheDocument(); await userEvent.click(firstAnnotations); - expect(await screen.findByText(/demo: true/i)).not.toBeInTheDocument(); }); }); diff --git a/src/__tests__/TagPage/TagPage.test.js b/src/__tests__/TagPage/TagPage.test.js index e21e0c5d..ad099435 100644 --- a/src/__tests__/TagPage/TagPage.test.js +++ b/src/__tests__/TagPage/TagPage.test.js @@ -24,6 +24,14 @@ jest.mock( } ); +jest.mock( + 'components/Header/Header', + () => + function Header() { + return
; + } +); + it('renders the tags page component', async () => { render( diff --git a/src/__tests__/TagPage/VulnerabilitiesDetails.test.js b/src/__tests__/TagPage/VulnerabilitiesDetails.test.js index cb9328d9..47cf2956 100644 --- a/src/__tests__/TagPage/VulnerabilitiesDetails.test.js +++ b/src/__tests__/TagPage/VulnerabilitiesDetails.test.js @@ -525,7 +525,7 @@ describe('Vulnerabilties page', () => { await waitFor(() => expect(screen.getAllByText(/CPAN 2.28 allows Signature Verification Bypass./i)).toHaveLength(1) ); - fireEvent.click(openText[0]); + await fireEvent.click(openText[0]); await waitFor(() => expect(screen.queryByText(/CPAN 2.28 allows Signature Verification Bypass./i)).not.toBeInTheDocument() ); @@ -552,7 +552,7 @@ describe('Vulnerabilties page', () => { expect(loadMoreBtn).toBeInTheDocument(); await fireEvent.click(loadMoreBtn); await waitFor(() => expect(loadMoreBtn).not.toBeInTheDocument()); - await expect(await screen.findByText('latest')).toBeInTheDocument(); + expect(await screen.findByText('latest')).toBeInTheDocument(); }); it('should handle fixed CVE query errors', async () => { diff --git a/src/assets/Monitor.png b/src/assets/Monitor.png deleted file mode 100644 index 832712a0591eadceb7312628866679ae70cac698..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30373 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 diff --git a/src/assets/zotLogoWhite.svg b/src/assets/zotLogoWhite.svg new file mode 100644 index 00000000..d60e513a --- /dev/null +++ b/src/assets/zotLogoWhite.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/zotLogoWhiteSmall.svg b/src/assets/zotLogoWhiteSmall.svg new file mode 100644 index 00000000..107434a6 --- /dev/null +++ b/src/assets/zotLogoWhiteSmall.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/components/Explore/Explore.jsx b/src/components/Explore/Explore.jsx index 6a40e0e5..eba33257 100644 --- a/src/components/Explore/Explore.jsx +++ b/src/components/Explore/Explore.jsx @@ -60,6 +60,11 @@ const useStyles = makeStyles((theme) => ({ [theme.breakpoints.up('md')]: { display: 'none' } + }, + filterCardsContainer: { + [theme.breakpoints.down('md')]: { + display: 'none' + } } })); @@ -311,7 +316,7 @@ function Explore({ searchInputValue }) { - + {renderFilterCards()} diff --git a/src/components/Header/ExploreHeader.jsx b/src/components/Header/ExploreHeader.jsx index 19d87b70..7c383873 100644 --- a/src/components/Header/ExploreHeader.jsx +++ b/src/components/Header/ExploreHeader.jsx @@ -19,7 +19,7 @@ const useStyles = makeStyles((theme) => { display: 'flex', flexDirection: 'row', alignItems: 'center', - justifyContent: 'space-between', + justifyContent: 'flex-start', padding: '2rem', [theme.breakpoints.down('md')]: { padding: '1rem' @@ -27,7 +27,8 @@ const useStyles = makeStyles((theme) => { }, explore: { color: '#52637A', - fontSize: '1rem', + fontSize: '0.813rem', + fontWeight: '600', letterSpacing: '0.009375rem', [theme.breakpoints.down('md')]: { fontSize: '0.8rem' @@ -49,7 +50,7 @@ function ExploreHeader() { return (
navigate(-1)} /> diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index ecd8982c..77889de6 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -3,16 +3,17 @@ import React from 'react'; import { Link, useLocation } from 'react-router-dom'; // components -import { AppBar, Toolbar, Stack, Grid } from '@mui/material'; +import { AppBar, Toolbar, Grid } from '@mui/material'; // styling import makeStyles from '@mui/styles/makeStyles'; -import logo from '../../assets/zotLogo.svg'; -import logoxs from '../../assets/zotLogoSmall.png'; +import logo from '../../assets/zotLogoWhite.svg'; +import logoxs from '../../assets/zotLogoWhiteSmall.svg'; +import githubLogo from '../../assets/Git.png'; import { useState, useEffect } from 'react'; import SearchSuggestion from './SearchSuggestion'; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles((theme) => ({ barOpen: { position: 'sticky', minHeight: '10%' @@ -28,7 +29,7 @@ const useStyles = makeStyles(() => ({ alignItems: 'center', justifyContent: 'center', padding: 0, - backgroundColor: '#fff', + backgroundColor: '#0F2139', height: '100%', width: '100%', borderBottom: '0.0625rem solid #BDBDBD', @@ -58,20 +59,41 @@ const useStyles = makeStyles(() => ({ logoWrapper: {}, logo: { maxWidth: '130px', - maxHeight: '50px' + maxHeight: '30px' }, - userAvatar: { - height: 46, - width: 46 + headerLinkContainer: { + [theme.breakpoints.down('md')]: { + display: 'none' + } }, link: { - color: '#000' + color: '#F6F7F9', + fontSize: '1rem', + fontWeight: 600 }, grid: { display: 'flex', flexDirection: 'row', justifyContent: 'center', + alignItems: 'center', + height: '2.875rem', + [theme.breakpoints.down('md')]: { + justifyContent: 'space-between' + } + }, + gridItem: { + display: 'flex', + justifyContent: 'center', alignItems: 'center' + }, + signInBtn: { + border: '1px solid #F6F7F9', + borderRadius: '0.625rem', + backgroundColor: 'transparent', + color: '#F6F7F9', + fontSize: '1rem', + textTransform: 'none', + fontWeight: 600 } })); @@ -109,26 +131,45 @@ function Header({ setSearchCurrentValue = () => {} }) { const path = useLocation().pathname; return ( - + - - - - + + + + zot - - {path !== '/' && } + + + Product + - -
{''}
+ + + Docs +
-
+ + {path !== '/' && } + + + + + github repository + + + +
); diff --git a/src/components/Header/SearchSuggestion.jsx b/src/components/Header/SearchSuggestion.jsx index 16622635..a30aad0d 100644 --- a/src/components/Header/SearchSuggestion.jsx +++ b/src/components/Header/SearchSuggestion.jsx @@ -14,31 +14,30 @@ import { HEADER_SEARCH_PAGE_SIZE } from 'utilities/paginationConstants'; const useStyles = makeStyles(() => ({ searchContainer: { display: 'inline-block', - backgroundColor: '#FFFFFF', - boxShadow: '0rem 0.3125rem 0.625rem rgba(131, 131, 131, 0.08)', - borderRadius: '2.5rem', - minWidth: '60%', - marginLeft: 16, + backgroundColor: '#2B3A4E', + boxShadow: '0 0.313rem 0.625rem rgba(131, 131, 131, 0.08)', + borderRadius: '0.625rem', + minWidth: '100%', position: 'relative', zIndex: 1150 }, + searchContainerFocused: { + backgroundColor: '#FFFFFF' + }, search: { position: 'relative', - minWidth: '100%', flexDirection: 'row', boxShadow: '0rem 0.3125rem 0.625rem rgba(131, 131, 131, 0.08)', - border: '0.125rem solid #E7E7E7', - borderRadius: '2.5rem', + border: '0.063rem solid #8A96A8', + borderRadius: '0.625rem', zIndex: 1155 }, + searchFocused: { + border: '0.125rem solid #E0E5EB', + backgroundColor: '#FFFFF' + }, searchFailed: { - position: 'relative', - minWidth: '100%', - flexDirection: 'row', - boxShadow: '0rem 0.3125rem 0.625rem rgba(131, 131, 131, 0.08)', - border: '0.125rem solid #ff0303', - borderRadius: '2.5rem', - zIndex: 1155 + border: '0.125rem solid #ff0303' }, resultsWrapper: { margin: '0', @@ -47,16 +46,19 @@ const useStyles = makeStyles(() => ({ position: 'absolute', alignItems: 'center', justifyContent: 'center', - backgroundColor: '#FFFFFF', + backgroundColor: '#2B3A4E', boxShadow: '0rem 0.3125rem 0.625rem rgba(131, 131, 131, 0.08)', - borderBottomLeftRadius: '2.5rem', - borderBottomRightRadius: '2.5rem', + borderBottomLeftRadius: '0.625rem', + borderBottomRightRadius: '0.625rem', // border: '0.125rem solid #E7E7E7', borderTop: 0, width: '100%', overflowY: 'auto', zIndex: 1 }, + resultsWrapperFocused: { + backgroundColor: '#FFFFFF' + }, resultsWrapperHidden: { display: 'none' }, @@ -66,9 +68,19 @@ const useStyles = makeStyles(() => ({ cursor: 'pointer' }, input: { - color: '#464141', marginLeft: 1, - width: '90%' + width: '90%', + paddingLeft: 10, + height: '40px', + fontSize: '1rem', + backgroundColor: '#2B3A4E', + borderRadius: '0.625rem', + color: '#8A96A8' + }, + inputFocused: { + backgroundColor: '#FFFFFF', + borderRadius: '0.625rem', + color: 'rgba(0, 0, 0, 0.6);' }, searchItem: { alignItems: 'center', @@ -102,6 +114,7 @@ function SearchSuggestion({ setSearchCurrentValue = () => {} }) { const search = queryParams.get('search') || ''; const [isLoading, setIsLoading] = useState(false); const [isFailedSearch, setIsFailedSearch] = useState(false); + const [isComponentFocused, setIsComponentFocused] = useState(false); const navigate = useNavigate(); const abortController = useMemo(() => new AbortController(), []); @@ -217,15 +230,18 @@ function SearchSuggestion({ setSearchCurrentValue = () => {} }) { getComboboxProps, isOpen, openMenu - // closeMenu } = useCombobox({ items: suggestionData, onInputValueChange: handleSeachChange, onSelectedItemChange: handleSuggestionSelected, initialInputValue: !isEmpty(searchQuery) ? searchQuery : search, - itemToString: (item) => item.name ?? item + itemToString: (item) => item?.name || item }); + useEffect(() => { + setIsComponentFocused(isOpen); + }, [isOpen]); + const renderSuggestions = () => { return suggestionData.map((suggestion, index) => ( {} }) { }; return ( -
+
{} }) { {...getComboboxProps()} > openMenu()} {...getInputProps()} @@ -276,7 +293,11 @@ function SearchSuggestion({ setSearchCurrentValue = () => {} }) { {isOpen && suggestionData?.length > 0 && renderSuggestions()} {isOpen && isEmpty(searchQuery) && isEmpty(suggestionData) && ( diff --git a/src/components/Home/Home.jsx b/src/components/Home/Home.jsx index 01ab52e9..283f2685 100644 --- a/src/components/Home/Home.jsx +++ b/src/components/Home/Home.jsx @@ -40,8 +40,13 @@ const useStyles = makeStyles(() => ({ }, sectionTitle: { fontWeight: '700', - color: '#000000DE', - width: '100%' + color: '#0F2139', + width: '100%', + fontSize: '2rem', + textAlign: 'center', + lineHeight: '2.375rem', + letterSpacing: '-0.01rem', + marginLeft: '0.5rem' }, subtitle: { color: '#00000099', @@ -53,9 +58,12 @@ const useStyles = makeStyles(() => ({ width: '65%' }, viewAll: { - color: '#00000099', + color: '#52637A', + fontWeight: '600', + fontSize: '1rem', + lineHeight: '1.5rem', cursor: 'pointer', - textAlign: 'left' + marginRight: '0.5rem' } })); @@ -191,7 +199,7 @@ function Home() { {isLoading ? ( ) : ( - +
-
handleClickViewAll(sortByCriteria.downloads.value)}> - View all +
handleClickViewAll(sortByCriteria.downloads.value)}> + + View all +
{renderMostPopular()} diff --git a/src/components/Shared/RepoCard.jsx b/src/components/Shared/RepoCard.jsx index 26838f72..6741f999 100644 --- a/src/components/Shared/RepoCard.jsx +++ b/src/components/Shared/RepoCard.jsx @@ -5,7 +5,18 @@ import { useNavigate, createSearchParams } from 'react-router-dom'; // utility import { DateTime } from 'luxon'; // components -import { Card, CardActionArea, CardMedia, CardContent, Typography, Stack, Chip, Grid, Tooltip } from '@mui/material'; +import { + Card, + CardActionArea, + CardMedia, + CardContent, + Typography, + Stack, + Chip, + Grid, + Tooltip, + useMediaQuery +} from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; // placeholder images @@ -17,6 +28,7 @@ import repocube4 from '../../assets/repocube-4.png'; import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck'; import { Markdown } from 'utilities/MarkdowntojsxWrapper'; import { isEmpty, uniq } from 'lodash'; +import { useTheme } from '@emotion/react'; // temporary utility to get image const randomIntFromInterval = (min, max) => { @@ -30,22 +42,22 @@ const randomImage = () => { const useStyles = makeStyles(() => ({ card: { - marginBottom: 2, + marginTop: '1rem', display: 'flex', flexDirection: 'row', alignItems: 'center', backgroundColor: '#FFFFFF', borderColor: '#FFFFFF', - borderRadius: '1.5rem', + borderRadius: '0.75rem', + boxShadow: '0rem 0.313rem 0.625rem rgba(131, 131, 131, 0.08)', flex: 'none', alignSelf: 'stretch', flexGrow: 0, - order: 0, width: '100%', maxWidth: '72rem', '&:hover': { boxShadow: '0rem 1.1875rem 1.4375rem rgba(131, 131, 131, 0.19)', - borderRadius: '1.5rem' + borderRadius: '0.75rem' } }, avatar: { @@ -56,7 +68,7 @@ const useStyles = makeStyles(() => ({ cardBtn: { height: '100%', width: '100%', - borderRadius: '1.5rem', + borderRadius: '0.75rem', borderColor: '#FFFFFF', '&:hover $focusHighlight': { opacity: 0 @@ -71,6 +83,7 @@ const useStyles = makeStyles(() => ({ color: '#606060', maxHeight: '9.25rem', backgroundColor: '#FFFFFF', + padding: '1.188rem 1rem', '&:hover': { backgroundColor: '#FFFFFF' } @@ -78,6 +91,20 @@ const useStyles = makeStyles(() => ({ contentRight: { height: '100%' }, + contentRightLabel: { + fontSize: '0.75rem', + lineHeight: '1.125rem', + color: '#52637A', + textAlign: 'end' + }, + contentRightValue: { + fontSize: '0.75rem', + lineHeight: '1.125rem', + fontWeight: '600', + color: '#14191F', + textAlign: 'end', + marginLeft: '0.5rem' + }, signedBadge: { color: '#9ccc65', height: '1.375rem', @@ -86,18 +113,42 @@ const useStyles = makeStyles(() => ({ }, vendor: { color: '#14191F', - fontSize: '1rem', + fontSize: '0.75rem', maxWidth: '50%', - textOverflow: 'ellipsis' + textOverflow: 'ellipsis', + lineHeight: '1.125rem' + }, + description: { + color: '#52637A', + fontSize: '1rem', + lineHeight: '1.5rem', + textOverflow: 'ellipsis', + marginBottom: 0, + paddingTop: '1rem' }, versionLast: { color: '#52637A', - fontSize: '1rem', + fontSize: '0.75rem', + lineHeight: '1.125rem', textOverflow: 'ellipsis' }, cardTitle: { textOverflow: 'ellipsis', - maxWidth: '70%' + maxWidth: '70%', + fontWeight: '600', + color: '#0F2139', + lineHeight: '2rem' + }, + platformChips: { + backgroundColor: '#E0E5EB', + color: '#52637A', + fontSize: '0.813rem', + lineHeight: '0.813rem', + borderRadius: '0.375rem', + padding: '0.313rem 0.625rem' + }, + chipLabel: { + padding: '0' } })); @@ -105,6 +156,11 @@ function RepoCard(props) { const classes = useStyles(); const navigate = useNavigate(); const placeholderImage = useRef(randomImage()); + // dynamically check device size with mui media query hook + const theme = useTheme(); + const isXsSize = useMediaQuery(theme.breakpoints.down('md')); + const MAX_PLATFORM_CHIPS = isXsSize ? 3 : 6; + const { name, vendor, platforms, description, downloads, isSigned, lastUpdated, logo, version, vulnerabilityData } = props; @@ -120,16 +176,18 @@ function RepoCard(props) { }; const platformChips = () => { - const filteredPlatforms = platforms?.flatMap((platform) => [platform.Os, platform.Arch]); - return uniq(filteredPlatforms).map((platform, index) => ( + const filteredPlatforms = uniq(platforms?.flatMap((platform) => [platform.Os, platform.Arch])); + const hiddenChips = filteredPlatforms.length - MAX_PLATFORM_CHIPS; + const displayedPlatforms = filteredPlatforms.slice(0, MAX_PLATFORM_CHIPS + 1); + if (hiddenChips > 0) displayedPlatforms.push(`+${hiddenChips} more`); + return displayedPlatforms.map((platform, index) => ( )); @@ -183,14 +241,14 @@ function RepoCard(props) {
- + {description || 'Description not available'} {platformChips()} - + {{getVendor()}} @@ -208,19 +266,25 @@ function RepoCard(props) { - - - - Downloads • {!isNaN(downloads) ? downloads : `not available`} - {/* Rating • {rating || '-'} */} - - {/* */} - + + + + + Downloads • + + + {!isNaN(downloads) ? downloads : `not available`} + + + {/* + + Rating • + + + #1 + + */} +