Skip to content

Commit 140d895

Browse files
committed
styling, icons, modal
1 parent 59957ea commit 140d895

File tree

4 files changed

+260
-20
lines changed

4 files changed

+260
-20
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
## Version 1.2.0 (2026-02-05)
44

5+
### ✨ Neue Features
6+
- **Modal-Modus**: Eigenes Modal-System für platzsparende Layouts
7+
- `data-relation-mode="modal"` aktiviert Modal-Darstellung
8+
- **Badge mit Anzahl** ausgewählter Einträge (live-Update)
9+
- Badge ist grau bei 0, blau bei Auswahl
10+
- Input-Feld wird ausgeblendet (nur Button sichtbar)
11+
- Frontend-kompatibel (keine Bootstrap-Abhängigkeit)
12+
- ESC-Taste zum Schließen
13+
- Body-Scroll-Lock während Modal aktiv
14+
- Smooth Animations mit Scale-Effekt
15+
- **Inline-Modus**: Standard-Darstellung (wie bisher)
16+
- **Dual-Mode-Support**: Frei wählbar per Attribut
17+
518
### 🔒 Security
619
- **XSS-Schutz**: Labels und Values werden jetzt korrekt escaped in JavaScript
720
- **Type Safety**: Strikte Typ-Prüfungen für alle API-Parameter implementiert

README.md

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@ Ermöglicht die Auswahl und Sortierung verknüpfter Datensätze mit erweiterten
2929

3030
## Anwendung
3131

32-
### Basis-Konfiguration
32+
### Modi
3333

34-
Das AddOn wird automatisch initialisiert, sobald ein Input-Feld das Attribut `data-relation-config` hat:
34+
Das AddOn unterstützt zwei Anzeigemodi:
35+
36+
#### **Inline-Modus (Standard)**
37+
Widget wird direkt unterhalb des Input-Feldes angezeigt:
3538

3639
```html
3740
<input type="text"
@@ -44,16 +47,58 @@ Das AddOn wird automatisch initialisiert, sobald ein Input-Feld das Attribut `da
4447
>
4548
```
4649

47-
**Hinweis:** Das Attribut `data-relation-mode` ist optional und wird aktuell nicht verwendet. Die Widget-Darstellung erfolgt immer inline.
50+
#### **Modal-Modus**
51+
Widget wird in einem Overlay-Dialog geöffnet (ideal für platzsparende Layouts und Frontend-Verwendung):
52+
53+
```html
54+
<input type="text"
55+
name="my_field"
56+
data-relation-mode="modal"
57+
data-relation-config='{
58+
"table": "rex_article",
59+
"valueField": "id",
60+
"labelField": "name"
61+
}'
62+
>
63+
```
64+
65+
**Modal-Features:**
66+
- 🎯 Eigenes Modal-System (keine Bootstrap-Abhängigkeit)
67+
-**Badge mit Anzahl** ausgewählter Einträge (live-Update)
68+
- 📱 Frontend-kompatibel
69+
- ⌨️ ESC-Taste zum Schließen
70+
- 🎨 Dark-Theme-Support
71+
- 📱 Responsive Design
72+
- 🔒 Body-Scroll-Lock während Modal offen ist
73+
- 💨 Smooth Animations
74+
75+
**UX im Modal-Modus:**
76+
- Input-Feld wird ausgeblendet
77+
- Button zeigt Badge mit Anzahl der Auswahlen
78+
- Badge ist grau bei 0 Einträgen, blau bei Auswahl
79+
- Live-Update der Badge-Anzahl bei Änderungen
4880

4981
### Beispiel für eine Relation in YForm
5082

5183
Das Feld wird als **Textfeld** mit dem Namen der Relation angelegt (z.B. `autoren_id`).
5284

5385
Bei den **individuellen Attributen** des Feldes wird folgendes eingetragen:
5486

87+
**Inline-Modus:**
88+
```json
89+
{
90+
"data-relation-config": "{
91+
\"table\": \"rex_autoren\",
92+
\"valueField\": \"id\",
93+
\"labelField\": \"vorname|nachname\"
94+
}"
95+
}
96+
```
97+
98+
**Modal-Modus:**
5599
```json
56100
{
101+
"data-relation-mode": "modal",
57102
"data-relation-config": "{
58103
\"table\": \"rex_autoren\",
59104
\"valueField\": \"id\",
@@ -69,6 +114,7 @@ Bei den **individuellen Attributen** des Feldes wird folgendes eingetragen:
69114
```html
70115
<input type="text"
71116
name="authors"
117+
data-relation-mode="modal"
72118
data-relation-config='{
73119
"table": "rex_authors",
74120
"valueField": "id",

assets/relation_select.css

Lines changed: 120 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
/* Relation Select AddOn Styles */
22

3+
/* SVG Icons */
4+
.relation-select-icon {
5+
display: inline-block;
6+
vertical-align: middle;
7+
fill: currentColor;
8+
}
9+
310
.relation-select-widget {
411
display: flex;
512
gap: 20px;
@@ -42,13 +49,26 @@
4249
margin-bottom: 5px;
4350
border-radius: 3px;
4451
background: var(--rex-panel-bg, #fff);
45-
transition: background-color 0.2s;
52+
transition: background-color 0.2s, border-color 0.2s;
4653
}
4754

4855
.relation-select-list li:hover {
4956
background-color: var(--rex-hover-bg, #f8f9fa);
5057
}
5158

59+
/* Available items are clickable */
60+
.relation-select-item-available {
61+
cursor: pointer;
62+
}
63+
64+
.relation-select-item-available:hover {
65+
border-color: var(--rex-link-color, #007bff);
66+
}
67+
68+
.relation-select-item-available .title {
69+
cursor: pointer;
70+
}
71+
5272
.relation-select-list li:last-child {
5373
margin-bottom: 0;
5474
}
@@ -64,6 +84,7 @@
6484
cursor: move;
6585
color: var(--rex-text-muted, #6c757d);
6686
margin-right: 5px;
87+
flex-shrink: 0;
6788
}
6889

6990
.relation-select-list .handle:hover {
@@ -73,17 +94,18 @@
7394
.relation-select-list .btn-link {
7495
padding: 2px 8px;
7596
color: var(--rex-link-color, #007bff);
97+
flex-shrink: 0;
7698
}
7799

78100
.relation-select-list .btn-link:hover {
79101
color: var(--rex-link-hover-color, #0056b3);
80102
}
81103

82-
.relation-select-list .add-item i {
104+
.relation-select-list .add-item .relation-select-icon {
83105
color: var(--rex-success-color, #28a745);
84106
}
85107

86-
.relation-select-list .remove-item i {
108+
.relation-select-list .remove-item .relation-select-icon {
87109
color: var(--rex-danger-color, #dc3545);
88110
}
89111

@@ -113,6 +135,27 @@
113135

114136
.relation-select-open-modal {
115137
margin-top: 5px;
138+
position: relative;
139+
}
140+
141+
.relation-select-badge {
142+
display: inline-block;
143+
min-width: 20px;
144+
padding: 3px 7px;
145+
font-size: 11px;
146+
font-weight: 600;
147+
line-height: 1;
148+
color: var(--rex-text-muted, #999);
149+
background-color: var(--rex-border-light, #e9ecef);
150+
border-radius: 10px;
151+
margin-left: 8px;
152+
transition: all 0.2s ease;
153+
}
154+
155+
.relation-select-badge.has-items {
156+
color: #fff;
157+
background-color: var(--rex-link-color, #007bff);
158+
transform: scale(1.1);
116159
}
117160

118161
.relation-select-modal {
@@ -303,6 +346,43 @@ body.rex-theme-dark .relation-select-list li:focus-within {
303346
outline-color: #409be4;
304347
}
305348

349+
body.rex-theme-dark .relation-select-modal-dialog {
350+
background: #202b35;
351+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
352+
}
353+
354+
body.rex-theme-dark .relation-select-modal-header,
355+
body.rex-theme-dark .relation-select-modal-footer {
356+
border-color: #26323f;
357+
}
358+
359+
body.rex-theme-dark .relation-select-modal-title {
360+
color: rgba(255, 255, 255, 0.75);
361+
}
362+
363+
body.rex-theme-dark .relation-select-modal-close {
364+
color: rgba(255, 255, 255, 0.45);
365+
}
366+
367+
body.rex-theme-dark .relation-select-modal-close:hover {
368+
background-color: #26323f;
369+
color: rgba(255, 255, 255, 0.75);
370+
}
371+
372+
body.rex-theme-dark .relation-select-modal-overlay {
373+
background: rgba(0, 0, 0, 0.7);
374+
}
375+
376+
body.rex-theme-dark .relation-select-badge {
377+
color: rgba(255, 255, 255, 0.45);
378+
background-color: #26323f;
379+
}
380+
381+
body.rex-theme-dark .relation-select-badge.has-items {
382+
color: #fff;
383+
background-color: #409be4;
384+
}
385+
306386
/* Apply dark theme based on system preference (auto mode) */
307387
@media (prefers-color-scheme: dark) {
308388
body:not(.rex-theme-light) .relation-select-available,
@@ -359,6 +439,43 @@ body.rex-theme-dark .relation-select-list li:focus-within {
359439
body:not(.rex-theme-light) .relation-select-list li:focus-within {
360440
outline-color: #409be4;
361441
}
442+
443+
body:not(.rex-theme-light) .relation-select-modal-dialog {
444+
background: #202b35;
445+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
446+
}
447+
448+
body:not(.rex-theme-light) .relation-select-modal-header,
449+
body:not(.rex-theme-light) .relation-select-modal-footer {
450+
border-color: #26323f;
451+
}
452+
453+
body:not(.rex-theme-light) .relation-select-modal-title {
454+
color: rgba(255, 255, 255, 0.75);
455+
}
456+
457+
body:not(.rex-theme-light) .relation-select-modal-close {
458+
color: rgba(255, 255, 255, 0.45);
459+
}
460+
461+
body:not(.rex-theme-light) .relation-select-modal-close:hover {
462+
background-color: #26323f;
463+
color: rgba(255, 255, 255, 0.75);
464+
}
465+
466+
body:not(.rex-theme-light) .relation-select-modal-overlay {
467+
background: rgba(0, 0, 0, 0.7);
468+
}
469+
470+
body:not(.rex-theme-light) .relation-select-badge {
471+
color: rgba(255, 255, 255, 0.45);
472+
background-color: #26323f;
473+
}
474+
475+
body:not(.rex-theme-light) .relation-select-badge.has-items {
476+
color: #fff;
477+
background-color: #409be4;
478+
}
362479
}
363480

364481

0 commit comments

Comments
 (0)