diff --git a/frontend/src/app/animations/toggle.animation.ts b/frontend/src/app/animations/toggle.animation.ts new file mode 100644 index 00000000..e2925db9 --- /dev/null +++ b/frontend/src/app/animations/toggle.animation.ts @@ -0,0 +1,38 @@ +import { + trigger, + transition, + style, + animate, + query, + group, +} from '@angular/animations'; + +const easing = 'cubic-bezier(0.4, 0.0, 0.2, 1)'; +const duration = '600ms'; + +export const toggleAnimation = trigger('toggle', [ + transition(':enter', [ + style({ height: 0, opacity: 0 }), + query('.details', [ + style({ transform: 'translateY(-100%)' }) + ], { optional: true }), + group([ + animate(`${duration} ${easing}`, style({ height: '*', opacity: 1 })), + query('.details', [ + animate(`${duration} ${easing}`, style({ transform: 'translateY(0)' })) + ], { optional: true }) + ]) + ]), + transition(':leave', [ + style({ height: '*', opacity: 1 }), + query('.details', [ + style({ transform: 'translateY(0)' }) + ], { optional: true }), + group([ + animate(`${duration} ${easing}`, style({ height: 0, opacity: 0 })), + query('.details', [ + animate(`${duration} ${easing}`, style({ transform: 'translateY(-100%)' })) + ], { optional: true }) + ]) + ]) +]); diff --git a/frontend/src/app/components/dashboard/dashboard.component.html b/frontend/src/app/components/dashboard/dashboard.component.html index 4990d246..f526a85d 100644 --- a/frontend/src/app/components/dashboard/dashboard.component.html +++ b/frontend/src/app/components/dashboard/dashboard.component.html @@ -113,6 +113,8 @@

Rocketadmin can not find any tables

> diff --git a/frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.css b/frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.css index 6f01a799..ee264a79 100644 --- a/frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.css +++ b/frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.css @@ -5,7 +5,9 @@ height: calc(100vh - 44px); width: 0; overflow-y: auto; - transition: width 400ms ease, transform 400ms ease, opacity 400ms ease; + transition: width 500ms cubic-bezier(0.4, 0, 0.2, 1), + transform 500ms cubic-bezier(0.4, 0, 0.2, 1), + opacity 400ms cubic-bezier(0.4, 0, 0.2, 1); } @media (width <= 600px) { @@ -19,6 +21,14 @@ opacity: 1; transform: translateX(24px); width: clamp(200px, 22vw, 400px); + transition: transform 500ms cubic-bezier(0.4, 0, 0.2, 1), + opacity 400ms cubic-bezier(0.4, 0, 0.2, 1), + width 0ms; +} + +.ai-panel-sidebar_open.ai-panel-sidebar_expanded { + width: calc(100vw - 65px); + transition: width 0ms; } @media (prefers-color-scheme: dark) { @@ -35,16 +45,53 @@ .ai-panel-sidebar-content { position: fixed; - top: 0; - left: calc(100% - clamp(200px, 22vw, 400px)); + top: 44px; + left: 100vw; display: flex; flex-direction: column; background-color: var(--mat-sidenav-content-background-color); border-left: solid 1px rgba(0, 0, 0, 0.12); - padding-top: 44px; - height: 100vh; + height: calc(100vh - 44px); width: clamp(200px, 22vw, 400px); - z-index: 0; + z-index: 100; + transition: width 500ms cubic-bezier(0.4, 0, 0.2, 1), + border-left 400ms ease; + visibility: hidden; +} + +.ai-panel-sidebar-content_open { + left: calc(100vw - clamp(200px, 22vw, 400px)); + visibility: visible; +} + +.ai-panel-sidebar-content_open.ai-panel-sidebar-content_expanded { + left: 65px; + right: 0; + width: auto; + padding-left: 175px; + border-left: none; + z-index: 1; + transition: padding-left 500ms cubic-bezier(0.4, 0, 0.2, 1), + opacity 400ms ease-out; +} + +.ai-panel-sidebar-content_open.ai-panel-sidebar-content_expanded.ai-panel-sidebar-content_sidebar-collapsed { + padding-left: 0; +} + +@media (width <= 800px) { + .ai-panel-sidebar-content { + width: 100%; + } + + .ai-panel-sidebar-content_open { + left: 0; + } + + .ai-panel-sidebar-content_open.ai-panel-sidebar-content_expanded { + left: 0; + width: 100%; + } } .ai-panel-sidebar-content ::ng-deep .ai-message table { @@ -113,6 +160,16 @@ padding-top: 20px; padding-left: 16px; padding-right: 16px; + flex-shrink: 0; + transition: max-width 350ms cubic-bezier(0.4, 0, 0.2, 1), + padding 300ms cubic-bezier(0.4, 0, 0.2, 1); +} + +.ai-panel-sidebar__actions { + display: flex; + align-items: center; + transition: right 350ms cubic-bezier(0.4, 0, 0.2, 1), + top 350ms cubic-bezier(0.4, 0, 0.2, 1); } @media (prefers-color-scheme: dark) { @@ -131,14 +188,19 @@ .ai-panel-chat { display: flex; flex-direction: column; - margin-top: auto; + flex: 1; + justify-content: flex-end; padding-left: 16px; padding-right: 16px; + overflow: hidden; + min-height: 0; } .ai-message-chain-box { height: calc(100vh - 44px - 252px - 48px); overflow-y: auto; + margin-bottom: 24px; + transition: max-width 350ms cubic-bezier(0.4, 0, 0.2, 1); } .ai-message-chain { @@ -151,22 +213,33 @@ .user-message { align-self: flex-end; - background-color: var(--color-primaryPalette-50); - color: var(--color-primaryPalette-50-contrast); + background-color: #f0f4f8; border-radius: 8px; - padding: 8px 8px 0; - margin: 4px 0; - width: 80%; + padding: 8px 8px 12px; + margin: 4px 0 16px; + max-width: 80%; } + +@media (prefers-color-scheme: dark) { + .user-message { + background-color: #2d3748; + } +} + .ai-message { align-self: flex-start; - background-color: var(--color-primaryPalette-100); - color: var(--color-primaryPalette-100-contrast); + background-color: rgba(168, 85, 247, 0.1); border-radius: 8px; padding: 8px 8px 0; margin: 4px 0; } +@media (prefers-color-scheme: dark) { + .ai-message { + background-color: rgba(168, 85, 247, 0.15); + } +} + .ai-error-message { border-radius: 8px; padding: 8px 8px 0; @@ -215,58 +288,233 @@ margin-bottom: 8px; } +.ai-welcome { + display: flex; + flex-direction: column; + gap: 16px; + margin-bottom: 24px; + flex-shrink: 0; + transition: max-width 350ms cubic-bezier(0.4, 0, 0.2, 1); +} + +.ai-welcome__message { + display: flex; + flex-direction: column; + gap: 4px; +} + +.ai-welcome__message p { + margin: 0; + line-height: 1.4; +} + +.ai-welcome__section { + display: flex; + flex-direction: column; + gap: 2px; +} + +.ai-welcome__section-title { + margin: 0; + font-size: 12px; + color: rgba(0, 0, 0, 0.5); +} + @media (prefers-color-scheme: dark) { - .suggestions { - background-color: #202020; + .ai-welcome__section-title { + color: rgba(255, 255, 255, 0.5); } } -.suggestions-title { - display: block; - color: rgba(0,0,0, 0.54); - padding: 16px 16px 0; +.suggestions-container { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.suggestion-chip { + display: inline-flex; + align-items: center; + background-color: var(--mat-sidenav-content-background-color); + border: 1px solid #d3d3d3; + border-radius: 16px; + padding: 4px 12px; + font-size: 12px; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.suggestion-chip:hover { + background-color: var(--color-primaryPalette-50); } @media (prefers-color-scheme: dark) { - .suggestions-title { - color: rgba(255,255,255, 0.54); + .suggestion-chip { + border-color: #4a4a4a; + } + + .suggestion-chip:hover { + background-color: rgba(255, 255, 255, 0.08); } } -.suggestion-button { - height: auto; - padding: 8px 16px; +.templates-container { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + padding: 0; + transition: gap 300ms cubic-bezier(0.4, 0, 0.2, 1); +} + +.template-card { + display: flex; + align-items: flex-start; + width: auto; + gap: 8px; + background-color: var(--mat-sidenav-content-background-color); + border: 1px solid #d3d3d3; + border-radius: 6px; + padding: 6px 10px; + text-align: left; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.template-card:hover { + background-color: var(--color-primaryPalette-50); +} + +.template-card__icon { + color: rgba(0, 0, 0, 0.5); + font-size: 16px; + width: 16px; + height: 16px; + flex-shrink: 0; + margin-top: 1px; } -.suggestion-button ::ng-deep .mdc-list-item__content { - text-overflow: initial; - /* white-space: wrap; */ - overflow: initial; +.template-card__content { + display: flex; + flex-direction: column; + gap: 0; } +.template-card__title { + font-size: 13px; + font-weight: 500; + color: rgba(0, 0, 0, 0.87); + line-height: 1.3; +} -.suggestion-button ::ng-deep .mdc-list-item__primary-text { - text-overflow: initial; - white-space: wrap; - overflow: initial; +.template-card__description { + font-size: 11px; + color: rgba(0, 0, 0, 0.5); + line-height: 1.3; +} + +@media (prefers-color-scheme: dark) { + .template-card { + border-color: #4a4a4a; + } + + .template-card:hover { + background-color: rgba(255, 255, 255, 0.08); + } + + .template-card__icon { + color: rgba(255, 255, 255, 0.5); + } + + .template-card__title { + color: rgba(255, 255, 255, 0.9); + } + + .template-card__description { + color: rgba(255, 255, 255, 0.5); + } } .loading { display: flex; justify-content: center; align-items: center; - height: 40px; + height: 50px; + flex-shrink: 0; +} + +.loading-content { + display: flex; + align-items: center; + gap: 8px; +} + +.loading-dots { + display: flex; + gap: 6px; + align-items: center; +} + +.loading-text { + font-size: 13px; + color: #9ca3af; +} + +.loading-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background-color: #9ca3af; + animation: loading-bounce 1.4s ease-in-out infinite; +} + +.loading-dot:nth-child(1) { + animation-delay: 0s; +} + +.loading-dot:nth-child(2) { + animation-delay: 0.15s; +} + +.loading-dot:nth-child(3) { + animation-delay: 0.3s; +} + +@keyframes loading-bounce { + 0%, 60%, 100% { + transform: translateY(0); + } + 30% { + transform: translateY(-8px); + } } .ai-message-form { position: relative; width: 100%; + flex-shrink: 0; + transition: max-width 350ms cubic-bezier(0.4, 0, 0.2, 1); } .ai-message-form__textarea { width: 100%; } +.ai-message-form__textarea ::ng-deep .mat-mdc-form-field-focus-overlay { + display: none; +} + +.ai-message-form__textarea ::ng-deep .mdc-text-field--focused .mdc-notched-outline__leading, +.ai-message-form__textarea ::ng-deep .mdc-text-field--focused .mdc-notched-outline__trailing { + border-color: #A855F7 !important; + border-width: 2px !important; +} + +.ai-message-form__textarea ::ng-deep .mdc-text-field--focused .mdc-notched-outline__notch { + border-color: #A855F7 !important; + border-width: 2px 0 !important; +} + .ai-message-form__textarea ::ng-deep .mat-mdc-text-field-wrapper { padding-bottom: 24px !important; } @@ -285,37 +533,36 @@ width: calc(100% - 4px); } -.ai-message-form__button { - +.ai-message-form__char-count { + color: rgba(0, 0, 0, 0.4); + font-size: 12px; } -.ai-panel-sidebar__message { - resize: none; - width: 100%; +@media (prefers-color-scheme: dark) { + .ai-message-form__char-count { + color: rgba(255, 255, 255, 0.4); + } } -.ai-placeholder { - margin-top:72px; - padding-left: 16px; - padding-right: 16px; - text-align: center; +.ai-message-form__button { + color: #A855F7 !important; } -@media (prefers-color-scheme: light) { - .ai-placeholder { - color: rgba(0, 0, 0, 0.64); - } +.ai-panel-sidebar__message { + resize: none; + width: 100%; } -@media (prefers-color-scheme: dark) { - .ai-placeholder { - color: rgba(255, 255, 255, 0.64); - } +.footer { + padding-bottom: 16px; + flex-shrink: 0; + transition: max-width 350ms cubic-bezier(0.4, 0, 0.2, 1); } .footer p { color: rgba(0, 0, 0, 0.36) !important; text-align: center; + margin: 0; } @media (prefers-color-scheme: dark) { @@ -327,3 +574,71 @@ .link { color: var(--color-accentedPalette-500); } + +/* Expanded state styles */ +.ai-panel-sidebar-content_expanded .ai-panel-chat { + align-items: center; +} + +.ai-panel-sidebar-content_expanded .ai-welcome { + width: 100%; + max-width: 800px; +} + +.ai-panel-sidebar-content_expanded .ai-message-chain-box { + width: 100%; + max-width: 800px; +} + +.ai-panel-sidebar-content_expanded .ai-message-form { + width: 100%; + max-width: 800px; +} + +.ai-panel-sidebar-content_expanded .footer { + width: 100%; + max-width: 800px; +} + +.ai-panel-sidebar-content_expanded .ai-panel-sidebar__header { + position: relative; + width: 100%; + max-width: 800px; + margin: 0 auto; + padding-left: 0; + padding-right: 0; + justify-content: flex-start; +} + +.ai-panel-sidebar-content_expanded .ai-panel-sidebar__actions { + position: fixed; + right: 16px; + top: 64px; +} + +.ai-panel-sidebar-content_expanded .ai-welcome__section { + gap: 4px !important; +} + +.ai-panel-sidebar-content_expanded .ai-welcome__section-title { + margin-bottom: 0 !important; +} + +.ai-panel-sidebar-content_expanded .templates-container, +.ai-panel-sidebar-content_expanded .suggestions-container { + margin-top: 0 !important; +} + +.ai-panel-sidebar-content_expanded .templates-container { + flex-direction: row; + flex-wrap: wrap; + gap: 12px; +} + +.ai-panel-sidebar-content_expanded .template-card { + width: auto; +} + +.ai-panel-sidebar-content_expanded .template-card__description { + white-space: nowrap; +} diff --git a/frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.html b/frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.html index 64f23ffc..d84d333d 100644 --- a/frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.html +++ b/frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.html @@ -1,20 +1,22 @@ -
+
-
+

- AI insights + AI insights for {{displayName}} + AI insights

- -
- -
- Insights from "{{displayName}}" table are waiting — type your query to unlock them. +
+ + +
@@ -28,33 +30,60 @@

-
- Suggested insights - - - -
+
+
+

Explore patterns, issues, and summaries instantly.

+
+
+

Suggestions for this table:

+
+ +
+
+ +
+

Templates:

+
+ +
+
+
-
-
- loading... +
+
+ Generating an answer +
+ + + +
- What should I analyze? + Ask a question about this table...