@nyaruka/temba-components 0.157.1 → 0.158.0

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.
@@ -21,36 +21,39 @@ const SCHEMES = {
21
21
  export class ContactDetails extends ContactStoreElement {
22
22
  static get styles() {
23
23
  return css`
24
- .urn {
25
- display: flex;
26
- padding: 0.4em 1em 0.8em 1em;
27
- border-bottom: 1px solid #e6e6e6;
28
- margin-bottom: 0.5em;
24
+ .wrapper {
25
+ padding-top: 0em;
29
26
  }
30
27
 
31
- .urn .path {
32
- margin-left: 0.2em;
28
+ /* Mirrors the disabled <temba-contact-field> row so the Groups
29
+ entry reads as just another field — same label color/size,
30
+ same horizontal inset, same bottom separator. Margin matches
31
+ the combined .wrapper + :host margins of contact-field
32
+ (0.5em + 1em) so spacing between rows stays uniform. */
33
+ .row {
34
+ padding-bottom: 0.6em;
35
+ border-bottom: 1px solid #ececec;
36
+ margin-bottom: 1.5em;
33
37
  }
34
38
 
35
- .wrapper {
36
- padding-top: 0em;
39
+ .row .label {
40
+ color: var(--text-2);
41
+ font-size: 12px;
42
+ font-weight: var(--w-medium);
43
+ margin-top: 0.25em;
44
+ margin-left: 0.25em;
37
45
  }
38
46
 
39
- .groups {
40
- padding: 0.4em 0.5em 0.6em 0.5em;
41
- border-bottom: 1px solid #e6e6e6;
42
- margin-bottom: 0.4em;
43
- }
44
- .group {
45
- margin-right: 0.7em;
46
- margin-bottom: 0.7em;
47
+ .row .value {
48
+ margin-left: 0.25em;
49
+ margin-top: 0.1em;
50
+ min-height: 1.75em;
51
+ display: flex;
52
+ flex-wrap: wrap;
53
+ gap: 0.4em;
47
54
  }
48
55
 
49
- .label {
50
- font-size: 0.8em;
51
- color: rgb(136, 136, 136);
52
- margin-left: 0.5em;
53
- margin-bottom: 0.4em;
56
+ .group {
54
57
  }
55
58
  `;
56
59
  }
@@ -68,20 +71,22 @@ export class ContactDetails extends ContactStoreElement {
68
71
  return html`
69
72
  <div class="wrapper">
70
73
  ${this.data.groups.length > 0
71
- ? html` <div class="groups">
74
+ ? html` <div class="row">
72
75
  <div class="label">Groups</div>
73
- ${this.data.groups.map((group) => {
74
- return html`<temba-label
75
- class="group"
76
- onclick="goto(event)"
77
- href="/contact/group/${group.uuid}/"
78
- icon=${group.is_dynamic ? Icon.group_smart : Icon.group}
79
- type="group"
80
- clickable
81
- >
82
- ${group.name}
83
- </temba-label>`;
84
- })}
76
+ <div class="value">
77
+ ${this.data.groups.map((group) => {
78
+ return html`<temba-label
79
+ class="group"
80
+ onclick="goto(event)"
81
+ href="/contact/group/${group.uuid}/"
82
+ icon=${group.is_dynamic ? Icon.group_smart : Icon.group}
83
+ type="group"
84
+ clickable
85
+ >
86
+ ${group.name}
87
+ </temba-label>`;
88
+ })}
89
+ </div>
85
90
  </div>`
86
91
  : null}
87
92
  ${this.data.urns.map((urn) => {
@@ -93,51 +93,34 @@ export class ContactFieldEditor extends RapidElement {
93
93
  --color-widget-border: rgb(235, 235, 235);
94
94
  }
95
95
 
96
- .prefix {
97
- border-top-left-radius: var(--curvature-widget);
98
- border-bottom-left-radius: var(--curvature-widget);
99
- cursor: pointer !important;
100
- white-space: nowrap;
101
- overflow: hidden;
102
- text-overflow: ellipsis;
103
- display: flex;
104
- /* Pin to the top-left of the host (temba-select :host is
105
- position: relative). Using top rather than margin-top keeps
106
- the absolute element out of the flex flow of .left-side so
107
- it doesn't push the selected value down. */
108
- position: absolute;
109
- top: -0.6em;
110
- left: 0.5em;
111
- pointer-events: none;
112
- background: #fff;
113
- border-radius: var(--curvature);
114
- }
115
-
116
- temba-select .prefix {
117
- top: -0.7em;
118
- }
119
-
120
96
  .wrapper {
121
97
  margin-bottom: 0.5em;
122
98
  }
123
99
 
124
- .prefix .name,
125
- .label .name {
126
- padding: 0em 0.4em;
127
- color: rgba(100, 100, 100, 0.7);
100
+ .field-label {
101
+ display: block;
102
+ font-size: 12px;
103
+ font-weight: var(--w-medium);
104
+ color: var(--text-2);
105
+ margin: 0 0 4px 2px;
128
106
  white-space: nowrap;
129
107
  overflow: hidden;
130
108
  text-overflow: ellipsis;
131
- font-size: 0.8em;
109
+ }
110
+
111
+ .label .name {
112
+ color: var(--text-2);
113
+ font-size: 12px;
114
+ font-weight: var(--w-medium);
132
115
  }
133
116
 
134
117
  .disabled .name {
135
- margin-top: 1em;
136
- margin-left: 0.75em;
118
+ margin-top: 0.25em;
119
+ margin-left: 0.25em;
137
120
  }
138
121
 
139
122
  .disabled .value {
140
- margin-left: 0.9em;
123
+ margin-left: 0.25em;
141
124
  margin-top: 0.1em;
142
125
  min-height: 1.75em;
143
126
  }
@@ -426,27 +409,30 @@ export class ContactFieldEditor extends RapidElement {
426
409
  }
427
410
 
428
411
  private renderDateField(state: TemplateResult) {
429
- return html` <temba-datepicker
430
- timezone=${this.timezone}
431
- value="${this.value ? this.value : ''}"
432
- @change=${this.handleDateChange}
433
- ?disabled=${this.disabled}
434
- time
435
- >
436
- <div class="prefix" slot="prefix">
437
- <div class="name">${this.name}</div>
438
- </div>
439
- <div class="postfix" slot="postfix">
440
- <div class="popper ${this.status} ${this.dirty ? 'dirty' : ''}">
441
- ${state}
412
+ return html`
413
+ <label id="field-label" class="field-label">${this.name}</label>
414
+ <temba-datepicker
415
+ aria-labelledby="field-label"
416
+ timezone=${this.timezone}
417
+ value="${this.value ? this.value : ''}"
418
+ @change=${this.handleDateChange}
419
+ ?disabled=${this.disabled}
420
+ time
421
+ >
422
+ <div class="postfix" slot="postfix">
423
+ <div class="popper ${this.status} ${this.dirty ? 'dirty' : ''}">
424
+ ${state}
425
+ </div>
442
426
  </div>
443
- </div>
444
- </temba-datepicker>`;
427
+ </temba-datepicker>
428
+ `;
445
429
  }
446
430
 
447
431
  private renderTextField(state: TemplateResult) {
448
432
  return html`
433
+ <label id="field-label" class="field-label">${this.name}</label>
449
434
  <temba-textinput
435
+ aria-labelledby="field-label"
450
436
  class="${this.status} ${this.dirty ? 'dirty' : ''}"
451
437
  value="${this.value ? this.value : ''}"
452
438
  @keyup=${this.handleInput}
@@ -454,10 +440,6 @@ export class ContactFieldEditor extends RapidElement {
454
440
  type=${this.getInputType(this.type)}
455
441
  ?disabled=${this.disabled}
456
442
  >
457
- <div class="prefix" slot="prefix">
458
- <div class="name">${this.name}</div>
459
- </div>
460
-
461
443
  <div class="postfix">
462
444
  <div
463
445
  class="popper ${this.iconClass} ${this.status} ${this.dirty
@@ -506,7 +488,9 @@ export class ContactFieldEditor extends RapidElement {
506
488
 
507
489
  public renderLocationField(level: string = 'state') {
508
490
  return html`
491
+ <label id="field-label" class="field-label">${this.name}</label>
509
492
  <temba-select
493
+ aria-labelledby="field-label"
510
494
  endpoint="/api/internal/locations.json?level=${level}"
511
495
  nameKey="path"
512
496
  valueKey="path"
@@ -516,14 +500,10 @@ export class ContactFieldEditor extends RapidElement {
516
500
  queryParam="query"
517
501
  searchable
518
502
  clearable
519
- inpsutStyle=${JSON.stringify({ 'margin-top': '1.1em !important;' })}
520
503
  values=${this.value
521
504
  ? JSON.stringify([{ path: this.value, osm_id: this.value }])
522
505
  : '[]'}
523
506
  >
524
- <div class="prefix" slot="prefix">
525
- <div class="name">${this.name}</div>
526
- </div>
527
507
  </temba-select>
528
508
  `;
529
509
  }
@@ -66,9 +66,8 @@ export class ContactFields extends ContactStoreElement {
66
66
 
67
67
  .toggle {
68
68
  display: flex;
69
- background: #fff;
70
69
  align-items: center;
71
- margin-bottom: 0.5em;
70
+ margin-top: 0.5em;
72
71
  }
73
72
 
74
73
  .disabled .toggle {
@@ -3,6 +3,7 @@ import { property } from 'lit/decorators.js';
3
3
  import { ContactStoreElement } from './ContactStoreElement';
4
4
  import { getDisplayName } from './ContactChat';
5
5
  import { ContactNote, CustomEventType } from '../interfaces';
6
+ import { designTokens } from '../styles/designTokens';
6
7
 
7
8
  export class ContactNotepad extends ContactStoreElement {
8
9
  @property({ type: Object, attribute: false })
@@ -14,9 +15,12 @@ export class ContactNotepad extends ContactStoreElement {
14
15
 
15
16
  static get styles() {
16
17
  return css`
18
+ ${designTokens}
19
+
17
20
  :host {
18
21
  height: 100%;
19
22
  display: flex;
23
+ margin-top: var(--gap);
20
24
  }
21
25
 
22
26
  .wrapper {
@@ -24,9 +28,13 @@ export class ContactNotepad extends ContactStoreElement {
24
28
  --color-widget-bg: transparent;
25
29
  --color-widget-bg-focused: transparent;
26
30
  outline: none;
27
- border-radius: var(--curvature);
28
31
  display: flex;
29
32
  flex-direction: column;
33
+ background: var(--surface-note);
34
+ border: 1px solid var(--border-note);
35
+ border-radius: var(--r-sm);
36
+ box-shadow: var(--shadow-2);
37
+ overflow: hidden;
30
38
  }
31
39
 
32
40
  .notepad {
@@ -92,6 +92,7 @@ export class ContactPending extends EndpointMonitorElement {
92
92
  display: flex;
93
93
  flex-direction: row;
94
94
  align-items: center;
95
+ background: var(--surface);
95
96
  box-shadow:
96
97
  0 0 8px 1px rgba(0, 0, 0, 0.055),
97
98
  0 0 0px 1px rgba(0, 0, 0, 0.02);
@@ -32,9 +32,11 @@ export const designTokens = css`
32
32
  /* neutrals */
33
33
  --bg: #f6f7f9;
34
34
  --surface: #ffffff;
35
+ --surface-note: #fff9c2;
35
36
  --sunken: #f1f3f5;
36
37
  --border: #e6e8ec;
37
38
  --border-strong: #d2d6dc;
39
+ --border-note: #ebdf6f;
38
40
  --text-1: #1a1f26;
39
41
  --text-2: #4d5664;
40
42
  --text-3: #7b8593;
@@ -30,9 +30,11 @@
30
30
  /* neutrals */
31
31
  --bg: #F6F7F9;
32
32
  --surface: #FFFFFF;
33
+ --surface-note: #FFF9C2;
33
34
  --sunken: #F1F3F5;
34
35
  --border: #E6E8EC;
35
36
  --border-strong: #D2D6DC;
37
+ --border-note: #EBDF6F;
36
38
  --text-1: #1A1F26;
37
39
  --text-2: #4D5664;
38
40
  --text-3: #7B8593;