-
Notifications
You must be signed in to change notification settings - Fork 61
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(web): add info card #16931
base: main
Are you sure you want to change the base?
feat(web): add info card #16931
Changes from 17 commits
2991578
bffca01
c31e2e4
c691abc
35efc7d
94a8575
ea88272
55ae166
f2bba67
ca42520
be27cbe
c28ada2
0f766cb
b9bdb0e
1507cab
51e8a4a
b3ce418
ec8e7b8
1eb0cb0
c11145c
859964a
9ec4527
3301830
50c504d
f80f403
dfb70bd
e907c68
b8fd9c9
569651a
e2080c6
e2a0b6a
d156f3c
5fd3723
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 | ||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,217 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
import * as React from 'react' | ||||||||||||||||||||||||||||||||||||||||||||||||||
import { useEffect, useState } from 'react' | ||||||||||||||||||||||||||||||||||||||||||||||||||
import { useWindowSize } from 'react-use' | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
import { | ||||||||||||||||||||||||||||||||||||||||||||||||||
Box, | ||||||||||||||||||||||||||||||||||||||||||||||||||
FocusableBox, | ||||||||||||||||||||||||||||||||||||||||||||||||||
GridColumn, | ||||||||||||||||||||||||||||||||||||||||||||||||||
GridContainer, | ||||||||||||||||||||||||||||||||||||||||||||||||||
GridRow, | ||||||||||||||||||||||||||||||||||||||||||||||||||
Icon, | ||||||||||||||||||||||||||||||||||||||||||||||||||
IconMapIcon, | ||||||||||||||||||||||||||||||||||||||||||||||||||
Inline, | ||||||||||||||||||||||||||||||||||||||||||||||||||
LinkV2, | ||||||||||||||||||||||||||||||||||||||||||||||||||
Stack, | ||||||||||||||||||||||||||||||||||||||||||||||||||
Tag, | ||||||||||||||||||||||||||||||||||||||||||||||||||
Text, | ||||||||||||||||||||||||||||||||||||||||||||||||||
} from '@island.is/island-ui/core' | ||||||||||||||||||||||||||||||||||||||||||||||||||
import { ActionCardProps } from '@island.is/island-ui/core/types' | ||||||||||||||||||||||||||||||||||||||||||||||||||
import { theme } from '@island.is/island-ui/theme' | ||||||||||||||||||||||||||||||||||||||||||||||||||
import { isDefined } from '@island.is/shared/utils' | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
import { BaseProps } from './InfoCard' | ||||||||||||||||||||||||||||||||||||||||||||||||||
import * as styles from './InfoCard.css' | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
const eyebrowColor = 'blueberry600' | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
export type DetailedProps = BaseProps & { | ||||||||||||||||||||||||||||||||||||||||||||||||||
logo?: string | ||||||||||||||||||||||||||||||||||||||||||||||||||
logoAlt?: string | ||||||||||||||||||||||||||||||||||||||||||||||||||
subEyebrow?: string | ||||||||||||||||||||||||||||||||||||||||||||||||||
//max 5 lines | ||||||||||||||||||||||||||||||||||||||||||||||||||
detailLines?: Array<{ | ||||||||||||||||||||||||||||||||||||||||||||||||||
icon: IconMapIcon | ||||||||||||||||||||||||||||||||||||||||||||||||||
text: string | ||||||||||||||||||||||||||||||||||||||||||||||||||
}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
tags?: Array<ActionCardProps['tag']> | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
export const DetailedInfoCard = ({ | ||||||||||||||||||||||||||||||||||||||||||||||||||
title, | ||||||||||||||||||||||||||||||||||||||||||||||||||
description, | ||||||||||||||||||||||||||||||||||||||||||||||||||
size = 'medium', | ||||||||||||||||||||||||||||||||||||||||||||||||||
eyebrow, | ||||||||||||||||||||||||||||||||||||||||||||||||||
subEyebrow, | ||||||||||||||||||||||||||||||||||||||||||||||||||
detailLines, | ||||||||||||||||||||||||||||||||||||||||||||||||||
tags, | ||||||||||||||||||||||||||||||||||||||||||||||||||
logo, | ||||||||||||||||||||||||||||||||||||||||||||||||||
logoAlt, | ||||||||||||||||||||||||||||||||||||||||||||||||||
link, | ||||||||||||||||||||||||||||||||||||||||||||||||||
}: DetailedProps) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
const [isTablet, setIsTablet] = useState(false) | ||||||||||||||||||||||||||||||||||||||||||||||||||
const { width } = useWindowSize() | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (width < theme.breakpoints.lg) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return setIsTablet(true) | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
setIsTablet(false) | ||||||||||||||||||||||||||||||||||||||||||||||||||
}, [width]) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
const renderLogo = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (!logo) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return null | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Box style={{ flex: '0 0 40px' }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<img height={40} src={logo} alt={logoAlt} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
const renderDetails = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (!detailLines?.length) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return null | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Box marginTop={2}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Stack space={1}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{detailLines?.slice(0, 5).map((d, index) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Box | ||||||||||||||||||||||||||||||||||||||||||||||||||
key={index} | ||||||||||||||||||||||||||||||||||||||||||||||||||
display="flex" | ||||||||||||||||||||||||||||||||||||||||||||||||||
flexDirection={'row'} | ||||||||||||||||||||||||||||||||||||||||||||||||||
alignItems="center" | ||||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Icon | ||||||||||||||||||||||||||||||||||||||||||||||||||
icon={d.icon} | ||||||||||||||||||||||||||||||||||||||||||||||||||
size="small" | ||||||||||||||||||||||||||||||||||||||||||||||||||
type="outline" | ||||||||||||||||||||||||||||||||||||||||||||||||||
color="blue400" | ||||||||||||||||||||||||||||||||||||||||||||||||||
useStroke | ||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Box marginLeft={2}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Text variant="medium">{d.text}</Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
))} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Stack> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
const renderTags = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (!tags?.length) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return null | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Inline space={1}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{tags | ||||||||||||||||||||||||||||||||||||||||||||||||||
.map((tag) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (!tag) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return null | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Tag disabled variant={tag.variant}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{tag.label} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Tag> | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||
.filter(isDefined)} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Inline> | ||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+114
to
+125
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. Add a unique When rendering a list of items in React using Apply this diff to fix the issue: {tags
- .map((tag) => {
+ .map((tag, index) => {
if (!tag) {
return null
}
return (
- <Tag disabled variant={tag.variant}>
+ <Tag key={tag.label} disabled variant={tag.variant}>
{tag.label}
</Tag>
)
})
.filter(isDefined)} Ensure that 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Biome (1.9.4)[error] 119-119: Missing key property for this element in iterable. The order of the items may change, and having a key can help React identify which item was moved. (lint/correctness/useJsxKeyInIterable) |
||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
const renderHeader = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Box | ||||||||||||||||||||||||||||||||||||||||||||||||||
display="flex" | ||||||||||||||||||||||||||||||||||||||||||||||||||
flexDirection="row" | ||||||||||||||||||||||||||||||||||||||||||||||||||
justifyContent="spaceBetween" | ||||||||||||||||||||||||||||||||||||||||||||||||||
marginBottom={3} | ||||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{subEyebrow ? ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Text fontWeight="semiBold" variant="eyebrow" color={eyebrowColor}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{eyebrow} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Text fontWeight="light" variant="eyebrow" color={eyebrowColor}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{subEyebrow} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
) : ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Text variant="eyebrow" color={eyebrowColor}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{eyebrow} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||
)} | ||||||||||||||||||||||||||||||||||||||||||||||||||
{renderLogo()} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
const renderContent = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
if (size === 'large' && !isTablet) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<GridContainer> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<GridRow direction="row"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<GridColumn span="8/12"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Text variant="h3" color="blue400"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{title} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{description && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Box flexGrow={1} marginTop={1}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Text>{description}</Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
)} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</GridColumn> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<GridColumn span="4/12">{renderDetails()}</GridColumn> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</GridRow> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</GridContainer> | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Text variant="h3" color="blue400"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{title} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{description && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Box marginTop={1}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Text>{description}</Text> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
)} | ||||||||||||||||||||||||||||||||||||||||||||||||||
{renderDetails()} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</> | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
<FocusableBox | ||||||||||||||||||||||||||||||||||||||||||||||||||
className={ | ||||||||||||||||||||||||||||||||||||||||||||||||||
size === 'large' | ||||||||||||||||||||||||||||||||||||||||||||||||||
? styles.infoCardWide | ||||||||||||||||||||||||||||||||||||||||||||||||||
: size === 'small' | ||||||||||||||||||||||||||||||||||||||||||||||||||
? styles.infoCardSmall | ||||||||||||||||||||||||||||||||||||||||||||||||||
: styles.infoCard | ||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||
component={LinkV2} | ||||||||||||||||||||||||||||||||||||||||||||||||||
href={link.href} | ||||||||||||||||||||||||||||||||||||||||||||||||||
background="white" | ||||||||||||||||||||||||||||||||||||||||||||||||||
borderColor="white" | ||||||||||||||||||||||||||||||||||||||||||||||||||
borderWidth="standard" | ||||||||||||||||||||||||||||||||||||||||||||||||||
width="full" | ||||||||||||||||||||||||||||||||||||||||||||||||||
borderRadius="standard" | ||||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Box width="full" paddingX={4} paddingY={3}> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{renderHeader()} | ||||||||||||||||||||||||||||||||||||||||||||||||||
{renderContent()} | ||||||||||||||||||||||||||||||||||||||||||||||||||
<Box marginTop={3} display="flex" justifyContent="spaceBetween"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
{renderTags()} | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</Box> | ||||||||||||||||||||||||||||||||||||||||||||||||||
</FocusableBox> | ||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { style } from '@vanilla-extract/css' | ||
|
||
export const infoCardSmall = style({ | ||
maxWidth: 310, | ||
}) | ||
|
||
export const infoCard = style({ | ||
maxWidth: 477, | ||
}) | ||
|
||
export const infoCardWide = style({ | ||
maxWidth: 978, | ||
}) | ||
|
||
export const wideTitleBox = style({ | ||
flexGrow: 2, | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import * as React from 'react' | ||
|
||
import { DetailedInfoCard, DetailedProps } from './DetailedInfoCard' | ||
import { SimpleInfoCard } from './SimpleInfoCard' | ||
|
||
export interface BaseProps { | ||
title: string | ||
description: string | ||
eyebrow: string | ||
size: 'large' | 'medium' | 'small' | ||
link: { | ||
label: string | ||
href: string | ||
} | ||
} | ||
|
||
export type InfoCardProps = | ||
| (BaseProps & { | ||
variant?: 'simple' | ||
}) | ||
| (DetailedProps & { | ||
variant: 'detailed' | ||
}) | ||
|
||
export const InfoCard = (props: InfoCardProps) => { | ||
if (props.variant === 'detailed') { | ||
return <DetailedInfoCard {...props} /> | ||
} else { | ||
return <SimpleInfoCard {...props} /> | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,49 @@ | ||||||||||||||||||||||||||||||||
import { useEffect, useState } from 'react' | ||||||||||||||||||||||||||||||||
import { useWindowSize } from 'react-use' | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
import { Inline, Stack } from '@island.is/island-ui/core' | ||||||||||||||||||||||||||||||||
import { theme } from '@island.is/island-ui/theme' | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
import { InfoCard, InfoCardProps } from './InfoCard' | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
export type InfoCardItemProps = Omit<InfoCardProps, 'size' | 'variant'> | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
interface Props { | ||||||||||||||||||||||||||||||||
cards: Array<InfoCardItemProps> | ||||||||||||||||||||||||||||||||
variant?: 'detailed' | 'simple' | ||||||||||||||||||||||||||||||||
columns?: 1 | 2 | 3 | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
export const InfoCardWrapper = ({ cards, variant, columns }: Props) => { | ||||||||||||||||||||||||||||||||
const [isMobile, setIsMobile] = useState(false) | ||||||||||||||||||||||||||||||||
const { width } = useWindowSize() | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
useEffect(() => { | ||||||||||||||||||||||||||||||||
if (width < theme.breakpoints.md) { | ||||||||||||||||||||||||||||||||
return setIsMobile(true) | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
setIsMobile(false) | ||||||||||||||||||||||||||||||||
}, [width]) | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
if (columns === 1 || isMobile) { | ||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||
<Stack space={3}> | ||||||||||||||||||||||||||||||||
{cards.map((c) => ( | ||||||||||||||||||||||||||||||||
<InfoCard variant={variant} size={'large'} {...c} /> | ||||||||||||||||||||||||||||||||
))} | ||||||||||||||||||||||||||||||||
Comment on lines
+31
to
+33
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. Add missing key prop to mapped InfoCard components React requires a unique key prop when rendering elements in an array to optimize rendering and maintain component state correctly. - <InfoCard variant={variant} size={'large'} {...c} />
+ <InfoCard key={c.id ?? c.title} variant={variant} size={'large'} {...c} />
🧰 Tools🪛 Biome (1.9.4)[error] 32-32: Missing key property for this element in iterable. The order of the items may change, and having a key can help React identify which item was moved. (lint/correctness/useJsxKeyInIterable) |
||||||||||||||||||||||||||||||||
</Stack> | ||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||
<Inline space={3}> | ||||||||||||||||||||||||||||||||
{cards.map((c) => ( | ||||||||||||||||||||||||||||||||
<InfoCard | ||||||||||||||||||||||||||||||||
variant={variant} | ||||||||||||||||||||||||||||||||
size={columns === 3 ? 'small' : 'medium'} | ||||||||||||||||||||||||||||||||
{...c} | ||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||
))} | ||||||||||||||||||||||||||||||||
Comment on lines
+40
to
+46
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. Add missing key prop to mapped InfoCard components Similar to the previous issue, add a unique key prop here as well. <InfoCard
+ key={c.id ?? c.title}
variant={variant}
size={columns === 3 ? 'small' : 'medium'}
{...c}
/> 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Biome (1.9.4)[error] 41-45: Missing key property for this element in iterable. The order of the items may change, and having a key can help React identify which item was moved. (lint/correctness/useJsxKeyInIterable) |
||||||||||||||||||||||||||||||||
</Inline> | ||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||
} |
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.
Fix incorrect use of
return
inuseEffect
The
useEffect
hook should not return the result ofsetIsTablet(true)
as it is not a cleanup function. Returning a value fromuseEffect
other than a cleanup function can lead to unexpected behavior.Apply this diff to fix the issue:
📝 Committable suggestion