PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 1.0.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v1.0.0
2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.10.0 All 48 releases
thinkrank / src / admin / styles / components.scss

components.scss in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 1.0.0, at src/admin/styles/components.scss

963 lines 20.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Reusable UI Components
3 *
4 * Base styles for buttons, cards, forms, and other UI elements
5 *
6 * @package ThinkRank
7 * @since 1.0.0
8 */
9
10 // Import shared variables for access to design tokens
11 @use '../../shared/styles/variables' as *;
12 @use 'components/index';
13
14 /* Scoped base styles for ThinkRank UI */
15 .thinkrank-ui {
16 /* Reset and base styles only within ThinkRank components */
17 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
18 line-height: 1.5;
19 color: #1f2937;
20
21 /* Ensure box-sizing is border-box for all ThinkRank elements */
22 *,
23 *::before,
24 *::after {
25 box-sizing: border-box;
26 }
27
28 /* ==========================================================================
29 ENHANCED CARD SYSTEM
30 ========================================================================== */
31
32 // Base card class with common properties
33 .thinkrank-card {
34 background: $white;
35 border-radius: $radius-lg;
36 border: 1px solid $border-light;
37 transition: all $transition-normal;
38 overflow: hidden;
39
40 // Base shadow
41 box-shadow: $shadow-sm;
42
43 // Variants
44 &--elevated {
45 box-shadow: $shadow-md;
46
47 &:hover {
48 box-shadow: $shadow-lg;
49 }
50 }
51
52 &--interactive {
53 cursor: pointer;
54
55 &:hover {
56 border-color: $border-medium;
57 box-shadow: $shadow-md;
58 }
59
60 &:active {
61 box-shadow: $shadow-sm;
62 }
63 }
64
65 &--flat {
66 box-shadow: none;
67 border: 1px solid $border-light;
68 }
69
70 &--bordered {
71 border: 2px solid $border-medium;
72 box-shadow: none;
73 }
74
75 // Size variants
76 &--compact {
77 border-radius: $radius-md;
78 }
79
80 &--large {
81 border-radius: $radius-xl;
82 }
83
84 // Color variants
85 &--primary {
86 border-color: rgba($primary-blue, 0.2);
87 background: linear-gradient(135deg, rgba($primary-blue, 0.02), $white);
88
89 &.thinkrank-card--interactive:hover {
90 border-color: rgba($primary-blue, 0.3);
91 box-shadow: 0 4px 12px rgba($primary-blue, 0.15);
92 }
93 }
94
95 &--success {
96 border-color: rgba($success-green, 0.2);
97 background: linear-gradient(135deg, rgba($success-green, 0.02), $white);
98
99 &.thinkrank-card--interactive:hover {
100 border-color: rgba($success-green, 0.3);
101 box-shadow: 0 4px 12px rgba($success-green, 0.15);
102 }
103 }
104
105 &--warning {
106 border-color: rgba($warning-orange, 0.2);
107 background: linear-gradient(135deg, rgba($warning-orange, 0.02), $white);
108
109 &.thinkrank-card--interactive:hover {
110 border-color: rgba($warning-orange, 0.3);
111 box-shadow: 0 4px 12px rgba($warning-orange, 0.15);
112 }
113 }
114
115 &--danger {
116 border-color: rgba($error-red, 0.2);
117 background: linear-gradient(135deg, rgba($error-red, 0.02), $white);
118
119 &.thinkrank-card--interactive:hover {
120 border-color: rgba($error-red, 0.3);
121 box-shadow: 0 4px 12px rgba($error-red, 0.15);
122 }
123 }
124
125 // Card sections
126 &__header {
127 padding: $spacing-2xl $spacing-2xl $spacing-lg;
128 border-bottom: 1px solid $border-light;
129 background: $gray-50;
130
131 &:last-child {
132 border-bottom: none;
133 padding-bottom: $spacing-2xl;
134 }
135
136 h1, h2, h3, h4, h5, h6 {
137 margin: 0 0 $spacing-sm 0;
138 color: $text-primary;
139 font-weight: $font-weight-semibold;
140 }
141
142 p {
143 margin: 0;
144 color: $text-secondary;
145 font-size: $font-size-sm;
146 }
147 }
148
149 &__body {
150 // Default padding - utilities can override this
151 padding: $spacing-2xl;
152
153 &:first-child {
154 padding-top: $spacing-2xl;
155 }
156
157 &:last-child {
158 padding-bottom: $spacing-2xl;
159 }
160
161 // Compact padding for nested cards
162 .thinkrank-card & {
163 padding: $spacing-lg;
164 }
165 }
166
167 &__footer {
168 padding: $spacing-lg $spacing-2xl $spacing-2xl;
169 border-top: 1px solid $border-light;
170 background: $gray-50;
171
172 &:last-child {
173 border-top: none;
174 padding-top: $spacing-2xl;
175 }
176
177 // Common footer patterns
178 &--actions {
179 display: flex;
180 align-items: center;
181 justify-content: space-between;
182 gap: $spacing-md;
183
184 @media (max-width: $breakpoint-sm) {
185 flex-direction: column;
186 align-items: stretch;
187
188 .thinkrank-btn {
189 width: 100%;
190 justify-content: center;
191 }
192 }
193 }
194 }
195
196 // Special card types
197 &--stat {
198 text-align: center;
199
200 .stat-number {
201 font-size: $font-size-3xl;
202 font-weight: $font-weight-bold;
203 color: $text-primary;
204 line-height: 1;
205 margin-bottom: $spacing-sm;
206 }
207
208 .stat-label {
209 font-size: $font-size-sm;
210 color: $text-secondary;
211 text-transform: uppercase;
212 letter-spacing: 0.05em;
213 font-weight: $font-weight-medium;
214 }
215 }
216
217 &--feature {
218 text-align: center;
219
220 .feature-icon {
221 width: 3rem;
222 height: 3rem;
223 margin: 0 auto $spacing-lg;
224 background: $gray-100;
225 border-radius: $radius-lg;
226 display: flex;
227 align-items: center;
228 justify-content: center;
229 color: $gray-600;
230 font-size: 1.5rem;
231 }
232
233 .feature-title {
234 font-size: $font-size-lg;
235 font-weight: $font-weight-semibold;
236 color: $text-primary;
237 margin-bottom: $spacing-sm;
238 }
239
240 .feature-description {
241 color: $text-secondary;
242 font-size: $font-size-sm;
243 line-height: $line-height-relaxed;
244 }
245 }
246 }
247
248 /* ==========================================================================
249 ENHANCED BUTTON SYSTEM
250 ========================================================================== */
251
252 // Base button class with common properties
253 .thinkrank-btn {
254 display: inline-flex;
255 align-items: center;
256 justify-content: center;
257 border-radius: $radius-md;
258 font-weight: $font-weight-medium;
259 font-size: $font-size-sm;
260 transition: all $transition-fast;
261 cursor: pointer;
262 border: 1px solid transparent;
263 text-decoration: none;
264 line-height: 1;
265
266 // Remove default button styles
267 background: none;
268 outline: none;
269
270 // Focus styles
271 &:focus {
272 outline: none;
273 box-shadow: 0 0 0 2px $primary-blue;
274 }
275
276 // Disabled state
277 &:disabled,
278 &.disabled {
279 opacity: 0.5;
280 cursor: not-allowed;
281 transform: none !important;
282 box-shadow: none !important;
283 }
284
285 // Icon spacing
286 svg, .dashicon {
287 margin-right: $spacing-sm;
288 flex-shrink: 0;
289
290 &:last-child {
291 margin-right: 0;
292 margin-left: $spacing-sm;
293 }
294
295 &:only-child {
296 margin: 0;
297 }
298 }
299
300 // Size variants
301 &--xs {
302 padding: $spacing-xs $spacing-sm;
303 font-size: $font-size-xs;
304 height: 1.5rem; // 24px
305 min-height: 1.5rem;
306 }
307
308 &--sm {
309 padding: $spacing-sm $spacing-md;
310 font-size: $font-size-xs;
311 height: $button-height-sm;
312 min-height: $button-height-sm;
313 }
314
315 &--base {
316 padding: $spacing-md $spacing-lg;
317 height: $button-height-md;
318 min-height: $button-height-md;
319 }
320
321 &--lg {
322 padding: $spacing-lg $spacing-xl;
323 height: $button-height-lg;
324 min-height: $button-height-lg;
325 font-size: $font-size-base;
326 }
327
328 // Style variants
329 &--primary {
330 background: $primary-blue;
331 color: $white;
332 border-color: $primary-blue;
333
334 &:hover:not(:disabled) {
335 background: $primary-blue-dark;
336 border-color: $primary-blue-dark;
337 transform: translateY(-1px);
338 box-shadow: 0 4px 12px rgba($primary-blue, 0.3);
339 }
340
341 &:active {
342 transform: translateY(0);
343 box-shadow: 0 2px 4px rgba($primary-blue, 0.3);
344 }
345 }
346
347 &--secondary {
348 background: $white;
349 color: $gray-700;
350 border-color: $gray-300;
351
352 &:hover:not(:disabled) {
353 background: $gray-50;
354 border-color: $gray-400;
355 transform: translateY(-1px);
356 box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
357 }
358
359 &:active {
360 transform: translateY(0);
361 box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
362 }
363 }
364
365 &--success {
366 background: $success-green;
367 color: $white;
368 border-color: $success-green;
369
370 &:hover:not(:disabled) {
371 background: $success-green-dark;
372 border-color: $success-green-dark;
373 transform: translateY(-1px);
374 box-shadow: 0 4px 12px rgba($success-green, 0.3);
375 }
376 }
377
378 &--warning {
379 background: $warning-orange;
380 color: $white;
381 border-color: $warning-orange;
382
383 &:hover:not(:disabled) {
384 background: $warning-orange-dark;
385 border-color: $warning-orange-dark;
386 transform: translateY(-1px);
387 box-shadow: 0 4px 12px rgba($warning-orange, 0.3);
388 }
389 }
390
391 &--danger {
392 background: $white;
393 color: $error-red;
394 border-color: $error-red;
395
396 &:hover:not(:disabled) {
397 background: $error-red;
398 color: $white;
399 transform: translateY(-1px);
400 box-shadow: 0 4px 12px rgba($error-red, 0.3);
401 }
402 }
403
404 &--ghost {
405 background: transparent;
406 color: $gray-600;
407 border-color: transparent;
408
409 &:hover:not(:disabled) {
410 background: $gray-100;
411 color: $gray-800;
412 }
413 }
414
415 &--link {
416 background: transparent;
417 color: $primary-blue;
418 border-color: transparent;
419 text-decoration: underline;
420
421 &:hover:not(:disabled) {
422 color: $primary-blue-dark;
423 text-decoration: none;
424 }
425 }
426
427 // Loading state
428 &--loading {
429 position: relative;
430 color: transparent;
431
432 &::after {
433 content: '';
434 position: absolute;
435 top: 50%;
436 left: 50%;
437 transform: translate(-50%, -50%);
438 width: 1rem;
439 height: 1rem;
440 border: 2px solid currentColor;
441 border-radius: 50%;
442 border-top-color: transparent;
443 animation: spin 1s linear infinite;
444 }
445 }
446
447 // Full width
448 &--full {
449 width: 100%;
450 }
451 }
452
453 // Legacy button classes (for backward compatibility)
454 .thinkrank-button-primary {
455 @extend .thinkrank-btn;
456 @extend .thinkrank-btn--primary;
457 @extend .thinkrank-btn--base;
458 }
459
460 .thinkrank-button-secondary {
461 @extend .thinkrank-btn;
462 @extend .thinkrank-btn--secondary;
463 @extend .thinkrank-btn--base;
464 }
465
466 // Spin animation for loading state
467 @keyframes spin {
468 to {
469 transform: translate(-50%, -50%) rotate(360deg);
470 }
471 }
472
473 /* Loading states */
474 .thinkrank-loading {
475 display: flex;
476 align-items: center;
477 justify-content: center;
478 padding: 2rem;
479
480 .spinner {
481 margin-right: 0.5rem;
482 }
483 }
484
485 /* Error states */
486 .thinkrank-error-notice {
487 margin-bottom: 1rem;
488 }
489
490 /* Form elements */
491 .thinkrank-form-group {
492 margin-bottom: 1rem;
493
494 label {
495 display: block;
496 margin-bottom: 0.25rem;
497 font-weight: 500;
498 color: #374151;
499 }
500
501 .description {
502 margin-top: 0.25rem;
503 font-size: 0.75rem;
504 color: #6b7280;
505 }
506 }
507
508 /* Input fields */
509 .thinkrank-input {
510 width: 100%;
511 padding: 0.5rem 0.75rem;
512 border: 1px solid #d1d5db;
513 border-radius: 6px;
514 font-size: 0.875rem;
515 line-height: 1.5;
516
517 &:focus {
518 outline: none;
519 border-color: #2563eb;
520 box-shadow: 0 0 0 1px #2563eb;
521 }
522
523 &:disabled {
524 background-color: #f9fafb;
525 color: #6b7280;
526 cursor: not-allowed;
527 }
528 }
529
530 /* Select fields */
531 .thinkrank-select {
532 width: 100%;
533 padding: 0.5rem 0.75rem;
534 border: 1px solid #d1d5db;
535 border-radius: 6px;
536 font-size: 0.875rem;
537 background-color: white;
538 background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
539 background-position: right 0.5rem center;
540 background-repeat: no-repeat;
541 background-size: 1.5em 1.5em;
542 padding-right: 2.5rem;
543
544 &:focus {
545 outline: none;
546 border-color: #2563eb;
547 box-shadow: 0 0 0 1px #2563eb;
548 }
549 }
550
551 /* Textarea */
552 .thinkrank-textarea {
553 width: 100%;
554 padding: 0.5rem 0.75rem;
555 border: 1px solid #d1d5db;
556 border-radius: 6px;
557 font-size: 0.875rem;
558 line-height: 1.5;
559 resize: vertical;
560 min-height: 2.75rem;
561
562 &:focus {
563 outline: none;
564 border-color: #2563eb;
565 box-shadow: 0 0 0 1px #2563eb;
566 }
567 }
568
569 /* Notices */
570 .thinkrank-notice {
571 padding: 0.75rem 1rem;
572 border-radius: 6px;
573 margin-bottom: 1rem;
574 border-left: 4px solid;
575
576 &.notice-success {
577 background-color: #f0fdf4;
578 border-left-color: #22c55e;
579 color: #166534;
580 }
581
582 &.notice-error {
583 background-color: #fef2f2;
584 border-left-color: #ef4444;
585 color: #dc2626;
586 }
587
588 &.notice-warning {
589 background-color: #fffbeb;
590 border-left-color: #f59e0b;
591 color: #92400e;
592 }
593
594 &.notice-info {
595 background-color: #eff6ff;
596 border-left-color: #3b82f6;
597 color: #1d4ed8;
598 }
599
600 p {
601 margin: 0;
602 }
603 }
604
605 /* Badges */
606 .thinkrank-badge {
607 display: inline-flex;
608 align-items: center;
609 padding: 0.25rem 0.75rem;
610 border-radius: 12px;
611 font-size: 0.75rem;
612 font-weight: 500;
613 text-transform: uppercase;
614 letter-spacing: 0.025em;
615
616 &.badge-success {
617 background-color: #dcfce7;
618 color: #166534;
619 border: 1px solid #bbf7d0;
620 }
621
622 &.badge-error {
623 background-color: #fef2f2;
624 color: #dc2626;
625 border: 1px solid #fecaca;
626 }
627
628 &.badge-warning {
629 background-color: #fef3c7;
630 color: #92400e;
631 border: 1px solid #fde68a;
632 }
633
634 &.badge-info {
635 background-color: #dbeafe;
636 color: #1d4ed8;
637 border: 1px solid #bfdbfe;
638 }
639 }
640
641 /* Model Badge Styles */
642 .model-badge {
643 display: inline-flex;
644 align-items: center;
645 padding: 0.25rem 0.5rem;
646 border-radius: 0.375rem;
647 font-size: 0.75rem;
648 font-weight: 500;
649 text-transform: none;
650 letter-spacing: 0;
651 white-space: nowrap;
652 vertical-align: middle;
653
654 &.openai {
655 background-color: rgba($openai-green, 0.1);
656 color: $openai-green-dark;
657 border: 1px solid rgba($openai-green, 0.2);
658 }
659
660 &.claude {
661 background-color: rgba($claude-orange, 0.1);
662 color: $claude-orange-dark;
663 border: 1px solid rgba($claude-orange, 0.2);
664 }
665
666 &.gemini {
667 background-color: rgba($purple, 0.1);
668 color: darken($purple, 20%);
669 border: 1px solid rgba($purple, 0.2);
670 }
671 }
672
673
674
675 /* Tooltips */
676 .thinkrank-tooltip {
677 position: relative;
678 display: inline-block;
679
680 .tooltip-content {
681 visibility: hidden;
682 width: 200px;
683 background-color: #1f2937;
684 color: white;
685 text-align: center;
686 border-radius: 6px;
687 padding: 0.5rem;
688 position: absolute;
689 z-index: 1000;
690 bottom: 125%;
691 left: 50%;
692 margin-left: -100px;
693 opacity: 0;
694 transition: opacity 0.3s;
695 font-size: 0.75rem;
696
697 &::after {
698 content: "";
699 position: absolute;
700 top: 100%;
701 left: 50%;
702 margin-left: -5px;
703 border-width: 5px;
704 border-style: solid;
705 border-color: #1f2937 transparent transparent transparent;
706 }
707 }
708
709 &:hover .tooltip-content {
710 visibility: visible;
711 opacity: 1;
712 }
713 }
714
715 /* ==========================================================================
716 AI-INSPIRED COMPONENTS
717 ========================================================================== */
718
719 .thinkrank-ai-card {
720 background: #ffffff;
721 border: 2px solid transparent;
722 border-radius: 16px;
723 position: relative;
724 overflow: hidden;
725
726 // Purple gradient border effect
727 &::before {
728 content: '';
729 position: absolute;
730 top: 0;
731 left: 0;
732 right: 0;
733 bottom: 0;
734 border-radius: 16px;
735 padding: 2px;
736 background: linear-gradient(135deg, #8b5cf6 0%, #a855f7 25%, #c084fc 50%, #e879f9 75%, #f0abfc 100%);
737 mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
738 mask-composite: xor;
739 -webkit-mask-composite: xor;
740 pointer-events: none;
741 }
742
743 &__header {
744 display: flex;
745 align-items: center;
746 gap: 16px;
747 padding: 24px 24px 0;
748 margin-bottom: 24px;
749 }
750
751 &__title {
752 h3 {
753 font-size: 20px;
754 font-weight: 600;
755 color: #1e293b;
756 margin: 0 0 4px 0;
757 }
758
759 p {
760 font-size: 14px;
761 color: #64748b;
762 margin: 0;
763 }
764 }
765
766 &__body {
767 padding: 0 24px;
768 }
769
770 &__footer {
771 padding: 24px;
772 border-top: 1px solid #e2e8f0;
773 margin-top: 24px;
774 background: #ffffff;
775 }
776 }
777
778 .thinkrank-ai-icon {
779 width: 48px;
780 height: 48px;
781 border-radius: 12px;
782 background: linear-gradient(135deg, #8b5cf6 0%, #a855f7 100%);
783 display: flex;
784 align-items: center;
785 justify-content: center;
786 flex-shrink: 0;
787
788 .thinkrank-sparkles {
789 font-size: 20px;
790 filter: drop-shadow(0 0 8px rgba(139, 92, 246, 0.3));
791 }
792 }
793
794 // WordPress Icon Styling
795 .thinkrank-icon {
796 display: inline-flex;
797 align-items: center;
798 justify-content: center;
799
800 svg {
801 width: 20px;
802 height: 20px;
803 fill: currentColor;
804 }
805 }
806
807 .thinkrank-ai-section {
808 margin-top: 32px;
809 padding-top: 24px;
810 border-top: 1px solid #e2e8f0;
811
812 &__title {
813 font-size: 16px;
814 font-weight: 600;
815 color: #374151;
816 margin: 0 0 16px 0;
817 display: flex;
818 align-items: center;
819 gap: 8px;
820
821 &::before {
822 content: '';
823 font-size: 14px;
824 }
825 }
826 }
827
828 .thinkrank-ai-btn {
829 width: 100%;
830 display: flex;
831 align-items: center;
832 justify-content: center;
833 gap: 8px;
834 padding: 16px 24px;
835 background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
836 color: white;
837 border: none;
838 border-radius: 12px;
839 font-size: 16px;
840 font-weight: 600;
841 cursor: pointer;
842 transition: all 0.3s ease;
843 position: relative;
844 overflow: hidden;
845
846 &::before {
847 content: '';
848 position: absolute;
849 top: 0;
850 left: -100%;
851 width: 100%;
852 height: 100%;
853 background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
854 transition: left 0.5s ease;
855 }
856
857 &:hover:not(:disabled) {
858 background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
859 transform: translateY(-1px);
860 box-shadow: 0 8px 25px rgba(30, 41, 59, 0.3);
861
862 &::before {
863 left: 100%;
864 }
865
866 .thinkrank-sparkles {
867 transform: scale(1.05);
868 }
869 }
870
871 &:disabled {
872 opacity: 0.7;
873 cursor: not-allowed;
874 transform: none;
875
876 &:hover {
877 transform: none;
878 box-shadow: none;
879 }
880 }
881
882 &--loading {
883 .components-spinner {
884 margin-right: 8px;
885 }
886 }
887 }
888
889 .thinkrank-sparkles {
890 display: inline-block;
891 transition: transform 0.3s ease;
892 }
893
894 /* Responsive utilities */
895 @media (max-width: 768px) {
896 .thinkrank-hide-mobile {
897 display: none !important;
898 }
899 }
900
901 @media (min-width: 769px) {
902 .thinkrank-hide-desktop {
903 display: none !important;
904 }
905 }
906
907 /* ==========================================================================
908 BUSINESS HOURS COMPONENT
909 ========================================================================== */
910
911 .business-hours-control {
912 .day-hours-row {
913 display: flex;
914 align-items: center;
915 gap: 10px;
916 margin-bottom: 8px;
917 padding: 8px;
918 border: 1px solid #ddd;
919 border-radius: 4px;
920 background: #fafafa;
921
922 &:hover {
923 background: #f0f0f0;
924 }
925
926 span:first-child {
927 min-width: 80px;
928 font-weight: 500;
929 text-transform: capitalize;
930 color: #1e1e1e;
931 }
932
933 .components-toggle-control {
934 margin: 0;
935 min-width: 60px;
936 }
937
938 input[type="time"]="time""] {
939 padding: 4px 8px;
940 border: 1px solid #ccd0d4;
941 border-radius: 3px;
942 font-size: 13px;
943
944 &:focus {
945 border-color: #007cba;
946 box-shadow: 0 0 0 1px #007cba;
947 outline: none;
948 }
949
950 &:disabled {
951 background: #f6f7f7;
952 color: #a7aaad;
953 }
954 }
955
956 span:not(:first-child) {
957 color: #646970;
958 font-size: 13px;
959 }
960 }
961 }
962 }
963