@purpurds/promotion-card 5.18.3 → 5.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- ._purpur-promotion-card_1vt4e_1{position:relative;width:100%;height:100%;color:var(--promotion-card-color);box-sizing:border-box}._purpur-promotion-card--without-image_1vt4e_8 ._purpur-promotion-card__content_1vt4e_8{position:relative;z-index:1}._purpur-promotion-card--without-image_1vt4e_8:before{content:"";position:absolute;width:100%;height:100%;background-color:var(--promotion-card-background);background-image:var(--promotion-card-background-image);background-position:right 50% center;background-size:cover;transform:rotateY(180deg)}@container promotion-card (min-width: 600px){._purpur-promotion-card--without-image_1vt4e_8:before{background-position:center center}}@container promotion-card (min-width: 1024px){._purpur-promotion-card--without-image_1vt4e_8:before{transform:rotateY(0)}}._purpur-promotion-card--with-image_1vt4e_33{display:grid;grid-template-areas:"image" "body";grid-template-rows:auto 1fr;background:var(--promotion-card-background)}@container promotion-card (min-width: 600px){._purpur-promotion-card--with-image_1vt4e_33{grid-template-areas:"body image";grid-template-columns:repeat(2,1fr)}}._purpur-promotion-card__card_1vt4e_45{container:promotion-card/inline-size;height:100%}._purpur-promotion-card__image-gradient_1vt4e_49{position:absolute;bottom:0;width:100%;height:100%;background:linear-gradient(0,var(--promotion-card-background),transparent 75%)}@container promotion-card (min-width: 600px){._purpur-promotion-card__image-gradient_1vt4e_49{left:0;top:0;width:100%;height:100%;background:linear-gradient(90deg,var(--promotion-card-background),transparent 75%)}}._purpur-promotion-card__content_1vt4e_8{grid-area:body;display:flex;flex-direction:column;justify-content:flex-end;height:100%;padding:var(--purpur-spacing-400);box-sizing:border-box}@container promotion-card (min-width: 1024px){._purpur-promotion-card__content--without-image_1vt4e_75{padding:var(--purpur-spacing-600)}._purpur-promotion-card__content--without-image_1vt4e_75 ._purpur-promotion-card__main-content_1vt4e_78{display:flex;gap:var(--purpur-spacing-300)}._purpur-promotion-card__content--without-image_1vt4e_75 ._purpur-promotion-card__heading_1vt4e_82{width:100%}}@container promotion-card (min-width: 600px){._purpur-promotion-card__content--with-image_1vt4e_87{flex-direction:column;justify-content:center;padding:var(--purpur-spacing-600) var(--purpur-spacing-400)}}@container promotion-card (min-width: 1024px){._purpur-promotion-card__content--with-image_1vt4e_87{padding:var(--purpur-spacing-1200) var(--purpur-spacing-600)}}._purpur-promotion-card__badge-wrapper_1vt4e_98{width:100%;padding-bottom:var(--purpur-spacing-200)}._purpur-promotion-card__heading_1vt4e_82,._purpur-promotion-card__body_1vt4e_102{width:100%}._purpur-promotion-card__heading_1vt4e_82{margin-bottom:var(--purpur-spacing-150);color:var(--promotion-card-color)}._purpur-promotion-card__body_1vt4e_102{display:flex;flex-direction:column}._purpur-promotion-card__body_1vt4e_102,._purpur-promotion-card__body_1vt4e_102 p,._purpur-promotion-card__body_1vt4e_102 h1,._purpur-promotion-card__body_1vt4e_102 h2,._purpur-promotion-card__body_1vt4e_102 h3,._purpur-promotion-card__body_1vt4e_102 h4,._purpur-promotion-card__body_1vt4e_102 h5,._purpur-promotion-card__body_1vt4e_102 h6,._purpur-promotion-card__body_1vt4e_102 ul,._purpur-promotion-card__body_1vt4e_102 ol{color:var(--promotion-card-color)}._purpur-promotion-card__image-wrapper_1vt4e_125{grid-area:image}._purpur-promotion-card__image-wrapper--decorative_1vt4e_128 picture,._purpur-promotion-card__image-wrapper--decorative_1vt4e_128 img,._purpur-promotion-card__image-wrapper--product_1vt4e_129 picture,._purpur-promotion-card__image-wrapper--product_1vt4e_129 img{display:block;width:100%;height:auto}._purpur-promotion-card__image-wrapper--decorative_1vt4e_128 img,._purpur-promotion-card__image-wrapper--product_1vt4e_129 img{object-fit:cover}._purpur-promotion-card__image-wrapper--decorative_1vt4e_128{position:relative;width:100%;aspect-ratio:3/2}@container promotion-card (min-width: 600px){._purpur-promotion-card__image-wrapper--decorative_1vt4e_128{aspect-ratio:unset}._purpur-promotion-card__image-wrapper--decorative_1vt4e_128 img{height:100%}}._purpur-promotion-card__image-wrapper--product_1vt4e_129{display:flex;justify-content:center;align-items:center;padding:var(--purpur-spacing-400)}._purpur-promotion-card_1vt4e_1 [class*=_purpur-cta-link_],._purpur-promotion-card_1vt4e_1 [class*=_purpur-button_]{width:100%}@container promotion-card (min-width: 600px){._purpur-promotion-card_1vt4e_1 [class*=_purpur-cta-link_],._purpur-promotion-card_1vt4e_1 [class*=_purpur-button_]{width:auto}}
1
+ ._purpur-promotion-card_qosug_1{position:relative;width:100%;height:100%;color:var(--promotion-card-color);box-sizing:border-box}._purpur-promotion-card--without-image_qosug_8 ._purpur-promotion-card__content_qosug_8{position:relative;z-index:1}._purpur-promotion-card--without-image_qosug_8:before{content:"";position:absolute;width:100%;height:100%;background-color:var(--promotion-card-background);background-image:var(--promotion-card-background-image);background-position:right 50% center;background-size:cover;transform:rotateY(180deg)}@container promotion-card (min-width: 600px){._purpur-promotion-card--without-image_qosug_8:before{background-position:center center}}@container promotion-card (min-width: 1024px){._purpur-promotion-card--without-image_qosug_8:before{transform:rotateY(0)}}._purpur-promotion-card--with-image_qosug_33{display:grid;grid-template-areas:"image" "body";grid-template-rows:auto 1fr;background:var(--promotion-card-background)}@container promotion-card (min-width: 600px){._purpur-promotion-card--with-image_qosug_33{grid-template-areas:"body image";grid-template-columns:repeat(2,1fr)}}._purpur-promotion-card__card_qosug_45{container:promotion-card/inline-size;height:100%}._purpur-promotion-card__image-gradient_qosug_49{position:absolute;bottom:0;width:100%;height:100%;background:linear-gradient(0,var(--promotion-card-background),transparent 75%)}@container promotion-card (min-width: 600px){._purpur-promotion-card__image-gradient_qosug_49{left:0;top:0;width:100%;height:100%;background:linear-gradient(90deg,var(--promotion-card-background),transparent 75%)}}._purpur-promotion-card__actions_qosug_65{display:flex;flex-wrap:wrap;gap:var(--purpur-spacing-200);padding-top:var(--purpur-spacing-400)}._purpur-promotion-card__content_qosug_8{grid-area:body;display:flex;flex-direction:column;justify-content:flex-end;height:100%;padding:var(--purpur-spacing-400);box-sizing:border-box}@container promotion-card (min-width: 1024px){._purpur-promotion-card__content--without-image_qosug_81{padding:var(--purpur-spacing-600)}._purpur-promotion-card__content--without-image_qosug_81 ._purpur-promotion-card__main-content_qosug_84{display:flex;gap:var(--purpur-spacing-300)}._purpur-promotion-card__content--without-image_qosug_81 ._purpur-promotion-card__heading_qosug_88{width:100%}}@container promotion-card (min-width: 600px){._purpur-promotion-card__content--with-image_qosug_93{flex-direction:column;justify-content:center;padding:var(--purpur-spacing-600) var(--purpur-spacing-400)}}@container promotion-card (min-width: 1024px){._purpur-promotion-card__content--with-image_qosug_93{padding:var(--purpur-spacing-1200) var(--purpur-spacing-600)}}._purpur-promotion-card__badge-wrapper_qosug_104{width:100%;padding-bottom:var(--purpur-spacing-200)}._purpur-promotion-card__heading_qosug_88,._purpur-promotion-card__body_qosug_108{width:100%}._purpur-promotion-card__heading_qosug_88{margin-bottom:var(--purpur-spacing-150);color:var(--promotion-card-color)}._purpur-promotion-card__main-content_qosug_84,._purpur-promotion-card__body_qosug_108{display:flex;flex-direction:column;flex-grow:1}._purpur-promotion-card__body_qosug_108,._purpur-promotion-card__body_qosug_108 p,._purpur-promotion-card__body_qosug_108 h1,._purpur-promotion-card__body_qosug_108 h2,._purpur-promotion-card__body_qosug_108 h3,._purpur-promotion-card__body_qosug_108 h4,._purpur-promotion-card__body_qosug_108 h5,._purpur-promotion-card__body_qosug_108 h6,._purpur-promotion-card__body_qosug_108 ul,._purpur-promotion-card__body_qosug_108 ol{color:var(--promotion-card-color)}._purpur-promotion-card__child-content_qosug_137{flex-grow:1}._purpur-promotion-card__image-wrapper_qosug_140{grid-area:image}._purpur-promotion-card__image-wrapper--decorative_qosug_143 picture,._purpur-promotion-card__image-wrapper--decorative_qosug_143 img,._purpur-promotion-card__image-wrapper--product_qosug_144 picture,._purpur-promotion-card__image-wrapper--product_qosug_144 img{display:block;width:100%;height:auto}._purpur-promotion-card__image-wrapper--decorative_qosug_143 img,._purpur-promotion-card__image-wrapper--product_qosug_144 img{object-fit:cover}._purpur-promotion-card__image-wrapper--decorative_qosug_143{position:relative;width:100%;aspect-ratio:3/2}@container promotion-card (min-width: 600px){._purpur-promotion-card__image-wrapper--decorative_qosug_143{aspect-ratio:unset}._purpur-promotion-card__image-wrapper--decorative_qosug_143 img{height:100%}}._purpur-promotion-card__image-wrapper--product_qosug_144{display:flex;justify-content:center;align-items:center;padding:var(--purpur-spacing-400)}._purpur-promotion-card_qosug_1 [class*=_purpur-cta-link_],._purpur-promotion-card_qosug_1 [class*=_purpur-button_]{width:100%}@container promotion-card (min-width: 600px){._purpur-promotion-card_qosug_1 [class*=_purpur-cta-link_],._purpur-promotion-card_qosug_1 [class*=_purpur-button_]{width:auto}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purpurds/promotion-card",
3
- "version": "5.18.3",
3
+ "version": "5.19.1",
4
4
  "license": "AGPL-3.0-only",
5
5
  "main": "./dist/promotion-card.cjs.js",
6
6
  "types": "./dist/promotion-card.d.ts",
@@ -16,11 +16,13 @@
16
16
  "source": "src/promotion-card.tsx",
17
17
  "dependencies": {
18
18
  "classnames": "~2.5.0",
19
- "@purpurds/badge": "5.18.3",
20
- "@purpurds/heading": "5.18.3",
21
- "@purpurds/card": "5.18.3",
22
- "@purpurds/icon": "5.18.3",
23
- "@purpurds/tokens": "5.18.3"
19
+ "@purpurds/card": "5.19.1",
20
+ "@purpurds/badge": "5.19.1",
21
+ "@purpurds/cta-link": "5.19.1",
22
+ "@purpurds/heading": "5.19.1",
23
+ "@purpurds/icon": "5.19.1",
24
+ "@purpurds/button": "5.19.1",
25
+ "@purpurds/tokens": "5.19.1"
24
26
  },
25
27
  "devDependencies": {
26
28
  "@rushstack/eslint-patch": "~1.10.0",
@@ -45,10 +47,9 @@
45
47
  "vite": "5.3.4",
46
48
  "vitest": "~1.5.0",
47
49
  "@purpurds/component-rig": "1.0.0",
48
- "@purpurds/cta-link": "5.18.3",
49
- "@purpurds/paragraph": "5.18.3",
50
- "@purpurds/grid": "5.18.3",
51
- "@purpurds/text-spacing": "5.18.3"
50
+ "@purpurds/paragraph": "5.19.1",
51
+ "@purpurds/text-spacing": "5.19.1",
52
+ "@purpurds/grid": "5.19.1"
52
53
  },
53
54
  "scripts": {
54
55
  "build:dev": "vite",
@@ -68,6 +68,12 @@
68
68
  background: linear-gradient(90deg, var(--promotion-card-background), transparent 75%);
69
69
  }
70
70
  }
71
+ &__actions {
72
+ display: flex;
73
+ flex-wrap: wrap;
74
+ gap: var(--purpur-spacing-200);
75
+ padding-top: var(--purpur-spacing-400);
76
+ }
71
77
 
72
78
  &__content {
73
79
  grid-area: body;
@@ -121,10 +127,16 @@
121
127
  color: var(--promotion-card-color);
122
128
  }
123
129
 
124
- &__body {
130
+ &__main-content {
125
131
  display: flex;
126
132
  flex-direction: column;
133
+ flex-grow: 1;
134
+ }
127
135
 
136
+ &__body {
137
+ display: flex;
138
+ flex-direction: column;
139
+ flex-grow: 1;
128
140
  &,
129
141
  p,
130
142
  h1,
@@ -139,12 +151,15 @@
139
151
  }
140
152
  }
141
153
 
154
+ &__child-content {
155
+ flex-grow: 1;
156
+ }
157
+
142
158
  &__image-wrapper {
143
159
  grid-area: image;
144
160
 
145
161
  &--decorative,
146
162
  &--product {
147
-
148
163
  picture,
149
164
  img {
150
165
  display: block;
@@ -187,4 +202,4 @@
187
202
  width: auto;
188
203
  }
189
204
  }
190
- }
205
+ }
@@ -1,6 +1,4 @@
1
- /* eslint-disable react/jsx-wrap-multilines */
2
1
  import React from "react";
3
- import { CtaLink } from "@purpurds/cta-link";
4
2
  import { Grid } from "@purpurds/grid";
5
3
  import { HeadingTag, TitleVariant } from "@purpurds/heading";
6
4
  import { IconCheckmark, IconOffering } from "@purpurds/icon";
@@ -8,13 +6,14 @@ import { Paragraph } from "@purpurds/paragraph";
8
6
  import type { Meta, StoryObj } from "@storybook/react";
9
7
 
10
8
  import "@purpurds/badge/styles";
9
+ import "@purpurds/button/styles";
11
10
  import "@purpurds/card/styles";
12
11
  import "@purpurds/cta-link/styles";
13
12
  import "@purpurds/grid/styles";
14
13
  import "@purpurds/heading/styles";
15
14
  import "@purpurds/icon/styles";
16
15
  import "@purpurds/paragraph/styles";
17
- import { PromotionCard, PromotionCardVariant, promotionCardVariants } from "./promotion-card";
16
+ import { PromotionCard, promotionCardVariants } from "./promotion-card";
18
17
 
19
18
  const meta = {
20
19
  title: "Components/PromotionCard",
@@ -28,6 +27,22 @@ const meta = {
28
27
  },
29
28
  ],
30
29
  },
30
+ args: {
31
+ variant: "primary",
32
+ badgeText: "Badge title",
33
+ badgeIcon: <IconOffering size="xs" />,
34
+ title: "Title goes here lorem ipsum",
35
+ actions: [
36
+ {
37
+ label: "Primary link",
38
+ href: "#",
39
+ },
40
+ {
41
+ label: "Secondary link",
42
+ href: "#",
43
+ },
44
+ ],
45
+ },
31
46
  argTypes: {
32
47
  variant: {
33
48
  control: "select",
@@ -62,7 +77,7 @@ const meta = {
62
77
  export default meta;
63
78
  type Story = StoryObj<typeof PromotionCard>;
64
79
 
65
- const Children = ({ variant = "primary" }: { variant?: PromotionCardVariant }) => (
80
+ const Children = () => (
66
81
  <>
67
82
  <Paragraph style={{ marginBottom: "var(--purpur-spacing-150)" }}>
68
83
  Lorem ipsum dolor sit amet consectetur. At velit mi ultricies in orci est condimentum. Et
@@ -71,8 +86,8 @@ const Children = ({ variant = "primary" }: { variant?: PromotionCardVariant }) =
71
86
 
72
87
  <ul
73
88
  style={{
74
- margin: "0 0 var(--purpur-spacing-400)",
75
89
  padding: 0,
90
+ margin: 0,
76
91
  listStyle: "none",
77
92
  }}
78
93
  >
@@ -86,30 +101,11 @@ const Children = ({ variant = "primary" }: { variant?: PromotionCardVariant }) =
86
101
  </li>
87
102
  ))}
88
103
  </ul>
89
-
90
- <div style={{ display: "flex", gap: "var(--purpur-spacing-200)", flexWrap: "wrap" }}>
91
- <CtaLink variant="primary" negative={variant === "primary"} href="#">
92
- Primary CTA link
93
- </CtaLink>
94
- <CtaLink variant="secondary" negative={variant === "primary"} href="#">
95
- Secondary CTA link
96
- </CtaLink>
97
- </div>
98
104
  </>
99
105
  );
100
106
 
101
- const props = {
102
- variant: "primary" as const,
103
- badgeText: "Badge title",
104
- badgeIcon: <IconOffering size="xs" />,
105
- title: "Title goes here lorem ipsum",
106
- titleTag: "h2" as const,
107
- titleVariant: "title-300" as const,
108
- };
109
-
110
107
  export const WithDecorativeImage: Story = {
111
108
  args: {
112
- ...props,
113
109
  hasGradient: true,
114
110
  decorativeImage: (
115
111
  <img
@@ -121,7 +117,7 @@ export const WithDecorativeImage: Story = {
121
117
  render: (args) => {
122
118
  return (
123
119
  <PromotionCard {...args}>
124
- <Children variant={args.variant} />
120
+ <Children />
125
121
  </PromotionCard>
126
122
  );
127
123
  },
@@ -129,7 +125,6 @@ export const WithDecorativeImage: Story = {
129
125
 
130
126
  export const WithProductImage: Story = {
131
127
  args: {
132
- ...props,
133
128
  productImage: (
134
129
  <picture
135
130
  style={{
@@ -150,7 +145,7 @@ export const WithProductImage: Story = {
150
145
  render: (args) => {
151
146
  return (
152
147
  <PromotionCard {...args}>
153
- <Children variant={args.variant} />
148
+ <Children />
154
149
  </PromotionCard>
155
150
  );
156
151
  },
@@ -158,7 +153,6 @@ export const WithProductImage: Story = {
158
153
 
159
154
  export const CardGroup: Story = {
160
155
  args: {
161
- ...props,
162
156
  hasGradient: true,
163
157
  decorativeImage: (
164
158
  <img
@@ -171,18 +165,24 @@ export const CardGroup: Story = {
171
165
  render: (args) => {
172
166
  return (
173
167
  <Grid colsMd={3}>
174
- <PromotionCard {...args}>
175
- <Paragraph>
176
- Buy mobile telephony, broadband or IT support from Telia receive half the price of
177
- Microsoft 365 for six months.
178
- </Paragraph>
168
+ <PromotionCard {...args} title="Lorem">
169
+ <Paragraph>Buy mobile telephony!</Paragraph>
179
170
  </PromotionCard>
180
- <PromotionCard {...args}>
171
+ <PromotionCard
172
+ {...args}
173
+ actions={[
174
+ {
175
+ label: "Primary link",
176
+ href: "#",
177
+ },
178
+ ]}
179
+ >
181
180
  <Paragraph>
182
- Get our popular broadband and we&apos;ll offer you two months and the initial fee.
181
+ Get our popular broadband and we&apos;ll offer you two months and the initial fee. Or
182
+ even three months if you&lsquo;re lucky
183
183
  </Paragraph>
184
184
  </PromotionCard>
185
- <PromotionCard {...args}>
185
+ <PromotionCard {...args} actions={undefined}>
186
186
  <Paragraph>
187
187
  Check out all our offers to explore the best we have to offer right now.
188
188
  </Paragraph>
@@ -193,15 +193,24 @@ export const CardGroup: Story = {
193
193
  };
194
194
 
195
195
  export const Showcase: Story = {
196
- args: {
197
- ...props,
198
- },
196
+ args: { children: <Children /> },
197
+ };
199
198
 
200
- render: (args) => {
201
- return (
202
- <PromotionCard {...args}>
203
- <Children variant={args.variant} />
204
- </PromotionCard>
205
- );
199
+ export const ActionButtons: Story = {
200
+ args: {
201
+ actions: [
202
+ {
203
+ label: "Primary button",
204
+ onClick: () => {
205
+ alert("Primary button clicked");
206
+ },
207
+ },
208
+ {
209
+ label: "Secondary button",
210
+ onClick: () => {
211
+ alert("Secondary button clicked");
212
+ },
213
+ },
214
+ ],
206
215
  },
207
216
  };
@@ -1,6 +1,8 @@
1
1
  import React, { DetailedHTMLProps, HTMLAttributes, ReactNode } from "react";
2
2
  import { Badge } from "@purpurds/badge";
3
+ import { Button } from "@purpurds/button";
3
4
  import { Card } from "@purpurds/card";
5
+ import { CtaLink } from "@purpurds/cta-link";
4
6
  import { Heading, HeadingTagType, TitleVariantType } from "@purpurds/heading";
5
7
  import c from "classnames/bind";
6
8
 
@@ -33,6 +35,9 @@ const colors: StyleRecord = {
33
35
  type DecorativeImage = { decorativeImage?: ReactNode; hasGradient?: boolean };
34
36
  type ProductImage = { productImage?: ReactNode; hasGradient?: never };
35
37
 
38
+ type CtaButton = { href?: never; onClick: () => void };
39
+ type CtaLink = { href: string; onClick?: never };
40
+
36
41
  export type PromotionCardProps = {
37
42
  ["data-testid"]?: string;
38
43
  variant?: PromotionCardVariant;
@@ -43,6 +48,7 @@ export type PromotionCardProps = {
43
48
  badgeText?: string;
44
49
  badgeIcon?: ReactNode;
45
50
  className?: string;
51
+ actions?: Array<{ label: string } & (CtaButton | CtaLink)>;
46
52
  children: ReactNode;
47
53
  } & (DecorativeImage | ProductImage);
48
54
 
@@ -59,6 +65,7 @@ export const PromotionCard = ({
59
65
  titleVariant = "title-300",
60
66
  enableTitleHyphenation = true,
61
67
  className,
68
+ actions,
62
69
  children,
63
70
  style,
64
71
  ...props
@@ -135,7 +142,34 @@ export const PromotionCard = ({
135
142
  >
136
143
  {title}
137
144
  </Heading>
138
- <div className={cx(`${rootClassName}__body`)}>{children}</div>
145
+ <div className={cx(`${rootClassName}__body`)}>
146
+ <div className={cx(`${rootClassName}__child-content`)}>{children}</div>
147
+ {actions && actions.length > 0 && (
148
+ <div className={cx(`${rootClassName}__actions`)}>
149
+ {actions.map(({ label, href, onClick }, index) =>
150
+ href ? (
151
+ <CtaLink
152
+ variant={index === 0 ? "primary" : "secondary"}
153
+ key={label}
154
+ href={href}
155
+ negative={variant === "primary"}
156
+ >
157
+ {label}
158
+ </CtaLink>
159
+ ) : (
160
+ <Button
161
+ variant={index === 0 ? "primary" : "secondary"}
162
+ key={label}
163
+ onClick={onClick}
164
+ negative={variant === "primary"}
165
+ >
166
+ {label}
167
+ </Button>
168
+ )
169
+ )}
170
+ </div>
171
+ )}
172
+ </div>
139
173
  </div>
140
174
  </div>
141
175