Skip to content
2 changes: 1 addition & 1 deletion frontend/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class AppComponent {
public appVersion = version;
userActivity;
userInactive: Subject<any> = new Subject();
currentFeatureNotificationId: string = 'saved-filters';
currentFeatureNotificationId: string = 'edit-schema';
isFeatureNotificationShown: boolean = false;

userLoggedIn = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@
}
}

.feature-notification__image {
.feature-notification__animation {
width: 100%;
border-radius: 8px;
height: auto;
overflow: hidden;
margin-bottom: 16px;
color: #6384ff;
}

.fn-svg {
display: block;
width: 100%;
height: auto;
}

.feature-notification__title {
Expand All @@ -47,3 +54,291 @@
gap: 8px;
margin-top: 16px;
}

/* ──────────────────────────────────────────── */
/* Three-act animation */
/* Cycle: 7s */
/* Act 1 (0–1.5s / 0–21%): empty + Add db */
/* Act 2 (1.5–3.5s / 21–50%): chat + typing */
/* Act 3 (3.5–5.5s / 50–79%): AI + diagram */
/* Hold (5.5–7s / 79–100%): linger & loop */
/* ──────────────────────────────────────────── */

.fn-placeholder,
.fn-add-button,
.fn-pointer-1,
.fn-click-ripple,
.fn-chat-title,
.fn-chat-divider,
.fn-input,
.fn-caret,
.fn-send-button,
.fn-typing-clip,
.fn-user-message,
.fn-ai-avatar,
.fn-table,
.fn-link,
.fn-schema-ready {
opacity: 0;
}

/* === ACT 1 elements === */

.fn-placeholder,
.fn-act--1 > circle,
.fn-act--1 > path,
.fn-act--1 > text {
animation: fn-fade-act1 10s ease-in-out infinite;
}

.fn-add-button {
animation: fn-add-btn 10s ease-in-out infinite;
transform-origin: 180px 93px;
}

.fn-pointer-1 {
animation: fn-pointer-1 10s ease-in-out infinite;
}

.fn-click-ripple {
animation: fn-click-ripple 10s ease-in-out infinite;
}

@keyframes fn-fade-act1 {
0% { opacity: 0; }
3% { opacity: 1; }
19% { opacity: 1; }
22% { opacity: 0; }
100% { opacity: 0; }
}

@keyframes fn-add-btn {
0% { opacity: 0; transform: scale(0.95); }
3% { opacity: 1; transform: scale(1); }
17% { opacity: 1; transform: scale(1); }
18% { opacity: 1; transform: scale(0.93); }
19% { opacity: 1; transform: scale(1); }
22% { opacity: 0; transform: scale(1); }
100% { opacity: 0; }
}

@keyframes fn-pointer-1 {
0%, 3% { opacity: 0; transform: translate(60px, 40px); }
5% { opacity: 1; transform: translate(60px, 40px); }
14% { opacity: 1; transform: translate(178px, 86px); }
17% { opacity: 1; transform: translate(178px, 86px) scale(0.85); }
19% { opacity: 1; transform: translate(178px, 86px) scale(1); }
22% { opacity: 0; transform: translate(178px, 86px); }
100% { opacity: 0; }
}

@keyframes fn-click-ripple {
0%, 17% { opacity: 0; r: 0; }
18% { opacity: 0.85; r: 6; }
21% { opacity: 0; r: 34; }
100% { opacity: 0; r: 0; }
}

/* === ACT 2 elements === */

.fn-chat-divider {
animation: fn-chat-frame 10s ease-in-out infinite;
}

.fn-chat-title--initial {
animation: fn-chat-title-initial 10s ease-in-out infinite;
}

.fn-chat-title--final {
animation: fn-chat-title-final 10s ease-in-out infinite;
}

@keyframes fn-chat-title-initial {
0%, 21% { opacity: 0; }
24% { opacity: 1; }
42% { opacity: 1; }
45% { opacity: 0; }
100% { opacity: 0; }
}

@keyframes fn-chat-title-final {
0%, 42% { opacity: 0; }
45% { opacity: 1; }
93% { opacity: 1; }
100% { opacity: 0; }
}

.fn-input {
animation: fn-input-in 10s ease-in-out infinite;
}

.fn-typing-clip {
animation: fn-typing 10s linear infinite;
}

.fn-caret {
animation: fn-caret-track 10s linear infinite;
}

.fn-send-button {
animation: fn-send-button 10s ease-in-out infinite;
transform-origin: 326px 151px;
}

.fn-user-message {
animation: fn-user-message 10s ease-in-out infinite;
}

@keyframes fn-chat-frame {
0%, 21% { opacity: 0; }
24% { opacity: 1; }
93% { opacity: 1; }
100% { opacity: 0; }
}

@keyframes fn-input-in {
0%, 21% { opacity: 0; transform: translateY(8px); }
24% { opacity: 1; transform: translateY(0); }
48% { opacity: 1; transform: translateY(0); }
50% { opacity: 0; transform: translateY(0); }
100% { opacity: 0; }
}

@keyframes fn-typing {
0%, 25% { width: 0; }
40% { width: 270px; }
48% { width: 270px; }
50% { width: 0; }
100% { width: 0; }
}

@keyframes fn-caret-track {
0%, 25% { opacity: 0; transform: translateX(0); }
27% { opacity: 1; transform: translateX(0); }
40% { opacity: 1; transform: translateX(255px); }
42% { opacity: 0; transform: translateX(255px); }
44% { opacity: 1; transform: translateX(255px); }
46% { opacity: 0; transform: translateX(255px); }
48% { opacity: 1; transform: translateX(255px); }
50% { opacity: 0; transform: translateX(255px); }
100% { opacity: 0; }
}

@keyframes fn-send-button {
0%, 40% { opacity: 0; transform: scale(0.9); }
43% { opacity: 1; transform: scale(0.9); }
44% { opacity: 1; transform: scale(1.15); }
46% { opacity: 1; transform: scale(1); }
47% { opacity: 1; transform: scale(0.9); }
48% { opacity: 1; transform: scale(1); }
50% { opacity: 0; transform: scale(1); }
100% { opacity: 0; }
}

@keyframes fn-user-message {
0%, 47% { opacity: 0; transform: translateY(80px) scale(0.95); }
50% { opacity: 1; transform: translateY(0) scale(1); }
93% { opacity: 1; transform: translateY(0) scale(1); }
100% { opacity: 0; }
}

/* === ACT 3 elements === */

.fn-ai-avatar {
animation: fn-ai-avatar 10s ease-in-out infinite;
transform-origin: 22px 50px;
}

.fn-table--1 { animation: fn-table-1 10s ease-out infinite; transform-origin: 69px 107px; }
.fn-table--2 { animation: fn-table-2 10s ease-out infinite; transform-origin: 181px 91px; }
.fn-table--3 { animation: fn-table-3 10s ease-out infinite; transform-origin: 293px 109px; }

.fn-link {
stroke-dasharray: 50;
stroke-dashoffset: 50;
}

.fn-link--1 { animation: fn-link-1 10s ease-in-out infinite; }
.fn-link--2 { animation: fn-link-2 10s ease-in-out infinite; }

.fn-schema-ready { animation: fn-schema-ready 10s ease-in-out infinite; }

@keyframes fn-ai-avatar {
0%, 53% { opacity: 0; transform: scale(0.7); }
56% { opacity: 1; transform: scale(1.1); }
58% { opacity: 1; transform: scale(1); }
93% { opacity: 1; transform: scale(1); }
100% { opacity: 0; }
}

@keyframes fn-table-1 {
0%, 56% { opacity: 0; transform: translateY(8px) scale(0.92); }
60% { opacity: 1; transform: translateY(0) scale(1); }
93% { opacity: 1; transform: translateY(0) scale(1); }
100% { opacity: 0; }
}

@keyframes fn-table-2 {
0%, 60% { opacity: 0; transform: translateY(8px) scale(0.92); }
64% { opacity: 1; transform: translateY(0) scale(1); }
93% { opacity: 1; transform: translateY(0) scale(1); }
100% { opacity: 0; }
}

@keyframes fn-table-3 {
0%, 64% { opacity: 0; transform: translateY(8px) scale(0.92); }
68% { opacity: 1; transform: translateY(0) scale(1); }
93% { opacity: 1; transform: translateY(0) scale(1); }
100% { opacity: 0; }
}

@keyframes fn-link-1 {
0%, 68% { stroke-dashoffset: 50; opacity: 0; }
70% { opacity: 1; }
74% { stroke-dashoffset: 0; opacity: 1; }
93% { stroke-dashoffset: 0; opacity: 1; }
100% { stroke-dashoffset: 50; opacity: 0; }
}

@keyframes fn-link-2 {
0%, 72% { stroke-dashoffset: 50; opacity: 0; }
74% { opacity: 1; }
78% { stroke-dashoffset: 0; opacity: 1; }
93% { stroke-dashoffset: 0; opacity: 1; }
100% { stroke-dashoffset: 50; opacity: 0; }
}

@keyframes fn-schema-ready {
0%, 76% { opacity: 0; transform: translateY(4px); }
80% { opacity: 1; transform: translateY(0); }
93% { opacity: 1; transform: translateY(0); }
100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
.fn-placeholder,
.fn-add-button,
.fn-pointer-1,
.fn-click-ripple,
.fn-chat-title--final,
.fn-chat-divider,
.fn-input,
.fn-caret,
.fn-send-button,
.fn-user-message,
.fn-ai-avatar,
.fn-table,
.fn-link,
.fn-schema-ready {
animation: none !important;
opacity: 1 !important;
transform: none !important;
stroke-dashoffset: 0 !important;
}
.fn-typing-clip {
animation: none !important;
width: 270px !important;
}
.fn-chat-title--initial { display: none !important; }
.fn-act--1 { display: none !important; }
}
Comment on lines +332 to +358
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reduced-motion shows Act 2 input field overlapping Act 3 content.

With prefers-reduced-motion: reduce, .fn-input is set to opacity: 1 (line 325), but the input field's y-position (136–166) overlaps with the "Schema ready" text (y=162). Since the final frame should show the completed schema state, the input field from the typing phase should be hidden.

🛠️ Proposed fix

Either remove .fn-input from the visible list and add it to the hidden elements, or hide the entire Act 2 group:

 `@media` (prefers-reduced-motion: reduce) {
 	.fn-placeholder,
 	.fn-add-button,
 	.fn-pointer-1,
 	.fn-click-ripple,
 	.fn-chat-title--final,
 	.fn-chat-divider,
-	.fn-input,
-	.fn-caret,
-	.fn-send-button,
-	.fn-user-message,
 	.fn-ai-avatar,
 	.fn-table,
 	.fn-link,
 	.fn-schema-ready {
 		animation: none !important;
 		opacity: 1 !important;
 		transform: none !important;
 		stroke-dashoffset: 0 !important;
 	}
+	.fn-input,
+	.fn-caret,
+	.fn-send-button {
+		display: none !important;
+	}
 	.fn-typing-clip {
 		animation: none !important;
 		width: 180px !important;
 	}
 	.fn-chat-title--initial { display: none !important; }
 	.fn-act--1 { display: none !important; }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/app/components/feature-notification/feature-notification.component.css`
around lines 318 - 344, The reduced-motion rule currently forces .fn-input to be
visible (opacity:1) causing it to overlap the Act 3 content; update the media
query so the Act 2 input is hidden in reduced-motion—either remove .fn-input
from the visible selector list and add it to the hidden selectors (e.g., include
.fn-input with display:none !important or the same hidden set as
.fn-chat-title--initial/.fn-act--1), or hide the whole Act 2 group by adding its
container (e.g., .fn-act--2) to the hidden selectors inside the `@media`
(prefers-reduced-motion: reduce) block so the final schema-ready frame is shown
without the typing input overlapping.

Loading
Loading