@oanda/labs-widget-common 1.0.219 → 1.0.220

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
1
  import type { FC, PropsWithChildren } from 'react';
2
- import React from 'react';
2
+ import React, { useState } from 'react';
3
3
 
4
4
  import { OandaLogoDark, OandaLogoLight } from '../../images';
5
5
  import { useLayoutProvider } from '../../providers';
@@ -7,22 +7,12 @@ import { cn } from '../../tailwind';
7
7
  import type { RenderComponentParams } from '../../types';
8
8
  import { Theme } from '../../types';
9
9
 
10
- const disclaimerStyles: Record<
11
- Theme,
12
- { wrapperStyle: string; borderStyle: string }
13
- > = {
14
- dark: {
15
- wrapperStyle: 'lw-h-6 lw-bg-[#262F3C]',
16
- borderStyle: 'lw-border-[#262F3C]',
17
- },
18
- light: {
19
- wrapperStyle: 'lw-shadow-[0_2px_8px_0_rgba(0,33,74,0.25)]',
20
- borderStyle: 'lw-border-[#e6e6e6]',
21
- },
22
- };
23
-
24
10
  type DisclaimerProps = PropsWithChildren &
25
- Omit<RenderComponentParams, 'Component'>;
11
+ Omit<RenderComponentParams, 'Component'> & {
12
+ text?: string;
13
+ isSlim?: boolean;
14
+ infoButtonPosition?: 'left' | 'top';
15
+ };
26
16
 
27
17
  export const Disclaimer: FC<DisclaimerProps> = ({
28
18
  children,
@@ -30,23 +20,28 @@ export const Disclaimer: FC<DisclaimerProps> = ({
30
20
  brandingSpace,
31
21
  fitContent = false,
32
22
  linkArea = 'full',
23
+ text,
24
+ isSlim,
25
+ infoButtonPosition = 'top',
33
26
  }) => {
34
27
  const { theme } = useLayoutProvider();
28
+ const isDark = theme === Theme.Dark;
35
29
 
36
- if (!logoLink) {
30
+ const [isLogoHovered, setIsLogoHovered] = useState(false);
31
+ const [isInfoHovered, setIsInfoHovered] = useState(false);
32
+
33
+ if (!logoLink && !text) {
37
34
  return children;
38
35
  }
39
36
 
40
- const isDark = theme !== 'light';
41
37
  const isClickable = linkArea === 'full';
42
- const { wrapperStyle, borderStyle } = disclaimerStyles[theme ?? Theme.Light];
43
38
 
44
39
  return (
45
40
  <div
46
41
  className={cn(
47
42
  'lw-relative lw-overflow-hidden',
48
43
  isClickable && 'lw-cursor-pointer',
49
- brandingSpace && brandingSpace === 'vertical' ? 'lw-pb-12' : 'lw-pb-2',
44
+ brandingSpace && brandingSpace === 'vertical' ? 'lw-pb-12' : 'lw-pb-0',
50
45
  !!fitContent && 'lw-w-fit'
51
46
  )}
52
47
  data-testid="disclaimer-wrapper"
@@ -54,34 +49,77 @@ export const Disclaimer: FC<DisclaimerProps> = ({
54
49
  onClick={() => isClickable && window.open(logoLink, '_blank')}
55
50
  >
56
51
  {children}
57
- <div
58
- className={cn(
59
- 'lw-absolute lw-z-20 lw-bottom-3 lw-right-1 lw-translate-x-[3.7rem] lw-rounded-l-full lw-transition lw-delay-150 lw-duration-300 lw-ease-in-out hover:lw-translate-x-2 [&:hover+div]:lw-translate-x-[3.7rem]',
60
- wrapperStyle
61
- )}
62
- >
52
+ {text && (
63
53
  <div
64
- className="lw-cursor-pointer"
65
- data-testid="disclaimer-wrapper-logo"
66
- role="presentation"
67
- onClick={(e) => {
68
- e.stopPropagation();
69
- window.open(logoLink, '_blank');
70
- }}
71
- >
72
- {isDark ? (
73
- <OandaLogoDark data-testid="disclaimer-wrapper-logo-dark" />
74
- ) : (
75
- <OandaLogoLight data-testid="disclaimer-wrapper-logo-light" />
54
+ className={cn(
55
+ 'lw-absolute lw-right-0 lw-top-0 lw-z-30 lw-flex lw-h-full lw-items-center lw-bg-border-primary lw-bg-opacity-90 lw-p-3 lw-text-sm lw-text-text-primary lw-delay-150 lw-duration-150 lw-ease-in-out',
56
+ isInfoHovered && 'lw-opacity-100',
57
+ !isInfoHovered && 'lw-opacity-0 lw-pointer-events-none'
76
58
  )}
59
+ onBlur={() => setIsInfoHovered(false)}
60
+ onMouseOut={() => setIsInfoHovered(false)}
61
+ >
62
+ {text}
77
63
  </div>
78
- </div>
64
+ )}
79
65
  <div
80
66
  className={cn(
81
- 'lw-absolute lw-bottom-2.5 lw-right-0 lw-h-7 lw-w-px lw-translate-x-0 lw-transition lw-delay-150 lw-duration-300',
82
- borderStyle
67
+ 'lw-absolute lw-bottom-3 lw-right-0 lw-z-20 lw-flex lw-transition lw-delay-100 lw-duration-300 lw-ease-in-out',
68
+ logoLink &&
69
+ !isLogoHovered &&
70
+ infoButtonPosition === 'left' &&
71
+ 'lw-translate-x-[55px]',
72
+ isSlim && 'lw-bottom-[6px]',
73
+ !isSlim && 'lw-bottom-2',
74
+ infoButtonPosition === 'left' && 'lw-flex-row lw-items-center',
75
+ infoButtonPosition === 'top' && 'lw-flex-col lw-items-end'
83
76
  )}
84
- />
77
+ >
78
+ {text && (
79
+ <div
80
+ className={cn(
81
+ 'lw-flex lw-h-[20px] lw-w-[20px] lw-items-center lw-justify-center lw-rounded-full lw-border lw-border-border-primary lw-pb-0.5 lw-text-sm lw-font-bold lw-text-text-secondary lw-shadow-basic',
82
+ isDark && 'lw-bg-dark-blue',
83
+ !isDark && 'lw-bg-bg-primary',
84
+ infoButtonPosition === 'top' && 'lw-mr-1',
85
+ infoButtonPosition === 'top' && !!logoLink && 'lw-mb-3',
86
+ infoButtonPosition === 'left' && 'lw-mr-2 '
87
+ )}
88
+ onFocus={() => setIsInfoHovered(true)}
89
+ onMouseOver={() => setIsInfoHovered(true)}
90
+ >
91
+ i
92
+ </div>
93
+ )}
94
+ {logoLink && (
95
+ <div
96
+ className={cn(
97
+ 'lw-cursor-pointer lw-rounded-l-full lw-bg-bg-primary lw-shadow-basic',
98
+ infoButtonPosition === 'top' &&
99
+ 'lw-transition lw-delay-100 lw-duration-300 lw-ease-in-out',
100
+ !isLogoHovered &&
101
+ infoButtonPosition === 'top' &&
102
+ 'lw-translate-x-[55px]'
103
+ )}
104
+ data-testid="disclaimer-wrapper-logo"
105
+ role="presentation"
106
+ onBlur={() => setIsLogoHovered(false)}
107
+ onClick={(e) => {
108
+ e.stopPropagation();
109
+ window.open(logoLink, '_blank');
110
+ }}
111
+ onFocus={() => setIsLogoHovered(true)}
112
+ onMouseOut={() => setIsLogoHovered(false)}
113
+ onMouseOver={() => setIsLogoHovered(true)}
114
+ >
115
+ {isDark ? (
116
+ <OandaLogoDark data-testid="disclaimer-wrapper-logo-dark" />
117
+ ) : (
118
+ <OandaLogoLight data-testid="disclaimer-wrapper-logo-light" />
119
+ )}
120
+ </div>
121
+ )}
122
+ </div>
85
123
  </div>
86
124
  );
87
125
  };
@@ -8,6 +8,11 @@ import { WidgetError } from '../Error';
8
8
  export type WidgetWrapperProps = PropsWithChildren &
9
9
  WidgetLink & {
10
10
  isParamError?: boolean | undefined;
11
+ disclaimer?: {
12
+ position?: 'left' | 'top';
13
+ text?: string;
14
+ };
15
+ isSlim?: boolean;
11
16
  } & Pick<WidgetStyling, 'brandingSpace' | 'fitContent'>;
12
17
 
13
18
  export const WidgetWrapper: FC<WidgetWrapperProps> = ({
@@ -17,12 +22,17 @@ export const WidgetWrapper: FC<WidgetWrapperProps> = ({
17
22
  brandingSpace,
18
23
  fitContent,
19
24
  isParamError,
25
+ disclaimer,
26
+ isSlim,
20
27
  }) => (
21
28
  <Disclaimer
22
29
  brandingSpace={brandingSpace}
23
30
  fitContent={fitContent}
31
+ infoButtonPosition={disclaimer?.position}
32
+ isSlim={isSlim}
24
33
  linkArea={linkArea}
25
34
  logoLink={logoLink}
35
+ text={disclaimer?.text}
26
36
  >
27
37
  {isParamError ? <WidgetError /> : children}
28
38
  </Disclaimer>
@@ -24,10 +24,12 @@ export const colorPalette = {
24
24
  white: '#FFFFFF',
25
25
  black: '#000000',
26
26
  grayLight: '#9EA4AC',
27
+ grayLight95: 'rgba(158, 164, 172, 0.95)',
27
28
  gray: '#7B8085',
28
29
  darkGray: '#1C1C1C',
29
30
  brightBlue: 'rgba(51, 88, 255, 0)',
30
31
  brightBlue30: 'rgba(51, 88, 255, 0.3)',
32
+ darkBlue: '#262f3c',
31
33
  };
32
34
 
33
35
  export const twColorPallete = toTwConfigKeys(colorPalette);
@@ -50,6 +50,7 @@ export const sharedPreset: Omit<Config, 'content'> = {
50
50
  boxShadow: {
51
51
  innerBorder: 'inset 0 0 0 1px',
52
52
  innerBorderBgColor: 'inset 0 0 0 2px hsl(var(--twc-bg-primary))',
53
+ basic: '0 2px 8px 0 rgba(0, 33, 74, 0.25)',
53
54
  },
54
55
  },
55
56
  fontFamily: {