app-tutor-ai-consumer 1.22.0 → 1.22.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.
Files changed (25) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +1 -1
  3. package/src/development-bootstrap.tsx +3 -0
  4. package/src/lib/components/button/button-default.tsx +1 -1
  5. package/src/lib/components/button/button.tsx +11 -8
  6. package/src/lib/components/button/styles.module.css +6 -0
  7. package/src/lib/components/icons/icon-names.d.ts +2 -0
  8. package/src/lib/components/icons/send.svg +5 -3
  9. package/src/lib/components/icons/sparkle-tutor-light.svg +15 -0
  10. package/src/lib/components/icons/sparkle-tutor.svg +19 -0
  11. package/src/modules/messages/components/chat-input/chat-input.tsx +4 -4
  12. package/src/modules/messages/components/chat-input/styles.module.css +4 -0
  13. package/src/modules/messages/components/message-actions/message-actions.tsx +15 -8
  14. package/src/modules/messages/components/message-item/message-item.tsx +1 -1
  15. package/src/modules/widget/components/ai-avatar/ai-avatar.tsx +19 -8
  16. package/src/modules/widget/components/avatar-animation/avatar-animation.tsx +1 -1
  17. package/src/modules/widget/components/greetings-card/greetings-card.tsx +5 -0
  18. package/src/modules/widget/components/header/header.spec.tsx +2 -2
  19. package/src/modules/widget/components/header/header.tsx +2 -2
  20. package/src/modules/widget/components/header/types.ts +1 -1
  21. package/src/modules/widget/components/information-page/constants.ts +3 -2
  22. package/src/modules/widget/components/information-page/information-page.tsx +4 -3
  23. package/src/modules/widget/components/scroll-to-bottom-button/scroll-to-bottom-button.tsx +2 -2
  24. package/src/modules/widget/components/starter-page/starter-page.spec.tsx +1 -1
  25. package/src/modules/widget/components/starter-page/starter-page.tsx +24 -22
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [1.22.1](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.22.0...v1.22.1) (2025-08-06)
2
+
3
+ ### Bug Fixes
4
+
5
+ - qa issues part 1 ([6b99c06](https://github.com/Hotmart-Org/app-tutor-ai-consumer/commit/6b99c06114fee13fb4d4dd68e4888392007988a4))
6
+
1
7
  # [1.22.0](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.21.2...v1.22.0) (2025-08-04)
2
8
 
3
9
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "app-tutor-ai-consumer",
3
- "version": "1.22.0",
3
+ "version": "1.22.1",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "dev": "rspack serve --env=development --config config/rspack/rspack.config.js",
@@ -23,6 +23,9 @@ if (devMode) {
23
23
  'bg-ai-dark fixed bottom-5 right-5 w-[27rem] h-[min(43rem,calc(100vh-2.5rem))] max-h-[calc(100vh-2.5rem)] z-10 rounded-[0.625rem] border border-neutral-200 shadow-lg overflow-hidden flex flex-col'
24
24
  )
25
25
 
26
+ // Theme setter
27
+ container.setAttribute('data-theme', 'dark')
28
+
26
29
  root?.appendChild(container)
27
30
 
28
31
  await window.startChatWidget(rootId, {
@@ -21,7 +21,7 @@ function ButtonDefault({
21
21
  <button
22
22
  {...props}
23
23
  className={clsx(
24
- 'rounded text-base font-medium outline-none focus-visible:ring-2 focus-visible:ring-blue-500',
24
+ 'rounded text-base font-medium outline-none focus-visible:ring-2 focus-visible:ring-neutral-500',
25
25
  className
26
26
  )}
27
27
  type={props.type ?? 'button'}
@@ -58,9 +58,10 @@ function Button({
58
58
  show={show}
59
59
  className={clsx(
60
60
  className,
61
+ styles.gradientButton,
61
62
  'group relative inline-flex items-center justify-center overflow-hidden rounded-lg p-[1px]',
62
63
  {
63
- 'bg-gradient-to-br from-[var(--ai-color-gradient-primary)] to-[var(--ai-color-gradient-accent)] hover:text-neutral-1000 group-hover:from-[var(--ai-color-gradient-primary)] group-hover:to-[var(--ai-color-gradient-accent)]':
64
+ 'bg-gradient-to-br from-[var(--ai-color-gradient-primary)] to-[var(--ai-color-gradient-accent)] hover:text-neutral-1000':
64
65
  !loading,
65
66
  'shine-box cursor-not-allowed': loading
66
67
  }
@@ -68,8 +69,11 @@ function Button({
68
69
  <span
69
70
  data-label='text-content'
70
71
  className={clsx(
71
- 'flex-1 rounded-lg bg-neutral-100 px-5 py-2.5 text-neutral-1000 transition-all duration-75 ease-in group-hover:bg-transparent',
72
- 'flex flex-nowrap'
72
+ 'rounded-lg transition-all duration-75 ease-in',
73
+ 'px-5 py-2.5',
74
+ 'text-neutral-1000',
75
+ 'bg-[var(--gradient-btn-hover-background)] hover:bg-[linear-gradient(to_right,_rgb(from_var(--gradient-btn-hover-foreground)_r_g_b_/_var(--gradient-btn-hover-foreground-opacity)),_rgb(from_var(--gradient-btn-hover-foreground)_r_g_b_/_var(--gradient-btn-hover-foreground-opacity))),_linear-gradient(to_right,_var(--gradient-btn-hover-background),_var(--gradient-btn-hover-background))] group-hover:bg-[linear-gradient(to_right,_rgb(from_var(--gradient-btn-hover-foreground)_r_g_b_/_var(--gradient-btn-hover-foreground-opacity)),_rgb(from_var(--gradient-btn-hover-foreground)_r_g_b_/_var(--gradient-btn-hover-foreground-opacity))),_linear-gradient(to_right,_var(--gradient-btn-hover-background),_var(--gradient-btn-hover-background))]',
76
+ 'flex flex-1 flex-nowrap'
73
77
  )}>
74
78
  <span className={clsx({ 'opacity-20': loading })}>{children}</span>
75
79
  </span>
@@ -142,12 +146,11 @@ function Button({
142
146
  )
143
147
  default:
144
148
  return (
145
- <button
149
+ <ButtonDefault
146
150
  className={clsx(
147
- 'rounded-full outline-none transition-colors duration-300 ease-in',
151
+ 'rounded-full outline-none transition-colors duration-100',
148
152
  {
149
- 'cursor-pointer ring-primary-500 hover:bg-neutral-300 focus:bg-neutral-300 focus-visible:ring-2':
150
- !props.disabled,
153
+ 'cursor-pointer hover:bg-neutral-400 focus:bg-neutral-400': !props.disabled,
151
154
  [disabledClasses]: props.disabled
152
155
  },
153
156
  styles.defaultButton,
@@ -157,7 +160,7 @@ function Button({
157
160
  disabled={props.disabled || loading}
158
161
  aria-busy={loading}>
159
162
  <ButtonContent loading={loading}>{children}</ButtonContent>
160
- </button>
163
+ </ButtonDefault>
161
164
  )
162
165
  }
163
166
  }
@@ -1,3 +1,9 @@
1
+ .gradientButton {
2
+ --gradient-btn-hover-background: var(--hc-color-neutral-100);
3
+ --gradient-btn-hover-foreground: var(--hc-color-neutral-1000);
4
+ --gradient-btn-hover-foreground-opacity: 0.07;
5
+ }
6
+
1
7
  .tertiary {
2
8
  &:hover {
3
9
  background-color: hsl(from currentColor h s calc(l - 30));
@@ -17,5 +17,7 @@ export type ValidIconNames =
17
17
  | 'like'
18
18
  | 'paste'
19
19
  | 'send'
20
+ | 'sparkle-tutor-light'
21
+ | 'sparkle-tutor'
20
22
  | 'stop'
21
23
  | 'warning'
@@ -1,3 +1,5 @@
1
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M0.459613 5.98654C0.0677077 5.85591 0.0646103 5.64514 0.467675 5.51078L14.7823 0.739229C15.1787 0.607109 15.406 0.828966 15.2949 1.21768L11.205 15.5324C11.0918 15.9287 10.8633 15.9425 10.6959 15.5657L7.99999 9.49997L12.5 3.50001L6.5 7.99997L0.459613 5.98654Z" fill="currentColor"/>
3
- </svg>
1
+ <svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd"
3
+ d="M13.1236 6.53816L1.66737 0.903633C1.43153 0.787637 1.2011 0.845082 1.02441 1.04583C0.842459 1.25255 0.772227 1.56418 0.928775 1.87216L3.08081 6.10592C3.41727 6.76784 3.41727 7.56083 3.08081 8.22275L0.928776 12.4565C0.772227 12.7645 0.842459 13.0761 1.02441 13.2828C1.2011 13.4836 1.43153 13.541 1.66737 13.425L13.1236 7.7905C13.3469 7.68066 13.4839 7.44778 13.4839 7.16433C13.4839 6.88089 13.3469 6.648 13.1236 6.53816ZM13.4723 5.82916L2.01609 0.194624C0.81102 -0.398066 -0.407713 0.986573 0.224422 2.23019L2.37646 6.46395C2.59855 6.90088 2.59855 7.42779 2.37646 7.86472L0.224423 12.0985C-0.407713 13.3421 0.811018 14.7267 2.01609 14.134L13.4723 8.49951C14.5412 7.9738 14.5412 6.35487 13.4723 5.82916Z"
4
+ fill="currentColor" />
5
+ </svg>
@@ -0,0 +1,15 @@
1
+ <svg viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <circle cx="28" cy="28.05" r="27" stroke="url(#paint0_linear_23639_22377)" stroke-width="2"/>
3
+ <circle cx="28" cy="28.05" r="23" fill="#E6E9ED"/>
4
+ <path d="M12.3207 28.0869C12.2793 28.082 12.2793 28.0181 12.3207 28.0132C26.995 26.2646 27.3639 17.5043 27.9665 12.331C27.9713 12.2901 28.0287 12.2901 28.0335 12.331C28.6361 17.5043 29.005 26.2646 43.6793 28.0132C43.7207 28.0181 43.7207 28.082 43.6793 28.0869C29.005 29.8354 28.6361 38.5958 28.0335 43.7691C28.0287 43.81 27.9713 43.81 27.9665 43.7691C27.3639 38.5958 26.995 29.8354 12.3207 28.0869Z" fill="url(#paint1_linear_23639_22377)"/>
5
+ <defs>
6
+ <linearGradient id="paint0_linear_23639_22377" x1="0" y1="28.05" x2="56" y2="28.05" gradientUnits="userSpaceOnUse">
7
+ <stop stop-color="#44D0FF"/>
8
+ <stop offset="1" stop-color="#B48EFF"/>
9
+ </linearGradient>
10
+ <linearGradient id="paint1_linear_23639_22377" x1="15" y1="11.8769" x2="40.3572" y2="44.2792" gradientUnits="userSpaceOnUse">
11
+ <stop stop-color="#44D0FF"/>
12
+ <stop offset="1" stop-color="#B48EFF"/>
13
+ </linearGradient>
14
+ </defs>
15
+ </svg>
@@ -0,0 +1,19 @@
1
+ <svg viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <circle cx="28" cy="28" r="27" stroke="url(#paint0_linear_23573_147690)" stroke-width="2" />
3
+ <circle cx="28" cy="28" r="23" fill="#282C2F" />
4
+ <path
5
+ d="M12.3207 28.0368C12.2793 28.0319 12.2793 27.9681 12.3207 27.9632C26.995 26.2146 27.3639 17.4543 27.9665 12.2809C27.9713 12.24 28.0287 12.24 28.0335 12.2809C28.6361 17.4543 29.005 26.2146 43.6793 27.9632C43.7207 27.9681 43.7207 28.0319 43.6793 28.0368C29.005 29.7854 28.6361 38.5457 28.0335 43.7191C28.0287 43.76 27.9713 43.76 27.9665 43.7191C27.3639 38.5457 26.995 29.7854 12.3207 28.0368Z"
6
+ fill="url(#paint1_linear_23573_147690)" />
7
+ <defs>
8
+ <linearGradient id="paint0_linear_23573_147690" x1="0" y1="28" x2="56" y2="28"
9
+ gradientUnits="userSpaceOnUse">
10
+ <stop stop-color="#44D0FF" />
11
+ <stop offset="1" stop-color="#B48EFF" />
12
+ </linearGradient>
13
+ <linearGradient id="paint1_linear_23573_147690" x1="15" y1="11.8268" x2="40.3572" y2="44.2291"
14
+ gradientUnits="userSpaceOnUse">
15
+ <stop stop-color="#44D0FF" />
16
+ <stop offset="1" stop-color="#B48EFF" />
17
+ </linearGradient>
18
+ </defs>
19
+ </svg>
@@ -85,15 +85,15 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
85
85
  <Button
86
86
  onClick={onSend}
87
87
  disabled={buttonDisabled || loading}
88
- className={clsx('flex size-8 flex-col items-center justify-center', {
89
- 'text-neutral-700': !buttonDisabled,
90
- 'text-neutral-400': buttonDisabled
88
+ className={clsx('flex flex-col items-center justify-center', styles.send, {
89
+ 'bg-neutral-900 text-neutral-100': !buttonDisabled,
90
+ 'text-neutral-900': buttonDisabled
91
91
  })}
92
92
  loading={loading}
93
93
  aria-label='Submit Button'>
94
94
  <Icon
95
95
  name='send'
96
- className='h-4 w-4 pr-0.5 pt-0.5 text-current transition-colors duration-150'
96
+ className={clsx('ml-0.5 h-4 w-4 p-0.5 text-current transition-colors duration-150')}
97
97
  />
98
98
  </Button>
99
99
  </div>
@@ -1,3 +1,7 @@
1
1
  .textArea {
2
2
  --custom-scrollbar-width: var(--hc-size-spacing-1);
3
3
  }
4
+
5
+ .send {
6
+ --custom-btn-padding: 0.125rem;
7
+ }
@@ -50,33 +50,40 @@ function MessageActions({ message, className, showActions = false }: MessageActi
50
50
  {dayjs(message.timestamp).format('DD/MM [•] LT')}
51
51
  </span>
52
52
  <div
53
- style={{ '--custom-btn-padding': '0.5rem' } as CSSProperties}
54
- className={clsx('flex flex-nowrap gap-2 text-neutral-600', {
53
+ style={{ '--custom-btn-padding': '0.125rem' } as CSSProperties}
54
+ className={clsx('flex flex-nowrap gap-3 text-neutral-600', {
55
55
  hidden: !showActions
56
56
  })}>
57
- <Button onClick={() => handleReaction()} aria-label={t('general.buttons.like')}>
57
+ <Button
58
+ className='hover:!bg-transparent hover:text-info-500 focus:!bg-transparent'
59
+ onClick={() => handleReaction()}
60
+ aria-label={t('general.buttons.like')}>
58
61
  <Icon
59
62
  name='like'
60
- className={clsx('h-3 w-3.5', {
63
+ className={clsx('size-3', {
61
64
  'text-info-500': reaction === ButtonReactions.LIKE
62
65
  })}
63
66
  />
64
67
  </Button>
65
68
  <Button
66
- className='rotate-180 scale-x-[-1]'
69
+ className='rotate-180 scale-x-[-1] hover:!bg-transparent hover:text-danger-500 focus:!bg-transparent'
67
70
  onClick={() => handleReaction(ButtonReactions.DISLIKE)}
68
71
  aria-label={t('general.buttons.dislike')}>
69
72
  <Icon
70
73
  name='like'
71
- className={clsx('h-3 w-3.5', {
74
+ className={clsx('size-3', {
72
75
  'text-danger-500': reaction === ButtonReactions.DISLIKE
73
76
  })}
74
77
  />
75
78
  </Button>
76
- <Button onClick={copyToClipboard} aria-label={t('general.buttons.copy')} disabled={copying}>
79
+ <Button
80
+ className='hover:!bg-transparent hover:text-info-500 focus:!bg-transparent'
81
+ onClick={copyToClipboard}
82
+ aria-label={t('general.buttons.copy')}
83
+ disabled={copying}>
77
84
  <Icon
78
85
  name={copied ? 'paste' : 'copy'}
79
- className={clsx('h-3 w-3.5', {
86
+ className={clsx('size-3', {
80
87
  'text-info-500': copied
81
88
  })}
82
89
  />
@@ -17,7 +17,7 @@ function MessageItem({ message }: { message: ParsedMessage }) {
17
17
  return (
18
18
  <div
19
19
  className={clsx(
20
- 'flex max-w-[min(90%,52rem)] flex-col items-end gap-2 text-sm/normal text-neutral-900',
20
+ 'flex max-w-[min(90%,52rem)] flex-col items-end gap-1 text-sm/normal text-neutral-900',
21
21
  {
22
22
  'self-end': messageFromUser
23
23
  }
@@ -1,20 +1,31 @@
1
1
  import clsx from 'clsx'
2
2
 
3
3
  import { Icon } from '@/src/lib/components'
4
+ import { useWidgetSettingsAtomValue } from '../../store'
4
5
 
5
- import styles from './styles.module.css'
6
-
7
- export type AIAvatarProps = { className?: string }
6
+ export type AIAvatarProps = { className?: string; size?: 'sm' | 'lg' }
8
7
 
9
8
  function AIAvatar({
10
- className = 'rounded-full border-4 border-neutral-100 bg-neutral-200'
9
+ className = 'rounded-full border-4 border-neutral-100 bg-neutral-200',
10
+ size = 'sm'
11
11
  }: AIAvatarProps) {
12
+ const settings = useWidgetSettingsAtomValue()
13
+ const isDarkTheme = settings?.config?.theme === 'dark'
12
14
  return (
13
15
  <figure
14
- className={clsx('flex h-9 w-9 items-center justify-center rounded-full', styles.avatar)}>
15
- <div className={clsx('flex h-8 w-8 items-center justify-center', className)}>
16
- <Icon name='ai-color' className='h-6 w-6' aria-label='AI avatar Icon' />
17
- </div>
16
+ className={clsx(
17
+ 'flex items-center justify-center rounded-full',
18
+ {
19
+ 'bg-neutral-100': isDarkTheme,
20
+ 'bg-white': !isDarkTheme
21
+ },
22
+ className
23
+ )}>
24
+ <Icon
25
+ name={!isDarkTheme ? 'sparkle-tutor-light' : 'sparkle-tutor'}
26
+ className={clsx({ 'h-9 w-9': size === 'sm', 'h-14 w-14': size === 'lg' })}
27
+ aria-label='AI avatar Icon'
28
+ />
18
29
  </figure>
19
30
  )
20
31
  }
@@ -4,7 +4,7 @@ const AVATAR_ANIMATION_URL = `${process.env.STATIC_URL}/tutor/tutor_sparkle.lott
4
4
 
5
5
  const AvatarAnimation = () => {
6
6
  return (
7
- <div className='flex h-11 w-11 items-center justify-center rounded-lg bg-ai-chat-response'>
7
+ <div className='flex h-11 w-11 items-center justify-center rounded-lg bg-neutral-300'>
8
8
  <DotLottieReact src={AVATAR_ANIMATION_URL} loop autoplay className='h-auto w-full' />
9
9
  </div>
10
10
  )
@@ -1,6 +1,8 @@
1
1
  import clsx from 'clsx'
2
2
  import { useTranslation } from 'react-i18next'
3
3
 
4
+ import { AIAvatar } from '../ai-avatar'
5
+
4
6
  export type GreetingsCardProps = {
5
7
  tutorName: string
6
8
  author?: string
@@ -12,6 +14,9 @@ function GreetingsCard({ author, tutorName, isDarkTheme = false }: GreetingsCard
12
14
 
13
15
  return (
14
16
  <div className='flex flex-col items-center justify-center'>
17
+ <div className='max-md:hidden md:mb-4 md:block'>
18
+ <AIAvatar size='lg' />
19
+ </div>
15
20
  <div className='flex flex-col items-center justify-center gap-4 text-center'>
16
21
  <div className='flex flex-col gap-2'>
17
22
  <span
@@ -19,7 +19,7 @@ describe('<WidgetHeader />', () => {
19
19
  it('should render WidgetHeaderContent when prop showContent is true', () => {
20
20
  renderComponent()
21
21
 
22
- expect(screen.getByText(/ai-color/i)).toBeInTheDocument()
22
+ expect(screen.getByText(/sparkle-tutor-light/i)).toBeInTheDocument()
23
23
 
24
24
  expect(screen.queryByRole('button', { name: /Arrow Left Icon/i })).not.toBeInTheDocument()
25
25
  })
@@ -33,7 +33,7 @@ describe('<WidgetHeader />', () => {
33
33
 
34
34
  expect(screen.getByRole('button', { name: /Arrow Left Icon/i })).toBeInTheDocument()
35
35
 
36
- expect(screen.queryByText(/ai-color/i)).not.toBeInTheDocument()
36
+ expect(screen.queryByText(/sparkle-tutor-light/i)).not.toBeInTheDocument()
37
37
  })
38
38
 
39
39
  it('should be able to render the remaining icons', () => {
@@ -43,7 +43,7 @@ export function WidgetHeaderContentWithoutMeta({ name }: { name?: string }) {
43
43
  }
44
44
 
45
45
  function WidgetHeader({
46
- enabledButtons,
46
+ enabledButtons = [],
47
47
  tutorName,
48
48
  showContentWithoutMeta,
49
49
  showContent = true
@@ -73,7 +73,7 @@ function WidgetHeader({
73
73
  </Button>
74
74
  </div>
75
75
  </div>
76
- <div className='grid-areas-[a_b] grid grid-cols-[1fr_auto] items-center'>
76
+ <div className='grid-areas-[a_b] grid grid-cols-[1fr_auto] items-center pb-4'>
77
77
  <div className='grid-area-[a] relative'>
78
78
  {showContent && !showContentWithoutMeta && <WidgetHeaderContent tutorName={name} />}
79
79
  {showContentWithoutMeta && !showContent && <WidgetHeaderContentWithoutMeta name={name} />}
@@ -3,7 +3,7 @@ import type { ValidIconNames } from '@/src/lib/components/icons/icon-names'
3
3
  export type WidgetHeaderContentProps = { tutorName?: string }
4
4
 
5
5
  export type WidgetHeaderProps = {
6
- enabledButtons: ValidIconNames[]
6
+ enabledButtons?: ValidIconNames[]
7
7
  showContent?: boolean
8
8
  showContentWithoutMeta?: boolean
9
9
  } & WidgetHeaderContentProps
@@ -1,3 +1,4 @@
1
+ import { t } from '@/src/config/i18n'
1
2
  import type { ValidIconNames } from '@/src/lib/components/icons/icon-names'
2
3
 
3
4
  type InfoItem = {
@@ -6,10 +7,10 @@ type InfoItem = {
6
7
  descKey: string
7
8
  }
8
9
 
9
- export const infoItems: InfoItem[] = [
10
+ export const infoItems: (config: { tutorName: string }) => InfoItem[] = ({ tutorName }) => [
10
11
  {
11
12
  icon: 'interrogation',
12
- titleKey: 'info.what_it_does_question',
13
+ titleKey: t('info.what_it_does_question', { tutor_name: tutorName }),
13
14
  descKey: 'info.what_it_does_answer'
14
15
  },
15
16
  {
@@ -13,6 +13,7 @@ function WidgetInformationPage() {
13
13
  const { t } = useTranslation()
14
14
  const [settings] = useWidgetSettingsAtom()
15
15
  const isDarkMode = settings?.config?.theme === 'dark'
16
+ const tutorName = settings?.tutorName ?? t('general.name')
16
17
 
17
18
  return (
18
19
  <PageLayout className='flex min-h-0 flex-col text-neutral-900 max-md:p-[1.125rem] md:p-5'>
@@ -27,20 +28,20 @@ function WidgetInformationPage() {
27
28
 
28
29
  <div className='my-8 flex justify-center'>
29
30
  <div className='flex flex-col items-center gap-2'>
30
- <AIAvatar />
31
+ <AIAvatar size='lg' />
31
32
 
32
33
  <h3
33
34
  className={clsx('font-bold', {
34
35
  'text-white': isDarkMode,
35
36
  'text-neutral-700': !isDarkMode
36
37
  })}>
37
- {settings?.tutorName ?? t('general.name')}
38
+ {tutorName}
38
39
  </h3>
39
40
  </div>
40
41
  </div>
41
42
 
42
43
  <div className='flex flex-col gap-5'>
43
- {infoItems.map((item) => (
44
+ {infoItems({ tutorName }).map((item) => (
44
45
  <InformationCard
45
46
  key={item.titleKey}
46
47
  icon={item.icon}
@@ -15,8 +15,8 @@ const ScrollToBottomButton = forwardRef<HTMLButtonElement, IScrollToBottomButton
15
15
  {...props}
16
16
  ref={ref}
17
17
  className={clsx(
18
- 'absolute bottom-4 left-1/2 flex size-7 cursor-pointer flex-col items-center justify-center rounded-full bg-neutral-400 text-sm text-neutral-900 outline-none transition-colors duration-300 ease-in hover:scale-110 hover:bg-neutral-500 focus:outline-none focus:ring-neutral-500 focus:ring-offset-2 focus-visible:ring-2 active:ring-2',
19
- { 'opacity-80': show, 'pointer-events-none opacity-0': !show },
18
+ 'absolute bottom-4 left-1/2 flex size-7 -translate-x-1/2 cursor-pointer flex-col items-center justify-center rounded-full border border-neutral-500 bg-neutral-300 text-sm text-neutral-900 outline-none transition-colors duration-300 ease-in hover:scale-110 hover:bg-neutral-400 focus:outline-none focus:ring-neutral-500 focus:ring-offset-2 focus-visible:ring-2 active:ring-2',
19
+ { 'opacity-90': show, 'pointer-events-none opacity-0': !show },
20
20
  className
21
21
  )}
22
22
  onClick={onClick}
@@ -27,7 +27,7 @@ describe('WidgetStarterPage', () => {
27
27
  expect(
28
28
  screen.getByRole('button', { name: /starter_page.what_does_tutor_do/i })
29
29
  ).toBeInTheDocument()
30
- expect(screen.getByRole('button', { name: /starter_page.wanna_summary/i })).toBeInTheDocument()
30
+ expect(screen.getByRole('button', { name: /starter_page.test_me/i })).toBeInTheDocument()
31
31
  })
32
32
 
33
33
  it('should post the slider button text content to the backend', async () => {
@@ -1,11 +1,9 @@
1
1
  import { useEffect, useMemo, useRef } from 'react'
2
2
  import { useQueryClient } from '@tanstack/react-query'
3
- import clsx from 'clsx'
4
- import type { MouseEventHandler } from 'react'
3
+ import type { CSSProperties, MouseEventHandler } from 'react'
5
4
  import { useTranslation } from 'react-i18next'
6
5
 
7
6
  import { Button, HorizontalDraggableScroll } from '@/src/lib/components'
8
- import type { ValidIconNames } from '@/src/lib/components/icons/icon-names'
9
7
  import { useRefEventListener } from '@/src/lib/hooks'
10
8
  import { ChatInput, useChatInputValueAtom } from '@/src/modules/messages/components'
11
9
  import { getAllMessagesQuery, useSendTextMessage } from '@/src/modules/messages/hooks'
@@ -17,8 +15,6 @@ import { GreetingsCard } from '../greetings-card'
17
15
  import { WidgetHeader } from '../header'
18
16
  import { PageLayout } from '../page-layout'
19
17
 
20
- import styles from './styles.module.css'
21
-
22
18
  function WidgetStarterPage() {
23
19
  const { t } = useTranslation()
24
20
  const [settings] = useWidgetSettingsAtom()
@@ -30,6 +26,7 @@ function WidgetStarterPage() {
30
26
  const limit = useMessagesMaxCount()
31
27
  const queryClient = useQueryClient()
32
28
  const name = settings?.tutorName ?? t('general.name')
29
+ const isDarkTheme = settings?.config?.theme === 'dark'
33
30
  const isSparkieReady = useInitSparkie()
34
31
 
35
32
  useRefEventListener<HTMLTextAreaElement>({
@@ -77,13 +74,15 @@ function WidgetStarterPage() {
77
74
  [conversationId, limit, profileId]
78
75
  )
79
76
 
80
- const headerBtns = useMemo(() => {
81
- const btnList = ['info', 'close']
82
-
83
- if (!isSparkieReady) return btnList
84
-
85
- return btnList.concat(['archive'])
86
- }, [isSparkieReady]) as ValidIconNames[]
77
+ const actionButtonStyle = useMemo(
78
+ () =>
79
+ isDarkTheme
80
+ ? undefined
81
+ : ({
82
+ '--gradient-btn-hover-foreground': '#0d0d0d'
83
+ } as CSSProperties),
84
+ [isDarkTheme]
85
+ )
87
86
 
88
87
  useEffect(() => {
89
88
  if (!conversationId || !profileId) return
@@ -102,24 +101,26 @@ function WidgetStarterPage() {
102
101
  />
103
102
  }>
104
103
  <div className='grid-areas-[a_b] grid h-full grid-cols-1 grid-rows-[1fr_auto]'>
105
- <div
106
- className={clsx('grid-area-[a] flex min-h-0 flex-col max-md:p-[1.125rem] md:p-5', {
107
- [styles.bg]: settings?.config?.theme === 'dark'
108
- })}>
109
- <WidgetHeader enabledButtons={headerBtns} tutorName={name} />
104
+ <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
+ <WidgetHeader
106
+ enabledButtons={isSparkieReady ? ['close', 'archive', 'info'] : ['close', 'info']}
107
+ showContent={false}
108
+ tutorName={name}
109
+ />
110
110
 
111
111
  <div className='my-auto'>
112
112
  <GreetingsCard
113
- author={settings?.user?.name}
113
+ author={settings?.user?.name?.split(' ')?.[0]}
114
114
  tutorName={name}
115
115
  isDarkTheme={settings?.config?.theme === 'dark'}
116
116
  />
117
117
  </div>
118
118
  </div>
119
- <HorizontalDraggableScroll className='grid-area-[b] mx-5 my-6 flex flex-shrink-0 snap-x snap-mandatory gap-2 overflow-x-auto whitespace-nowrap [scrollbar-width:none] [&::-webkit-scrollbar]:hidden'>
119
+ <HorizontalDraggableScroll className='grid-area-[b] my-4 flex flex-shrink-0 snap-x snap-mandatory gap-2 overflow-x-auto whitespace-nowrap [scrollbar-width:none] [&::-webkit-scrollbar]:hidden'>
120
120
  <Button
121
121
  variant='gradient-outline'
122
- className='shrink-0 snap-end text-sm'
122
+ style={actionButtonStyle}
123
+ className='ml-5 shrink-0 text-sm'
123
124
  onClick={handleAskQuestion}
124
125
  loading={!isSparkieReady}>
125
126
  <span>🤖 </span>
@@ -127,11 +128,12 @@ function WidgetStarterPage() {
127
128
  </Button>
128
129
  <Button
129
130
  variant='gradient-outline'
130
- className='shrink-0 snap-end text-sm'
131
+ style={actionButtonStyle}
132
+ className='mr-5 shrink-0 text-sm'
131
133
  onClick={handleAskQuestion}
132
134
  loading={!isSparkieReady}>
133
135
  <span>📝 </span>
134
- {t('starter_page.wanna_summary')}
136
+ {t('starter_page.test_me')}
135
137
  </Button>
136
138
  </HorizontalDraggableScroll>
137
139
  </div>