app-tutor-ai-consumer 1.22.2 → 1.23.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ # [1.23.0](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.22.3...v1.23.0) (2025-08-11)
2
+
3
+ ### Features
4
+
5
+ - add metadata properties to widget settings and component IDs to customize on agent page ([04c244d](https://github.com/Hotmart-Org/app-tutor-ai-consumer/commit/04c244dcb4170665f6a216ce69c119e358118ef5))
6
+ - adding component id ([82b25ce](https://github.com/Hotmart-Org/app-tutor-ai-consumer/commit/82b25ce4a4974d3739dae09dc21928d5b3b78544))
7
+
8
+ ## [1.22.3](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.22.2...v1.22.3) (2025-08-08)
9
+
1
10
  ## [1.22.2](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.22.1...v1.22.2) (2025-08-07)
2
11
 
3
12
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "app-tutor-ai-consumer",
3
- "version": "1.22.2",
3
+ "version": "1.23.0",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "dev": "rspack serve --env=development --config config/rspack/rspack.config.js",
@@ -42,6 +42,7 @@ function HorizontalDraggableScroll({ children, className }: HorizontalDraggableS
42
42
 
43
43
  return (
44
44
  <div
45
+ id='tutor-ai-consumer-horizontal-draggable-scroll'
45
46
  ref={containerRef}
46
47
  onMouseDown={handleMouseDown}
47
48
  onMouseMove={handleMouseMove}
@@ -0,0 +1,5 @@
1
+ <svg viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M11.3016 1.60522H8.62451V0.112061H13.8506V5.33813H12.3574V2.66105L9.15242 5.86604L8.0966 4.81022L11.3016 1.60522ZM0.412109 8.32446H1.90527V11.0016L5.11027 7.79655L6.16609 8.85237L2.9611 12.0574H5.63818V13.5505H0.412109V8.32446Z"
4
+ fill="currentColor" />
5
+ </svg>
@@ -12,6 +12,7 @@ export type ValidIconNames =
12
12
  | 'copy-solid'
13
13
  | 'copy'
14
14
  | 'double-check'
15
+ | 'expand'
15
16
  | 'gallery'
16
17
  | 'info'
17
18
  | 'interrogation'
@@ -22,7 +22,7 @@
22
22
 
23
23
  .right:before {
24
24
  top: 50%;
25
- right: 97%;
25
+ right: 96%;
26
26
  transform: translateY(-50%) rotateZ(-90deg);
27
27
  }
28
28
 
@@ -34,6 +34,6 @@
34
34
 
35
35
  .left:before {
36
36
  top: 50%;
37
- left: 97%;
37
+ left: 96%;
38
38
  transform: translateY(-50%) rotateZ(90deg);
39
- }
39
+ }
@@ -71,7 +71,12 @@ function useSendTextMessage() {
71
71
  router: questionParam ? 'summary' : undefined,
72
72
  osVersion: browserInfo.version,
73
73
  platformDetail: browserInfo.name,
74
- ucode: settings.user?.ucode
74
+ ucode: settings.user?.ucode,
75
+ agentProductId: settings.config?.metadata?.agentProductId,
76
+ agentName: settings.config?.metadata?.agentName,
77
+ courseName: settings.config?.metadata?.courseName,
78
+ source: settings.config?.metadata?.source,
79
+ prompt: settings.config?.metadata?.promptId
75
80
  },
76
81
  externalId: v4(),
77
82
  namespace: settings.namespace,
@@ -1,6 +1,7 @@
1
1
  import { useEffect, useMemo, useRef } from 'react'
2
2
  import { useInfiniteQuery } from '@tanstack/react-query'
3
3
 
4
+ import { useMediaQuery } from '@/src/lib/hooks'
4
5
  import { isTextEmpty } from '@/src/lib/utils/is-text-empty'
5
6
  import { ChatInput, MessagesList, useChatInputValueAtom } from '@/src/modules/messages/components'
6
7
  import { MessagesContainer } from '@/src/modules/messages/components/messages-container'
@@ -25,6 +26,7 @@ function ChatPage() {
25
26
  const limit = useMessagesMaxCount()
26
27
  const [value, setValue] = useChatInputValueAtom()
27
28
  const [, setWidgetLoading] = useWidgetLoadingAtom()
29
+ const isMobile = useMediaQuery({ maxSize: 'md' })
28
30
 
29
31
  const conversationId = useMemo(() => settings?.conversationId, [settings?.conversationId])
30
32
  const profileId = useMemo(() => profileQuery.data?.id, [profileQuery.data?.id])
@@ -72,7 +74,11 @@ function ChatPage() {
72
74
  />
73
75
  }>
74
76
  <div className='max-md:px-[1.125rem] max-md:pt-[1.125rem] md:px-5 md:pt-5'>
75
- <WidgetHeader enabledButtons={['info', 'close']} tutorName={settings?.tutorName} />
77
+ <WidgetHeader
78
+ enabledButtons={['info', 'close', 'arrow-left']}
79
+ tutorName={settings?.tutorName}
80
+ showContentWithoutMeta={!isMobile}
81
+ />
76
82
  </div>
77
83
  <MessagesContainer
78
84
  ref={scrollerRef}
@@ -1,2 +1 @@
1
- export * from './header'
2
- export { default as WidgetHeader } from './header'
1
+ export { default as WidgetHeader } from './widget-header'
@@ -2,7 +2,7 @@ import { render, screen } from '@/src/config/tests'
2
2
  import * as Hooks from '@/src/lib/hooks'
3
3
 
4
4
  import WidgetHeaderPropsBuilder from './__tests__/widget-header-props.builder'
5
- import WidgetHeader from './header'
5
+ import WidgetHeader from './widget-header'
6
6
 
7
7
  describe('<WidgetHeader />', () => {
8
8
  const defaultProps = new WidgetHeaderPropsBuilder()
@@ -29,10 +29,10 @@ describe('<WidgetHeader />', () => {
29
29
  expect(screen.queryByRole('button', { name: /Arrow Left Icon/i })).not.toBeInTheDocument()
30
30
  })
31
31
 
32
- it('should render WidgetHeaderContentWithoutMeta when prop showContentWithoutMeta is true and showContent is false', () => {
32
+ it('should render WidgetHeaderContentWithoutMeta when prop showContentWithoutMeta is true', () => {
33
33
  const props = new WidgetHeaderPropsBuilder()
34
+ .withEnabledButtons(['close', 'arrow-left'])
34
35
  .withShowContentWithoutMeta(true)
35
- .withShowContent(false)
36
36
 
37
37
  renderComponent(props)
38
38
 
@@ -0,0 +1,150 @@
1
+ import { useMemo } from 'react'
2
+ import clsx from 'clsx'
3
+ import { useTranslation } from 'react-i18next'
4
+
5
+ import { DataHubService } from '@/src/config/datahub'
6
+ import { ClickTutorMinimizeSchema } from '@/src/config/datahub/schemas/tutor'
7
+ import { Button, Icon, Tooltip } from '@/src/lib/components'
8
+ import { useMediaQuery } from '@/src/lib/hooks'
9
+ import { TutorWidgetEvents } from '../../events'
10
+ import { useWidgetGoBackTabAtom, useWidgetTabsAtom } from '../../store'
11
+ import { AIAvatar } from '../ai-avatar'
12
+
13
+ import type { WidgetHeaderProps } from './types'
14
+
15
+ import styles from './styles.module.css'
16
+
17
+ function WidgetHeaderActions({
18
+ actionButtons
19
+ }: {
20
+ actionButtons: ('archive' | 'expand' | 'info')[]
21
+ }) {
22
+ const { t } = useTranslation()
23
+ const [, setTab] = useWidgetTabsAtom()
24
+ const isMobile = useMediaQuery({ maxSize: 'md' })
25
+
26
+ const handleClickArchive = () => {
27
+ setTab('chat')
28
+ }
29
+
30
+ const handleClickInfo = () => {
31
+ setTab('information')
32
+ }
33
+
34
+ const handleClickExpand = () => {
35
+ TutorWidgetEvents['tutor-app-widget-expand'].dispatch()
36
+ }
37
+
38
+ if (!(Number(actionButtons?.length) > 0)) return null
39
+
40
+ return (
41
+ <>
42
+ <div
43
+ className={clsx('flex max-w-max items-center gap-3 text-neutral-700', styles.btnContainer)}>
44
+ {actionButtons.includes('archive') && (
45
+ <Tooltip show={!isMobile} content={t('general.buttons.archive')}>
46
+ <Button
47
+ show={actionButtons.includes('archive')}
48
+ onClick={handleClickArchive}
49
+ aria-label={t('general.buttons.archive') + ' Icon'}>
50
+ <Icon name='archive' className='h-4 w-4' aria-hidden />
51
+ </Button>
52
+ </Tooltip>
53
+ )}
54
+ {actionButtons.includes('info') && (
55
+ <Tooltip show={!isMobile} content={t('general.buttons.info')} position='left'>
56
+ <Button
57
+ show={actionButtons.includes('info')}
58
+ onClick={handleClickInfo}
59
+ aria-label={t('general.buttons.info') + ' Icon'}>
60
+ <Icon name='info' className='h-4 w-4' aria-hidden />
61
+ </Button>
62
+ </Tooltip>
63
+ )}
64
+ {actionButtons.includes('expand') && (
65
+ <Tooltip show={!isMobile} content={t('general.buttons.expand')} position='left'>
66
+ <Button
67
+ show={actionButtons.includes('expand')}
68
+ onClick={handleClickExpand}
69
+ aria-label={t('general.buttons.expand') + ' Icon'}>
70
+ <Icon name='expand' className='h-3.5 w-3.5' aria-hidden />
71
+ </Button>
72
+ </Tooltip>
73
+ )}
74
+ </div>
75
+ </>
76
+ )
77
+ }
78
+
79
+ function WidgetHeader({
80
+ enabledButtons = [],
81
+ tutorName,
82
+ showContentWithoutMeta,
83
+ showContent = true
84
+ }: WidgetHeaderProps) {
85
+ const { t } = useTranslation()
86
+ const [, goBack] = useWidgetGoBackTabAtom()
87
+ const name = tutorName ?? t('general.name')
88
+
89
+ const handleHideWidget = () => {
90
+ TutorWidgetEvents['c3po-app-widget-hide'].dispatch()
91
+ DataHubService.sendEvent({ schema: new ClickTutorMinimizeSchema() })
92
+ }
93
+
94
+ const actionButtons = useMemo(
95
+ () => enabledButtons.filter((btn) => btn === 'archive' || btn === 'info' || btn === 'expand'),
96
+ [enabledButtons]
97
+ )
98
+
99
+ const hasToShowActions = useMemo(() => Number(actionButtons?.length) > 0, [actionButtons?.length])
100
+
101
+ return (
102
+ <div
103
+ id='tutor-ai-consumer-widget-header'
104
+ className='mb-4 mt-0.5 flex flex-col gap-2 text-neutral-900'>
105
+ <div className='flex justify-end'>
106
+ <div className={styles.closeContainer}>
107
+ <Button
108
+ className='text-neutral-500'
109
+ show={enabledButtons.includes('close')}
110
+ onClick={handleHideWidget}
111
+ aria-label='Close Icon'>
112
+ <Icon name='close' className='h-3 w-3' aria-hidden />
113
+ </Button>
114
+ </div>
115
+ </div>
116
+ <div
117
+ className={clsx('grid items-center max-md:gap-2 md:gap-4', styles.btnContainer, {
118
+ 'grid-cols-[auto_1fr_auto]': enabledButtons.includes('arrow-left'),
119
+ 'grid-cols-[1fr_auto]': !enabledButtons.includes('arrow-left') && hasToShowActions,
120
+ 'grid-cols-[1fr]': !enabledButtons.includes('arrow-left') && !hasToShowActions
121
+ })}>
122
+ {enabledButtons.includes('arrow-left') && (
123
+ <div>
124
+ <Button aria-label='Arrow Left Icon' onClick={goBack}>
125
+ <Icon name='arrow-left' className='h-3.5 w-3.5' aria-hidden />
126
+ </Button>
127
+ </div>
128
+ )}
129
+ <div
130
+ className={clsx('flex w-full items-center gap-2', {
131
+ 'justify-center': showContentWithoutMeta
132
+ })}>
133
+ {showContent && (
134
+ <>
135
+ {!showContentWithoutMeta && <AIAvatar />}
136
+ {name && <h4 className='text-sm/loose font-bold'>{name}</h4>}
137
+ </>
138
+ )}
139
+ </div>
140
+ {hasToShowActions ? (
141
+ <WidgetHeaderActions actionButtons={actionButtons} />
142
+ ) : (
143
+ <div className='h-6 w-6' />
144
+ )}
145
+ </div>
146
+ </div>
147
+ )
148
+ }
149
+
150
+ export default WidgetHeader
@@ -16,40 +16,39 @@ function WidgetInformationPage() {
16
16
  const tutorName = settings?.tutorName ?? t('general.name')
17
17
 
18
18
  return (
19
- <PageLayout className='flex min-h-0 flex-col text-neutral-900 max-md:p-[1.125rem] md:p-5'>
20
- <div className='mb-4'>
19
+ <PageLayout className='flex min-h-0 flex-col text-neutral-900'>
20
+ <div className='max-md:px-[1.125rem] max-md:py-[1.125rem] md:px-5 md:py-5'>
21
21
  <WidgetHeader
22
- enabledButtons={['close']}
23
- showContent={false}
22
+ enabledButtons={['close', 'arrow-left']}
24
23
  showContentWithoutMeta
25
24
  tutorName={t('info.title')}
26
25
  />
27
- </div>
28
26
 
29
- <div className='my-8 flex justify-center'>
30
- <div className='flex flex-col items-center gap-2'>
31
- <AIAvatar size='lg' />
32
-
33
- <h3
34
- className={clsx('font-bold', {
35
- 'text-white': isDarkMode,
36
- 'text-neutral-700': !isDarkMode
37
- })}>
38
- {tutorName}
39
- </h3>
27
+ <div className='my-8 flex justify-center'>
28
+ <div className='flex flex-col items-center gap-2'>
29
+ <AIAvatar size='lg' />
30
+
31
+ <h3
32
+ className={clsx('font-bold', {
33
+ 'text-white': isDarkMode,
34
+ 'text-neutral-700': !isDarkMode
35
+ })}>
36
+ {tutorName}
37
+ </h3>
38
+ </div>
40
39
  </div>
41
- </div>
42
40
 
43
- <div className='flex flex-col gap-5'>
44
- {infoItems({ tutorName: t('general.name') }).map((item) => (
45
- <InformationCard
46
- key={item.titleKey}
47
- icon={item.icon}
48
- title={t(item.titleKey)}
49
- description={t(item.descKey)}
50
- isDarkMode={isDarkMode}
51
- />
52
- ))}
41
+ <div className='flex flex-col gap-5'>
42
+ {infoItems({ tutorName: t('general.name') }).map((item) => (
43
+ <InformationCard
44
+ key={item.titleKey}
45
+ icon={item.icon}
46
+ title={t(item.titleKey)}
47
+ description={t(item.descKey)}
48
+ isDarkMode={isDarkMode}
49
+ />
50
+ ))}
51
+ </div>
53
52
  </div>
54
53
  </PageLayout>
55
54
  )
@@ -23,7 +23,9 @@ function PageLayout({ asideChild, children, className }: PageLayoutProps) {
23
23
  {children}
24
24
  </div>
25
25
  {asideChild && (
26
- <div className='grid-area-[aside] flex-shrink-0 border-t border-t-neutral-300 px-5 py-4'>
26
+ <div
27
+ id='tutor-ai-consumer-page-layout-aside'
28
+ className='grid-area-[aside] flex-shrink-0 border-t border-t-neutral-300 px-5 py-4'>
27
29
  {asideChild}
28
30
  </div>
29
31
  )}
@@ -4,7 +4,7 @@ import type { CSSProperties, MouseEventHandler } from 'react'
4
4
  import { useTranslation } from 'react-i18next'
5
5
 
6
6
  import { Button, HorizontalDraggableScroll } from '@/src/lib/components'
7
- import { useRefEventListener } from '@/src/lib/hooks'
7
+ import { useMediaQuery, useRefEventListener } from '@/src/lib/hooks'
8
8
  import { ChatInput, useChatInputValueAtom } from '@/src/modules/messages/components'
9
9
  import { getAllMessagesQuery, useSendTextMessage } from '@/src/modules/messages/hooks'
10
10
  import { useMessagesMaxCount } from '@/src/modules/messages/store'
@@ -28,6 +28,7 @@ function WidgetStarterPage() {
28
28
  const name = settings?.tutorName ?? t('general.name')
29
29
  const isDarkTheme = settings?.config?.theme === 'dark'
30
30
  const isSparkieReady = useInitSparkie()
31
+ const isMobile = useMediaQuery({ maxSize: 'md' })
31
32
 
32
33
  useRefEventListener<HTMLTextAreaElement>({
33
34
  config: {
@@ -104,7 +105,7 @@ function WidgetStarterPage() {
104
105
  <div className='grid-area-[a] flex min-h-0 flex-col max-md:px-[1.125rem] max-md:pt-[1.125rem] md:px-5 md:pt-5'>
105
106
  <WidgetHeader
106
107
  enabledButtons={isSparkieReady ? ['close', 'archive', 'info'] : ['close', 'info']}
107
- showContent={false}
108
+ showContent={isMobile}
108
109
  tutorName={name}
109
110
  />
110
111
 
@@ -7,7 +7,8 @@ export const TutorWidgetEventTypes = {
7
7
  CLOSE: 'c3po-app-widget-close',
8
8
  HIDE: 'c3po-app-widget-hide',
9
9
  LOADED: 'tutor-app-widget-loaded',
10
- THEME_CHANGE: 'c3po-app-widget-theme-change'
10
+ THEME_CHANGE: 'c3po-app-widget-theme-change',
11
+ EXPAND: 'tutor-app-widget-expand'
11
12
  } as const
12
13
 
13
14
  export const TutorWidgetEvents = {
@@ -94,7 +95,24 @@ export const TutorWidgetEvents = {
94
95
  dispatch: (payload) => {
95
96
  window.dispatchEvent(new CustomEvent(TutorWidgetEventTypes.THEME_CHANGE, payload))
96
97
  }
97
- } as ITutorWidgetEvent<{ theme: Theme }>
98
+ } as ITutorWidgetEvent<{ theme: Theme }>,
99
+
100
+ [TutorWidgetEventTypes.EXPAND]: {
101
+ name: TutorWidgetEventTypes.EXPAND,
102
+ handler: (callback: () => void) => {
103
+ const listener: EventListener = () => {
104
+ callback()
105
+ }
106
+ window.addEventListener(TutorWidgetEventTypes.EXPAND, listener)
107
+
108
+ return () => {
109
+ window.removeEventListener(TutorWidgetEventTypes.EXPAND, listener)
110
+ }
111
+ },
112
+ dispatch: (payload) => {
113
+ window.dispatchEvent(new CustomEvent(TutorWidgetEventTypes.EXPAND, payload))
114
+ }
115
+ } as ITutorWidgetEvent<void>
98
116
  } as const
99
117
 
100
118
  export const ACTION_EVENTS = {
package/src/types.ts CHANGED
@@ -51,6 +51,14 @@ export type WidgetSettingProps = {
51
51
  classType?: ClassTypes
52
52
  config?: {
53
53
  theme?: Theme
54
+ metadata?: {
55
+ parent?: 'AGENT' | 'TUTOR'
56
+ agentProductId?: number
57
+ agentName?: string
58
+ courseName?: string
59
+ source?: string
60
+ promptId?: string
61
+ }
54
62
  }
55
63
  }
56
64
 
@@ -1,118 +0,0 @@
1
- import clsx from 'clsx'
2
- import { useTranslation } from 'react-i18next'
3
-
4
- import { DataHubService } from '@/src/config/datahub'
5
- import { ClickTutorMinimizeSchema } from '@/src/config/datahub/schemas/tutor'
6
- import { Button, Icon, Tooltip } from '@/src/lib/components'
7
- import { useMediaQuery } from '@/src/lib/hooks'
8
- import { TutorWidgetEvents } from '../../events'
9
- import { useWidgetGoBackTabAtom, useWidgetTabsAtom } from '../../store'
10
- import { AIAvatar } from '../ai-avatar'
11
-
12
- import type { WidgetHeaderContentProps, WidgetHeaderProps } from './types'
13
-
14
- import styles from './styles.module.css'
15
-
16
- export function WidgetHeaderContent({ tutorName }: WidgetHeaderContentProps) {
17
- return (
18
- <div className='flex w-full gap-2'>
19
- <AIAvatar />
20
- <div className='flex flex-col justify-center'>
21
- {tutorName && <h4 className='text-sm/loose font-bold'>{tutorName}</h4>}
22
- </div>
23
- </div>
24
- )
25
- }
26
-
27
- export function WidgetHeaderContentWithoutMeta({ name }: { name?: string }) {
28
- const { t } = useTranslation()
29
- const [, goBack] = useWidgetGoBackTabAtom()
30
- const tutorName = name ?? t('general.name')
31
-
32
- return (
33
- <div
34
- className={clsx(
35
- 'grid-areas-[a_b] grid grid-cols-[auto_1fr] items-center gap-1',
36
- styles.withoutMetaContainer
37
- )}>
38
- <Button className='grid-area-[a]' aria-label='Arrow Left Icon' onClick={goBack}>
39
- <Icon name='arrow-left' className='h-3.5 w-3.5' aria-hidden />
40
- </Button>
41
- <div className='grid-area-[b] flex min-h-6 justify-center text-center'>
42
- <span className='absolute bottom-0 left-1/2 -translate-x-1/2 text-base font-bold'>
43
- {tutorName}
44
- </span>
45
- </div>
46
- </div>
47
- )
48
- }
49
-
50
- function WidgetHeader({
51
- enabledButtons = [],
52
- tutorName,
53
- showContentWithoutMeta,
54
- showContent = true
55
- }: WidgetHeaderProps) {
56
- const { t } = useTranslation()
57
- const [, setTab] = useWidgetTabsAtom()
58
- const name = tutorName ?? t('general.name')
59
- const isMobile = useMediaQuery({ maxSize: 'md' })
60
-
61
- const handleClickArchive = () => {
62
- setTab('chat')
63
- }
64
-
65
- const handleClickInfo = () => {
66
- setTab('information')
67
- }
68
-
69
- const handleHideWidget = () => {
70
- TutorWidgetEvents['c3po-app-widget-hide'].dispatch()
71
- DataHubService.sendEvent({ schema: new ClickTutorMinimizeSchema() })
72
- }
73
-
74
- return (
75
- <div className='mt-0.5 flex flex-col gap-2 text-neutral-900'>
76
- <div className='flex justify-end'>
77
- <div className={styles.closeContainer}>
78
- <Button
79
- className='text-neutral-500'
80
- show={enabledButtons.includes('close')}
81
- onClick={handleHideWidget}
82
- aria-label='Close Icon'>
83
- <Icon name='close' className='h-3 w-3' aria-hidden />
84
- </Button>
85
- </div>
86
- </div>
87
- <div className='grid-areas-[a_b] grid grid-cols-[1fr_auto] items-center pb-4'>
88
- <div className='grid-area-[a] relative'>
89
- {showContent && !showContentWithoutMeta && <WidgetHeaderContent tutorName={name} />}
90
- {showContentWithoutMeta && !showContent && <WidgetHeaderContentWithoutMeta name={name} />}
91
- </div>
92
-
93
- <div className='grid-area-[b] ml-auto shrink-0'>
94
- <div className={clsx('flex max-w-max gap-3 text-neutral-700', styles.btnContainer)}>
95
- <Tooltip show={!isMobile} content={t('general.buttons.archive')}>
96
- <Button
97
- show={enabledButtons.includes('archive')}
98
- onClick={handleClickArchive}
99
- aria-label={t('general.buttons.archive') + ' Icon'}>
100
- <Icon name='archive' className='h-4 w-4' aria-hidden />
101
- </Button>
102
- </Tooltip>
103
- <Tooltip show={!isMobile} content={t('general.buttons.info')} position='left'>
104
- <Button
105
- show={enabledButtons.includes('info')}
106
- onClick={handleClickInfo}
107
- aria-label={t('general.buttons.info') + ' Icon'}>
108
- <Icon name='info' className='h-4 w-4' aria-hidden />
109
- </Button>
110
- </Tooltip>
111
- </div>
112
- </div>
113
- </div>
114
- </div>
115
- )
116
- }
117
-
118
- export default WidgetHeader