Skip to content

Commit 9c031e4

Browse files
Merge pull request #1782 from karinakharchenko/updates-popup-edit-schema
feature-notification: animated Edit Schema with AI popup
2 parents 37fee2f + 8a588ba commit 9c031e4

3 files changed

Lines changed: 428 additions & 9 deletions

File tree

frontend/src/app/app.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class AppComponent {
6262
public appVersion = version;
6363
userActivity;
6464
userInactive: Subject<any> = new Subject();
65-
currentFeatureNotificationId: string = 'saved-filters';
65+
currentFeatureNotificationId: string = 'edit-schema';
6666
isFeatureNotificationShown: boolean = false;
6767

6868
userLoggedIn = null;

frontend/src/app/components/feature-notification/feature-notification.component.css

Lines changed: 311 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,32 @@
1818
}
1919
}
2020

21-
.feature-notification__image {
21+
@media (max-width: 640px) {
22+
.feature-notification {
23+
left: 12px;
24+
right: 12px;
25+
bottom: 12px;
26+
width: auto;
27+
max-width: 480px;
28+
margin: 0 auto;
29+
padding: 14px;
30+
border-radius: 14px;
31+
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.2), 0 4px 8px rgba(0, 0, 0, 0.12);
32+
}
33+
}
34+
35+
.feature-notification__animation {
36+
width: 100%;
2237
border-radius: 8px;
23-
height: auto;
38+
overflow: hidden;
2439
margin-bottom: 16px;
40+
color: #6384ff;
41+
}
42+
43+
.fn-svg {
44+
display: block;
2545
width: 100%;
46+
height: auto;
2647
}
2748

2849
.feature-notification__title {
@@ -47,3 +68,291 @@
4768
gap: 8px;
4869
margin-top: 16px;
4970
}
71+
72+
/* ──────────────────────────────────────────── */
73+
/* Three-act animation */
74+
/* Cycle: 7s */
75+
/* Act 1 (0–1.5s / 0–21%): empty + Add db */
76+
/* Act 2 (1.5–3.5s / 21–50%): chat + typing */
77+
/* Act 3 (3.5–5.5s / 50–79%): AI + diagram */
78+
/* Hold (5.5–7s / 79–100%): linger & loop */
79+
/* ──────────────────────────────────────────── */
80+
81+
.fn-placeholder,
82+
.fn-add-button,
83+
.fn-pointer-1,
84+
.fn-click-ripple,
85+
.fn-chat-title,
86+
.fn-chat-divider,
87+
.fn-input,
88+
.fn-caret,
89+
.fn-send-button,
90+
.fn-typing-clip,
91+
.fn-user-message,
92+
.fn-ai-avatar,
93+
.fn-table,
94+
.fn-link,
95+
.fn-schema-ready {
96+
opacity: 0;
97+
}
98+
99+
/* === ACT 1 elements === */
100+
101+
.fn-placeholder,
102+
.fn-act--1 > circle,
103+
.fn-act--1 > path,
104+
.fn-act--1 > text {
105+
animation: fn-fade-act1 10s ease-in-out infinite;
106+
}
107+
108+
.fn-add-button {
109+
animation: fn-add-btn 10s ease-in-out infinite;
110+
transform-origin: 180px 93px;
111+
}
112+
113+
.fn-pointer-1 {
114+
animation: fn-pointer-1 10s ease-in-out infinite;
115+
}
116+
117+
.fn-click-ripple {
118+
animation: fn-click-ripple 10s ease-in-out infinite;
119+
}
120+
121+
@keyframes fn-fade-act1 {
122+
0% { opacity: 0; }
123+
3% { opacity: 1; }
124+
19% { opacity: 1; }
125+
22% { opacity: 0; }
126+
100% { opacity: 0; }
127+
}
128+
129+
@keyframes fn-add-btn {
130+
0% { opacity: 0; transform: scale(0.95); }
131+
3% { opacity: 1; transform: scale(1); }
132+
17% { opacity: 1; transform: scale(1); }
133+
18% { opacity: 1; transform: scale(0.93); }
134+
19% { opacity: 1; transform: scale(1); }
135+
22% { opacity: 0; transform: scale(1); }
136+
100% { opacity: 0; }
137+
}
138+
139+
@keyframes fn-pointer-1 {
140+
0%, 3% { opacity: 0; transform: translate(60px, 40px); }
141+
5% { opacity: 1; transform: translate(60px, 40px); }
142+
14% { opacity: 1; transform: translate(178px, 86px); }
143+
17% { opacity: 1; transform: translate(178px, 86px) scale(0.85); }
144+
19% { opacity: 1; transform: translate(178px, 86px) scale(1); }
145+
22% { opacity: 0; transform: translate(178px, 86px); }
146+
100% { opacity: 0; }
147+
}
148+
149+
@keyframes fn-click-ripple {
150+
0%, 17% { opacity: 0; r: 0; }
151+
18% { opacity: 0.85; r: 6; }
152+
21% { opacity: 0; r: 34; }
153+
100% { opacity: 0; r: 0; }
154+
}
155+
156+
/* === ACT 2 elements === */
157+
158+
.fn-chat-divider {
159+
animation: fn-chat-frame 10s ease-in-out infinite;
160+
}
161+
162+
.fn-chat-title--initial {
163+
animation: fn-chat-title-initial 10s ease-in-out infinite;
164+
}
165+
166+
.fn-chat-title--final {
167+
animation: fn-chat-title-final 10s ease-in-out infinite;
168+
}
169+
170+
@keyframes fn-chat-title-initial {
171+
0%, 21% { opacity: 0; }
172+
24% { opacity: 1; }
173+
42% { opacity: 1; }
174+
45% { opacity: 0; }
175+
100% { opacity: 0; }
176+
}
177+
178+
@keyframes fn-chat-title-final {
179+
0%, 42% { opacity: 0; }
180+
45% { opacity: 1; }
181+
93% { opacity: 1; }
182+
100% { opacity: 0; }
183+
}
184+
185+
.fn-input {
186+
animation: fn-input-in 10s ease-in-out infinite;
187+
}
188+
189+
.fn-typing-clip {
190+
animation: fn-typing 10s linear infinite;
191+
}
192+
193+
.fn-caret {
194+
animation: fn-caret-track 10s linear infinite;
195+
}
196+
197+
.fn-send-button {
198+
animation: fn-send-button 10s ease-in-out infinite;
199+
transform-origin: 326px 151px;
200+
}
201+
202+
.fn-user-message {
203+
animation: fn-user-message 10s ease-in-out infinite;
204+
}
205+
206+
@keyframes fn-chat-frame {
207+
0%, 21% { opacity: 0; }
208+
24% { opacity: 1; }
209+
93% { opacity: 1; }
210+
100% { opacity: 0; }
211+
}
212+
213+
@keyframes fn-input-in {
214+
0%, 21% { opacity: 0; transform: translateY(8px); }
215+
24% { opacity: 1; transform: translateY(0); }
216+
48% { opacity: 1; transform: translateY(0); }
217+
50% { opacity: 0; transform: translateY(0); }
218+
100% { opacity: 0; }
219+
}
220+
221+
@keyframes fn-typing {
222+
0%, 25% { width: 0; }
223+
40% { width: 270px; }
224+
48% { width: 270px; }
225+
50% { width: 0; }
226+
100% { width: 0; }
227+
}
228+
229+
@keyframes fn-caret-track {
230+
0%, 25% { opacity: 0; transform: translateX(0); }
231+
27% { opacity: 1; transform: translateX(0); }
232+
40% { opacity: 1; transform: translateX(255px); }
233+
42% { opacity: 0; transform: translateX(255px); }
234+
44% { opacity: 1; transform: translateX(255px); }
235+
46% { opacity: 0; transform: translateX(255px); }
236+
48% { opacity: 1; transform: translateX(255px); }
237+
50% { opacity: 0; transform: translateX(255px); }
238+
100% { opacity: 0; }
239+
}
240+
241+
@keyframes fn-send-button {
242+
0%, 40% { opacity: 0; transform: scale(0.9); }
243+
43% { opacity: 1; transform: scale(0.9); }
244+
44% { opacity: 1; transform: scale(1.15); }
245+
46% { opacity: 1; transform: scale(1); }
246+
47% { opacity: 1; transform: scale(0.9); }
247+
48% { opacity: 1; transform: scale(1); }
248+
50% { opacity: 0; transform: scale(1); }
249+
100% { opacity: 0; }
250+
}
251+
252+
@keyframes fn-user-message {
253+
0%, 47% { opacity: 0; transform: translateY(80px) scale(0.95); }
254+
50% { opacity: 1; transform: translateY(0) scale(1); }
255+
93% { opacity: 1; transform: translateY(0) scale(1); }
256+
100% { opacity: 0; }
257+
}
258+
259+
/* === ACT 3 elements === */
260+
261+
.fn-ai-avatar {
262+
animation: fn-ai-avatar 10s ease-in-out infinite;
263+
transform-origin: 22px 50px;
264+
}
265+
266+
.fn-table--1 { animation: fn-table-1 10s ease-out infinite; transform-origin: 69px 107px; }
267+
.fn-table--2 { animation: fn-table-2 10s ease-out infinite; transform-origin: 181px 91px; }
268+
.fn-table--3 { animation: fn-table-3 10s ease-out infinite; transform-origin: 293px 109px; }
269+
270+
.fn-link {
271+
stroke-dasharray: 50;
272+
stroke-dashoffset: 50;
273+
}
274+
275+
.fn-link--1 { animation: fn-link-1 10s ease-in-out infinite; }
276+
.fn-link--2 { animation: fn-link-2 10s ease-in-out infinite; }
277+
278+
.fn-schema-ready { animation: fn-schema-ready 10s ease-in-out infinite; }
279+
280+
@keyframes fn-ai-avatar {
281+
0%, 53% { opacity: 0; transform: scale(0.7); }
282+
56% { opacity: 1; transform: scale(1.1); }
283+
58% { opacity: 1; transform: scale(1); }
284+
93% { opacity: 1; transform: scale(1); }
285+
100% { opacity: 0; }
286+
}
287+
288+
@keyframes fn-table-1 {
289+
0%, 56% { opacity: 0; transform: translateY(8px) scale(0.92); }
290+
60% { opacity: 1; transform: translateY(0) scale(1); }
291+
93% { opacity: 1; transform: translateY(0) scale(1); }
292+
100% { opacity: 0; }
293+
}
294+
295+
@keyframes fn-table-2 {
296+
0%, 60% { opacity: 0; transform: translateY(8px) scale(0.92); }
297+
64% { opacity: 1; transform: translateY(0) scale(1); }
298+
93% { opacity: 1; transform: translateY(0) scale(1); }
299+
100% { opacity: 0; }
300+
}
301+
302+
@keyframes fn-table-3 {
303+
0%, 64% { opacity: 0; transform: translateY(8px) scale(0.92); }
304+
68% { opacity: 1; transform: translateY(0) scale(1); }
305+
93% { opacity: 1; transform: translateY(0) scale(1); }
306+
100% { opacity: 0; }
307+
}
308+
309+
@keyframes fn-link-1 {
310+
0%, 68% { stroke-dashoffset: 50; opacity: 0; }
311+
70% { opacity: 1; }
312+
74% { stroke-dashoffset: 0; opacity: 1; }
313+
93% { stroke-dashoffset: 0; opacity: 1; }
314+
100% { stroke-dashoffset: 50; opacity: 0; }
315+
}
316+
317+
@keyframes fn-link-2 {
318+
0%, 72% { stroke-dashoffset: 50; opacity: 0; }
319+
74% { opacity: 1; }
320+
78% { stroke-dashoffset: 0; opacity: 1; }
321+
93% { stroke-dashoffset: 0; opacity: 1; }
322+
100% { stroke-dashoffset: 50; opacity: 0; }
323+
}
324+
325+
@keyframes fn-schema-ready {
326+
0%, 76% { opacity: 0; transform: translateY(4px); }
327+
80% { opacity: 1; transform: translateY(0); }
328+
93% { opacity: 1; transform: translateY(0); }
329+
100% { opacity: 0; }
330+
}
331+
332+
@media (prefers-reduced-motion: reduce) {
333+
.fn-placeholder,
334+
.fn-add-button,
335+
.fn-pointer-1,
336+
.fn-click-ripple,
337+
.fn-chat-title--final,
338+
.fn-chat-divider,
339+
.fn-input,
340+
.fn-caret,
341+
.fn-send-button,
342+
.fn-user-message,
343+
.fn-ai-avatar,
344+
.fn-table,
345+
.fn-link,
346+
.fn-schema-ready {
347+
animation: none !important;
348+
opacity: 1 !important;
349+
transform: none !important;
350+
stroke-dashoffset: 0 !important;
351+
}
352+
.fn-typing-clip {
353+
animation: none !important;
354+
width: 270px !important;
355+
}
356+
.fn-chat-title--initial { display: none !important; }
357+
.fn-act--1 { display: none !important; }
358+
}

0 commit comments

Comments
 (0)