@transferwise/components 0.0.0-experimental-1664fea → 0.0.0-experimental-850e2db

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.
Files changed (52) hide show
  1. package/build/index.js +1 -0
  2. package/build/index.js.map +1 -1
  3. package/build/index.mjs +1 -1
  4. package/build/main.css +212 -0
  5. package/build/styles/listItem/ListItem.css +212 -0
  6. package/build/styles/main.css +212 -0
  7. package/build/types/index.d.ts +2 -0
  8. package/build/types/index.d.ts.map +1 -1
  9. package/build/types/listItem/ListItem.d.ts +50 -0
  10. package/build/types/listItem/ListItem.d.ts.map +1 -0
  11. package/build/types/listItem/ListItemAdditionalInfo.d.ts +9 -0
  12. package/build/types/listItem/ListItemAdditionalInfo.d.ts.map +1 -0
  13. package/build/types/listItem/ListItemButton.d.ts +6 -0
  14. package/build/types/listItem/ListItemButton.d.ts.map +1 -0
  15. package/build/types/listItem/ListItemCheckbox.d.ts +4 -0
  16. package/build/types/listItem/ListItemCheckbox.d.ts.map +1 -0
  17. package/build/types/listItem/ListItemIconButton.d.ts +8 -0
  18. package/build/types/listItem/ListItemIconButton.d.ts.map +1 -0
  19. package/build/types/listItem/ListItemMedia.d.ts +19 -0
  20. package/build/types/listItem/ListItemMedia.d.ts.map +1 -0
  21. package/build/types/listItem/ListItemNavigation.d.ts +4 -0
  22. package/build/types/listItem/ListItemNavigation.d.ts.map +1 -0
  23. package/build/types/listItem/ListItemSwitch.d.ts +3 -0
  24. package/build/types/listItem/ListItemSwitch.d.ts.map +1 -0
  25. package/build/types/listItem/index.d.ts +6 -0
  26. package/build/types/listItem/index.d.ts.map +1 -0
  27. package/build/types/listItem/prompt/Prompt.d.ts +12 -0
  28. package/build/types/listItem/prompt/Prompt.d.ts.map +1 -0
  29. package/build/types/listItem/useItemControl.d.ts +5 -0
  30. package/build/types/listItem/useItemControl.d.ts.map +1 -0
  31. package/package.json +2 -2
  32. package/src/index.ts +2 -0
  33. package/src/listItem/ListItem.css +212 -0
  34. package/src/listItem/ListItem.less +210 -0
  35. package/src/listItem/ListItem.spec.tsx +35 -0
  36. package/src/listItem/ListItem.story.tsx +461 -0
  37. package/src/listItem/ListItem.tsx +282 -0
  38. package/src/listItem/ListItemAdditionalInfo.tsx +31 -0
  39. package/src/listItem/ListItemButton.spec.tsx +92 -0
  40. package/src/listItem/ListItemButton.tsx +24 -0
  41. package/src/listItem/ListItemCheckbox.tsx +14 -0
  42. package/src/listItem/ListItemIconButton.tsx +16 -0
  43. package/src/listItem/ListItemMedia.tsx +52 -0
  44. package/src/listItem/ListItemNavigation.tsx +23 -0
  45. package/src/listItem/ListItemSwitch.tsx +8 -0
  46. package/src/listItem/index.ts +10 -0
  47. package/src/listItem/prompt/Prompt.spec.tsx +77 -0
  48. package/src/listItem/prompt/Prompt.story.tsx +170 -0
  49. package/src/listItem/prompt/Prompt.tsx +44 -0
  50. package/src/listItem/useItemControl.tsx +23 -0
  51. package/src/main.css +212 -0
  52. package/src/main.less +1 -0
@@ -0,0 +1,170 @@
1
+ import Link from '../../link';
2
+ import { Sentiment } from '../../common';
3
+ import { Prompt, ListItemPromptProps } from './Prompt';
4
+ import { lorem40 } from '../../test-utils';
5
+ import { StoryObj } from '@storybook/react';
6
+
7
+ export default {
8
+ component: Prompt,
9
+ title: 'Content/ListItem/Prompt',
10
+ args: {
11
+ type: Sentiment.NEGATIVE,
12
+ children: 'You have done a terrible thing',
13
+ },
14
+ argTypes: {
15
+ type: {
16
+ options: [
17
+ Sentiment.POSITIVE,
18
+ Sentiment.NEGATIVE,
19
+ Sentiment.NEUTRAL,
20
+ Sentiment.WARNING,
21
+ 'discount',
22
+ 'savings',
23
+ ],
24
+ control: { type: 'radio' },
25
+ description: 'The type of prompt to display',
26
+ },
27
+ action: {
28
+ table: {
29
+ disable: true,
30
+ },
31
+ },
32
+ children: {
33
+ type: {
34
+ name: 'string',
35
+ required: true,
36
+ description: 'The content of the prompt',
37
+ },
38
+ },
39
+ },
40
+ };
41
+
42
+ type CustomStory = StoryObj<
43
+ ListItemPromptProps & {
44
+ interactivity?: 'none' | 'full-anchor' | 'full-button' | 'link';
45
+ }
46
+ >;
47
+
48
+ export const Basic: CustomStory = {
49
+ args: {
50
+ interactivity: 'none',
51
+ },
52
+ argTypes: {
53
+ interactivity: {
54
+ options: ['none', 'full-button', 'full-anchor', 'link'],
55
+ control: { type: 'radio' },
56
+ description: 'The type of interactivity to display',
57
+ },
58
+ },
59
+ render: ({ interactivity, ...args }) => {
60
+ return (
61
+ <div>
62
+ <Prompt
63
+ type={args.type}
64
+ action={
65
+ interactivity === 'full-anchor'
66
+ ? { href: 'wise.com' }
67
+ : interactivity === 'full-button'
68
+ ? {
69
+ onClick: () => {
70
+ console.log('clicked');
71
+ },
72
+ }
73
+ : undefined
74
+ }
75
+ >
76
+ {args.children} {interactivity === 'link' && <Link href="www.wise.com">with a link</Link>}
77
+ </Prompt>
78
+ </div>
79
+ );
80
+ },
81
+ };
82
+
83
+ export const Variants = () => {
84
+ return (
85
+ <>
86
+ <div className="m-b-2">
87
+ <Prompt type={Sentiment.POSITIVE}>
88
+ Positive prompt <Link href="www.wise.com">with a link to amazing content</Link>
89
+ </Prompt>
90
+ </div>
91
+ <div className="m-b-2">
92
+ <Prompt type={Sentiment.NEGATIVE}>
93
+ Negative prompt <Link href="www.wise.com">with a link to amazing content</Link>
94
+ </Prompt>
95
+ </div>
96
+ <div className="m-b-2">
97
+ <Prompt type={Sentiment.NEUTRAL}>
98
+ Neutral prompt <Link href="www.wise.com">with a link to amazing content</Link>
99
+ </Prompt>
100
+ </div>
101
+ <div className="m-b-2">
102
+ <Prompt type={Sentiment.WARNING}>
103
+ Warning prompt <Link href="www.wise.com">with a link to amazing content</Link>
104
+ </Prompt>
105
+ </div>
106
+ <div className="m-b-2">
107
+ <Prompt type="discount">
108
+ Discount prompt <Link href="www.wise.com">with a link to amazing content</Link>
109
+ </Prompt>
110
+ </div>
111
+ <div className="m-b-2">
112
+ <Prompt type="savings">
113
+ Savings prompt <Link href="www.wise.com">with a link to amazing content</Link>
114
+ </Prompt>
115
+ </div>
116
+ <div className="m-b-2">
117
+ <Prompt
118
+ type="discount"
119
+ action={{
120
+ href: 'www.wise.com',
121
+ target: '_self',
122
+ 'aria-label': 'hidden anchor tags are accessible, right?',
123
+ }}
124
+ >
125
+ The whole prompt is secretly clickable
126
+ </Prompt>
127
+ </div>
128
+ <div className="m-b-2">
129
+ <Prompt
130
+ type="negative"
131
+ action={{
132
+ href: 'www.wise.com',
133
+ target: '_self',
134
+ 'aria-label': 'clickable <a>',
135
+ }}
136
+ >
137
+ The whole prompt is secretly clickable as an anchor tag
138
+ </Prompt>
139
+ </div>
140
+ <div className="m-b-2">
141
+ <Prompt
142
+ type="warning"
143
+ action={{
144
+ onClick: () => {
145
+ console.log('clicked');
146
+ },
147
+ 'aria-label': 'clickable button',
148
+ }}
149
+ >
150
+ The whole prompt is secretly clickable as a button
151
+ </Prompt>
152
+ </div>
153
+ <div className="m-b-2">
154
+ <Prompt
155
+ type="neutral"
156
+ action={{
157
+ href: 'www.wise.com',
158
+ target: '_self',
159
+ 'aria-label': 'clickable prompt',
160
+ }}
161
+ >
162
+ The whole prompt is secretly clickable
163
+ </Prompt>
164
+ </div>
165
+ <div className="m-b-2" style={{ maxWidth: '300px' }}>
166
+ <Prompt type="warning">The prompt has very long text that wraps {lorem40}</Prompt>
167
+ </div>
168
+ </>
169
+ );
170
+ };
@@ -0,0 +1,44 @@
1
+ import { Confetti, Tags } from '@transferwise/icons';
2
+ import { Sentiment } from '../../common';
3
+ import StatusIcon from '../../statusIcon';
4
+ import { clsx } from 'clsx';
5
+ import { LinkProps } from '../../link';
6
+ import Body from '../../body';
7
+
8
+ export type ListItemPromptProps = {
9
+ type:
10
+ | `${Sentiment.POSITIVE | Sentiment.NEGATIVE | Sentiment.NEUTRAL | Sentiment.WARNING}`
11
+ | 'discount'
12
+ | 'savings';
13
+ children: React.ReactNode;
14
+ action?: Pick<LinkProps, 'href' | 'target' | 'onClick'> & { 'aria-label'?: string };
15
+ };
16
+
17
+ export const Prompt = ({ type, children, action }: ListItemPromptProps) => {
18
+ const Wrapper = action?.href ? 'a' : action?.onClick ? 'button' : 'span';
19
+
20
+ const icon =
21
+ type === 'discount' ? (
22
+ <Tags size={16} />
23
+ ) : type === 'savings' ? (
24
+ <Confetti size={16} />
25
+ ) : (
26
+ <StatusIcon size={16} sentiment={type} />
27
+ );
28
+
29
+ return (
30
+ <Wrapper
31
+ className={clsx(
32
+ 'wds-list-item-prompt',
33
+ type,
34
+ (action?.href || action?.onClick) && 'np-prompt-interactive',
35
+ )}
36
+ {...(action ?? {})}
37
+ >
38
+ <div className="np-prompt-icon">{icon}</div>
39
+ <Body>{children}</Body>
40
+ </Wrapper>
41
+ );
42
+ };
43
+
44
+ export default Prompt;
@@ -0,0 +1,23 @@
1
+ import { useContext, useEffect } from 'react';
2
+ import {
3
+ ListItemContext,
4
+ ListItemContextData,
5
+ ListItemControlProps,
6
+ ListItemTypes,
7
+ } from './ListItem';
8
+
9
+ export function useItemControl(controlType: ListItemTypes, controlProps?: ListItemControlProps) {
10
+ const {
11
+ setControlType,
12
+ setControlProps,
13
+ props: baseItemProps,
14
+ } = useContext<ListItemContextData>(ListItemContext);
15
+
16
+ useEffect(() => {
17
+ setControlType(controlType);
18
+ // @ts-expect-error TODO: fix the type error later
19
+ setControlProps(controlProps);
20
+ }, [controlType, controlProps, setControlType, setControlProps]);
21
+
22
+ return { baseItemProps };
23
+ }
package/src/main.css CHANGED
@@ -2618,6 +2618,218 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
2618
2618
  border-radius: 9999px !important;
2619
2619
  border-radius: var(--radius-full) !important;
2620
2620
  }
2621
+ .wds-list-item {
2622
+ list-style: none;
2623
+ width: 100%;
2624
+ padding: 0;
2625
+ border-radius: 16px;
2626
+ border-radius: var(--radius-medium);
2627
+ background-color: #ffffff;
2628
+ background-color: var(--color-background-screen);
2629
+ gap: 16px;
2630
+ gap: var(--size-16);
2631
+ }
2632
+ .wds-list-item .partially-interactive {
2633
+ padding: 16px;
2634
+ padding: var(--size-16);
2635
+ }
2636
+ .wds-list-item label,
2637
+ .wds-list-item a {
2638
+ padding: 16px;
2639
+ padding: var(--size-16);
2640
+ }
2641
+ .wds-list-item-interactive label {
2642
+ cursor: pointer;
2643
+ }
2644
+ .wds-list-item-interactive:hover {
2645
+ background-color: var(--color-background-screen-hover);
2646
+ }
2647
+ .wds-list-item-interactive:hover .wds-list-item-control .wds-Button {
2648
+ background-color: var(--Button-background-hover);
2649
+ color: var(--Button-color-hover);
2650
+ transition: none;
2651
+ }
2652
+ .wds-list-item-interactive:active {
2653
+ background-color: var(--color-background-screen-active);
2654
+ }
2655
+ .wds-list-item-interactive .wds-list-item-control .wds-Button {
2656
+ transition: none;
2657
+ }
2658
+ .wds-list-item-media-image {
2659
+ width: var(--item-media-image-size);
2660
+ height: var(--item-media-image-size);
2661
+ }
2662
+ .wds-list-item-body {
2663
+ width: 100%;
2664
+ }
2665
+ .wds-list-item-title {
2666
+ color: #37517e;
2667
+ color: var(--color-content-primary);
2668
+ }
2669
+ .wds-list-item-additional-info {
2670
+ color: #768e9c;
2671
+ color: var(--color-content-tertiary);
2672
+ }
2673
+ .wds-list-item-value {
2674
+ flex: 0 0 auto;
2675
+ }
2676
+ .wds-list-item-control {
2677
+ flex: 0 0 auto;
2678
+ }
2679
+ .wds-list-item-navigation,
2680
+ .wds-list-item-navigation:hover,
2681
+ .wds-list-item-navigation:focus {
2682
+ -webkit-text-decoration: none;
2683
+ text-decoration: none;
2684
+ }
2685
+ .wds-list-item-spotlight-active {
2686
+ background-color: rgba(134,167,189,0.10196);
2687
+ background-color: var(--color-background-neutral);
2688
+ }
2689
+ .wds-list-item-spotlight-active:not(.disabled):not(:disabled):hover {
2690
+ background-color: var(--color-background-neutral-hover);
2691
+ }
2692
+ .wds-list-item-spotlight-active:not(.disabled):not(:disabled):active {
2693
+ background-color: var(--color-background-neutral-active);
2694
+ }
2695
+ .wds-list-item-spotlight-inactive {
2696
+ background-color: rgba(134, 167, 189, 0.025);
2697
+ border: 1px dashed rgba(0,0,0,0.10196);
2698
+ border: 1px dashed var(--color-border-neutral);
2699
+ }
2700
+ @supports (color: color-mix(in lch, red, blue)) {
2701
+ .wds-list-item-spotlight-inactive {
2702
+ background-color: color-mix(in srgb, var(--color-background-neutral) 25%, transparent);
2703
+ }
2704
+ }
2705
+ .wds-list-item-spotlight-inactive:not(.disabled):not(:disabled):hover {
2706
+ background-color: color-mix(in srgb, var(--color-background-neutral-hover) 25%, transparent);
2707
+ }
2708
+ .wds-list-item-spotlight-inactive:not(.disabled):not(:disabled):active {
2709
+ background-color: color-mix(in srgb, var(--color-background-neutral-active) 25%, transparent);
2710
+ }
2711
+ .wds-list-item-prompt {
2712
+ display: inline-flex;
2713
+ padding-top: calc(8px / 2);
2714
+ padding-top: calc(var(--padding-x-small) / 2);
2715
+ padding-bottom: calc(8px / 2);
2716
+ padding-bottom: calc(var(--padding-x-small) / 2);
2717
+ padding-left: calc(8px - 1px);
2718
+ padding-left: calc(var(--padding-x-small) - 1px);
2719
+ padding-right: 8px;
2720
+ padding-right: var(--padding-x-small);
2721
+ border-radius: 10px;
2722
+ border-radius: var(--radius-small);
2723
+ word-break: break-word;
2724
+ word-wrap: break-word;
2725
+ }
2726
+ .wds-list-item-prompt .np-prompt-icon {
2727
+ padding-right: calc(12px / 2);
2728
+ padding-right: calc(var(--size-12) / 2);
2729
+ padding-top: calc(4px - 1px);
2730
+ padding-top: calc(var(--size-4) - 1px);
2731
+ padding-bottom: calc(4px - 1px);
2732
+ padding-bottom: calc(var(--size-4) - 1px);
2733
+ }
2734
+ .wds-list-item-prompt .np-prompt-icon .tw-icon-tags,
2735
+ .wds-list-item-prompt .np-prompt-icon .tw-icon-confetti {
2736
+ color: var(--color-sentiment-positive-primary);
2737
+ }
2738
+ .wds-list-item-prompt a {
2739
+ text-underline-offset: calc(4px / 2);
2740
+ text-underline-offset: calc(var(--size-4) / 2);
2741
+ }
2742
+ .wds-list-item-prompt.np-prompt-interactive {
2743
+ -webkit-text-decoration: none;
2744
+ text-decoration: none;
2745
+ cursor: pointer;
2746
+ border: none;
2747
+ }
2748
+ .wds-list-item-prompt.negative {
2749
+ background-color: var(--color-sentiment-negative-secondary);
2750
+ color: var(--color-sentiment-negative-primary);
2751
+ }
2752
+ .wds-list-item-prompt.negative a {
2753
+ color: var(--color-sentiment-negative-primary);
2754
+ }
2755
+ .wds-list-item-prompt.negative a:hover {
2756
+ color: var(--color-sentiment-negative-primary-hover);
2757
+ }
2758
+ .wds-list-item-prompt.negative a:active {
2759
+ color: var(--color-sentiment-negative-primary-active);
2760
+ }
2761
+ .np-prompt-interactive.wds-list-item-prompt.negative:hover {
2762
+ background-color: color-mix(in srgb, var(--color-sentiment-negative-secondary) 95%, var(--color-sentiment-negative-primary));
2763
+ }
2764
+ .np-prompt-interactive.wds-list-item-prompt.negative:active {
2765
+ background-color: color-mix(in srgb, var(--color-sentiment-negative-secondary) 90%, var(--color-sentiment-negative-primary));
2766
+ }
2767
+ .wds-list-item-prompt.positive,
2768
+ .wds-list-item-prompt.discount,
2769
+ .wds-list-item-prompt.savings {
2770
+ background-color: var(--color-sentiment-positive-secondary);
2771
+ color: var(--color-sentiment-positive-primary);
2772
+ }
2773
+ .wds-list-item-prompt.positive a,
2774
+ .wds-list-item-prompt.discount a,
2775
+ .wds-list-item-prompt.savings a {
2776
+ color: var(--color-sentiment-positive-primary);
2777
+ }
2778
+ .wds-list-item-prompt.positive a:hover,
2779
+ .wds-list-item-prompt.discount a:hover,
2780
+ .wds-list-item-prompt.savings a:hover {
2781
+ color: var(--color-sentiment-positive-primary-hover);
2782
+ }
2783
+ .wds-list-item-prompt.positive a:active,
2784
+ .wds-list-item-prompt.discount a:active,
2785
+ .wds-list-item-prompt.savings a:active {
2786
+ color: var(--color-sentiment-positive-primary-active);
2787
+ }
2788
+ .np-prompt-interactive.wds-list-item-prompt.positive:hover,
2789
+ .np-prompt-interactive.wds-list-item-prompt.discount:hover,
2790
+ .np-prompt-interactive.wds-list-item-prompt.savings:hover {
2791
+ background-color: color-mix(in srgb, var(--color-sentiment-positive-secondary) 95%, var(--color-sentiment-positive-primary));
2792
+ }
2793
+ .np-prompt-interactive.wds-list-item-prompt.positive:active,
2794
+ .np-prompt-interactive.wds-list-item-prompt.discount:active,
2795
+ .np-prompt-interactive.wds-list-item-prompt.savings:active {
2796
+ background-color: color-mix(in srgb, var(--color-sentiment-positive-secondary) 90%, var(--color-sentiment-positive-primary));
2797
+ }
2798
+ .wds-list-item-prompt.neutral {
2799
+ background-color: rgba(134,167,189,0.10196);
2800
+ background-color: var(--color-background-neutral);
2801
+ color: #37517e;
2802
+ color: var(--color-content-primary);
2803
+ }
2804
+ .wds-list-item-prompt.neutral a {
2805
+ color: #37517e;
2806
+ color: var(--color-content-primary);
2807
+ }
2808
+ .np-prompt-interactive.wds-list-item-prompt.neutral:hover {
2809
+ background-color: var(--color-background-neutral-hover);
2810
+ }
2811
+ .np-prompt-interactive.wds-list-item-prompt.neutral:active {
2812
+ background-color: var(--color-background-neutral-active);
2813
+ }
2814
+ .wds-list-item-prompt.warning {
2815
+ background-color: var(--color-sentiment-warning-secondary);
2816
+ color: var(--color-sentiment-warning-content);
2817
+ }
2818
+ .wds-list-item-prompt.warning a {
2819
+ color: var(--color-sentiment-warning-content);
2820
+ }
2821
+ .wds-list-item-prompt.warning a:hover {
2822
+ color: var(--color-sentiment-warning-content-hover);
2823
+ }
2824
+ .wds-list-item-prompt.warning a:active {
2825
+ color: var(--color-sentiment-warning-content-active);
2826
+ }
2827
+ .np-prompt-interactive.wds-list-item-prompt.warning:hover {
2828
+ background-color: color-mix(in srgb, var(--color-sentiment-warning-secondary) 90%, var(--color-sentiment-warning-primary));
2829
+ }
2830
+ .np-prompt-interactive.wds-list-item-prompt.warning:active {
2831
+ background-color: color-mix(in srgb, var(--color-sentiment-warning-secondary) 80%, var(--color-sentiment-warning-primary));
2832
+ }
2621
2833
  .np-field-control {
2622
2834
  margin-top: 4px;
2623
2835
  margin-top: var(--size-4);
package/src/main.less CHANGED
@@ -38,6 +38,7 @@
38
38
  @import "./image/Image.less";
39
39
  @import "./info/Info.less";
40
40
  @import "./inputs/Input.less";
41
+ @import "./listItem/ListItem.less";
41
42
  @import "./field/Field.less";
42
43
  @import "./inputs/InputGroup.less";
43
44
  @import "./inputs/SelectInput.less";