Qwikode commited on
Commit
5f455e6
·
1 Parent(s): 9792e93

fix(ui): header gradient and textarea border effect

Browse files
app/components/chat/BaseChat.module.scss CHANGED
@@ -17,3 +17,107 @@
17
  .Chat {
18
  opacity: 1;
19
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  .Chat {
18
  opacity: 1;
19
  }
20
+
21
+ .RayContainer {
22
+ --gradient-opacity: 0.85;
23
+ --ray-gradient: radial-gradient(rgba(83, 196, 255, var(--gradient-opacity)) 0%, rgba(43, 166, 255, 0) 100%);
24
+ transition: opacity 0.25s linear;
25
+ position: fixed;
26
+ inset: 0;
27
+ pointer-events: none;
28
+ user-select: none;
29
+ }
30
+
31
+ .LightRayOne {
32
+ width: 480px;
33
+ height: 680px;
34
+ transform: rotate(80deg);
35
+ top: -540px;
36
+ left: 250px;
37
+ filter: blur(110px);
38
+ position: absolute;
39
+ border-radius: 100%;
40
+ background: var(--ray-gradient);
41
+ }
42
+
43
+ .LightRayTwo {
44
+ width: 110px;
45
+ height: 400px;
46
+ transform: rotate(-20deg);
47
+ top: -280px;
48
+ left: 350px;
49
+ mix-blend-mode: overlay;
50
+ opacity: 0.6;
51
+ filter: blur(60px);
52
+ position: absolute;
53
+ border-radius: 100%;
54
+ background: var(--ray-gradient);
55
+ }
56
+
57
+ .LightRayThree {
58
+ width: 400px;
59
+ height: 370px;
60
+ top: -350px;
61
+ left: 200px;
62
+ mix-blend-mode: overlay;
63
+ opacity: 0.6;
64
+ filter: blur(21px);
65
+ position: absolute;
66
+ border-radius: 100%;
67
+ background: var(--ray-gradient);
68
+ }
69
+
70
+ .LightRayFour {
71
+ position: absolute;
72
+ width: 330px;
73
+ height: 370px;
74
+ top: -330px;
75
+ left: 50px;
76
+ mix-blend-mode: overlay;
77
+ opacity: 0.5;
78
+ filter: blur(21px);
79
+ border-radius: 100%;
80
+ background: var(--ray-gradient);
81
+ }
82
+
83
+ .LightRayFive {
84
+ position: absolute;
85
+ width: 110px;
86
+ height: 400px;
87
+ transform: rotate(-40deg);
88
+ top: -280px;
89
+ left: -10px;
90
+ mix-blend-mode: overlay;
91
+ opacity: 0.8;
92
+ filter: blur(60px);
93
+ border-radius: 100%;
94
+ background: var(--ray-gradient);
95
+ }
96
+
97
+ .PromptEffectContainer {
98
+ --prompt-container-offset: 50px;
99
+ --prompt-line-stroke-width: 1px;
100
+ position: absolute;
101
+ pointer-events: none;
102
+ inset: calc(var(--prompt-container-offset) / -2);
103
+ width: calc(100% + var(--prompt-container-offset));
104
+ height: calc(100% + var(--prompt-container-offset));
105
+ }
106
+
107
+ .PromptEffectLine {
108
+ width: calc(100% - var(--prompt-container-offset) + var(--prompt-line-stroke-width));
109
+ height: calc(100% - var(--prompt-container-offset) + var(--prompt-line-stroke-width));
110
+ x: calc(var(--prompt-container-offset) / 2 - var(--prompt-line-stroke-width) / 2);
111
+ y: calc(var(--prompt-container-offset) / 2 - var(--prompt-line-stroke-width) / 2);
112
+ rx: calc(8px - var(--prompt-line-stroke-width));
113
+ fill: transparent;
114
+ stroke-width: var(--prompt-line-stroke-width);
115
+ stroke: url(#line-gradient);
116
+ stroke-dasharray: 35px 65px;
117
+ stroke-dashoffset: 10;
118
+ }
119
+
120
+ .PromptShine {
121
+ fill: url(#shine-gradient);
122
+ mix-blend-mode: overlay;
123
+ }
app/components/chat/BaseChat.tsx CHANGED
@@ -160,6 +160,13 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
160
  )}
161
  data-chat-visible={showChat}
162
  >
 
 
 
 
 
 
 
163
  <ClientOnly>{() => <Menu />}</ClientOnly>
164
  <div ref={scrollRef} className="flex flex-col lg:flex-row overflow-y-auto w-full h-full">
165
  <div className={classNames(styles.Chat, 'flex flex-col flex-grow lg:min-w-[var(--chat-min-width)] h-full')}>
@@ -192,12 +199,38 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
192
  </ClientOnly>
193
  <div
194
  className={classNames(
195
- ' bg-bolt-elements-background-depth-2 p-3 rounded-lg border border-bolt-elements-borderColor relative w-full max-w-chat mx-auto z-prompt mb-6',
196
  {
197
  'sticky bottom-2': chatStarted,
198
  },
199
  )}
200
  >
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  <ModelSelector
202
  key={provider?.name + ':' + modelList.length}
203
  model={model}
@@ -219,12 +252,12 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
219
 
220
  <div
221
  className={classNames(
222
- 'shadow-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background backdrop-filter backdrop-blur-[8px] rounded-lg overflow-hidden transition-all',
223
  )}
224
  >
225
  <textarea
226
  ref={textareaRef}
227
- className={`w-full pl-4 pt-4 pr-16 focus:outline-none focus:ring-0 focus:border-none focus:shadow-none resize-none text-md text-bolt-elements-textPrimary placeholder-bolt-elements-textTertiary bg-transparent transition-all`}
228
  onKeyDown={(event) => {
229
  if (event.key === 'Enter') {
230
  if (event.shiftKey) {
@@ -300,8 +333,16 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
300
  </div>
301
  </div>
302
  {!chatStarted && (
303
- <div id="examples" className="relative w-full max-w-xl mx-auto mt-8 flex justify-center">
304
- <div className="flex flex-col space-y-2 [mask-image:linear-gradient(to_bottom,black_0%,transparent_180%)] hover:[mask-image:none]">
 
 
 
 
 
 
 
 
305
  {EXAMPLE_PROMPTS.map((examplePrompt, index) => {
306
  return (
307
  <button
@@ -309,10 +350,10 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
309
  onClick={(event) => {
310
  sendMessage?.(event, examplePrompt.text);
311
  }}
312
- className="group flex items-center w-full gap-2 justify-center bg-transparent text-bolt-elements-textTertiary hover:text-bolt-elements-textPrimary transition-theme"
313
  >
314
  {examplePrompt.text}
315
- <div className="i-ph:arrow-bend-down-left" />
316
  </button>
317
  );
318
  })}
 
160
  )}
161
  data-chat-visible={showChat}
162
  >
163
+ <div className={classNames(styles.RayContainer)}>
164
+ <div className={classNames(styles.LightRayOne)}></div>
165
+ <div className={classNames(styles.LightRayTwo)}></div>
166
+ <div className={classNames(styles.LightRayThree)}></div>
167
+ <div className={classNames(styles.LightRayFour)}></div>
168
+ <div className={classNames(styles.LightRayFive)}></div>
169
+ </div>
170
  <ClientOnly>{() => <Menu />}</ClientOnly>
171
  <div ref={scrollRef} className="flex flex-col lg:flex-row overflow-y-auto w-full h-full">
172
  <div className={classNames(styles.Chat, 'flex flex-col flex-grow lg:min-w-[var(--chat-min-width)] h-full')}>
 
199
  </ClientOnly>
200
  <div
201
  className={classNames(
202
+ 'bg-bolt-elements-background-depth-2 p-3 rounded-lg border border-bolt-elements-borderColor relative w-full max-w-chat mx-auto z-prompt mb-6',
203
  {
204
  'sticky bottom-2': chatStarted,
205
  },
206
  )}
207
  >
208
+ <svg className={classNames(styles.PromptEffectContainer)}>
209
+ <defs>
210
+ <linearGradient
211
+ id="line-gradient"
212
+ x1="20%"
213
+ y1="0%"
214
+ x2="-14%"
215
+ y2="10%"
216
+ gradientUnits="userSpaceOnUse"
217
+ gradientTransform="rotate(-45)"
218
+ >
219
+ <stop offset="0%" stop-color="#1488fc" stop-opacity="0%"></stop>
220
+ <stop offset="40%" stop-color="#1488fc" stop-opacity="80%"></stop>
221
+ <stop offset="50%" stop-color="#1488fc" stop-opacity="80%"></stop>
222
+ <stop offset="100%" stop-color="#1488fc" stop-opacity="0%"></stop>
223
+ </linearGradient>
224
+ <linearGradient id="shine-gradient">
225
+ <stop offset="0%" stop-color="white" stop-opacity="0%"></stop>
226
+ <stop offset="40%" stop-color="#8adaff" stop-opacity="80%"></stop>
227
+ <stop offset="50%" stop-color="#8adaff" stop-opacity="80%"></stop>
228
+ <stop offset="100%" stop-color="white" stop-opacity="0%"></stop>
229
+ </linearGradient>
230
+ </defs>
231
+ <rect className={classNames(styles.PromptEffectLine)} pathLength="100" stroke-linecap="round"></rect>
232
+ <rect className={classNames(styles.PromptShine)} x="48" y="24" width="70" height="1"></rect>
233
+ </svg>
234
  <ModelSelector
235
  key={provider?.name + ':' + modelList.length}
236
  model={model}
 
252
 
253
  <div
254
  className={classNames(
255
+ 'relative shadow-xs border border-bolt-elements-borderColor backdrop-blur rounded-lg',
256
  )}
257
  >
258
  <textarea
259
  ref={textareaRef}
260
+ className={`w-full pl-4 pt-4 pr-16 focus:outline-none resize-none text-bolt-elements-textPrimary placeholder-bolt-elements-textTertiary bg-transparent text-sm`}
261
  onKeyDown={(event) => {
262
  if (event.key === 'Enter') {
263
  if (event.shiftKey) {
 
333
  </div>
334
  </div>
335
  {!chatStarted && (
336
+ <div
337
+ id="examples"
338
+ className="relative flex flex-col gap-9 w-full max-w-3xl mx-auto flex justify-center mt-6"
339
+ >
340
+ <div
341
+ className="flex flex-wrap justify-center gap-2"
342
+ style={{
343
+ animation: '.25s ease-out 0s 1 _fade-and-move-in_g2ptj_1 forwards',
344
+ }}
345
+ >
346
  {EXAMPLE_PROMPTS.map((examplePrompt, index) => {
347
  return (
348
  <button
 
350
  onClick={(event) => {
351
  sendMessage?.(event, examplePrompt.text);
352
  }}
353
+ className="border border-bolt-elements-borderColor rounded-full bg-gray-50 hover:bg-gray-100 dark:bg-gray-950 dark:hover:bg-gray-900 text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary px-3 py-1 text-xs transition-theme"
354
  >
355
  {examplePrompt.text}
356
+ {/* <div className="i-ph:arrow-bend-down-left" /> */}
357
  </button>
358
  );
359
  })}
app/components/header/HeaderActionButtons.client.tsx CHANGED
@@ -19,7 +19,7 @@ export function HeaderActionButtons({}: HeaderActionButtonsProps) {
19
  <div className="flex border border-bolt-elements-borderColor rounded-md overflow-hidden">
20
  <Button
21
  active={showChat}
22
- disabled={!canHideChat || isSmallViewport} // expand button is disabled on mobile as it's needed
23
  onClick={() => {
24
  if (canHideChat) {
25
  chatStore.setKey('showChat', !showChat);
 
19
  <div className="flex border border-bolt-elements-borderColor rounded-md overflow-hidden">
20
  <Button
21
  active={showChat}
22
+ disabled={!canHideChat || isSmallViewport} // expand button is disabled on mobile as it's not needed
23
  onClick={() => {
24
  if (canHideChat) {
25
  chatStore.setKey('showChat', !showChat);