allaw-ui 3.7.1 → 3.7.3

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.
@@ -9,6 +9,25 @@
9
9
  gap: 0.5rem;
10
10
  }
11
11
 
12
+ /* Classes d'alignement */
13
+ .tiny-info.left {
14
+ width: 100%;
15
+ justify-content: flex-start;
16
+ text-align: left;
17
+ }
18
+
19
+ .tiny-info.center {
20
+ width: 100%;
21
+ justify-content: center;
22
+ text-align: center;
23
+ }
24
+
25
+ .tiny-info.right {
26
+ width: 100%;
27
+ justify-content: flex-end;
28
+ text-align: right;
29
+ }
30
+
12
31
  .tiny-info.bold14 {
13
32
  font-size: 14px;
14
33
  font-weight: 700;
@@ -86,20 +86,27 @@ var Modal = function (_a) {
86
86
  };
87
87
  var renderModalContent = function () {
88
88
  return (React.createElement(React.Fragment, null,
89
- React.createElement("div", { className: style.modalHeadingWrapper },
90
- React.createElement(Heading, { text: title, variant: "h4", color: "noir", align: "left" })),
91
- React.createElement("div", { className: style.modalParagraphWrapper },
92
- React.createElement(Paragraph, { text: description, variant: "medium", size: "default", className: style.modalParagraph })),
93
- renderContent && (React.createElement("div", { className: style.modalCustomWrapper }, renderContent({ isOpen: show, onClose: onCancel }))),
94
- !renderContent && customContent && (React.createElement("div", { className: style.modalCustomWrapper },
95
- React.createElement(customContent.component, __assign({}, (customContent.props || {}))))),
96
- !renderContent && !customContent && children && (React.createElement("div", { className: style.modalCustomWrapper }, children)),
97
- !renderContent &&
98
- !customContent &&
99
- !children &&
100
- imageConfig &&
101
- !imgError && (React.createElement("div", { className: "".concat(style.modalImageWrapper, " ").concat(imageConfig.className || ""), style: __assign({ padding: imageConfig.padding }, imageConfig.style) },
102
- React.createElement("img", { src: imageConfig.url, alt: imageConfig.alt || "", width: imageConfig.width, height: imageConfig.height, onError: handleImageError, className: style.modalImage })))));
89
+ React.createElement("header", { className: style.modalHeader },
90
+ React.createElement("div", { className: style.modalHeadingWrapper },
91
+ React.createElement(Heading, { text: title, variant: "h4", color: "noir", align: "left" })),
92
+ React.createElement("button", { className: style.modalCloseButton, onClick: onCancel, "aria-label": "Fermer", type: "button" },
93
+ React.createElement("span", { className: style.modalCloseIcon }, "\u00D7"))),
94
+ React.createElement("section", { className: style.modalBody },
95
+ React.createElement("div", { className: style.modalParagraphWrapper },
96
+ React.createElement(Paragraph, { text: description, variant: "medium", size: "default", className: style.modalParagraph })),
97
+ renderContent && (React.createElement("div", { className: style.modalCustomWrapper }, renderContent({ isOpen: show, onClose: onCancel }))),
98
+ !renderContent && customContent && (React.createElement("div", { className: style.modalCustomWrapper },
99
+ React.createElement(customContent.component, __assign({}, (customContent.props || {}))))),
100
+ !renderContent && !customContent && children && (React.createElement("div", { className: style.modalCustomWrapper }, children)),
101
+ !renderContent &&
102
+ !customContent &&
103
+ !children &&
104
+ imageConfig &&
105
+ !imgError && (React.createElement("div", { className: "".concat(style.modalImageWrapper, " ").concat(imageConfig.className || ""), style: __assign({ padding: imageConfig.padding }, imageConfig.style) },
106
+ React.createElement("img", { src: imageConfig.url, alt: imageConfig.alt || "", width: imageConfig.width, height: imageConfig.height, onError: handleImageError, className: style.modalImage })))),
107
+ React.createElement("footer", { className: style.modalFooter },
108
+ cancelLabel && (React.createElement(SecondaryButton, { label: cancelLabel, onClick: onCancel, startIconName: "allaw-icon-close", startIcon: true })),
109
+ React.createElement(PrimaryButton, { label: confirmLabel, variant: isDanger ? "warning" : "default", onClick: onConfirm, startIconName: confirmIconName, startIcon: true }))));
103
110
  };
104
111
  // Générer les styles pour la largeur maximale responsive
105
112
  var getMaxWidthStyles = function () {
@@ -203,11 +210,7 @@ var Modal = function (_a) {
203
210
  ? "".concat(horizontalOffset.right, "px")
204
211
  : undefined,
205
212
  } },
206
- React.createElement("div", { className: "".concat(style.modalContent, " ").concat(show ? style.modal : "", " ").concat(getMaxWidthClasses(), " ").concat(getDynamicModalClass()), ref: modalContentRef, style: __assign({}, getMaxWidthStyles()) },
207
- renderModalContent(),
208
- React.createElement("div", { className: style.modalButtons },
209
- cancelLabel && (React.createElement(SecondaryButton, { label: cancelLabel, onClick: onCancel, startIconName: "allaw-icon-close", startIcon: true })),
210
- React.createElement(PrimaryButton, { label: confirmLabel, variant: isDanger ? "warning" : "default", onClick: onConfirm, startIconName: confirmIconName, startIcon: true })))));
213
+ React.createElement("div", { className: "".concat(style.modalContent, " ").concat(show ? style.modal : "", " ").concat(getMaxWidthClasses(), " ").concat(getDynamicModalClass()), ref: modalContentRef, style: __assign({}, getMaxWidthStyles()) }, renderModalContent())));
211
214
  return ReactDOM.createPortal(modalContent, portalContainerRef.current);
212
215
  };
213
216
  export default Modal;
@@ -254,30 +254,89 @@
254
254
  .modalContent {
255
255
  background: #fff;
256
256
  border-radius: 16px;
257
- padding: 2rem;
258
257
  max-width: 500px;
259
258
  width: 90%;
260
259
  animation: fadeIn 0.2s ease-out;
261
260
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
262
- max-height: 90vh;
261
+ max-height: calc(100vh - 120px);
263
262
  display: flex;
264
263
  flex-direction: column;
265
264
  }
266
265
 
266
+ .modalHeader {
267
+ flex-shrink: 0;
268
+ padding: 2rem 2rem 0 2rem;
269
+ background: #fff;
270
+ border-radius: 16px 16px 0 0;
271
+ display: flex;
272
+ justify-content: space-between;
273
+ align-items: flex-start;
274
+ gap: 1rem;
275
+ }
276
+
267
277
  .modalHeadingWrapper {
268
- margin-bottom: 1.5rem;
278
+ flex: 1;
269
279
  display: flex;
270
280
  justify-content: start;
271
281
  }
272
282
 
273
- .modalParagraphWrapper {
274
- margin-bottom: 2.5rem;
283
+ .modalCloseButton {
284
+ background: none;
285
+ border: none;
286
+ cursor: pointer;
287
+ padding: 0.25rem;
288
+ margin: -0.25rem -0.25rem -0.25rem 0;
289
+ border-radius: 0.375rem;
290
+ transition: background-color 0.2s ease;
291
+ flex-shrink: 0;
292
+ }
293
+
294
+ .modalCloseButton:hover {
295
+ background-color: #f3f4f6;
296
+ }
297
+
298
+ .modalCloseIcon {
299
+ font-size: 1.5rem;
300
+ line-height: 1;
301
+ color: #6b7280;
302
+ font-weight: 300;
303
+ display: block;
304
+ width: 24px;
305
+ height: 24px;
306
+ text-align: center;
307
+ }
308
+
309
+ .modalBody {
310
+ flex: 1;
275
311
  overflow-y: auto;
312
+ padding: 1.5rem 2rem;
313
+ }
314
+
315
+ .modalBody::-webkit-scrollbar {
316
+ width: 8px;
317
+ }
318
+
319
+ .modalBody::-webkit-scrollbar-track {
320
+ background: #f1f1f1;
321
+ border-radius: 4px;
322
+ }
323
+
324
+ .modalBody::-webkit-scrollbar-thumb {
325
+ background: #cbd5e1;
326
+ border-radius: 4px;
327
+ }
328
+
329
+ .modalBody::-webkit-scrollbar-thumb:hover {
330
+ background: #94a3b8;
331
+ }
332
+
333
+ .modalParagraphWrapper {
334
+ margin-bottom: 1rem;
276
335
  }
277
336
 
278
337
  .modalImageWrapper {
279
338
  text-align: center;
280
- margin: 0 0 2.5rem 0;
339
+ margin: 1rem 0;
281
340
  }
282
341
 
283
342
  .modalImage {
@@ -288,18 +347,40 @@
288
347
 
289
348
  .modalCustomWrapper {
290
349
  width: 100%;
291
- margin-bottom: 2.5rem;
350
+ margin-top: 1rem;
292
351
  }
293
352
 
294
353
  .modalParagraph {
295
354
  text-align: left;
296
355
  }
297
356
 
357
+ .modalFooter {
358
+ flex-shrink: 0;
359
+ padding: 0 2rem 2rem 2rem;
360
+ background: #fff;
361
+ border-radius: 0 0 16px 16px;
362
+ display: flex;
363
+ justify-content: space-between;
364
+ gap: 16px;
365
+ }
366
+
367
+ .modalFooter button {
368
+ flex: 1;
369
+ }
370
+
371
+ .modalFooter button:only-child {
372
+ width: 100%;
373
+ }
374
+
375
+ /* Deprecated - gardé pour backward compatibility */
298
376
  .modalButtons {
377
+ flex-shrink: 0;
378
+ padding: 0 2rem 2rem 2rem;
379
+ background: #fff;
380
+ border-radius: 0 0 16px 16px;
299
381
  display: flex;
300
382
  justify-content: space-between;
301
383
  gap: 16px;
302
- margin-top: auto;
303
384
  }
304
385
 
305
386
  .modalButtons button {
@@ -322,7 +403,6 @@
322
403
  position: fixed;
323
404
  bottom: 0;
324
405
  justify-content: flex-start;
325
- padding: 2rem;
326
406
  border-bottom-left-radius: 0;
327
407
  border-bottom-right-radius: 0;
328
408
  max-height: none;
@@ -330,6 +410,21 @@
330
410
  max-width: 100%;
331
411
  }
332
412
 
413
+ .modalHeader {
414
+ padding: 1.5rem 2rem 0 2rem;
415
+ border-radius: 0;
416
+ }
417
+
418
+ .modalBody {
419
+ padding: 1rem 2rem;
420
+ }
421
+
422
+ .modalFooter,
423
+ .modalButtons {
424
+ padding: 0 2rem 1.5rem 2rem;
425
+ border-radius: 0;
426
+ }
427
+
333
428
  .modalOverlay {
334
429
  padding-top: 0 !important;
335
430
  padding-bottom: 0 !important;
@@ -123,4 +123,6 @@ export const WithLargeContentAndMaxWidth: any;
123
123
  export const WithCustomBreakpoints: any;
124
124
  export const WithManyBreakpoints: any;
125
125
  export const WithMixedUnitsBreakpoints: any;
126
+ export const WithScrollableContent: any;
127
+ export const WithScrollableContentMobile: any;
126
128
  import Modal from "./Modal";
@@ -307,3 +307,67 @@ WithMixedUnitsBreakpoints.args = __assign(__assign({}, Default.args), { title: "
307
307
  { breakpoint: 1200, maxWidth: 900 },
308
308
  ],
309
309
  } });
310
+ // Nouvelle story pour tester le scroll avec header/footer fixes
311
+ export var WithScrollableContent = Template.bind({});
312
+ WithScrollableContent.args = {
313
+ show: false,
314
+ title: "Modal avec contenu scrollable",
315
+ description: "Cette modal contient beaucoup de contenu pour tester le comportement de scroll. Le header (titre + bouton fermer) et le footer (boutons) doivent rester fixes pendant que seul le corps de la modal défile.",
316
+ confirmLabel: "Valider",
317
+ cancelLabel: "Annuler",
318
+ children: (React.createElement("div", { style: { textAlign: "left" } },
319
+ React.createElement("h3", { style: { marginBottom: "1rem", color: "#1f2937" } }, "Contenu tr\u00E8s long pour tester le scroll"),
320
+ Array.from({ length: 20 }, function (_, i) { return (React.createElement("div", { key: i, style: {
321
+ marginBottom: "1.5rem",
322
+ padding: "1rem",
323
+ backgroundColor: i % 2 === 0 ? "#f9fafb" : "#f3f4f6",
324
+ borderRadius: "0.5rem",
325
+ border: "1px solid #e5e7eb",
326
+ } },
327
+ React.createElement("h4", { style: { margin: "0 0 0.5rem 0", color: "#374151" } },
328
+ "Section ",
329
+ i + 1),
330
+ React.createElement("p", { style: { margin: 0, color: "#6b7280", lineHeight: "1.6" } }, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."),
331
+ i === 5 && (React.createElement("div", { style: {
332
+ marginTop: "1rem",
333
+ padding: "1rem",
334
+ backgroundColor: "#dbeafe",
335
+ borderRadius: "0.375rem",
336
+ border: "1px solid #93c5fd",
337
+ } },
338
+ React.createElement("p", { style: { margin: 0, fontSize: "0.875rem", color: "#1e40af" } },
339
+ "\uD83D\uDCA1 ",
340
+ React.createElement("strong", null, "Note importante :"),
341
+ " Pendant que vous scrollez ce contenu, v\u00E9rifiez que le titre en haut et les boutons en bas restent toujours visibles et fixes."))),
342
+ i === 10 && (React.createElement("div", { style: {
343
+ marginTop: "1rem",
344
+ padding: "1rem",
345
+ backgroundColor: "#ecfdf5",
346
+ borderRadius: "0.375rem",
347
+ border: "1px solid #86efac",
348
+ } },
349
+ React.createElement("p", { style: { margin: 0, fontSize: "0.875rem", color: "#047857" } },
350
+ "\u2705 ",
351
+ React.createElement("strong", null, "Test r\u00E9ussi :"),
352
+ " Si vous voyez ce message au milieu du scroll, l'architecture header/body/footer fonctionne correctement !"))))); }),
353
+ React.createElement("div", { style: {
354
+ padding: "1.5rem",
355
+ backgroundColor: "#fef2f2",
356
+ borderRadius: "0.5rem",
357
+ border: "2px solid #fecaca",
358
+ textAlign: "center",
359
+ } },
360
+ React.createElement("h4", { style: { margin: "0 0 1rem 0", color: "#dc2626" } }, "\uD83C\uDFAF Fin du contenu scrollable"),
361
+ React.createElement("p", { style: { margin: 0, color: "#991b1b", fontSize: "0.875rem" } }, "Vous avez atteint la fin du contenu. Les boutons Annuler/Valider doivent toujours \u00EAtre visibles en bas de la modal.")))),
362
+ };
363
+ // Story pour tester sur viewport mobile restreint
364
+ export var WithScrollableContentMobile = Template.bind({});
365
+ WithScrollableContentMobile.args = __assign(__assign({}, WithScrollableContent.args), { title: "Test mobile - Scroll fixe", description: "Version optimisée pour tester le comportement sur écrans mobiles avec hauteur réduite." });
366
+ WithScrollableContentMobile.parameters = {
367
+ viewport: {
368
+ defaultViewport: "mobile1",
369
+ },
370
+ backgrounds: {
371
+ default: "light",
372
+ },
373
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allaw-ui",
3
- "version": "3.7.1",
3
+ "version": "3.7.3",
4
4
  "description": "Composants UI pour l'application Allaw",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",