Skip to content

Commit fcbe129

Browse files
Flexible heading sizes in card (#1336)
* Remove className from Heading * Enable custom Heading sizes * Add changeset
1 parent 50d33a2 commit fcbe129

File tree

3 files changed

+77
-78
lines changed

3 files changed

+77
-78
lines changed

.changeset/plenty-pots-relax.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
"@obosbbl/grunnmuren-react": patch
3+
---
4+
5+
`<Card>` now respects the `size` prop (if set) on it's `<Heading>`. This makes it possible to customize the size of the heading in a `<Card>`:
6+
7+
``` tsx
8+
<Card>
9+
<Content>
10+
<Heading level={3} size="m">Medium heading</Heading>
11+
<p>
12+
This heading is customized
13+
</p>
14+
</Content>
15+
</Card>
16+
```

packages/react/src/card/card.stories.tsx

Lines changed: 22 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ const meta: Meta<typeof Card> = {
2121
render: () => (
2222
<Card>
2323
<Content>
24-
<Heading className="heading-s" level={3}>
25-
Min bolig
26-
</Heading>
24+
<Heading level={3}>Min bolig</Heading>
2725
<p>
2826
Her finner du alt om din nye bolig og hva som venter deg fremover. Du
2927
finner dine dokumenter, salgsoppgave og mye mer.
@@ -54,9 +52,7 @@ export const WithBackground = () => {
5452
key={bgColor}
5553
>
5654
<Content>
57-
<Heading className="heading-s" level={3}>
58-
Bakgrunn {bgColor}
59-
</Heading>
55+
<Heading level={3}>Bakgrunn {bgColor}</Heading>
6056
<p>Dette kortet har {bgColor} som bakgrunnsfarge</p>
6157
</Content>
6258
</Card>
@@ -74,9 +70,7 @@ export const WithImage = () => (
7470
/>
7571
</Media>
7672
<Content>
77-
<Heading className="heading-s" level={3}>
78-
Kort med bilde
79-
</Heading>
73+
<Heading level={3}>Kort med bilde</Heading>
8074
<p>
8175
Dette kortet har et bilde og er uten border. Derfor er alle hjørner på
8276
bildet avrundet.
@@ -94,9 +88,7 @@ export const OutlinedWithImageAnd = () => (
9488
/>
9589
</Media>
9690
<Content>
97-
<Heading className="heading-s" level={3}>
98-
Kort med bilde og border
99-
</Heading>
91+
<Heading level={3}>Kort med bilde og border</Heading>
10092
<p>
10193
Dette kortet har et bilde og border. Derfor er kun hjørnene i toppen
10294
avrundet.
@@ -109,9 +101,7 @@ export const WithIconTop = () => (
109101
<Card variant="outlined">
110102
<PiggyBank />
111103
<Content>
112-
<Heading className="heading-s" level={3}>
113-
Kort med ikon i topp
114-
</Heading>
104+
<Heading level={3}>Kort med ikon i topp</Heading>
115105
<p>Dette kortet har svart border og et ikon i toppen</p>
116106
</Content>
117107
</Card>
@@ -120,9 +110,7 @@ export const WithIconTop = () => (
120110
export const WithIconBottom = () => (
121111
<Card variant="outlined">
122112
<Content>
123-
<Heading className="heading-s" level={3}>
124-
Kort med ikon i bunn
125-
</Heading>
113+
<Heading level={3}>Kort med ikon i bunn</Heading>
126114
<p>Dette kortet har svart border og et ikon i bunn</p>
127115
</Content>
128116
<PiggyBank />
@@ -174,9 +162,7 @@ export const CardWithInlineTopIllustration = () => (
174162
<Card variant="outlined" className="w-72">
175163
<Illustration />
176164
<Content>
177-
<Heading className="heading-s" level={3}>
178-
Utemiljø og grøntanlegg
179-
</Heading>
165+
<Heading level={3}>Utemiljø og grøntanlegg</Heading>
180166
<p>
181167
Et godt utemiljø er viktig for trivselen. Vi har en egen utenhusavdeling
182168
med flinke folk som kan hjelpe med realisering av nye prosjekter.
@@ -192,9 +178,7 @@ export const CardWithCoveringIllustration = () => (
192178
</Media>
193179
<Content>
194180
<div className="grid gap-1">
195-
<Heading className="heading-s" level={3}>
196-
Rødbergvn 88C
197-
</Heading>
181+
<Heading level={3}>Rødbergvn 88C</Heading>
198182
<small className="description">Bjerke - Oslo</small>
199183
</div>
200184
<small className="description -order-1">
@@ -220,7 +204,7 @@ export const CardWithCoveringIllustration = () => (
220204
export const ClickableWithIcon = () => (
221205
<Card variant="outlined">
222206
<Content>
223-
<Heading className="heading-s" level={3}>
207+
<Heading level={3}>
224208
<CardLink href="#card">Klikkbar med ikon</CardLink>
225209
</Heading>
226210
<p>Dette kortet er klikkbart og har svart border med et ikon</p>
@@ -238,7 +222,7 @@ export const ClickableWithImage = () => (
238222
/>
239223
</Media>
240224
<Content>
241-
<Heading className="heading-s" level={3}>
225+
<Heading level={3}>
242226
<CardLink href="#card">Klikkbar med bilde</CardLink>
243227
</Heading>
244228
<p>
@@ -252,7 +236,7 @@ export const ClickableWithImage = () => (
252236
export const ClickableWithBackground = () => (
253237
<Card className="bg-blue-dark text-white">
254238
<Content>
255-
<Heading className="heading-s" level={3}>
239+
<Heading level={3}>
256240
<CardLink href="#card">Klikkbar med bakgrunnsfarge</CardLink>
257241
</Heading>
258242
<p>Dette kortet er klikkbart og har en bakgrunnsfarge</p>
@@ -270,9 +254,7 @@ export const ClickableWithImageAndCTA = () => (
270254
/>
271255
</Media>
272256
<Content>
273-
<Heading className="heading-s" level={3}>
274-
Med bilde og CTA
275-
</Heading>
257+
<Heading level={3}>Med bilde og CTA</Heading>
276258
<p>Dette kortet har bilde og er klikkbart mot en CTA-lenke</p>
277259
<CardLink className="group/cta">
278260
<Button href="#cta" variant="tertiary">
@@ -287,9 +269,7 @@ export const ClickableWithImageAndCTA = () => (
287269
export const ClickableWithBackgroundAndCTA = () => (
288270
<Card className="bg-blue-dark text-white">
289271
<Content>
290-
<Heading className="heading-s" level={3}>
291-
Bakgrunnsfarge og CTA
292-
</Heading>
272+
<Heading level={3}>Bakgrunnsfarge og CTA</Heading>
293273
<p>Dette kortet har bakgrunnsfarge og er klikkbart mot en CTA-lenke.</p>
294274
<CardLink className="group/cta mt-1">
295275
<Button href="#cta" variant="tertiary">
@@ -312,7 +292,7 @@ export const ClickableWithOtherClickableElements = () => (
312292
</Media>
313293
<Content className="grow">
314294
<div className="grid gap-1">
315-
<Heading className="heading-s" level={3}>
295+
<Heading level={3}>
316296
<CardLink href="#card">Rødbergvn 88C</CardLink>
317297
</Heading>
318298
<small className="description">Bjerke - Oslo</small>
@@ -355,7 +335,7 @@ export const ClickableWithOtherClickableElementsAndBackgroundColor = () => (
355335
</Media>
356336
<Content>
357337
<div className="grid gap-1">
358-
<Heading className="heading-s" level={3}>
338+
<Heading level={3}>
359339
<CardLink href="#card">Rødbergvn 88C</CardLink>
360340
</Heading>
361341
<small className="description">Bjerke - Oslo</small>
@@ -405,7 +385,7 @@ export const ClickableWithBadge = () => (
405385
</Media>
406386
<Content>
407387
<div className="grid gap-1">
408-
<Heading className="heading-s" level={3}>
388+
<Heading level={3}>
409389
<CardLink href="#card">Rødbergvn 88C</CardLink>
410390
</Heading>
411391
<small className="description">Bjerke - Oslo</small>
@@ -455,7 +435,7 @@ export const ClickableWithBadgeRight = () => (
455435
</Media>
456436
<Content>
457437
<div className="grid gap-1">
458-
<Heading className="heading-s" level={3}>
438+
<Heading level={3}>
459439
<CardLink href="#card">Rødbergvn 88C</CardLink>
460440
</Heading>
461441
<small className="description">Bjerke - Oslo</small>
@@ -500,9 +480,7 @@ export const HorizontalLeft = () => (
500480
/>
501481
</Media>
502482
<Content>
503-
<Heading className="heading-s" level={3}>
504-
Med bilde til venstre
505-
</Heading>
483+
<Heading level={3}>Med bilde til venstre</Heading>
506484
<p>
507485
Dette kortet har bilde til venstre på større skjermer og er klikkbart
508486
mot en CTA-lenke
@@ -520,9 +498,7 @@ export const HorizontalLeft = () => (
520498
export const HorizontalRight = () => (
521499
<Card layout="horizontal">
522500
<Content>
523-
<Heading className="heading-s" level={3}>
524-
Med bilde til høyre
525-
</Heading>
501+
<Heading level={3}>Med bilde til høyre</Heading>
526502
<p>
527503
Dette kortet har bilde til høyre på større skjermer og er klikkbart mot
528504
en CTA-lenke
@@ -547,9 +523,7 @@ export const HorizontalWithIconLeft = () => (
547523
<Card layout="horizontal" variant="outlined">
548524
<PiggyBank />
549525
<Content>
550-
<Heading className="heading-s" level={3}>
551-
Med ikon til venstre
552-
</Heading>
526+
<Heading level={3}>Med ikon til venstre</Heading>
553527
<p>
554528
Dette kortet er liggende, har et ikon til venstre og er klikkbart mot en
555529
CTA-lenke
@@ -567,9 +541,7 @@ export const HorizontalWithIconLeft = () => (
567541
export const HorizontalWithIconRight = () => (
568542
<Card layout="horizontal" variant="outlined">
569543
<Content>
570-
<Heading className="heading-s" level={3}>
571-
Med ikon til høyre
572-
</Heading>
544+
<Heading level={3}>Med ikon til høyre</Heading>
573545
<p>
574546
Dette kortet er liggende, har et ikon til høyre og er klikkbart mot en
575547
CTA-lenke
@@ -590,9 +562,7 @@ export const WithAvatar = () => (
590562
<Avatar src="https://res.cloudinary.com/obosit-prd-ch-clry/image/upload/v1578474487/Boligkonferansen/obosbk%202017/Daniel_Kj%C3%B8rberg_Siraj_1x1.jpg" />
591563
<Content>
592564
<div className="flex flex-col-reverse gap-2">
593-
<Heading className="heading-s" level={3}>
594-
Daniel Kjørberg Siraj
595-
</Heading>
565+
<Heading level={3}>Daniel Kjørberg Siraj</Heading>
596566
<Description>Konsernsjef (CEO)</Description>
597567
</div>
598568
<p>Dette kortet er liggende, med et rundt bilde til høyre</p>

packages/react/src/card/card.tsx

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
import { type VariantProps, cva } from 'cva';
2-
import { Link, type LinkProps as RACLinkProps } from 'react-aria-components';
1+
import { type VariantProps, cva, cx } from 'cva';
2+
import {
3+
Link,
4+
Provider,
5+
type LinkProps as RACLinkProps,
6+
} from 'react-aria-components';
7+
import { HeadingContext } from '../content';
38

49
type CardProps = VariantProps<typeof cardVariants> & {
510
children?: React.ReactNode;
@@ -13,15 +18,6 @@ const cardVariants = cva({
1318
'flex gap-y-4', // y-gap ensures a vertical spacing for both verical layout and responsive horizontal layout
1419
'relative', // Needed for positiong of the clickable pseudo-element (and can also be used for other absolute positioned elements the consumer might add)
1520

16-
// **** Heading ****
17-
'[&_[data-slot="heading"]]:inline',
18-
'[&_[data-slot="heading"]]:heading-s',
19-
'[&_[data-slot="heading"]]:leading-6', // A bit more line height than the default is necessary to make the underline align with the text if the heading has a card link
20-
'[&_[data-slot="heading"]]:w-fit',
21-
'[&_[data-slot="heading"]]:text-pretty',
22-
'[&_[data-slot="heading"]]:hyphens-auto',
23-
'[&_[data-slot="heading"]]:[word-break:break-word]', // necessary to make hyphens work in grid containers in Safari
24-
2521
// **** Content ****
2622
'[&_[data-slot="content"]]:flex [&_[data-slot="content"]]:flex-col [&_[data-slot="content"]]:gap-y-4',
2723

@@ -41,21 +37,7 @@ const cardVariants = cva({
4137
// **** Hover ****
4238
// Enables the zoom hover effect on media (note that we can't use group-hover/card here, because there might be other clickable elements in the card aside from the heading)
4339
'[&:has([data-slot="card-link"]_a:hover)_[data-slot="media"]>img]:scale-110',
44-
// **** Card link in Heading ****
4540
'[&:has([data-slot="heading"]_[data-slot="card-link"]:hover)_[data-slot="media"]>img]:scale-110',
46-
// Border (bottom/top) is set to transparent to make sure the bottom underline is not visible when the card is hovered
47-
// Border top is set to even out the border bottom used for the underline
48-
'[&_[data-slot="heading"]_[data-slot="card-link"]]:no-underline',
49-
'[&_[data-slot="heading"]_[data-slot="card-link"]]:border-y-2',
50-
'[&_[data-slot="heading"]_[data-slot="card-link"]]:border-y-transparent',
51-
'[&_[data-slot="heading"]_[data-slot="card-link"]]:transition-colors',
52-
'[&_[data-slot="heading"]_[data-slot="card-link"]:hover]:border-b-current',
53-
// Mimic heading styles for the card link if placed in the heading slot. This is necessary to make the custom underline align with the link text
54-
'[&_[data-slot="heading"]_[data-slot="card-link"]]:heading-s',
55-
'[&_[data-slot="heading"]_[data-slot="card-link"]]:leading-6',
56-
'[&_[data-slot="heading"]_[data-slot="card-link"]]:text-pretty',
57-
'[&_[data-slot="heading"]_[data-slot="card-link"]]:hyphens-auto',
58-
'[&_[data-slot="heading"]_[data-slot="card-link"]]:[word-break:break-word]', // necessary to make hyphens work in grid containers in Safari
5941

6042
// **** Fail-safe for interactive elements ****
6143
// Make interactive elements clickable by themselves, while the rest of the card is clickable as a whole
@@ -171,7 +153,38 @@ const Card = ({
171153
});
172154
return (
173155
<div className={className} {...restProps}>
174-
{children}
156+
<Provider
157+
values={[
158+
[
159+
HeadingContext,
160+
{
161+
size: 's',
162+
className: cx([
163+
'inline',
164+
'w-fit',
165+
'text-pretty',
166+
'hyphens-auto',
167+
'[word-break:break-word]', // necessary to make hyphens work in grid containers in Safari
168+
// **** Card link in Heading ****
169+
// Border (bottom/top) is set to transparent to make sure the bottom underline is not visible when the card is hovered
170+
// Border top is set to even out the border bottom used for the underline
171+
'*:data-[slot="card-link"]:no-underline',
172+
'*:data-[slot="card-link"]:border-y-2',
173+
'*:data-[slot="card-link"]:border-y-transparent',
174+
'*:data-[slot="card-link"]:transition-colors',
175+
'*:data-[slot="card-link"]:hover:border-b-current',
176+
// Mimic heading styles for the card link if placed in the heading slot. This is necessary to make the custom underline align with the link text
177+
'*:data-[slot="card-link"]:font-inherit',
178+
'*:data-[slot="card-link"]:text-pretty',
179+
'*:data-[slot="card-link"]:hyphens-auto',
180+
'*:data-[slot="card-link"]:[word-break:break-word]', // necessary to make hyphens work in grid containers in Safari
181+
]),
182+
},
183+
],
184+
]}
185+
>
186+
{children}
187+
</Provider>
175188
</div>
176189
);
177190
};

0 commit comments

Comments
 (0)