Skip to content

Commit 7ffa0a2

Browse files
feat: add slide toggle with lock/edit icons and animated help tooltip
- Replace checkbox with slide toggle showing lock/edit icons inside - Add animated help popup showing chip vs editable input comparison - Toggle animation shows text being typed to demonstrate editability - Reduce quick edit column width for better layout Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c3defe7 commit 7ffa0a2

3 files changed

Lines changed: 306 additions & 13 deletions

File tree

frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-dialog/saved-filters-dialog.component.css

Lines changed: 270 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.filters-content {
22
display: grid;
3-
grid-template-columns: 32px auto 228px 0 1fr 120px;
3+
grid-template-columns: 32px auto 228px 0 1fr 100px;
44
grid-column-gap: 8px;
55
align-content: flex-start;
66
align-items: center;
@@ -142,17 +142,285 @@
142142
width: 14px;
143143
height: 14px;
144144
color: rgba(0, 0, 0, 0.35);
145-
cursor: help;
145+
cursor: pointer;
146+
}
147+
148+
/* Quick edit help menu styles */
149+
::ng-deep .quick-edit-help-menu {
150+
max-width: none !important;
151+
}
152+
153+
.quick-edit-help-content {
154+
padding: 16px;
155+
cursor: default;
156+
}
157+
158+
.quick-edit-help-text {
159+
margin: 0 0 12px 0;
160+
font-size: 13px;
161+
color: rgba(0, 0, 0, 0.7);
162+
line-height: 1.4;
163+
}
164+
165+
/* Animated example */
166+
.quick-edit-animated-example {
167+
display: flex;
168+
align-items: center;
169+
gap: 16px;
170+
}
171+
172+
.example-toggle-animated {
173+
flex-shrink: 0;
174+
}
175+
176+
.toggle-track {
177+
width: 36px;
178+
height: 20px;
179+
border-radius: 10px;
180+
background-color: rgba(0, 0, 0, 0.25);
181+
position: relative;
182+
animation: toggleTrack 3s ease-in-out infinite;
183+
}
184+
185+
.toggle-thumb {
186+
width: 16px;
187+
height: 16px;
188+
border-radius: 50%;
189+
background-color: #fff;
190+
position: absolute;
191+
top: 2px;
192+
left: 2px;
193+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
194+
animation: toggleThumb 3s ease-in-out infinite;
195+
}
196+
197+
@keyframes toggleTrack {
198+
0%, 40% {
199+
background-color: rgba(0, 0, 0, 0.25);
200+
}
201+
50%, 90% {
202+
background-color: #C177FC;
203+
}
204+
100% {
205+
background-color: rgba(0, 0, 0, 0.25);
206+
}
207+
}
208+
209+
@keyframes toggleThumb {
210+
0%, 40% {
211+
left: 2px;
212+
}
213+
50%, 90% {
214+
left: 18px;
215+
}
216+
100% {
217+
left: 2px;
218+
}
219+
}
220+
221+
.example-filter-animated {
222+
position: relative;
223+
height: 36px;
224+
min-width: 110px;
225+
margin-top: 4px;
226+
}
227+
228+
.example-chip-animated {
229+
position: absolute;
230+
top: 0;
231+
left: 0;
232+
background-color: rgba(0, 0, 0, 0.08);
233+
border-radius: 16px;
234+
padding: 5px 12px;
235+
font-size: 12px;
236+
color: rgba(0, 0, 0, 0.7);
237+
white-space: nowrap;
238+
animation: chipFade 3s ease-in-out infinite;
239+
}
240+
241+
.example-editable-animated {
242+
position: absolute;
243+
top: 0;
244+
left: 0;
245+
display: flex;
246+
align-items: center;
247+
gap: 4px;
248+
background-color: transparent;
249+
border: 1px solid #C177FC;
250+
border-radius: 4px;
251+
padding: 8px 8px 4px 8px;
252+
opacity: 0;
253+
animation: editableFade 3s ease-in-out infinite;
254+
}
255+
256+
.example-editable-label {
257+
position: absolute;
258+
top: -8px;
259+
left: 8px;
260+
font-size: 10px;
261+
color: #C177FC;
262+
background-color: #fff;
263+
padding: 0 4px;
264+
}
265+
266+
.example-editable-value {
267+
font-size: 12px;
268+
color: rgba(0, 0, 0, 0.87);
269+
display: flex;
270+
align-items: center;
271+
}
272+
273+
.typing-text::after {
274+
content: 'active';
275+
animation: typeText 3s ease-in-out infinite;
276+
}
277+
278+
@keyframes typeText {
279+
0%, 40% {
280+
content: '';
281+
}
282+
45% {
283+
content: 'p';
284+
}
285+
50% {
286+
content: 'pe';
287+
}
288+
55% {
289+
content: 'pen';
290+
}
291+
60% {
292+
content: 'pend';
293+
}
294+
65% {
295+
content: 'pendi';
296+
}
297+
70%, 90% {
298+
content: 'pending';
299+
}
300+
100% {
301+
content: '';
302+
}
303+
}
304+
305+
.example-typing-cursor {
306+
font-size: 12px;
307+
color: #C177FC;
308+
font-weight: 300;
309+
animation: cursorBlink 0.5s step-end infinite;
310+
}
311+
312+
@keyframes cursorBlink {
313+
0%, 50% {
314+
opacity: 1;
315+
}
316+
51%, 100% {
317+
opacity: 0;
318+
}
319+
}
320+
321+
@keyframes chipFade {
322+
0%, 40% {
323+
opacity: 1;
324+
}
325+
50%, 90% {
326+
opacity: 0;
327+
}
328+
100% {
329+
opacity: 1;
330+
}
331+
}
332+
333+
@keyframes editableFade {
334+
0%, 40% {
335+
opacity: 0;
336+
}
337+
50%, 90% {
338+
opacity: 1;
339+
}
340+
100% {
341+
opacity: 0;
342+
}
343+
}
344+
345+
@media (prefers-color-scheme: dark) {
346+
.quick-edit-help-text {
347+
color: rgba(255, 255, 255, 0.7);
348+
}
349+
350+
.toggle-track {
351+
animation: toggleTrackDark 3s ease-in-out infinite;
352+
}
353+
354+
@keyframes toggleTrackDark {
355+
0%, 40% {
356+
background-color: rgba(255, 255, 255, 0.3);
357+
}
358+
50%, 90% {
359+
background-color: #C177FC;
360+
}
361+
100% {
362+
background-color: rgba(255, 255, 255, 0.3);
363+
}
364+
}
365+
366+
.example-chip-animated {
367+
background-color: rgba(255, 255, 255, 0.12);
368+
color: rgba(255, 255, 255, 0.7);
369+
}
370+
371+
.example-editable-animated {
372+
background-color: transparent;
373+
}
374+
375+
.example-editable-label {
376+
color: #C177FC;
377+
background-color: #424242;
378+
}
379+
380+
.example-editable-value {
381+
color: rgba(255, 255, 255, 0.87);
382+
}
383+
384+
.example-typing-cursor {
385+
color: #C177FC;
386+
}
146387
}
147388

148389
.quick-edit-toggle {
149390
grid-column: 6;
150391
margin-top: -16px;
151392
align-self: center;
393+
justify-self: center;
394+
}
395+
396+
/* Hide default icons */
397+
.quick-edit-toggle ::ng-deep .mdc-switch__icons {
398+
display: none;
399+
}
400+
401+
/* Style the thumb to contain our icon */
402+
.quick-edit-toggle ::ng-deep .mdc-switch__handle {
152403
display: flex;
404+
align-items: center;
153405
justify-content: center;
154406
}
155407

408+
/* Add lock icon when unchecked */
409+
.quick-edit-toggle ::ng-deep .mdc-switch__handle::after {
410+
font-family: 'Material Icons';
411+
content: 'lock';
412+
font-size: 16px;
413+
position: absolute;
414+
color: #fff;
415+
}
416+
417+
/* Add edit icon when checked */
418+
.quick-edit-toggle.mat-mdc-slide-toggle-checked ::ng-deep .mdc-switch__handle::after {
419+
content: 'edit';
420+
font-size: 16px;
421+
color: #fff;
422+
}
423+
156424
@media (prefers-color-scheme: dark) {
157425
.quick-edit-title {
158426
color: rgba(255, 255, 255, 0.5);

frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-dialog/saved-filters-dialog.component.html

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,33 @@ <h1 mat-dialog-title class="filters-header">
5252
<div class="quick-edit-header" *ngIf="hasSelectedFilters">
5353
<span class="quick-edit-title">Quick edit</span>
5454
<mat-icon class="quick-edit-info-icon"
55-
matTooltip="Enable to change this value directly from the table view"
56-
matTooltipPosition="above">
55+
[matMenuTriggerFor]="quickEditHelpMenu">
5756
info_outline
5857
</mat-icon>
58+
<mat-menu #quickEditHelpMenu="matMenu" class="quick-edit-help-menu">
59+
<div class="quick-edit-help-content" (click)="$event.stopPropagation()">
60+
<p class="quick-edit-help-text">Enable to change this value<br>directly from the table view</p>
61+
<div class="quick-edit-animated-example">
62+
<div class="example-toggle-animated">
63+
<div class="toggle-track">
64+
<div class="toggle-thumb"></div>
65+
</div>
66+
</div>
67+
<div class="example-filter-animated">
68+
<div class="example-chip-animated">
69+
<span>status = active</span>
70+
</div>
71+
<div class="example-editable-animated">
72+
<span class="example-editable-label">status:</span>
73+
<span class="example-editable-value">
74+
<span class="typing-text"></span>
75+
<span class="example-typing-cursor">|</span>
76+
</span>
77+
</div>
78+
</div>
79+
</div>
80+
</div>
81+
</mat-menu>
5982
</div>
6083

6184
<!-- Added Filters -->
@@ -178,13 +201,13 @@ <h1 mat-dialog-title class="filters-header">
178201
}"
179202
></ndc-dynamic>
180203
</ng-template>
181-
<div class="quick-edit-toggle">
182-
<mat-slide-toggle
183-
[checked]="dynamicColumn === value.key"
184-
(change)="toggleDynamicColumn(value.key)"
185-
color="primary">
186-
</mat-slide-toggle>
187-
</div>
204+
<mat-slide-toggle
205+
class="quick-edit-toggle"
206+
[checked]="dynamicColumn === value.key"
207+
[matTooltip]="dynamicColumn === value.key ? 'Disable editing' : 'Enable editing'"
208+
matTooltipPosition="above"
209+
(change)="toggleDynamicColumn(value.key)">
210+
</mat-slide-toggle>
188211
</ng-container>
189212

190213
<!-- Add Condition Button -->

frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-dialog/saved-filters-dialog.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/materia
1111
import { MatFormFieldModule } from '@angular/material/form-field';
1212
import { MatIconModule } from '@angular/material/icon';
1313
import { MatInputModule } from '@angular/material/input';
14+
import { MatMenuModule } from '@angular/material/menu';
1415
import { MatSelectModule } from '@angular/material/select';
15-
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
1616
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
17+
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
1718
import { MatTooltipModule } from '@angular/material/tooltip';
1819
import { RouterModule } from '@angular/router';
1920
import { ContentLoaderComponent } from 'src/app/components/ui-components/content-loader/content-loader.component';
@@ -38,6 +39,8 @@ import { Angulartics2, Angulartics2OnModule } from 'angulartics2';
3839
MatButtonModule,
3940
MatIconModule,
4041
MatSelectModule,
42+
MatSlideToggleModule,
43+
MatMenuModule,
4144
MatCheckboxModule,
4245
MatRadioModule,
4346
DynamicModule,
@@ -46,7 +49,6 @@ import { Angulartics2, Angulartics2OnModule } from 'angulartics2';
4649
MatSnackBarModule,
4750
ContentLoaderComponent,
4851
Angulartics2OnModule,
49-
MatSlideToggleModule,
5052
MatTooltipModule
5153
],
5254
templateUrl: './saved-filters-dialog.component.html',

0 commit comments

Comments
 (0)