@netlify/spark-ui 1.5.0-alpha.13 → 1.5.0-alpha.2

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 (48) hide show
  1. package/dist/assets/AskNetlify.css +1 -1
  2. package/dist/assets/SearchHeading.css +1 -1
  3. package/dist/assets/SearchLink.css +1 -1
  4. package/dist/assets/SearchModal.css +1 -1
  5. package/dist/components/preact/AskNetlify/AskNetlify.d.ts +1 -6
  6. package/dist/components/preact/AskNetlify/AskNetlify.js +2057 -2166
  7. package/dist/components/preact/Icon/index.d.ts +2 -2
  8. package/dist/components/preact/Icon/index.js +72 -108
  9. package/dist/components/preact/SearchModal/components/SearchModal/SearchModal.js +50 -43
  10. package/dist/components/preact/SearchModal/components/SearchWindow.js +19 -21
  11. package/dist/components/preact/SearchModal/hooks/useSearchToggles.d.ts +1 -3
  12. package/dist/components/preact/SearchModal/hooks/useSearchToggles.js +10 -13
  13. package/package.json +2 -3
  14. package/packages/components/preact/AskNetlify/AskNetlify.css +109 -166
  15. package/packages/components/preact/AskNetlify/AskNetlify.tsx +21 -27
  16. package/packages/components/preact/Icon/index.tsx +53 -72
  17. package/packages/components/preact/SearchModal/components/SearchHeading/SearchHeading.css +4 -5
  18. package/packages/components/preact/SearchModal/components/SearchLink/SearchLink.css +9 -9
  19. package/packages/components/preact/SearchModal/components/SearchModal/SearchModal.css +28 -10
  20. package/packages/components/preact/SearchModal/components/SearchModal/SearchModal.tsx +12 -4
  21. package/packages/components/preact/SearchModal/components/SearchWindow.tsx +5 -8
  22. package/packages/components/preact/SearchModal/hooks/useSearchToggles.ts +3 -11
  23. package/packages/styles/tokens.css +0 -4
  24. package/packages/utils/theme.ts +0 -4
  25. package/dist/components/preact/SpriteIcon/index.d.ts +0 -7
  26. package/dist/components/preact/SpriteIcon/index.js +0 -7
  27. package/dist/components/preact/icons/AskNetlify.d.ts +0 -5
  28. package/dist/components/preact/icons/AskNetlify.js +0 -69
  29. package/dist/components/preact/icons/Book.d.ts +0 -5
  30. package/dist/components/preact/icons/Book.js +0 -23
  31. package/dist/components/preact/icons/CircleQuestion.d.ts +0 -5
  32. package/dist/components/preact/icons/CircleQuestion.js +0 -25
  33. package/dist/components/preact/icons/Comment.d.ts +0 -5
  34. package/dist/components/preact/icons/Comment.js +0 -23
  35. package/dist/components/preact/icons/Lightbulb.d.ts +0 -5
  36. package/dist/components/preact/icons/Lightbulb.js +0 -34
  37. package/dist/components/preact/icons/MagnifyingGlass.d.ts +0 -5
  38. package/dist/components/preact/icons/MagnifyingGlass.js +0 -23
  39. package/packages/assets/icons/AskNetlify.svg +0 -23
  40. package/packages/assets/icons/icons.svg +0 -10
  41. package/packages/assets/icons/lightbulb.svg +0 -4
  42. package/packages/components/preact/SpriteIcon/index.tsx +0 -13
  43. package/packages/components/preact/icons/AskNetlify.tsx +0 -46
  44. package/packages/components/preact/icons/Book.tsx +0 -20
  45. package/packages/components/preact/icons/CircleQuestion.tsx +0 -22
  46. package/packages/components/preact/icons/Comment.tsx +0 -20
  47. package/packages/components/preact/icons/Lightbulb.tsx +0 -26
  48. package/packages/components/preact/icons/MagnifyingGlass.tsx +0 -20
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@netlify/spark-ui",
3
3
  "description": "Assets, design tokens, components, and utilities",
4
- "version": "1.5.0-alpha.13",
4
+ "version": "1.5.0-alpha.2",
5
5
  "type": "module",
6
6
  "main": "dist/components/preact/index.js",
7
7
  "types": "dist/components/preact/index.d.ts",
@@ -25,7 +25,6 @@
25
25
  "exports": {
26
26
  "./preact": "./dist/components/preact/index.js",
27
27
  "./assets/*.css": "./dist/assets/*.css",
28
- "./assets/icons/*.svg": "./packages/assets/icons/*.svg",
29
28
  "./logos/*.svg": "./packages/assets/logos/*.svg",
30
29
  "./styles/*.css": "./packages/styles/*.css",
31
30
  "./components": "./packages/components/index.ts",
@@ -34,7 +33,7 @@
34
33
  "./analytics": "./packages/analytics/index.ts"
35
34
  },
36
35
  "dependencies": {
37
- "@kapaai/react-sdk": "^0.1.3",
36
+ "@kapaai/react-sdk": "^0.1.2",
38
37
  "@preact/preset-vite": "^2.10.1",
39
38
  "@shikijs/transformers": "^3.3.0",
40
39
  "glob": "^11.0.1",
@@ -1,52 +1,35 @@
1
- /* ----------------------------- */
2
- /* Layout Containers */
3
- /* ----------------------------- */
4
1
  .chat-container {
5
2
  opacity: 0;
6
3
  animation: appearContainer 120ms ease-in-out forwards;
7
4
  animation-delay: 140ms;
8
5
  }
9
6
 
7
+ @keyframes appearContainer {
8
+ 0% {
9
+ opacity: 0;
10
+ }
11
+ 100% {
12
+ opacity: 1;
13
+ }
14
+ }
15
+
10
16
  .conversation {
11
- display: grid;
12
- align-items: flex-end;
13
17
  height: calc(var(--n-search-container-height) + var(--n-search-footer-height));
14
18
  padding: var(--n-search-padding-inline);
15
- overflow-y: auto;
16
19
  scroll-behavior: smooth;
20
+ overflow-y: auto;
21
+ display: grid;
22
+ align-items: flex-end;
17
23
  gap: var(--space-s);
18
24
  }
19
25
 
20
- .form-wrapper {
21
- display: flex;
22
- align-items: center;
23
- position: relative;
24
- height: var(--n-search-input-height);
25
- }
26
-
27
- .form-wrapper::after {
28
- content: '';
29
- display: block;
30
- position: absolute;
31
- top: 0;
32
- left: 0;
33
- width: 100%;
34
- height: 1px;
35
- background: var(--color-bg-3);
36
- }
37
-
38
- /* ----------------------------- */
39
- /* Conversation and Message UI */
40
- /* ----------------------------- */
41
26
  .question {
42
27
  border: none;
43
- border-radius: var(--radius-pill);
44
- transform: translateX(-0.75rem);
45
28
  color: var(--color-text-1);
46
- font-size: var(--step--1);
47
29
  font-weight: var(--font-weight-regular);
48
- text-align: left;
49
- text-wrap: pretty;
30
+ font-size: var(--step--1);
31
+ border-radius: var(--radius-pill);
32
+ transform: translateX(-0.75rem);
50
33
  }
51
34
 
52
35
  .question-list li {
@@ -58,37 +41,99 @@
58
41
  .question-list li:nth-child(1) {
59
42
  animation-delay: 0.5s;
60
43
  }
44
+
61
45
  .question-list li:nth-child(2) {
62
46
  animation-delay: 0.3s;
63
47
  }
48
+
64
49
  .question-list li:nth-child(3) {
65
50
  animation-delay: 0.1s;
66
51
  }
67
52
 
53
+ @keyframes fadeInUp {
54
+ to {
55
+ opacity: 1;
56
+ transform: translateY(0);
57
+ }
58
+ }
59
+
68
60
  .message {
69
61
  display: grid;
70
- grid-template-columns: minmax(0, 1fr);
71
62
  gap: var(--space-s);
72
- margin-block-start: var(--space-2xl);
73
63
  }
74
64
 
75
65
  .message-bubble {
76
- width: fit-content;
77
- max-width: 85%;
78
66
  padding: var(--space-xs) var(--space-s);
79
67
  background: var(--search-answer-message-color);
80
68
  border-radius: var(--radius-l);
69
+ width: fit-content;
70
+ max-width: 85%;
81
71
  font-size: var(--step-0);
82
72
  }
83
73
 
74
+ .prose {
75
+ font-size: var(--step--0);
76
+
77
+ > * + * {
78
+ margin-top: var(--flow-space, var(--space-xs));
79
+ }
80
+
81
+ h1,
82
+ h2,
83
+ h3 {
84
+ font-size: var(--step-1);
85
+ }
86
+
87
+ h4,
88
+ h5,
89
+ h6 {
90
+ font-size: var(--step-0);
91
+ }
92
+
93
+ pre {
94
+ background: var(--neutral-light-700);
95
+ border-radius: var(--radius-m);
96
+ max-width: 100%;
97
+ box-sizing: border-box;
98
+ padding: var(--space-s);
99
+ color: var(--color-text-inverse);
100
+ overflow-x: auto;
101
+ }
102
+
103
+ code {
104
+ overflow-x: auto;
105
+ }
106
+
107
+ code[class*='language-'],
108
+ pre[class*='language-'] {
109
+ display: block;
110
+ font-size: var(--font-size-text-xs);
111
+ }
112
+ }
113
+
84
114
  .user-message {
85
115
  margin-inline-start: auto;
86
116
  background: var(--search-user-message-color);
87
117
  }
88
118
 
89
- /* ----------------------------- */
90
- /* Form UI */
91
- /* ----------------------------- */
119
+ .form-wrapper {
120
+ display: flex;
121
+ align-items: center;
122
+ position: relative;
123
+ height: var(--n-search-input-height);
124
+ }
125
+
126
+ .form-wrapper::after {
127
+ content: '';
128
+ display: block;
129
+ width: 100%;
130
+ height: 1px;
131
+ background: var(--color-bg-3);
132
+ position: absolute;
133
+ top: 0;
134
+ left: 0;
135
+ }
136
+
92
137
  .form-input {
93
138
  border: none;
94
139
  outline: none;
@@ -96,11 +141,12 @@
96
141
  }
97
142
 
98
143
  .form-submit {
144
+ border: none;
99
145
  padding: 0.7rem;
146
+ border-radius: var(--radius-pill);
100
147
  margin-inline-end: var(--space-2xs);
101
148
  border: none;
102
- border-radius: var(--radius-pill);
103
- background: var(--color-link-1);
149
+ background: var(--color-link);
104
150
  color: var(--neutral-000);
105
151
  transition: background-color 150ms ease-out;
106
152
  }
@@ -115,148 +161,45 @@
115
161
 
116
162
  .form-submit[disabled] {
117
163
  background: var(--neutral-500);
118
- }
119
164
 
120
- .form-submit[disabled] > * {
121
- opacity: 0.5;
165
+ & > * {
166
+ opacity: 0.5;
167
+ }
122
168
  }
123
169
 
124
- /* ----------------------------- */
125
- /* Buttons */
126
- /* ----------------------------- */
127
170
  .button-back {
171
+ width: fit-content;
172
+ background: transparent;
128
173
  position: absolute;
129
174
  z-index: 1;
130
- width: fit-content;
131
- margin: 1rem;
132
175
  padding: 0.5rem 1rem;
133
176
  background: var(--search-back-btn-bg-color);
134
- border: 0.5px solid var(--color-bg-3);
177
+ margin: 1rem;
178
+ border: 2px solid var(--color-bg-3);
135
179
  border-radius: var(--radius-pill);
136
180
  font-size: var(--step--1);
137
- color: var(--color-text-1);
181
+ border: 1px solid;
138
182
  cursor: pointer;
183
+ border-color: var(--color-bg-3);
184
+ color: var(--color-text-1);
185
+ border-width: 0.5px;
139
186
  }
140
187
 
141
- /* ----------------------------- */
142
- /* Typography & Prose */
143
- /* ----------------------------- */
144
- .prose {
145
- font-size: var(--step--0);
146
- }
147
-
148
- .prose > * + * {
149
- margin-top: var(--flow-space, var(--space-s));
150
- }
151
-
152
- .prose :where(ol, ul, li) > * + * {
153
- margin-top: var(--flow-space, var(--space-3xs));
154
- }
155
-
156
- .prose h1,
157
- .prose h2,
158
- .prose h3 {
159
- font-size: var(--step-1);
160
- }
161
-
162
- .prose h4,
163
- .prose h5,
164
- .prose h6 {
165
- font-size: var(--step-0);
166
- }
167
-
168
- .prose pre {
169
- max-width: 100%;
170
- padding: var(--space-s);
171
- background: var(--neutral-light-700);
172
- border-radius: var(--radius-m);
173
- box-sizing: border-box;
174
- color: var(--neutral-100);
175
- overflow-x: auto;
176
- }
177
-
178
- .prose code {
179
- overflow-x: auto;
180
- }
181
-
182
- .prose code[class*='language-'],
183
- .prose pre[class*='language-'] {
184
- display: block;
185
- font-size: var(--font-size-text-xs);
186
- }
187
-
188
- /* ----------------------------- */
189
- /* Loaders and SVG Effects */
190
- /* ----------------------------- */
191
- .message-loader {
192
- width: 2.5rem;
193
- height: auto;
188
+ .pulsing {
194
189
  display: block;
195
- color: var(--search-loading-color);
196
- }
197
-
198
- .message-loader :where(#ask-netlify-tick-1, #ask-netlify-tick-2, #ask-netlify-tick-3) {
199
- opacity: 0;
200
- animation: fadeIn 800ms ease-in-out infinite;
201
- }
202
-
203
- .message-loader #ask-netlify-tick-1 {
204
- animation-delay: 100ms;
205
- }
206
-
207
- .message-loader #ask-netlify-tick-2 {
208
- animation-delay: 200ms;
209
- }
210
-
211
- .message-loader #ask-netlify-tick-3 {
212
- animation-delay: 300ms;
213
- }
214
-
215
- .message-loader :where(#ask-netlify-eyelid-left, #ask-netlify-eyelid-right) {
216
- transform-origin: top center;
217
- transform: scaleY(1);
218
- animation: askEyeBlink 4s infinite;
219
- animation-delay: 1s;
220
- }
221
-
222
- /* ----------------------------- */
223
- /* Animations and Keyframes */
224
- /* ----------------------------- */
225
- @keyframes fadeIn {
226
- 0% {
227
- opacity: 0;
228
- }
229
- 100% {
230
- opacity: 1;
231
- }
232
- }
233
-
234
- @keyframes fadeInUp {
235
- to {
236
- opacity: 1;
237
- transform: translateY(0);
238
- }
190
+ width: 1rem;
191
+ height: 1rem;
192
+ clip-path: circle(40%);
193
+ background: var(--search-loading-color);
194
+ animation: pulsing 2.5s infinite ease-in-out;
239
195
  }
240
196
 
241
- @keyframes askEyeBlink {
197
+ @keyframes pulsing {
242
198
  0%,
243
- 5% {
244
- transform: scaleY(1);
245
- }
246
- 6%,
247
- 10% {
248
- transform: scaleY(1.3);
249
- }
250
- 11%,
251
- 15% {
252
- transform: scaleY(1);
253
- }
254
- 16%,
255
- 20% {
256
- transform: scaleY(1.3);
257
- }
258
- 21%,
259
199
  100% {
260
- transform: scaleY(1);
200
+ transform: scale(0.9);
201
+ }
202
+ 50% {
203
+ transform: scale(1.05);
261
204
  }
262
205
  }
@@ -1,15 +1,10 @@
1
1
  import { useState, useRef, useEffect } from 'preact/hooks';
2
2
  import { marked } from 'marked';
3
3
  import { KapaProvider, useChat } from '@kapaai/react-sdk';
4
- import Icon from '../Icon';
5
4
 
6
5
  import './AskNetlify.css';
7
6
 
8
- interface AskNetlifyProps {
9
- setModalState?: (state?: { current: string }) => void;
10
- }
11
-
12
- function AskNetlify(props: AskNetlifyProps) {
7
+ function AskNetlify(props) {
13
8
  return (
14
9
  <KapaProvider
15
10
  integrationId="3c0789a6-c6a8-4fbc-b0cc-235f9e4a6351"
@@ -24,36 +19,34 @@ function AskNetlify(props: AskNetlifyProps) {
24
19
  );
25
20
  }
26
21
 
27
- function ChatInterface({ setModalState }: AskNetlifyProps) {
22
+ function ChatInterface({ setModalState }) {
28
23
  const [message, setMessage] = useState('');
29
24
  const { conversation, submitQuery, isGeneratingAnswer, isPreparingAnswer, stopGeneration } =
30
25
  useChat();
31
26
 
32
27
  const chatRef = useRef(null);
33
28
 
34
- const questions: Record<string, string> = {
35
- 'a69747ed-505b-4e98-8535-fd357c327516': 'How do I deploy an app to Netlify using AI?',
36
- 'e477f4dd-7159-4c31-8a18-4dfc7e84d927': 'How does Netlify simplify my CI/CD pipeline?',
37
- '39229ddb-9000-4e83-bbf8-54f1c1e55ed4':
38
- 'How does Netlify help improve my site’s Core Web Vitals?',
39
- '5c41b3c2-4c90-4cf7-9f24-f0d0b8f0f759':
40
- 'What are the benefits of using Netlify with a headless CMS?',
41
- '0270de6c-387e-401f-b24c-6ae1166db477':
42
- 'What are the benefits of hosting on Netlify’s edge network?',
29
+ const QandAMap = {
30
+ '487cda5f-e852-4223-85dd-d18ab58dc7a9': "Why can't I add my domain to Netlify DNS?",
31
+ 'd133a822-dbe1-4870-8a94-212c5841f194': 'Why is my website not loading?',
32
+ 'e477f4dd-7159-4c31-8a18-4dfc7e84d927': 'How do I set up environment variables?',
43
33
  };
44
34
 
45
- const handleSubmit = (e: Event) => {
35
+ const handleSubmit = e => {
46
36
  e.preventDefault();
47
37
 
48
- const input = e.target as HTMLInputElement;
49
- const questionId = input?.getAttribute('data-id');
50
- const question = questionId ? questions[questionId] : message;
38
+ const id = e.target.getAttribute('data-id');
51
39
 
52
- if (question.trim()) {
53
- submitQuery(question.trim());
40
+ if (id) {
41
+ const question = QandAMap[id];
42
+ if (question.trim()) {
43
+ submitQuery(question.trim());
44
+ }
45
+ setMessage('');
54
46
  }
55
47
 
56
48
  if (message.trim()) {
49
+ submitQuery(message.trim());
57
50
  setMessage('');
58
51
  }
59
52
  };
@@ -68,7 +61,7 @@ function ChatInterface({ setModalState }: AskNetlifyProps) {
68
61
  <button
69
62
  class="button button-back"
70
63
  data-button-variant="outline"
71
- onClick={() => setModalState && setModalState({ current: 'search' })}
64
+ onClick={() => setModalState({ current: 'search' })}
72
65
  aria-label={'Return to search'}
73
66
  >
74
67
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
@@ -82,7 +75,7 @@ function ChatInterface({ setModalState }: AskNetlifyProps) {
82
75
  <div ref={chatRef} className="conversation n-search-window">
83
76
  {!conversation.length && (
84
77
  <ul class="question-list" role="list">
85
- {Object.entries(questions).map(([id, question]) => (
78
+ {Object.entries(QandAMap).map(([id, question]) => (
86
79
  <li>
87
80
  <button class="question" onClick={handleSubmit} data-id={id}>
88
81
  {question}
@@ -111,9 +104,7 @@ function ChatInterface({ setModalState }: AskNetlifyProps) {
111
104
  />
112
105
  </div>
113
106
  ) : (
114
- <div class="message-loader">
115
- <Icon name="askNetlify" />
116
- </div>
107
+ <span class="pulsing"></span>
117
108
  )}
118
109
  </div>
119
110
  </div>
@@ -129,6 +120,9 @@ function ChatInterface({ setModalState }: AskNetlifyProps) {
129
120
  placeholder="Ask a question..."
130
121
  disabled={isGeneratingAnswer}
131
122
  />
123
+ {/* <button type="submit" className="form-submit" disabled={isGeneratingAnswer}>
124
+ Send
125
+ </button> */}
132
126
 
133
127
  {isGeneratingAnswer ? (
134
128
  <button