Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,32 @@
}
}

.feature-notification__image {
@media (max-width: 640px) {
.feature-notification {
left: 12px;
right: 12px;
bottom: 12px;
width: auto;
max-width: 480px;
margin: 0 auto;
padding: 14px;
border-radius: 14px;
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.2), 0 4px 8px rgba(0, 0, 0, 0.12);
}
}

.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 +68,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