superdesk-ui-framework 5.0.3 → 5.0.5

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.
Files changed (34) hide show
  1. package/app/scripts/helpers/dropdown.helper.js +9 -0
  2. package/app/styles/_buttons.scss +4 -1
  3. package/app/styles/_helpers.scss +25 -6
  4. package/app/styles/_popover.scss +8 -8
  5. package/app/styles/_tooltips.scss +83 -0
  6. package/app/styles/design-tokens/_design-tokens-general.scss +6 -0
  7. package/app/styles/form-elements/_checkbox.scss +9 -5
  8. package/app/styles/form-elements/_inputs.scss +7 -1
  9. package/app-typescript/components/Autocomplete.tsx +1 -1
  10. package/app-typescript/components/DatePicker.tsx +1 -0
  11. package/app-typescript/components/Form/InputWrapper.tsx +1 -1
  12. package/app-typescript/components/Popover.tsx +2 -0
  13. package/app-typescript/components/SelectGrid.tsx +3 -1
  14. package/app-typescript/components/Tooltip.tsx +1 -1
  15. package/app-typescript/components/TooltipV2.tsx +10 -21
  16. package/app-typescript/components/_Positioner.tsx +2 -0
  17. package/dist/components/Popover.tsx +31 -8
  18. package/dist/components/Tooltips.tsx +15 -13
  19. package/dist/components/utilities/SpacingUtilities.tsx +126 -126
  20. package/dist/components/utilities/TextUtilities.tsx +51 -37
  21. package/dist/examples.bundle.js +265 -195
  22. package/dist/superdesk-ui.bundle.css +146 -41
  23. package/dist/superdesk-ui.bundle.js +28 -25
  24. package/package.json +1 -1
  25. package/react/components/Autocomplete.js +2 -1
  26. package/react/components/DatePicker.js +1 -1
  27. package/react/components/Form/InputWrapper.js +2 -1
  28. package/react/components/Popover.d.ts +1 -0
  29. package/react/components/Popover.js +1 -1
  30. package/react/components/SelectGrid.js +2 -1
  31. package/react/components/Tooltip.js +1 -1
  32. package/react/components/TooltipV2.js +10 -18
  33. package/react/components/_Positioner.d.ts +1 -0
  34. package/react/components/_Positioner.js +1 -1
@@ -192,6 +192,15 @@ angular.module('superdesk-ui.helper.dropdown', ['superdesk-ui.helper.position'])
192
192
  }
193
193
 
194
194
  $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass).then(() => {
195
+ // NOTE: this checks whether there is at least one dropdown open - not only this instance
196
+ const legacyAngularDropdownOpen = document.querySelector('.dropdown.open') != null;
197
+
198
+ if (legacyAngularDropdownOpen) {
199
+ document.body.classList.add('legacyAngularDropdownOpen');
200
+ } else {
201
+ document.body.classList.remove('legacyAngularDropdownOpen');
202
+ }
203
+
195
204
  if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
196
205
  toggleInvoker($scope, {open: !!isOpen});
197
206
  }
@@ -372,6 +372,7 @@ $icn-button-focus-box-shadow: 0 0 0 2px $sd-colour--focus-shadow;
372
372
  [class^="icon-"], [class*=" icon-"] {
373
373
  color: var(--color-icon-default) !important;
374
374
  vertical-align: baseline !important;
375
+ pointer-events: none;
375
376
  }
376
377
 
377
378
  &:hover {
@@ -401,8 +402,10 @@ $icn-button-focus-box-shadow: 0 0 0 2px $sd-colour--focus-shadow;
401
402
  }
402
403
  }
403
404
 
404
- &--disabled {
405
+ &--disabled,
406
+ &:disabled {
405
407
  opacity: $icn-button-opacity-disabled;
408
+ pointer-events: none;
406
409
 
407
410
  &:hover, &:active, &:focus-visible {
408
411
  background-color: transparent !important;
@@ -1866,21 +1866,22 @@ h6 {
1866
1866
 
1867
1867
  // LINE HIGHT
1868
1868
  .line-height-1 {
1869
- line-height: 1;
1869
+ line-height: var(--l-height-none);
1870
1870
  }
1871
1871
  .line-height-xs {
1872
- line-height: 1.1;
1872
+ line-height: var(--l-height-xs);
1873
1873
  }
1874
1874
  .line-height-sm {
1875
- line-height: 1.2;
1875
+ line-height: var(--l-height-sm);
1876
1876
  }
1877
1877
  .line-height-md {
1878
- line-height: 1.4;
1878
+ line-height: var(--l-height-md);
1879
1879
  }
1880
1880
  .line-height-lg {
1881
- line-height: 1.5;
1881
+ line-height: var(--l-height-lg);
1882
1882
  }
1883
1883
 
1884
+
1884
1885
  // LINE CLAMP
1885
1886
  // limit the number of horizontal lines in an elemnt (e.g. <p>)
1886
1887
  // it doesn't work if the element has set flex-grow: 1;
@@ -2204,6 +2205,8 @@ h6 {
2204
2205
  container-type: inline-size;
2205
2206
  container-name: left-panel;
2206
2207
  }
2208
+
2209
+
2207
2210
  .new-form-layout {
2208
2211
  --form-group-gap: var(--gap-5);
2209
2212
  --form-layout-gap: var(--gap-4);
@@ -2216,22 +2219,38 @@ h6 {
2216
2219
  background-color: var(--color-surface-base);
2217
2220
  border-radius: var(--b-radius--large);
2218
2221
  border: 1px solid var(--color-line-light);
2219
-
2220
2222
  .new-form-heading {
2221
2223
  font-family: $baseFontFamilySerif;
2222
2224
  font-weight: 900;
2223
2225
  font-size: var(--form-heading-font-size);
2224
2226
  line-height: 1.2;
2225
2227
  }
2228
+ legend {
2229
+ float: left;
2230
+ }
2226
2231
  }
2227
2232
  .new-form-group {
2228
2233
  display: flex;
2229
2234
  gap: var(--form-group-gap);
2235
+ &.new-form-group--grid {
2236
+ display: grid;
2237
+ grid-template-columns: repeat(4, 1fr);
2238
+ gap: var(--form-group-gap);
2239
+ }
2230
2240
  }
2231
2241
  .new-form-group-item {
2232
2242
  display: flex;
2233
2243
  flex-direction: column;
2234
2244
  flex-grow: 1;
2245
+ &.new-form-group-item--span-2 {
2246
+ grid-column: span 2;
2247
+ }
2248
+ &.new-form-group-item--span-3 {
2249
+ grid-column: span 3;
2250
+ }
2251
+ &.new-form-group-item--span-4 {
2252
+ grid-column: span 4;
2253
+ }
2235
2254
  }
2236
2255
 
2237
2256
  @container left-panel (width <= 900px) {
@@ -1,9 +1,9 @@
1
1
  .sd-popover {
2
- background: var(--sd-colour-bg--05);
3
- color: #fff;
4
- padding: 8px 12px 12px;
5
- border-radius: $border-radius__base--medium;
6
- box-shadow: 0 3px 7px rgba(0,0,0,0.3);
2
+ background: var(--color-surface-base);
3
+ color: var(--color-text-default);
4
+ padding: var(--space--1) var(--space--1-5) var(--space--1-5);
5
+ border-radius: var(--b-radius--medium);
6
+ box-shadow: var(--sd-shadow--z4);
7
7
  max-width: 320px !important;
8
8
  }
9
9
 
@@ -11,15 +11,15 @@
11
11
  display: flex;
12
12
  justify-content: space-between;
13
13
  align-items: center;
14
- margin-block-end: 4px;
14
+ margin-block-end: var(--space--0-5);
15
15
  min-height: 20px;
16
16
  }
17
17
 
18
18
  .sd-popover__title {
19
- font-size: 11px;
19
+ font-size: var(--text-size-xx-small);
20
20
  line-height: 1;
21
21
  text-transform: uppercase;
22
- color: #ccc;
22
+ color: var(--color-text-muted);
23
23
  padding: 0;
24
24
  margin: 0;
25
25
  }
@@ -340,3 +340,86 @@
340
340
  .p-tooltip-right {
341
341
  margin-inline-start: 8px;
342
342
  }
343
+
344
+
345
+
346
+
347
+ // NEW TOOLTIP STYLES ----------------------------------------------------------------------------
348
+
349
+ .tooltip {
350
+ --tooltip-arrow_border: 6px;
351
+ margin: calc(var(--tooltip-arrow_border) / 2);
352
+ border-radius: var(--b-radius--medium);
353
+ padding: var(--space--1) var(--space--1-5);
354
+ font-size: var(--text-size-small);
355
+ position: relative;
356
+ background-color: var(--sd-colour-background__tooltip);
357
+ box-shadow: var(--sd-shadow--z3);
358
+ color: var(--color-text-ondark);
359
+ opacity: 1;
360
+ transition: opacity 400ms ease-out, margin 200ms ease-out;
361
+ transition-behavior: allow-discrete;
362
+
363
+ @starting-style {
364
+ opacity: 0;
365
+ }
366
+
367
+ &::before {
368
+ content: '';
369
+ border: var(--tooltip-arrow_border) solid transparent;
370
+ border-width: var(--tooltip-arrow_border);
371
+ z-index: 1001;
372
+ user-select: none;
373
+ pointer-events: none;
374
+ position: absolute;
375
+ overflow: hidden;
376
+ }
377
+ }
378
+
379
+ [data-popper-placement^="top"] {
380
+ .tooltip {
381
+ margin-block-end: var(--tooltip-arrow_border);
382
+ &::before {
383
+ inset-block-end: calc(var(--tooltip-arrow_border) * -1);
384
+ inset-inline-start: calc(50% - var(--tooltip-arrow_border));
385
+ border-bottom-width: 0;
386
+ border-top-color: var(--sd-colour-background__tooltip);
387
+ }
388
+ }
389
+ }
390
+
391
+ [data-popper-placement^="bottom"] {
392
+ .tooltip {
393
+ margin-block-start: var(--tooltip-arrow_border);
394
+ &::before {
395
+ inset-block-start: calc(var(--tooltip-arrow_border) * -1);
396
+ inset-inline-start: calc(50% - var(--tooltip-arrow_border));
397
+ border-top-width: 0;
398
+ border-bottom-color: var(--sd-colour-background__tooltip);
399
+ }
400
+ }
401
+ }
402
+
403
+ [data-popper-placement^="left"] {
404
+ .tooltip {
405
+ margin-inline-end: var(--tooltip-arrow_border);
406
+ &::before {
407
+ inset-inline-end: calc(var(--tooltip-arrow_border) * -1);
408
+ inset-block-start: calc(50% - var(--tooltip-arrow_border));
409
+ border-right-width: 0;
410
+ border-left-color: var(--sd-colour-background__tooltip);
411
+ }
412
+ }
413
+ }
414
+
415
+ [data-popper-placement^="right"] {
416
+ .tooltip {
417
+ margin-inline-start: var(--tooltip-arrow_border);
418
+ &::before {
419
+ inset-inline-start: calc(var(--tooltip-arrow_border) * -1);
420
+ inset-block-start: calc(50% - var(--tooltip-arrow_border));
421
+ border-left-width: 0;
422
+ border-right-color: var(--sd-colour-background__tooltip);
423
+ }
424
+ }
425
+ }
@@ -70,6 +70,12 @@
70
70
  --text-size-x-large: calc(var(--text-size--base) * 2.4); // 24px;
71
71
  --text-size-xx-large: calc(var(--text-size--base) * 3.2); // 32px;
72
72
 
73
+ // LINE HEIGHT
74
+ --l-height-none: 1;
75
+ --l-height-xs: 1.1;
76
+ --l-height-sm: 1.2;
77
+ --l-height-md: 1.4;
78
+ --l-height-lg: 1.5;
73
79
 
74
80
  // SHADOW
75
81
  --sd-shadow--z1: 0 0 0 1px var(--sd-shadow-outline), 0 1px 3px hsla(0, 0%, 0%, 0.16), 0 0 1px hsla(0, 0%, 0%, 0.1);
@@ -8,8 +8,9 @@ $checkButtonBorderColorHover: var(--sd-colour-line--strong);
8
8
  $checkButtonBorderRadius: $border-radius__base--small;
9
9
 
10
10
  @mixin check-base {
11
- width: 1.6rem;
12
- height: 1.6rem;
11
+ --check-size: 1.6rem;
12
+ width: var(--check-size);
13
+ height: var(--check-size);
13
14
  display: inline-block;
14
15
  position: relative;
15
16
  background: transparent;
@@ -17,6 +18,7 @@ $checkButtonBorderRadius: $border-radius__base--small;
17
18
  vertical-align: middle;
18
19
  font-family: $baseFontFamily;
19
20
  transition: all 0.2s ease-out;
21
+ flex: 0 0 var(--check-size);
20
22
  }
21
23
 
22
24
  .sd-checkbox {
@@ -132,7 +134,8 @@ $checkButtonBorderRadius: $border-radius__base--small;
132
134
  }
133
135
 
134
136
  i + label {
135
- margin-inline-start: 8px;
137
+ margin-inline-start: var(--space--1);
138
+ font-size: var(--text-size-small);
136
139
  }
137
140
 
138
141
  &::after {
@@ -383,7 +386,7 @@ $checkButtonBorderRadius: $border-radius__base--small;
383
386
  }
384
387
 
385
388
  i + .sd-check-button__text-label {
386
- margin-inline-start: $sd-base-increment;
389
+ margin-inline-start: var(--space--1);
387
390
  }
388
391
 
389
392
  &:hover {
@@ -501,7 +504,8 @@ $checkButtonBorderRadius: $border-radius__base--small;
501
504
 
502
505
  .sd-check-new + label,
503
506
  .sd-radio-new + label {
504
- margin-inline-start: $sd-base-increment;
507
+ margin-inline-start: var(--space--1);
508
+ font-size: var(--text-size-small);
505
509
  }
506
510
 
507
511
  .sd-check-new + label:empty,
@@ -781,7 +781,7 @@ input[type="color" i].sd-input__color-input::-webkit-color-swatch {
781
781
  margin: 0;
782
782
  display: grid;
783
783
  grid-template-columns: auto 1fr auto;
784
- grid-template-rows: $form-label-height auto auto;
784
+ grid-template-rows: $form-label-height auto 1fr;
785
785
  grid-gap: 0;
786
786
  position: relative;
787
787
  align-self: stretch;
@@ -940,6 +940,12 @@ input[type="color" i].sd-input__color-input::-webkit-color-swatch {
940
940
  margin: 0;
941
941
  grid-row: 1/2;
942
942
  grid-column: 2/4;
943
+ span {
944
+ overflow: hidden;
945
+ text-overflow: ellipsis;
946
+ white-space: nowrap;
947
+ max-width: 100%;
948
+ }
943
949
  }
944
950
 
945
951
  .sd-input__label--required::after {
@@ -126,7 +126,7 @@ export class Autocomplete extends React.Component<IProps, IState> {
126
126
  <div className={classes}>
127
127
  {this.props.label && !this.props.isSearchField ? (
128
128
  <label className="sd-input__label" htmlFor={this.htmlId}>
129
- {this.props.label}
129
+ <span>{this.props.label}</span>
130
130
  </label>
131
131
  ) : null}
132
132
 
@@ -304,6 +304,7 @@ export class DatePickerISO extends React.PureComponent<IDatePickerISO> {
304
304
  }}
305
305
  disabled={this.props.disabled}
306
306
  preview={this.props.preview}
307
+ hideClearButton={this.props.hideClearButton}
307
308
  headerButtonBar={this.props.headerButtonBar}
308
309
  dateFormat={this.props.dateFormat}
309
310
  locale={this.props.locale}
@@ -95,7 +95,7 @@ export class InputWrapper extends React.Component<IProps, IState> {
95
95
  id={this.props.htmlId + 'label'}
96
96
  tabIndex={this.props.tabindex === undefined ? undefined : -1}
97
97
  >
98
- {this.props.label}
98
+ <span>{this.props.label}</span>
99
99
  </label>
100
100
  <div className="sd-input__input-container">{this.props.children}</div>
101
101
  {this.props.maxLength && (
@@ -7,6 +7,7 @@ interface IProps {
7
7
  triggerSelector: string; // CSS selector for an element that will be used to toggle the popover.
8
8
  displayCloseButton?: boolean; // defaults to true
9
9
  placement?: PopperOptions['placement']; // defaults to auto
10
+ theme?: 'light-ui' | 'dark-ui';
10
11
  }
11
12
 
12
13
  export class Popover extends React.Component<IProps> {
@@ -14,6 +15,7 @@ export class Popover extends React.Component<IProps> {
14
15
  return (
15
16
  <Positioner
16
17
  triggerSelector={this.props.triggerSelector}
18
+ theme={this.props.theme}
17
19
  placement={this.props.placement ?? 'auto'}
18
20
  className="sd-popover"
19
21
  >
@@ -171,7 +171,9 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
171
171
  aria-label={this.props.label}
172
172
  key={this.props.label}
173
173
  >
174
- <label className="sd-input__label">{this.props.label}</label>
174
+ <label className="sd-input__label">
175
+ <span>{this.props.label}</span>
176
+ </label>
175
177
  <TriggerTemplate onClick={this.mountPopup} />
176
178
  </div>
177
179
  <OverlayPanel
@@ -37,7 +37,7 @@ export class Tooltip extends React.PureComponent<IProps> {
37
37
  return (
38
38
  <TooltipV2 content={this.props.text ?? ''} placement={flowToPlacement(this.props.flow)}>
39
39
  {({attributes}) => (
40
- <div {...attributes} style={{display: 'inline-flex'}}>
40
+ <div {...attributes} style={{display: 'contents'}}>
41
41
  {this.props.children}
42
42
  </div>
43
43
  )}
@@ -24,27 +24,16 @@ export class TooltipV2 extends React.PureComponent<IPropsTooltipV2> {
24
24
  placement={this.props.placement ?? 'top'}
25
25
  component={() => {
26
26
  return (
27
- <div data-theme="dark-ui">
28
- <div
29
- style={{
30
- background: 'var(--color-bg-100)',
31
- color: 'var(--color-text)',
32
- borderRadius: 'var(--b-radius--medium)',
33
- paddingInline: 'var(--space--0-5)',
34
- fontSize: 'var(--text-size-x-small)',
35
- margin: 2,
36
- }}
37
- >
38
- {(() => {
39
- if (typeof this.props.content === 'string') {
40
- return <span>{this.props.content}</span>;
41
- } else {
42
- const Component = this.props.content;
27
+ <div className="tooltip">
28
+ {(() => {
29
+ if (typeof this.props.content === 'string') {
30
+ return <span>{this.props.content}</span>;
31
+ } else {
32
+ const Component = this.props.content;
43
33
 
44
- return <Component />;
45
- }
46
- })()}
47
- </div>
34
+ return <Component />;
35
+ }
36
+ })()}
48
37
  </div>
49
38
  );
50
39
  }}
@@ -63,7 +52,7 @@ export class TooltipV2 extends React.PureComponent<IPropsTooltipV2> {
63
52
  return this.props.children({attributes});
64
53
  } else {
65
54
  return (
66
- <span {...attributes} style={{display: 'inline-flex'}}>
55
+ <span {...attributes} style={{display: 'contents'}}>
67
56
  {this.props.children}
68
57
  </span>
69
58
  );
@@ -93,6 +93,7 @@ class PopperWrapper extends React.Component<IPropsPopperWrapper> {
93
93
  }}
94
94
  tabIndex={0}
95
95
  role="dialog"
96
+ data-theme={this.props.theme}
96
97
  aria-labelledby="popoverTitle"
97
98
  onKeyDown={(event) => {
98
99
  if (event.key === 'Escape') {
@@ -111,6 +112,7 @@ interface IPropsPositioner {
111
112
  triggerSelector: string;
112
113
  placement: PopperOptions['placement'];
113
114
  className?: string;
115
+ theme?: 'light-ui' | 'dark-ui';
114
116
  }
115
117
 
116
118
  interface IStatePositioner {
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import {Popover, PropsList, Prop} from '../../../app-typescript';
2
+ import {Popover, PropsList, Prop, Button, ButtonGroup} from '../../../app-typescript';
3
3
 
4
4
  import * as Markup from '../../js/react';
5
5
 
@@ -23,13 +23,20 @@ export class PopoverDoc extends React.Component {
23
23
  <Markup.ReactMarkupPreview>
24
24
  <div className="docs-page__content-row docs-page__content-row--no-margin">
25
25
  <div className="form__row">
26
- <button
27
- className="btn btn-default btn--small"
28
- aria-haspopup="true"
29
- id="button-view-content"
30
- >
31
- Open popover
32
- </button>
26
+ <ButtonGroup>
27
+ <Button
28
+ aria-haspopup="true"
29
+ id="button-view-content"
30
+ text="Open popover"
31
+ onClick={() => false}
32
+ />
33
+ <Button
34
+ aria-haspopup="true"
35
+ id="button-view-content-dark"
36
+ text="Open popover"
37
+ onClick={() => false}
38
+ />
39
+ </ButtonGroup>
33
40
 
34
41
  <Popover
35
42
  triggerSelector="#button-view-content"
@@ -38,6 +45,15 @@ export class PopoverDoc extends React.Component {
38
45
  >
39
46
  Donec sed odio dui. Aenean lacinia bibendum nulla sed consectetur.
40
47
  </Popover>
48
+ <Popover
49
+ triggerSelector="#button-view-content-dark"
50
+ title="Popover test"
51
+ placement="top-end"
52
+ theme="dark-ui"
53
+ >
54
+ Enforce a dark theme. Donec sed odio dui. Aenean lacinia bibendum nulla sed
55
+ consectetur.
56
+ </Popover>
41
57
  </div>
42
58
  </div>
43
59
  </Markup.ReactMarkupPreview>
@@ -83,6 +99,13 @@ export class PopoverDoc extends React.Component {
83
99
  default="auto"
84
100
  description="Define the placement of the Popover."
85
101
  />
102
+ <Prop
103
+ name="theme"
104
+ isRequired={false}
105
+ type="light-ui | dark-ui"
106
+ default="/"
107
+ description="Define the theme of the Popover. It will inherit the default theme if not set."
108
+ />
86
109
  </PropsList>
87
110
  </section>
88
111
  );
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
 
3
3
  import * as Markup from '../../js/react';
4
4
 
5
- import {Tooltip, Prop, PropsList, Button} from '../../../app-typescript';
5
+ import {Tooltip, Prop, PropsList, Button, ButtonGroup} from '../../../app-typescript';
6
6
 
7
7
  export default class TooltipDoc extends React.Component {
8
8
  render() {
@@ -20,18 +20,20 @@ export default class TooltipDoc extends React.Component {
20
20
  <Markup.ReactMarkup>
21
21
  <Markup.ReactMarkupPreview>
22
22
  <div className="docs-page__content-row docs-page__content-row--no-margin">
23
- <Tooltip content="I'm on top">
24
- <Button text="top" onClick={() => false} />
25
- </Tooltip>
26
- <Tooltip content="I'm at the bottom" placement="bottom">
27
- <Button text="bottom" onClick={() => false} />
28
- </Tooltip>
29
- <Tooltip content="I open on the left" placement="left">
30
- <Button text="left" onClick={() => false} />
31
- </Tooltip>
32
- <Tooltip content="Right on!" placement="right">
33
- <Button text="right" onClick={() => false} />
34
- </Tooltip>
23
+ <ButtonGroup>
24
+ <Tooltip content="I'm on top">
25
+ <Button text="top" onClick={() => false} />
26
+ </Tooltip>
27
+ <Tooltip content="I'm at the bottom" placement="bottom">
28
+ <Button text="bottom" onClick={() => false} />
29
+ </Tooltip>
30
+ <Tooltip content="I open on the left" placement="left">
31
+ <Button text="left" onClick={() => false} />
32
+ </Tooltip>
33
+ <Tooltip content="Right on!" placement="right">
34
+ <Button text="right" onClick={() => false} />
35
+ </Tooltip>
36
+ </ButtonGroup>
35
37
  </div>
36
38
  </Markup.ReactMarkupPreview>
37
39
  <Markup.ReactMarkupCode>