@dnax/ui 0.0.11 → 0.0.13

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/styles/main.css CHANGED
@@ -66,9 +66,14 @@ body {
66
66
  /* Safe-area intégrées à la règle de base .q-footer (plus bas) */
67
67
 
68
68
  /* Contenu de page : pas de padding par défaut (barres dans le flux).
69
- Compensation UNIQUEMENT si une barre est fixée (:has) : 50px + safe-area */
69
+ Compensation UNIQUEMENT si une barre est fixée (:has) : 50px + safe-area.
70
+ Safe-area bas : le contenu scroillé jusqu'au bout ne passe pas sous la barre
71
+ d'accueil iOS. */
70
72
  .q-page {
71
73
  flex: 1 1 auto; /* prend l'espace restant */
74
+ padding-bottom: 0;
75
+ padding-bottom: constant(safe-area-inset-bottom);
76
+ padding-bottom: env(safe-area-inset-bottom);
72
77
  }
73
78
 
74
79
  .q-app:has(.q-header--fixed) .q-page {
@@ -577,6 +582,20 @@ html.dark body {
577
582
  z-index: 100;
578
583
  }
579
584
 
585
+ /* no-padding : horizontal collé aux bords — safe-area conservées */
586
+ .q-footer--no-padding {
587
+ padding: 4px 0;
588
+ padding-bottom: 0;
589
+ padding-bottom: constant(safe-area-inset-bottom);
590
+ padding-bottom: env(safe-area-inset-bottom);
591
+ padding-left: 0;
592
+ padding-left: constant(safe-area-inset-left);
593
+ padding-left: env(safe-area-inset-left);
594
+ padding-right: 0;
595
+ padding-right: constant(safe-area-inset-right);
596
+ padding-right: env(safe-area-inset-right);
597
+ }
598
+
580
599
  .q-footer--elevated {
581
600
  box-shadow: 0 -2px 4px rgb(0 0 0 / 0.2);
582
601
  }
@@ -708,11 +727,30 @@ html.dark body {
708
727
  height: 2px;
709
728
  background-color: var(--q-tabs-active-color);
710
729
  transition:
711
- transform 0.25s ease,
712
- width 0.25s ease;
730
+ transform var(--q-tabs-duration, 0.25s) ease,
731
+ width var(--q-tabs-duration, 0.25s) ease;
713
732
  will-change: transform, width;
714
733
  }
715
734
 
735
+ /* — transitions animées (prop animated + transition) —
736
+ L'indicateur est la star du changement de tab : chaque preset lui donne une
737
+ courbe différente (spring = léger overshoot, smooth = expo-out velouté,
738
+ elastic = rebond marqué). */
739
+ .q-tabs--animated .q-tabs__indicator {
740
+ transition-duration: var(--q-tabs-duration, 0.45s);
741
+ }
742
+ .q-tabs--anim-spring .q-tabs__indicator {
743
+ transition-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1); /* back-out : dépasse puis se pose */
744
+ }
745
+ .q-tabs--anim-smooth .q-tabs__indicator {
746
+ transition-duration: var(--q-tabs-duration, 0.5s);
747
+ transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); /* expo-out : glisse velouté */
748
+ }
749
+ .q-tabs--anim-elastic .q-tabs__indicator {
750
+ transition-duration: var(--q-tabs-duration, 0.6s);
751
+ transition-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* rebond prononcé */
752
+ }
753
+
716
754
  /* ===== QTabPanels / QTabPanel ===== */
717
755
  .q-tab-panels {
718
756
  position: relative;
@@ -801,7 +839,9 @@ html.dark body {
801
839
  padding: 0 16px;
802
840
  border: none;
803
841
  background: transparent;
804
- color: inherit;
842
+ /* Couleur des tabs inactifs : inactive-color (QTabs) sinon couleur héritée.
843
+ .q-tab--active (plus bas) reprend la main par ordre de source. */
844
+ color: var(--q-tabs-inactive-color, inherit);
805
845
  font: inherit;
806
846
  font-size: 14px;
807
847
  font-weight: 500;
@@ -822,9 +862,15 @@ html.dark body {
822
862
  transform: scale(0.94);
823
863
  }
824
864
 
825
- /* pop du tab actif (overshoot, prop animated) */
826
- .q-tabs--animated .q-tab--active {
827
- animation: q-tab-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
865
+ /* pop du tab actif (overshoot) — spring (défaut) et elastic */
866
+ .q-tabs--anim-spring .q-tab--active,
867
+ .q-tabs--anim-elastic .q-tab--active {
868
+ animation: q-tab-pop var(--q-tabs-duration, 0.3s) cubic-bezier(0.34, 1.56, 0.64, 1);
869
+ }
870
+
871
+ /* smooth : le contenu du tab actif monte et apparaît (label + icône) */
872
+ .q-tabs--anim-smooth .q-tab--active .q-tab__content {
873
+ animation: q-tab-rise var(--q-tabs-duration, 0.32s) cubic-bezier(0.16, 1, 0.3, 1) both;
828
874
  }
829
875
 
830
876
  .q-tab--active {
@@ -837,8 +883,12 @@ html.dark body {
837
883
  outline-offset: -2px;
838
884
  }
839
885
 
840
- .q-tab:hover {
841
- background-color: rgb(0 0 0 / 0.04);
886
+ /* Mobile : le :hover reste collé après le tap (pas de souris) → réservé aux
887
+ devices avec hover réel (souris / trackpad) */
888
+ @media (hover: hover) and (pointer: fine) {
889
+ .q-tab:hover {
890
+ background-color: rgb(0 0 0 / 0.04);
891
+ }
842
892
  }
843
893
 
844
894
  .q-tab:disabled,
@@ -928,6 +978,63 @@ html.dark body {
928
978
  }
929
979
  }
930
980
 
981
+ @keyframes q-tab-rise {
982
+ from {
983
+ opacity: 0;
984
+ transform: translateY(6px);
985
+ }
986
+ to {
987
+ opacity: 1;
988
+ transform: none;
989
+ }
990
+ }
991
+
992
+ /* — collapse-inactive : les tabs inactifs ne montrent que l'icône ; le tab
993
+ actif s'étend (icône + label) avec une largeur animée (pattern mobile
994
+ bottom-nav). max-width 0 → 999px : la largeur utilisée = min(naturelle, max)
995
+ → le label se déplie jusqu'à sa largeur réelle, le tab suit.
996
+ PAS d'overflow: hidden : le texte n'est pas tronqué pendant l'ouverture —
997
+ il apparaît entier en FONDU (opacity), plus joli que le glissement. */
998
+ .q-tabs--collapse-inactive .q-tab__content {
999
+ gap: 0;
1000
+ }
1001
+ .q-tabs--collapse-inactive .q-tab__label {
1002
+ max-width: 0;
1003
+ opacity: 0;
1004
+ white-space: nowrap; /* pas de retour à la ligne pendant l'ouverture */
1005
+ transition:
1006
+ max-width var(--q-tabs-duration, 0.3s) cubic-bezier(0.16, 1, 0.3, 1),
1007
+ opacity var(--q-tabs-duration, 0.25s) ease;
1008
+ }
1009
+ .q-tabs--collapse-inactive .q-tab--active .q-tab__content {
1010
+ gap: 6px;
1011
+ }
1012
+ .q-tabs--collapse-inactive .q-tab--active .q-tab__label {
1013
+ max-width: 999px;
1014
+ opacity: 1;
1015
+ }
1016
+
1017
+ /* Crossfade : pendant que le label du tab inactif s'estompe, celui du tab
1018
+ actif apparaît en fondu — simultanément. Les animations d'entrée du tab
1019
+ (pop/rise) sont neutralisées en mode collapse pour ne pas geler ou masquer
1020
+ le fade du label entrant ; l'indicateur garde son spring (transition width). */
1021
+ .q-tabs--collapse-inactive.q-tabs--anim-spring .q-tab--active,
1022
+ .q-tabs--collapse-inactive.q-tabs--anim-elastic .q-tab--active,
1023
+ .q-tabs--collapse-inactive.q-tabs--anim-smooth .q-tab--active .q-tab__content {
1024
+ animation: none;
1025
+ }
1026
+
1027
+ @media (prefers-reduced-motion: reduce) {
1028
+ .q-tabs--animated .q-tabs__indicator,
1029
+ .q-tabs--anim-spring .q-tab--active,
1030
+ .q-tabs--anim-elastic .q-tab--active,
1031
+ .q-tabs--anim-smooth .q-tab--active .q-tab__content,
1032
+ .q-tabs--collapse-inactive .q-tab__label {
1033
+ transition-duration: 0s;
1034
+ animation: none;
1035
+ }
1036
+ }
1037
+
931
1038
  .q-tab__content {
932
1039
  display: flex;
933
1040
  flex-direction: inherit;
@@ -4492,11 +4599,8 @@ html.dark body {
4492
4599
  }
4493
4600
 
4494
4601
  .q-bottom-sheet__header {
4495
- display: flex;
4496
- align-items: flex-start;
4497
- justify-content: space-between;
4498
- gap: 12px;
4499
- padding: 12px 16px 8px;
4602
+ padding: 0; /* le padding est porté par le <q-toolbar> embarqué */
4603
+ border-bottom: 1px solid rgb(0 0 0 / 0.08);
4500
4604
  }
4501
4605
 
4502
4606
  .q-bottom-sheet__header-text {
@@ -4546,11 +4650,23 @@ html.dark body {
4546
4650
  }
4547
4651
 
4548
4652
  .q-bottom-sheet__footer {
4549
- display: flex;
4550
- align-items: center;
4551
- justify-content: flex-end;
4552
- gap: 8px;
4553
- padding: 8px 16px 16px;
4653
+ padding: 0; /* le padding est porté par le <q-toolbar> embarqué */
4654
+ border-top: 1px solid rgb(0 0 0 / 0.08);
4655
+ }
4656
+
4657
+ .q-bottom-sheet__footer .q-toolbar {
4658
+ justify-content: flex-end; /* actions alignées à droite (défaut) */
4659
+ }
4660
+
4661
+ .q-bottom-sheet__footer--no-padding .q-toolbar,
4662
+ .q-bottom-sheet__header--no-padding .q-toolbar,
4663
+ .q-dialog__header--no-padding .q-toolbar {
4664
+ padding: 0; /* no-padding : contenu collé aux bords */
4665
+ }
4666
+
4667
+ .q-bottom-sheet__panel--dark .q-bottom-sheet__header,
4668
+ .q-bottom-sheet__panel--dark .q-bottom-sheet__footer {
4669
+ border-color: rgb(255 255 255 / 0.12);
4554
4670
  }
4555
4671
 
4556
4672
  /* — transitions (slide vertical type vaul) — */
@@ -5751,6 +5867,8 @@ html.dark body {
5751
5867
  max-width: 90vw;
5752
5868
  max-height: 90vh;
5753
5869
  overflow: auto;
5870
+ /* Le scroll du contenu ne doit jamais se chaîner à la page derrière */
5871
+ overscroll-behavior: contain;
5754
5872
  background-color: #fff;
5755
5873
  color: inherit;
5756
5874
  border-radius: var(--q-radius);
@@ -5815,14 +5933,28 @@ html.dark body {
5815
5933
 
5816
5934
  /* safe-area : l'encoche en haut est gérée par le header, la barre d'accueil en bas par le footer */
5817
5935
  .q-dialog__content--maximized .q-dialog__header,
5818
- .q-dialog__content--top .q-dialog__header {
5936
+ .q-dialog__content--top .q-dialog__header,
5937
+ .q-dialog__content--left .q-dialog__header,
5938
+ .q-dialog__content--right .q-dialog__header {
5819
5939
  padding-top: 0;
5820
5940
  padding-top: constant(safe-area-inset-top);
5821
5941
  padding-top: env(safe-area-inset-top);
5822
5942
  }
5823
5943
 
5944
+ /* fullscreen en paysage : l'encoche latérale passe dans le header (comme QHeader) */
5945
+ .q-dialog__content--maximized .q-dialog__header {
5946
+ padding-left: 0;
5947
+ padding-left: constant(safe-area-inset-left);
5948
+ padding-left: env(safe-area-inset-left);
5949
+ padding-right: 0;
5950
+ padding-right: constant(safe-area-inset-right);
5951
+ padding-right: env(safe-area-inset-right);
5952
+ }
5953
+
5824
5954
  .q-dialog__content--maximized .q-dialog__footer,
5825
- .q-dialog__content--bottom .q-dialog__footer {
5955
+ .q-dialog__content--bottom .q-dialog__footer,
5956
+ .q-dialog__content--left .q-dialog__footer,
5957
+ .q-dialog__content--right .q-dialog__footer {
5826
5958
  padding-bottom: 0;
5827
5959
  padding-bottom: constant(safe-area-inset-bottom);
5828
5960
  padding-bottom: env(safe-area-inset-bottom);
@@ -5844,11 +5976,7 @@ html.dark body {
5844
5976
  position: sticky;
5845
5977
  top: 0;
5846
5978
  z-index: 1;
5847
- display: flex;
5848
- align-items: flex-start;
5849
- justify-content: space-between;
5850
- gap: 12px;
5851
- padding: 16px;
5979
+ padding: 0; /* le padding est porté par le <q-toolbar> embarqué */
5852
5980
  border-bottom: 1px solid rgb(0 0 0 / 0.08);
5853
5981
  background-color: inherit; /* reste opaque pendant le scroll du body */
5854
5982
  }
@@ -5899,15 +6027,30 @@ html.dark body {
5899
6027
  position: sticky;
5900
6028
  bottom: 0;
5901
6029
  z-index: 1;
5902
- display: flex;
5903
- align-items: center;
5904
- justify-content: flex-end;
5905
- gap: 8px;
5906
- padding: 12px 16px 16px;
6030
+ padding: 0; /* le padding est porté par le <q-toolbar> embarqué */
5907
6031
  border-top: 1px solid rgb(0 0 0 / 0.08);
5908
6032
  background-color: inherit;
5909
6033
  }
5910
6034
 
6035
+ .q-dialog__footer .q-toolbar {
6036
+ justify-content: flex-end; /* actions alignées à droite (défaut) */
6037
+ }
6038
+
6039
+ .q-dialog__footer--no-padding .q-toolbar {
6040
+ padding: 0; /* no-padding : actions collées aux bords */
6041
+ }
6042
+
6043
+ .q-dialog__body {
6044
+ min-height: 0;
6045
+ padding: 4px 16px 16px;
6046
+ }
6047
+
6048
+ .q-dialog__body--scrollable {
6049
+ flex: 1 1 auto;
6050
+ overflow-y: auto;
6051
+ overscroll-behavior: contain;
6052
+ }
6053
+
5911
6054
  .q-dialog__trigger {
5912
6055
  display: inline-flex;
5913
6056
  align-items: center;
@@ -6321,11 +6464,80 @@ html.dark body {
6321
6464
  z-index: 0;
6322
6465
  pointer-events: none;
6323
6466
  }
6324
- .q-container--bg > :not(.q-container__bg) {
6467
+ .q-container--bg > :not(.q-container__bg, .q-container__img) {
6325
6468
  position: relative;
6326
6469
  z-index: 1;
6327
6470
  }
6328
6471
 
6472
+ /* — image de fond (prop background-image) : couche cover derrière le contenu — */
6473
+ .q-container__img {
6474
+ position: absolute;
6475
+ inset: 0;
6476
+ z-index: 0;
6477
+ width: 100%;
6478
+ height: 100%;
6479
+ object-fit: var(--q-container-img-fit, cover);
6480
+ pointer-events: none;
6481
+ user-select: none;
6482
+ }
6483
+
6484
+ /* taille CSS libre ("50%", "400px"…) : boîte centrée (translate séparé de
6485
+ transform → compose avec le Ken Burns), image entière visible */
6486
+ .q-container__img--sized {
6487
+ width: var(--q-container-img-size);
6488
+ height: var(--q-container-img-size);
6489
+ left: 50%;
6490
+ top: 50%;
6491
+ translate: -50% -50%;
6492
+ object-fit: contain;
6493
+ }
6494
+
6495
+ /* glassmorphisée : floutée + saturée + léger zoom pour masquer les bords du blur */
6496
+ .q-container__img--glass {
6497
+ filter: blur(14px) saturate(1.4);
6498
+ transform: scale(1.15);
6499
+ }
6500
+
6501
+ /* — Ken Burns indéterminé (prop background-animated) : zoom + panoramique
6502
+ lents qui bouclent — direction et durée configurables (défaut alternate 24s) */
6503
+ .q-container__img--animated {
6504
+ animation:
6505
+ q-container-kenburns var(--q-container-kenburns-duration, 24s) ease-in-out
6506
+ var(--q-container-kenburns-direction, alternate) infinite;
6507
+ will-change: transform;
6508
+ }
6509
+ @keyframes q-container-kenburns {
6510
+ 0% {
6511
+ transform: scale(1.06) translate(0%, 0%);
6512
+ }
6513
+ 30% {
6514
+ transform: scale(1.18) translate(-2%, -1.5%);
6515
+ }
6516
+ 60% {
6517
+ transform: scale(1.14) translate(2%, 1.5%);
6518
+ }
6519
+ 100% {
6520
+ transform: scale(1.22) translate(-1%, 2%);
6521
+ }
6522
+ }
6523
+
6524
+ /* — glassmorphism du conteneur (prop glass) : fond translucide + flou de ce
6525
+ qui est derrière + bordure claire (variables personnalisables) — */
6526
+ .q-container--glass {
6527
+ --q-container-glass-bg: rgb(255 255 255 / 0.14);
6528
+ --q-container-glass-border: rgb(255 255 255 / 0.3);
6529
+ --q-container-glass-blur: 14px;
6530
+ background-color: var(--q-container-glass-bg);
6531
+ border: 1px solid var(--q-container-glass-border);
6532
+ -webkit-backdrop-filter: blur(var(--q-container-glass-blur)) saturate(1.4);
6533
+ backdrop-filter: blur(var(--q-container-glass-blur)) saturate(1.4);
6534
+ box-shadow: 0 8px 32px rgb(0 0 0 / 0.12);
6535
+ }
6536
+ .dark .q-container--glass {
6537
+ --q-container-glass-bg: rgb(255 255 255 / 0.06);
6538
+ --q-container-glass-border: rgb(255 255 255 / 0.14);
6539
+ }
6540
+
6329
6541
  /* grid : grille de carrés qui s'estompe vers les bords */
6330
6542
  .q-container__bg--grid {
6331
6543
  background-image:
@@ -6537,6 +6749,9 @@ html.dark body {
6537
6749
  .q-container__wave {
6538
6750
  animation: none;
6539
6751
  }
6752
+ .q-container__img--animated {
6753
+ animation: none;
6754
+ }
6540
6755
  }
6541
6756
 
6542
6757
  /* ===== QMarquee — bandeau défilant infini ===== */