@superbuilders/incept-renderer 0.1.7 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -439,13 +439,35 @@ interface ValidateResult {
439
439
 
440
440
  ## Theming
441
441
 
442
- The package includes two built-in themes and supports custom themes via CSS variables.
442
+ The package includes two built-in themes and supports custom themes via CSS variables. **You are not required to use the built-in styles** — you can fully customize the appearance to match your application's design system.
443
+
444
+ ### Required CSS Imports
445
+
446
+ Import the base theme CSS in your app's root layout or global styles:
447
+
448
+ ```tsx
449
+ // In your layout.tsx or globals.css
450
+ import "@superbuilders/incept-renderer/styles/themes.css"
451
+ ```
443
452
 
444
453
  ### Built-in Themes
445
454
 
446
455
  #### Duolingo (Default)
447
456
 
448
- Clean, friendly design inspired by Duolingo's learning interface.
457
+ Clean, friendly design inspired by Duolingo's learning interface with a vibrant color palette.
458
+
459
+ **For the complete Duolingo experience**, import the Duolingo theme CSS which includes:
460
+ - Full Duolingo color palette (owl green, macaw blue, cardinal red, etc.)
461
+ - Rounded square choice indicators (A, B, C, D)
462
+ - Filled checkboxes with inset gap effect
463
+ - HTML content styling (lists, typography)
464
+ - Dark mode support
465
+
466
+ ```tsx
467
+ // In your layout.tsx or globals.css
468
+ import "@superbuilders/incept-renderer/styles/themes.css"
469
+ import "@superbuilders/incept-renderer/styles/duolingo.css" // Full Duolingo styling
470
+ ```
449
471
 
450
472
  ```tsx
451
473
  <QTIRenderer theme="duolingo" ... />
@@ -461,19 +483,200 @@ Bold, high-contrast design with thick borders and sharp shadows.
461
483
 
462
484
  ### Custom Themes
463
485
 
464
- Create your own theme by overriding CSS variables:
486
+ Create your own theme by defining CSS variables for `[data-qti-theme="your-theme-name"]` in your stylesheet, then pass that theme name to the `QTIRenderer` component.
487
+
488
+ ```tsx
489
+ <QTIRenderer theme="my-custom-theme" ... />
490
+ ```
491
+
492
+ ### CSS Variables Reference
493
+
494
+ Below is the **complete list of CSS variables** you can override when creating a custom theme. All variables are optional — any variable you don't define will fall back to the default value.
495
+
496
+ #### Container Variables
497
+
498
+ Controls the main question container/card appearance.
499
+
500
+ | Variable | Description | Default |
501
+ |----------|-------------|---------|
502
+ | `--qti-container-bg` | Background color of the container | `var(--background, #ffffff)` |
503
+ | `--qti-container-border` | Border color of the container | `var(--border, #e5e5e5)` |
504
+ | `--qti-container-border-width` | Border thickness | `2px` |
505
+ | `--qti-container-radius` | Border radius (rounded corners) | `var(--radius, 0.5rem)` |
506
+ | `--qti-container-shadow` | Box shadow | `none` |
507
+
508
+ #### Typography Variables
509
+
510
+ Controls fonts and text styling throughout the renderer.
511
+
512
+ | Variable | Description | Default |
513
+ |----------|-------------|---------|
514
+ | `--qti-font-family` | Font family for all QTI text | `inherit` |
515
+ | `--qti-font-weight` | Base font weight | `500` |
516
+ | `--qti-tracking` | Letter spacing | `normal` |
517
+
518
+ #### Choice Variables
519
+
520
+ Controls the appearance of answer choices (radio buttons, checkboxes).
521
+
522
+ | Variable | Description | Default |
523
+ |----------|-------------|---------|
524
+ | `--qti-choice-bg` | Default background of choices | `var(--background, #ffffff)` |
525
+ | `--qti-choice-border` | Default border color of choices | `var(--accent, #f4f4f5)` |
526
+ | `--qti-choice-hover-bg` | Background on hover | `var(--muted, #f4f4f5)` |
527
+ | `--qti-choice-selected-bg` | Background when selected | `oklch(0.9 0.1 220 / 0.3)` |
528
+ | `--qti-choice-selected-border` | Border when selected | `oklch(0.6 0.2 250)` |
529
+ | `--qti-choice-correct-bg` | Background for correct answers | `oklch(0.9 0.15 140 / 0.3)` |
530
+ | `--qti-choice-correct-border` | Border for correct answers | `#22c55e` |
531
+ | `--qti-choice-incorrect-bg` | Background for incorrect answers | `oklch(0.9 0.1 25 / 0.3)` |
532
+ | `--qti-choice-incorrect-border` | Border for incorrect answers | `#ef4444` |
533
+
534
+ #### Button Variables
535
+
536
+ Controls the appearance of buttons (if using the QTI button classes).
537
+
538
+ | Variable | Description | Default |
539
+ |----------|-------------|---------|
540
+ | `--qti-button-bg` | Button background color | `var(--primary, #18181b)` |
541
+ | `--qti-button-text` | Button text color | `var(--primary-foreground, #ffffff)` |
542
+ | `--qti-button-border` | Button border color | `var(--primary, #18181b)` |
543
+ | `--qti-button-shadow` | Button box shadow | `none` |
544
+ | `--qti-button-radius` | Button border radius | `var(--radius, 0.5rem)` |
545
+ | `--qti-button-font-weight` | Button font weight | `700` |
546
+
547
+ #### Feedback Variables
548
+
549
+ Controls the appearance of feedback messages shown after validation.
550
+
551
+ | Variable | Description | Default |
552
+ |----------|-------------|---------|
553
+ | `--qti-feedback-bg` | Feedback container background | `var(--background, #ffffff)` |
554
+ | `--qti-feedback-border` | Feedback container border | `var(--border, #e5e5e5)` |
555
+ | `--qti-feedback-correct-text` | Text color for correct feedback | `#22c55e` |
556
+ | `--qti-feedback-correct-icon-bg` | Icon background for correct | `#22c55e` |
557
+ | `--qti-feedback-incorrect-text` | Text color for incorrect feedback | `#ef4444` |
558
+ | `--qti-feedback-incorrect-icon-bg` | Icon background for incorrect | `#ef4444` |
559
+
560
+ #### Input Variables (Text Entry, Textarea, Dropdowns)
561
+
562
+ Controls the appearance of text input fields, textareas, and select/dropdown elements.
563
+
564
+ | Variable | Description | Default |
565
+ |----------|-------------|---------|
566
+ | `--qti-input-bg` | Input background color | `var(--background, #ffffff)` |
567
+ | `--qti-input-border` | Input border color | `var(--border, #e5e5e5)` |
568
+ | `--qti-input-border-width` | Input border thickness | `2px` |
569
+ | `--qti-input-radius` | Input border radius | `var(--radius, 0.5rem)` |
570
+ | `--qti-input-shadow` | Input box shadow | `none` |
571
+ | `--qti-input-focus-border` | Border color when focused | `var(--ring, #2563eb)` |
572
+ | `--qti-input-focus-shadow` | Box shadow when focused | `0 0 0 2px rgba(37, 99, 235, 0.2)` |
573
+ | `--qti-input-correct-border` | Border for correct text answers | `#22c55e` |
574
+ | `--qti-input-incorrect-border` | Border for incorrect text answers | `#ef4444` |
575
+
576
+ #### Choice Indicator Variables (Radio/Checkbox Circles)
577
+
578
+ Controls the appearance of the radio button and checkbox indicators.
579
+
580
+ | Variable | Description | Default |
581
+ |----------|-------------|---------|
582
+ | `--qti-indicator-size` | Size of the indicator | `1.5rem` |
583
+ | `--qti-indicator-bg` | Default background | `var(--background, #ffffff)` |
584
+ | `--qti-indicator-border` | Default border color | `var(--border, #d4d4d8)` |
585
+ | `--qti-indicator-border-width` | Border thickness | `2px` |
586
+ | `--qti-indicator-radius` | Border radius (use `9999px` for circles, `0` for squares) | `9999px` |
587
+ | `--qti-indicator-checked-bg` | Background when checked | `var(--primary, #18181b)` |
588
+ | `--qti-indicator-checked-border` | Border when checked | `var(--primary, #18181b)` |
589
+ | `--qti-indicator-checked-text` | Checkmark/dot color | `var(--primary-foreground, #ffffff)` |
590
+
591
+ #### Progress Bar Variables
592
+
593
+ Controls the appearance of progress indicators.
594
+
595
+ | Variable | Description | Default |
596
+ |----------|-------------|---------|
597
+ | `--qti-progress-bg` | Progress bar background (empty part) | `var(--muted, #f4f4f5)` |
598
+ | `--qti-progress-fill` | Progress bar fill color | `var(--primary, #18181b)` |
599
+ | `--qti-progress-height` | Height of the progress bar | `0.5rem` |
600
+ | `--qti-progress-radius` | Border radius | `var(--radius, 0.5rem)` |
601
+ | `--qti-progress-border` | Border color | `transparent` |
602
+ | `--qti-progress-border-width` | Border thickness | `0px` |
603
+
604
+ #### Content Variables (Question Text, Prompts)
605
+
606
+ Controls the appearance of HTML content (question text, prompts, instructions).
607
+
608
+ | Variable | Description | Default |
609
+ |----------|-------------|---------|
610
+ | `--qti-content-font-size` | Font size for content | `1.125rem` |
611
+ | `--qti-content-line-height` | Line height for content | `1.625` |
612
+ | `--qti-content-font-weight` | Font weight for content | `500` |
613
+
614
+ #### Image Grid Variables
615
+
616
+ Controls the layout of image-based choice interactions.
617
+
618
+ | Variable | Description | Default |
619
+ |----------|-------------|---------|
620
+ | `--qti-grid-gap` | Gap between grid items | `1rem` |
621
+ | `--qti-image-card-min-height` | Minimum height of image cards | `180px` |
622
+ | `--qti-image-card-padding` | Padding inside image cards | `1rem` |
623
+ | `--qti-image-max-height` | Maximum height of images | `160px` |
624
+
625
+ #### Order Interaction Variables (Drag-and-Drop Sorting)
626
+
627
+ Controls the appearance of the order interaction container that holds draggable items.
628
+
629
+ | Variable | Description | Default |
630
+ |----------|-------------|---------|
631
+ | `--qti-order-container-bg` | Container background | `var(--muted, #f4f4f5)` |
632
+ | `--qti-order-container-border` | Container border color | `transparent` |
633
+ | `--qti-order-container-border-width` | Container border thickness | `2px` |
634
+ | `--qti-order-container-radius` | Container border radius | `0.75rem` |
635
+ | `--qti-order-container-padding` | Container padding | `1rem` |
636
+ | `--qti-order-container-gap` | Gap between drag items | `0.5rem` |
637
+ | `--qti-order-container-correct-bg` | Background when correct | `oklch(0.9 0.15 140 / 0.2)` |
638
+ | `--qti-order-container-correct-border` | Border when correct | `#22c55e` |
639
+ | `--qti-order-container-incorrect-bg` | Background when incorrect | `oklch(0.9 0.1 25 / 0.2)` |
640
+ | `--qti-order-container-incorrect-border` | Border when incorrect | `#ef4444` |
641
+
642
+ #### Order Item Variables (Drag Tokens)
643
+
644
+ Controls the appearance of individual draggable items/tokens.
645
+
646
+ | Variable | Description | Default |
647
+ |----------|-------------|---------|
648
+ | `--qti-order-item-bg` | Item background | `var(--background, #ffffff)` |
649
+ | `--qti-order-item-border` | Item border color | `var(--border, #e5e5e5)` |
650
+ | `--qti-order-item-border-width` | Item border thickness | `1px` |
651
+ | `--qti-order-item-radius` | Item border radius | `0.5rem` |
652
+ | `--qti-order-item-padding` | Item padding | `1rem` |
653
+ | `--qti-order-item-shadow` | Item box shadow | `0 1px 2px rgba(0, 0, 0, 0.05)` |
654
+ | `--qti-order-item-hover-border` | Border on hover | `oklch(0.6 0.2 250)` |
655
+ | `--qti-order-item-hover-shadow` | Shadow on hover | `0 4px 6px rgba(0, 0, 0, 0.1)` |
656
+ | `--qti-order-item-dragging-border` | Border while dragging | `oklch(0.6 0.2 250)` |
657
+ | `--qti-order-item-dragging-shadow` | Shadow while dragging | `0 8px 16px rgba(0, 0, 0, 0.15)` |
658
+ | `--qti-order-item-handle-color` | Drag handle icon color | `var(--muted-foreground, #71717a)` |
659
+
660
+ ### Complete Custom Theme Example
661
+
662
+ Here's a complete example defining all variables for a custom theme:
465
663
 
466
664
  ```css
467
- /* In your globals.css */
665
+ /* In your globals.css or styles file */
468
666
  [data-qti-theme="my-custom-theme"] {
469
- /* Container styling */
667
+ /* ========== Container ========== */
470
668
  --qti-container-bg: #ffffff;
471
669
  --qti-container-border: #e0e0e0;
472
670
  --qti-container-border-width: 1px;
473
671
  --qti-container-radius: 12px;
474
672
  --qti-container-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
475
673
 
476
- /* Choice styling */
674
+ /* ========== Typography ========== */
675
+ --qti-font-family: "Inter", system-ui, sans-serif;
676
+ --qti-font-weight: 400;
677
+ --qti-tracking: normal;
678
+
679
+ /* ========== Choices (Radio/Checkbox Cards) ========== */
477
680
  --qti-choice-bg: #f8f8f8;
478
681
  --qti-choice-border: #d0d0d0;
479
682
  --qti-choice-hover-bg: #f0f0f0;
@@ -484,30 +687,151 @@ Create your own theme by overriding CSS variables:
484
687
  --qti-choice-incorrect-bg: #ffebee;
485
688
  --qti-choice-incorrect-border: #f44336;
486
689
 
487
- /* Button styling */
690
+ /* ========== Buttons ========== */
488
691
  --qti-button-bg: #2196f3;
489
692
  --qti-button-text: #ffffff;
490
693
  --qti-button-border: transparent;
491
694
  --qti-button-shadow: none;
695
+ --qti-button-radius: 8px;
696
+ --qti-button-font-weight: 600;
492
697
 
493
- /* Typography */
494
- --qti-font-family: system-ui, sans-serif;
495
- --qti-font-weight: 400;
496
-
497
- /* Feedback styling */
698
+ /* ========== Feedback Messages ========== */
498
699
  --qti-feedback-bg: #ffffff;
499
700
  --qti-feedback-border: #e0e0e0;
500
701
  --qti-feedback-correct-text: #2e7d32;
702
+ --qti-feedback-correct-icon-bg: #4caf50;
501
703
  --qti-feedback-incorrect-text: #c62828;
704
+ --qti-feedback-incorrect-icon-bg: #f44336;
705
+
706
+ /* ========== Text Inputs / Textareas / Dropdowns ========== */
707
+ --qti-input-bg: #ffffff;
708
+ --qti-input-border: #d0d0d0;
709
+ --qti-input-border-width: 1px;
710
+ --qti-input-radius: 8px;
711
+ --qti-input-shadow: none;
712
+ --qti-input-focus-border: #2196f3;
713
+ --qti-input-focus-shadow: 0 0 0 3px rgba(33, 150, 243, 0.2);
714
+ --qti-input-correct-border: #4caf50;
715
+ --qti-input-incorrect-border: #f44336;
716
+
717
+ /* ========== Choice Indicators (Radio/Checkbox Circles) ========== */
718
+ --qti-indicator-size: 1.5rem;
719
+ --qti-indicator-bg: #ffffff;
720
+ --qti-indicator-border: #d0d0d0;
721
+ --qti-indicator-border-width: 2px;
722
+ --qti-indicator-radius: 9999px; /* Use 0 for square checkboxes */
723
+ --qti-indicator-checked-bg: #2196f3;
724
+ --qti-indicator-checked-border: #2196f3;
725
+ --qti-indicator-checked-text: #ffffff;
726
+
727
+ /* ========== Progress Bar ========== */
728
+ --qti-progress-bg: #e0e0e0;
729
+ --qti-progress-fill: #2196f3;
730
+ --qti-progress-height: 8px;
731
+ --qti-progress-radius: 4px;
732
+ --qti-progress-border: transparent;
733
+ --qti-progress-border-width: 0;
734
+
735
+ /* ========== Content (Question Text) ========== */
736
+ --qti-content-font-size: 1.125rem;
737
+ --qti-content-line-height: 1.6;
738
+ --qti-content-font-weight: 400;
739
+
740
+ /* ========== Image Grids ========== */
741
+ --qti-grid-gap: 1rem;
742
+ --qti-image-card-min-height: 180px;
743
+ --qti-image-card-padding: 1rem;
744
+ --qti-image-max-height: 160px;
745
+
746
+ /* ========== Order Interaction (Drag-and-Drop Container) ========== */
747
+ --qti-order-container-bg: #f5f5f5;
748
+ --qti-order-container-border: #e0e0e0;
749
+ --qti-order-container-border-width: 1px;
750
+ --qti-order-container-radius: 12px;
751
+ --qti-order-container-padding: 1rem;
752
+ --qti-order-container-gap: 0.75rem;
753
+ --qti-order-container-correct-bg: rgba(76, 175, 80, 0.15);
754
+ --qti-order-container-correct-border: #4caf50;
755
+ --qti-order-container-incorrect-bg: rgba(244, 67, 54, 0.15);
756
+ --qti-order-container-incorrect-border: #f44336;
757
+
758
+ /* ========== Order Items (Drag Tokens) ========== */
759
+ --qti-order-item-bg: #ffffff;
760
+ --qti-order-item-border: #e0e0e0;
761
+ --qti-order-item-border-width: 1px;
762
+ --qti-order-item-radius: 8px;
763
+ --qti-order-item-padding: 1rem;
764
+ --qti-order-item-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
765
+ --qti-order-item-hover-border: #2196f3;
766
+ --qti-order-item-hover-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);
767
+ --qti-order-item-dragging-border: #2196f3;
768
+ --qti-order-item-dragging-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
769
+ --qti-order-item-handle-color: #9e9e9e;
770
+ }
771
+
772
+ /* Optional: Dark mode support for your custom theme */
773
+ .dark[data-qti-theme="my-custom-theme"],
774
+ [data-qti-theme="my-custom-theme"] .dark {
775
+ /* Container */
776
+ --qti-container-bg: #1a1a1a;
777
+ --qti-container-border: #333333;
778
+
779
+ /* Choices */
780
+ --qti-choice-bg: #252525;
781
+ --qti-choice-border: #444444;
782
+ --qti-choice-hover-bg: #333333;
783
+ --qti-choice-selected-bg: rgba(33, 150, 243, 0.2);
784
+ --qti-choice-selected-border: #2196f3;
785
+ --qti-choice-correct-bg: rgba(76, 175, 80, 0.2);
786
+ --qti-choice-incorrect-bg: rgba(244, 67, 54, 0.2);
787
+
788
+ /* Feedback */
789
+ --qti-feedback-bg: #1a1a1a;
790
+ --qti-feedback-border: #333333;
791
+
792
+ /* Inputs */
793
+ --qti-input-bg: #252525;
794
+ --qti-input-border: #444444;
795
+
796
+ /* Indicators */
797
+ --qti-indicator-bg: #252525;
798
+ --qti-indicator-border: #444444;
799
+
800
+ /* Progress */
801
+ --qti-progress-bg: #333333;
802
+
803
+ /* Order Interaction */
804
+ --qti-order-container-bg: #252525;
805
+ --qti-order-container-border: #444444;
806
+ --qti-order-container-correct-bg: rgba(76, 175, 80, 0.2);
807
+ --qti-order-container-incorrect-bg: rgba(244, 67, 54, 0.2);
808
+
809
+ /* Order Items */
810
+ --qti-order-item-bg: #1a1a1a;
811
+ --qti-order-item-border: #444444;
812
+ --qti-order-item-handle-color: #888888;
502
813
  }
503
814
  ```
504
815
 
505
- Then use it:
816
+ Then use your custom theme:
506
817
 
507
818
  ```tsx
508
819
  <QTIRenderer theme="my-custom-theme" ... />
509
820
  ```
510
821
 
822
+ ### Partial Overrides
823
+
824
+ You don't need to define all variables. You can create a theme that only overrides specific values:
825
+
826
+ ```css
827
+ /* Minimal custom theme - only changes colors */
828
+ [data-qti-theme="brand-colors"] {
829
+ --qti-choice-selected-bg: #your-brand-color-light;
830
+ --qti-choice-selected-border: #your-brand-color;
831
+ --qti-button-bg: #your-brand-color;
832
+ }
833
+ ```
834
+
511
835
  ---
512
836
 
513
837
  ## Complete Examples