@payfit/unity-illustrations 1.0.0 → 1.1.0

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.
@@ -1,5 +1,5 @@
1
+ import { VariantProps } from '@payfit/unity-themes';
1
2
  import { ImgHTMLAttributes } from 'react';
2
- import { VariantProps } from 'tailwind-variants';
3
3
  import { UnityIllustrationAsset } from '../../generated/illustrationAssets.js';
4
4
  export declare const illustratedPicture: import('tailwind-variants').TVReturnType<{} | {} | {}, undefined, "uy:object-contain uy:aspect-auto", {} | {}, undefined, import('tailwind-variants').TVReturnType<unknown, undefined, "uy:object-contain uy:aspect-auto", unknown, unknown, undefined>>;
5
5
  export declare const illustratedIcon: import('tailwind-variants').TVReturnType<{
@@ -21,25 +21,34 @@ export declare const illustratedIcon: import('tailwind-variants').TVReturnType<{
21
21
  lg: string;
22
22
  };
23
23
  }, undefined, "uy:object-contain uy:aspect-square", unknown, unknown, undefined>>;
24
- export interface IllustrationPropsBase extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'children'> {
24
+ interface IllustrationPropsCore extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'children' | 'alt'> {
25
25
  /**
26
26
  * The illustration asset to render. Must be imported from @payfit/unity-illustrations
27
27
  */
28
28
  src: UnityIllustrationAsset;
29
- /** Accessible name for the illustration */
29
+ }
30
+ interface NonDecorativeIllustrationProps extends IllustrationPropsCore {
31
+ /** Whether this is decorative (hidden from screen readers) */
32
+ isDecorative?: false | undefined;
33
+ /** Accessible name for the illustration - required when not decorative */
30
34
  alt: string;
31
35
  /** Optional description for complex illustrations */
32
36
  description?: string;
37
+ }
38
+ interface DecorativeIllustrationProps extends IllustrationPropsCore {
33
39
  /** Whether this is decorative (hidden from screen readers) */
34
- isDecorative?: boolean;
40
+ isDecorative: true;
41
+ /** Accessible name for the illustration - optional when decorative */
42
+ alt?: string;
35
43
  }
36
- export interface IllustratedPictureProps extends IllustrationPropsBase, VariantProps<typeof illustratedPicture> {
44
+ export type IllustrationPropsBase = NonDecorativeIllustrationProps | DecorativeIllustrationProps;
45
+ export type IllustratedPictureProps = IllustrationPropsBase & VariantProps<typeof illustratedPicture> & {
37
46
  /**
38
47
  * The illustration variant. It can be a regular picture or an illustrated icon
39
48
  */
40
49
  variant: 'picture';
41
- }
42
- export interface IllustratedIconProps extends IllustrationPropsBase, VariantProps<typeof illustratedIcon> {
50
+ };
51
+ export type IllustratedIconProps = IllustrationPropsBase & VariantProps<typeof illustratedIcon> & {
43
52
  /**
44
53
  * The illustration variant. It can be a regular picture or an illustrated icon
45
54
  */
@@ -48,7 +57,7 @@ export interface IllustratedIconProps extends IllustrationPropsBase, VariantProp
48
57
  * The size of the illustration. It only applies to illustrated icons
49
58
  */
50
59
  size: VariantProps<typeof illustratedIcon>['size'];
51
- }
60
+ };
52
61
  export type IllustrationProps = IllustratedPictureProps | IllustratedIconProps;
53
62
  /**
54
63
  * Renders illustrations from the Unity design system with consistent styling and accessibility features.
@@ -78,3 +87,4 @@ export type IllustrationProps = IllustratedPictureProps | IllustratedIconProps;
78
87
  * See the [usage documentation](https://unity-illustrations.payfit.io/?path=/docs/introduction-usage--docs) for complete examples and best practices.
79
88
  */
80
89
  export declare const Illustration: import('react').ForwardRefExoticComponent<IllustrationProps & import('react').RefAttributes<HTMLImageElement>>;
90
+ export {};
@@ -1,9 +1,9 @@
1
1
  import { jsx as c } from "react/jsx-runtime";
2
2
  import { forwardRef as m } from "react";
3
- import { tv as a } from "tailwind-variants";
4
- const y = a({
3
+ import { uyTv as o } from "@payfit/unity-themes";
4
+ const y = o({
5
5
  base: "uy:object-contain uy:aspect-auto"
6
- }), p = a({
6
+ }), d = o({
7
7
  base: "uy:object-contain uy:aspect-square",
8
8
  variants: {
9
9
  size: {
@@ -12,40 +12,39 @@ const y = a({
12
12
  lg: "uy:size-12"
13
13
  }
14
14
  }
15
- }), d = m(
15
+ }), p = m(
16
16
  ({
17
17
  src: r,
18
- alt: i,
19
- description: o,
20
- isDecorative: t = !1,
21
- variant: n,
22
- className: s,
23
- ...e
24
- }, l) => {
25
- const u = n === "picture" ? y({ className: s }) : p({
26
- className: s,
27
- size: e.size
28
- });
18
+ alt: s,
19
+ isDecorative: i = !1,
20
+ variant: a,
21
+ className: e,
22
+ ...t
23
+ }, n) => {
24
+ const u = a === "picture" ? y({ className: e }) : d({
25
+ className: e,
26
+ size: t.size
27
+ }), l = i ? t.description : void 0;
29
28
  return /* @__PURE__ */ c(
30
29
  "img",
31
30
  {
32
- ref: l,
31
+ ref: n,
33
32
  src: r.url,
34
- alt: t ? "" : i,
35
- title: t ? void 0 : i,
33
+ alt: i ? "" : s,
34
+ title: i ? void 0 : s,
36
35
  className: u,
37
- role: t ? "presentation" : "img",
38
- "aria-hidden": t,
39
- "aria-description": o,
36
+ role: i ? "presentation" : "img",
37
+ "aria-hidden": i,
38
+ "aria-description": l,
40
39
  loading: "lazy",
41
- ...e
40
+ ...t
42
41
  }
43
42
  );
44
43
  }
45
44
  );
46
- d.displayName = "Illustration";
45
+ p.displayName = "Illustration";
47
46
  export {
48
- d as Illustration,
49
- p as illustratedIcon,
47
+ p as Illustration,
48
+ d as illustratedIcon,
50
49
  y as illustratedPicture
51
50
  };
@@ -9,7 +9,7 @@ import { IllustratedIconProps, IllustratedPictureProps } from '../illustration/I
9
9
  * @property {UnityIllustrationName} name - The name of the illustration to load dynamically.
10
10
  * This must be one of the valid illustration names from the Unity illustration library.
11
11
  * @property {'picture' | 'icon'} variant - The illustration variant. It can be a regular picture or an illustrated icon.
12
- * @property {string} alt - Accessible name for the illustration.
12
+ * @property {string} alt - Accessible name for the illustration (required when isDecorative is false or undefined).
13
13
  * @property {string} [description] - Optional description for complex illustrations.
14
14
  * @property {boolean} [isDecorative] - Whether this is decorative (hidden from screen readers).
15
15
  * @property {'sm' | 'md' | 'lg'} [size] - The size of the illustration. Required when variant is 'icon'.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payfit/unity-illustrations",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "module": "./dist/esm/index.js",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -25,37 +25,33 @@
25
25
  "dist",
26
26
  "src"
27
27
  ],
28
+ "dependencies": {
29
+ "svgo": "3.3.2"
30
+ },
28
31
  "devDependencies": {
29
32
  "@payfit/code-pushup-tools": "0.0.0-use.local",
30
33
  "@payfit/hr-app-eslint": "0.0.0-use.local",
31
34
  "@payfit/hr-apps-tsconfigs": "0.0.0-use.local",
32
- "@payfit/unity-themes": "1.0.0",
35
+ "@payfit/unity-themes": "1.1.0",
33
36
  "@payfit/vite-configs": "0.0.0-use.local",
34
- "@storybook/addon-a11y": "9.1.3",
35
- "@storybook/addon-docs": "9.1.3",
36
- "@storybook/addon-links": "9.1.3",
37
- "@storybook/react-vite": "9.1.3",
37
+ "@storybook/addon-a11y": "9.1.5",
38
+ "@storybook/addon-docs": "9.1.5",
39
+ "@storybook/addon-links": "9.1.5",
40
+ "@storybook/react-vite": "9.1.5",
38
41
  "@storybook/test-runner": "0.23.0",
39
42
  "@types/react": "18.3.18",
40
43
  "@types/react-dom": "18.3.5",
41
44
  "react": "18.3.1",
42
45
  "react-dom": "18.3.1",
43
- "storybook": "9.1.3",
46
+ "storybook": "9.1.5",
44
47
  "svgo": "3.3.2",
45
48
  "tailwindcss": "4.1.11",
46
49
  "tsx": "4.17.0",
47
50
  "vite": "6.3.5"
48
51
  },
49
52
  "peerDependencies": {
50
- "@payfit/unity-themes": "1.0.0",
51
- "react": "^18",
52
- "react-dom": "^18",
53
- "svgo": "3.3.2",
54
- "tailwind-variants": "2.1.0"
55
- },
56
- "peerDependenciesMeta": {
57
- "svgo": {
58
- "optional": true
59
- }
53
+ "@payfit/unity-themes": "1.1.0",
54
+ "react": "18.3.1",
55
+ "react-dom": "18.3.1"
60
56
  }
61
57
  }
@@ -66,7 +66,73 @@ const meta = {
66
66
  },
67
67
  },
68
68
  argTypes: {
69
- src: { control: 'select' },
69
+ src: {
70
+ control: 'select',
71
+ description:
72
+ 'The illustration asset to render. Must be imported from @payfit/unity-illustrations',
73
+ table: {
74
+ type: { summary: 'UnityIllustrationAsset' },
75
+ category: 'Required',
76
+ },
77
+ type: { name: 'other', required: true, value: 'UnityIllustrationAsset' },
78
+ },
79
+ variant: {
80
+ control: 'select',
81
+ options: ['picture', 'icon'],
82
+ description:
83
+ 'The illustration variant. It can be a regular picture or an illustrated icon',
84
+ table: {
85
+ type: { summary: "'picture' | 'icon'" },
86
+ category: 'Required',
87
+ },
88
+ type: { name: 'enum', required: true, value: ['picture', 'icon'] },
89
+ },
90
+ alt: {
91
+ control: 'text',
92
+ description:
93
+ 'Accessible name for the illustration. Required when isDecorative is `true`',
94
+ table: {
95
+ type: { summary: 'string' },
96
+ category: 'Accessibility',
97
+ },
98
+ },
99
+ description: {
100
+ control: 'text',
101
+ description:
102
+ 'Optional description for complex illustrations. Active only when isDecorative is `true`',
103
+ table: {
104
+ type: { summary: 'string' },
105
+ category: 'Accessibility',
106
+ },
107
+ },
108
+ isDecorative: {
109
+ control: 'boolean',
110
+ description:
111
+ 'Whether the illustration is decorative (hidden from screen readers). When `true`, `alt` becomes optional',
112
+ table: {
113
+ type: { summary: 'boolean' },
114
+ defaultValue: { summary: 'false' },
115
+ category: 'Accessibility',
116
+ },
117
+ },
118
+ size: {
119
+ control: 'select',
120
+ options: ['sm', 'md', 'lg'],
121
+ description: 'The size of the illustration. Only applies to icon variant',
122
+ if: { arg: 'variant', eq: 'icon' },
123
+ table: {
124
+ type: { summary: "'sm' | 'md' | 'lg'" },
125
+ category: 'Icon Variant',
126
+ },
127
+ },
128
+ className: {
129
+ control: 'text',
130
+ description: 'Additional CSS classes for styling',
131
+ table: {
132
+ type: { summary: 'string' },
133
+ category: 'Styling',
134
+ },
135
+ },
70
136
  },
71
137
  } satisfies Meta<typeof Illustration>
72
138
 
@@ -79,6 +145,7 @@ export const Primary: Story = {
79
145
  variant: 'picture',
80
146
  src: Binoculars,
81
147
  className: 'uy:size-[150px]',
148
+ alt: 'Binoculars illustration',
82
149
  },
83
150
  }
84
151
 
@@ -106,32 +173,66 @@ export const IllustratedIcon: Story = {
106
173
  render: function Render(args) {
107
174
  return (
108
175
  <div className="uy:grid uy:grid-cols-3 uy:items-center uy:gap-200">
109
- <Illustration {...args} variant="icon" size="sm" src={FAQ} />
110
- <Illustration {...args} variant="icon" size="md" src={FAQ} />
111
- <Illustration {...args} variant="icon" size="lg" src={FAQ} />
176
+ <Illustration
177
+ {...args}
178
+ variant="icon"
179
+ size="sm"
180
+ src={FAQ}
181
+ alt="FAQ icon small"
182
+ />
183
+ <Illustration
184
+ {...args}
185
+ variant="icon"
186
+ size="md"
187
+ src={FAQ}
188
+ alt="FAQ icon medium"
189
+ />
190
+ <Illustration
191
+ {...args}
192
+ variant="icon"
193
+ size="lg"
194
+ src={FAQ}
195
+ alt="FAQ icon large"
196
+ />
112
197
  <Illustration
113
198
  {...args}
114
199
  variant="icon"
115
200
  size="sm"
116
201
  src={FAQWithBackground}
202
+ alt="FAQ with background icon small"
117
203
  />
118
204
  <Illustration
119
205
  {...args}
120
206
  variant="icon"
121
207
  size="md"
122
208
  src={FAQWithBackground}
209
+ alt="FAQ with background icon medium"
123
210
  />
124
211
  <Illustration
125
212
  {...args}
126
213
  variant="icon"
127
214
  size="lg"
128
215
  src={FAQWithBackground}
216
+ alt="FAQ with background icon large"
129
217
  />
130
218
  </div>
131
219
  )
132
220
  },
133
221
  }
134
222
 
223
+ /**
224
+ * You can make the illustration decorative by setting the `isDecorative` prop to `true`.
225
+ * When `isDecorative` is `true`, `alt` becomes optional. Screen readers will ignore the illustration and not read the `alt` or the `description` attributes. Use this when the illustration is purely decorative or visual appeal, and does not provide any information.
226
+ */
227
+ export const IsDecorative: Story = {
228
+ args: {
229
+ variant: 'picture',
230
+ src: VisuallyImpaired,
231
+ className: 'uy:size-[50vmin]',
232
+ isDecorative: true,
233
+ },
234
+ }
235
+
135
236
  /**
136
237
  * You can create responsive layouts where illustrations adapt to different viewport sizes
137
238
  * by combining responsive Tailwind classes with the illustration component (with media and container queries). Use Unity theme
@@ -1,17 +1,17 @@
1
1
  import { forwardRef } from 'react'
2
2
 
3
+ import type { VariantProps } from '@payfit/unity-themes'
3
4
  import type { ImgHTMLAttributes } from 'react'
4
- import type { VariantProps } from 'tailwind-variants'
5
5
 
6
6
  import type { UnityIllustrationAsset } from '../../generated/illustrationAssets'
7
7
 
8
- import { tv } from 'tailwind-variants'
8
+ import { uyTv } from '@payfit/unity-themes'
9
9
 
10
- export const illustratedPicture = tv({
10
+ export const illustratedPicture = uyTv({
11
11
  base: 'uy:object-contain uy:aspect-auto',
12
12
  })
13
13
 
14
- export const illustratedIcon = tv({
14
+ export const illustratedIcon = uyTv({
15
15
  base: 'uy:object-contain uy:aspect-square',
16
16
  variants: {
17
17
  size: {
@@ -22,41 +22,56 @@ export const illustratedIcon = tv({
22
22
  },
23
23
  })
24
24
 
25
- export interface IllustrationPropsBase
26
- extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'children'> {
25
+ interface IllustrationPropsCore
26
+ extends Omit<
27
+ ImgHTMLAttributes<HTMLImageElement>,
28
+ 'src' | 'children' | 'alt'
29
+ > {
27
30
  /**
28
31
  * The illustration asset to render. Must be imported from @payfit/unity-illustrations
29
32
  */
30
33
  src: UnityIllustrationAsset
31
- /** Accessible name for the illustration */
34
+ }
35
+
36
+ interface NonDecorativeIllustrationProps extends IllustrationPropsCore {
37
+ /** Whether this is decorative (hidden from screen readers) */
38
+ isDecorative?: false | undefined
39
+ /** Accessible name for the illustration - required when not decorative */
32
40
  alt: string
33
41
  /** Optional description for complex illustrations */
34
42
  description?: string
35
- /** Whether this is decorative (hidden from screen readers) */
36
- isDecorative?: boolean
37
43
  }
38
44
 
39
- export interface IllustratedPictureProps
40
- extends IllustrationPropsBase,
41
- VariantProps<typeof illustratedPicture> {
42
- /**
43
- * The illustration variant. It can be a regular picture or an illustrated icon
44
- */
45
- variant: 'picture'
45
+ interface DecorativeIllustrationProps extends IllustrationPropsCore {
46
+ /** Whether this is decorative (hidden from screen readers) */
47
+ isDecorative: true
48
+ /** Accessible name for the illustration - optional when decorative */
49
+ alt?: string
46
50
  }
47
51
 
48
- export interface IllustratedIconProps
49
- extends IllustrationPropsBase,
50
- VariantProps<typeof illustratedIcon> {
51
- /**
52
- * The illustration variant. It can be a regular picture or an illustrated icon
53
- */
54
- variant: 'icon'
55
- /**
56
- * The size of the illustration. It only applies to illustrated icons
57
- */
58
- size: VariantProps<typeof illustratedIcon>['size']
59
- }
52
+ export type IllustrationPropsBase =
53
+ | NonDecorativeIllustrationProps
54
+ | DecorativeIllustrationProps
55
+
56
+ export type IllustratedPictureProps = IllustrationPropsBase &
57
+ VariantProps<typeof illustratedPicture> & {
58
+ /**
59
+ * The illustration variant. It can be a regular picture or an illustrated icon
60
+ */
61
+ variant: 'picture'
62
+ }
63
+
64
+ export type IllustratedIconProps = IllustrationPropsBase &
65
+ VariantProps<typeof illustratedIcon> & {
66
+ /**
67
+ * The illustration variant. It can be a regular picture or an illustrated icon
68
+ */
69
+ variant: 'icon'
70
+ /**
71
+ * The size of the illustration. It only applies to illustrated icons
72
+ */
73
+ size: VariantProps<typeof illustratedIcon>['size']
74
+ }
60
75
 
61
76
  export type IllustrationProps = IllustratedPictureProps | IllustratedIconProps
62
77
 
@@ -92,7 +107,6 @@ export const Illustration = forwardRef<HTMLImageElement, IllustrationProps>(
92
107
  {
93
108
  src,
94
109
  alt,
95
- description,
96
110
  isDecorative: decorative = false,
97
111
  variant,
98
112
  className,
@@ -108,6 +122,10 @@ export const Illustration = forwardRef<HTMLImageElement, IllustrationProps>(
108
122
  size: (props as IllustratedIconProps).size,
109
123
  })
110
124
 
125
+ const description = decorative
126
+ ? (props as NonDecorativeIllustrationProps).description
127
+ : undefined
128
+
111
129
  return (
112
130
  <img
113
131
  ref={ref}
@@ -24,6 +24,69 @@ const meta = {
24
24
  'VisuallyImpaired',
25
25
  'Library',
26
26
  ],
27
+ description:
28
+ 'The name of the illustration to load dynamically. This must be one of the valid illustration names from the Unity illustration library',
29
+ table: {
30
+ type: { summary: 'UnityIllustrationName' },
31
+ category: 'Required',
32
+ },
33
+ },
34
+ variant: {
35
+ control: 'select',
36
+ options: ['picture', 'icon'],
37
+ description:
38
+ 'The illustration variant. It can be a regular picture or an illustrated icon',
39
+ table: {
40
+ type: { summary: "'picture' | 'icon'" },
41
+ category: 'Required',
42
+ },
43
+ },
44
+ alt: {
45
+ control: 'text',
46
+ description:
47
+ 'Accessible name for the illustration. Required when isDecorative is `true`',
48
+ table: {
49
+ type: { summary: 'string' },
50
+ category: 'Accessibility',
51
+ },
52
+ },
53
+ // @ts-expect-error - Typescript can't handle the union type properly, but the prop exist
54
+ description: {
55
+ control: 'text',
56
+ description:
57
+ 'Optional description for complex illustrations. Active only when isDecorative is `true`',
58
+ table: {
59
+ type: { summary: 'string' },
60
+ category: 'Accessibility',
61
+ },
62
+ },
63
+ isDecorative: {
64
+ control: 'boolean',
65
+ description:
66
+ 'Whether the illustration is decorative (hidden from screen readers). When `true`, `alt` becomes optional',
67
+ table: {
68
+ type: { summary: 'boolean' },
69
+ defaultValue: { summary: 'false' },
70
+ category: 'Accessibility',
71
+ },
72
+ },
73
+ size: {
74
+ control: 'select',
75
+ options: ['sm', 'md', 'lg'],
76
+ description: 'The size of the illustration. Only applies to icon variant',
77
+ if: { arg: 'variant', eq: 'icon' },
78
+ table: {
79
+ type: { summary: "'sm' | 'md' | 'lg'" },
80
+ category: 'Icon Variant',
81
+ },
82
+ },
83
+ className: {
84
+ control: 'text',
85
+ description: 'Additional CSS classes for styling',
86
+ table: {
87
+ type: { summary: 'string' },
88
+ category: 'Styling',
89
+ },
27
90
  },
28
91
  },
29
92
  } satisfies Meta<typeof LazyIllustration>
@@ -55,6 +118,7 @@ export const IllustratedPicture: Story = {
55
118
  variant: 'picture',
56
119
  name: 'VisuallyImpaired',
57
120
  className: 'uy:size-[50vmin]',
121
+ alt: 'Visually impaired person illustration',
58
122
  },
59
123
  }
60
124
 
@@ -25,7 +25,7 @@ import {
25
25
  * @property {UnityIllustrationName} name - The name of the illustration to load dynamically.
26
26
  * This must be one of the valid illustration names from the Unity illustration library.
27
27
  * @property {'picture' | 'icon'} variant - The illustration variant. It can be a regular picture or an illustrated icon.
28
- * @property {string} alt - Accessible name for the illustration.
28
+ * @property {string} alt - Accessible name for the illustration (required when isDecorative is false or undefined).
29
29
  * @property {string} [description] - Optional description for complex illustrations.
30
30
  * @property {boolean} [isDecorative] - Whether this is decorative (hidden from screen readers).
31
31
  * @property {'sm' | 'md' | 'lg'} [size] - The size of the illustration. Required when variant is 'icon'.
@@ -116,7 +116,10 @@ export const LazyIllustration = forwardRef<
116
116
  return <div className={clsx} />
117
117
  }
118
118
 
119
- return <Illustration ref={ref} src={illustration} {...props} />
119
+ // Handle the discriminated union by using type assertion
120
+ // This is safe because LazyIllustrationProps inherits from IllustrationProps (excluding src and name)
121
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
122
+ return <Illustration ref={ref} src={illustration} {...(props as any)} />
120
123
  })
121
124
 
122
125
  LazyIllustration.displayName = 'LazyIllustration'
@@ -6,7 +6,7 @@
6
6
  // - Images: 0
7
7
  // - Animated: 0
8
8
  // - Size optimization: 5682.0KB → 3460.7KB (-39.1%)
9
- // - Generated: 2025-08-27T12:34:59.297Z
9
+ // - Generated: 2025-09-16T10:01:56.890Z
10
10
  //
11
11
 
12
12
  // Re-export shared types