• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

keplergl / kepler.gl / 12604159536

03 Jan 2025 09:26PM UTC coverage: 66.843% (-0.5%) from 67.344%
12604159536

Pull #2892

github

web-flow
Merge 894aa31a5 into 0b67c5409
Pull Request #2892: [fix] Prevent infinite useEffects loop

5959 of 10355 branches covered (57.55%)

Branch coverage included in aggregate %.

13 of 16 new or added lines in 1 file covered. (81.25%)

484 existing lines in 25 files now uncovered.

12215 of 16834 relevant lines covered (72.56%)

89.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.75
/src/components/src/common/styled-components.tsx
1
// SPDX-License-Identifier: MIT
2
// Copyright contributors to the kepler.gl project
3

4
import {media} from '@kepler.gl/styles';
5
import {RGBColor} from '@kepler.gl/types';
6
import classnames from 'classnames';
7
import DatePicker from 'react-date-picker';
8
import TimePicker from 'react-time-picker';
9
import ReactTooltip from 'react-tooltip';
10
import styled from 'styled-components';
11

12
export const SelectText = styled.span`
10✔
13
  color: ${props => props.theme.labelColor};
10✔
14
  font-size: ${props => props.theme.selectFontSize};
10✔
15
  font-weight: 400;
16

17
  i {
18
    font-size: 13px;
19
    margin-right: 6px;
20
  }
21
`;
22

23
export const SelectTextBold = styled(SelectText)`
10✔
24
  color: ${props => props.theme.textColor};
10✔
25
  font-weight: 500;
26
`;
27

28
export const IconRoundSmall = styled.div`
10✔
29
  display: flex;
30
  width: 18px;
31
  height: 18px;
32
  border-radius: 9px;
33
  background-color: ${props => props.theme.secondaryBtnBgdHover};
28✔
34
  color: ${props => props.theme.secondaryBtnColor};
28✔
35
  align-items: center;
36
  justify-content: center;
37

38
  :hover {
39
    cursor: pointer;
40
    background-color: ${props => props.theme.secondaryBtnBgdHover};
28✔
41
  }
42
`;
43

44
export const CenterFlexbox = styled.div`
10✔
45
  display: flex;
46
  align-items: center;
47
`;
48

49
export const CenterVerticalFlexbox = styled.div`
10✔
50
  display: flex;
51
  flex-direction: column;
52
  align-items: center;
53
`;
54

55
export const EndHorizontalFlexbox = styled.div`
10✔
56
  display: flex;
57
  flex-direction: row;
58
  align-items: end;
59
`;
60

61
export const SpaceBetweenFlexbox = styled.div`
10✔
62
  display: flex;
63
  justify-content: space-between;
64
  margin-left: -16px;
65
`;
66

67
export const SBFlexboxItem = styled.div`
10✔
68
  flex-grow: 1;
69
  margin-left: 16px;
70
`;
71

72
export const SBFlexboxNoMargin = styled.div`
10✔
73
  display: flex;
74
  justify-content: space-between;
75
`;
76

77
export const PanelLabel = styled.label.attrs({
10✔
78
  className: 'side-panel-panel__label'
79
})`
80
  color: ${props => props.theme.labelColor};
231✔
81
  display: inline-block;
82
  font-size: 11px;
83
  font-weight: 400;
84
  margin-bottom: 4px;
85
  text-transform: capitalize;
86
`;
87

88
export const PanelLabelWrapper = styled.div.attrs({
10✔
89
  className: 'side-panel-panel__label-wrapper'
90
})`
91
  display: flex;
92
  align-items: self-start;
93
`;
94

95
export const PanelLabelBold = styled(PanelLabel)`
10✔
96
  font-weight: 500;
97
`;
98

99
export const PanelHeaderTitle = styled.span.attrs(props => ({
11✔
100
  className: classnames('side-panel-panel__header__title', props.className)
101
}))`
102
  color: ${props => props.theme.textColor};
11✔
103
  font-size: 13px;
104
  letter-spacing: 0.43px;
105
  text-transform: capitalize;
106
`;
107

108
export const PanelHeaderContent = styled.div`
10✔
109
  display: flex;
110
  align-items: center;
111
  color: ${props => props.theme.textColor};
26✔
112
  padding-left: 12px;
113

114
  .icon {
115
    color: ${props => props.theme.labelColor};
26✔
116
    display: flex;
117
    align-items: center;
118
    margin-right: 12px;
119
  }
120
`;
121

122
export const PanelContent = styled.div.attrs(props => ({
17✔
123
  className: classnames('side-panel-panel__content', props.className)
124
}))`
125
  background-color: ${props => props.theme.panelContentBackground};
17✔
126
  padding: 12px;
127
`;
128

129
interface SidePanelSectionProps {
130
  disabled?: boolean;
131
}
132

133
export const SidePanelSection = styled.div.attrs(props => ({
300✔
134
  className: classnames('side-panel-section', props.className)
135
}))<SidePanelSectionProps>`
136
  margin-bottom: 12px;
137

138
  opacity: ${props => (props.disabled ? 0.4 : 1)};
300✔
139
  pointer-events: ${props => (props.disabled ? 'none' : 'all')};
300✔
140
`;
141

142
export const SidePanelDivider = styled.div.attrs({
10✔
143
  className: 'side-panel-divider'
144
})`
145
  border-bottom: ${props => props.theme.sidepanelDividerBorder} solid
29✔
146
    ${props => props.theme.panelBorderColor};
29✔
147
  margin-bottom: ${props => props.theme.sidepanelDividerMargin}px;
29✔
148
  height: ${props => props.theme.sidepanelDividerHeight}px;
29✔
149
`;
150

151
type TooltipProps = {interactive?: boolean};
152
export const Tooltip = styled(ReactTooltip)<TooltipProps>`
10✔
153
  &.__react_component_tooltip {
154
    font-size: ${props => props.theme.tooltipFontSize};
366✔
155
    font-weight: 400;
156
    padding: 7px 18px;
157
    box-shadow: ${props => props.theme.tooltipBoxShadow};
366✔
158

159
    &.type-dark {
160
      background-color: ${props => props.theme.tooltipBg};
366✔
161
      color: ${props => props.theme.tooltipColor};
366✔
162
      &.place-bottom {
163
        :after {
164
          border-bottom-color: ${props => props.theme.tooltipBg};
366✔
165
        }
166
      }
167

168
      &.place-top {
169
        :after {
170
          border-top-color: ${props => props.theme.tooltipBg};
366✔
171
        }
172
      }
173

174
      &.place-right {
175
        :after {
176
          border-right-color: ${props => props.theme.tooltipBg};
366✔
177
        }
178
      }
179

180
      &.place-left {
181
        :after {
182
          border-left-color: ${props => props.theme.tooltipBg};
366✔
183
        }
184
      }
185
    }
186
  }
187
`;
188

189
export type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
190
  className?: string;
191
  ref?: React.ForwardedRef<HTMLElement>;
192
  children?: React.ReactNode;
193
  negative?: boolean;
194
  secondary?: boolean;
195
  link?: boolean;
196
  floating?: boolean;
197
  cta?: boolean;
198
  large?: boolean;
199
  small?: boolean;
200
  disabled?: boolean;
201
  width?: string;
202
  inactive?: boolean;
203
  size?: string;
204
};
205

206
// this needs to be an actual button to be able to set disabled attribute correctly
207
export const Button = styled.button.attrs(props => ({
462✔
208
  className: classnames('button', props.className)
209
}))<ButtonProps>`
210
  align-items: center;
211
  background-color: ${props =>
212
    props.negative
462!
213
      ? props.theme.negativeBtnBgd
214
      : props.secondary
462✔
215
      ? props.theme.secondaryBtnBgd
216
      : props.link
338✔
217
      ? props.theme.linkBtnBgd
218
      : props.floating
301!
219
      ? props.theme.floatingBtnBgd
220
      : props.cta
301✔
221
      ? props.theme.ctaBtnBgd
222
      : props.theme.primaryBtnBgd};
223
  border-radius: ${props => props.theme.primaryBtnRadius};
462✔
224
  color: ${props =>
225
    props.negative
462!
226
      ? props.theme.negativeBtnColor
227
      : props.secondary
462✔
228
      ? props.theme.secondaryBtnColor
229
      : props.link
338✔
230
      ? props.theme.linkBtnColor
231
      : props.floating
301!
232
      ? props.theme.floatingBtnColor
233
      : props.cta
301✔
234
      ? props.theme.ctaBtnColor
235
      : props.theme.primaryBtnColor};
236
  cursor: pointer;
237
  display: inline-flex;
238
  font-size: ${props =>
239
    props.large
462✔
240
      ? props.theme.primaryBtnFontSizeLarge
241
      : props.small
438✔
242
      ? props.theme.primaryBtnFontSizeSmall
243
      : props.theme.primaryBtnFontSizeDefault};
244
  font-weight: 500;
245
  font-family: ${props => props.theme.btnFontFamily};
462✔
246
  justify-content: center;
247
  letter-spacing: 0.3px;
248
  line-height: 14px;
249
  outline: 0;
250
  padding: ${props => (props.large ? '14px 32px' : props.small ? '6px 9px' : '9px 12px')};
462✔
251
  text-align: center;
252
  transition: ${props => props.theme.transition};
462✔
253
  vertical-align: middle;
254
  width: ${props => props.width || 'auto'};
462✔
255
  opacity: ${props => (props.disabled ? 0.4 : 1)};
462✔
256
  pointer-events: ${props => (props.disabled ? 'none' : 'all')};
462✔
257
  border: ${props =>
258
    props.negative
462!
259
      ? props.theme.negativeBtnBorder
260
      : props.secondary
462✔
261
      ? props.theme.secondaryBtnBorder
262
      : props.floating
338!
263
      ? props.theme.floatingBtnBorder
264
      : props.link
338✔
265
      ? props.theme.linkBtnBorder
266
      : props.theme.primaryBtnBorder};
267
  :hover,
268
  :focus,
269
  :active,
270
  &.active {
271
    background-color: ${props =>
272
      props.negative
462!
273
        ? props.theme.negativeBtnBgdHover
274
        : props.secondary
462✔
275
        ? props.theme.secondaryBtnBgdHover
276
        : props.link
338✔
277
        ? props.theme.linkBtnActBgdHover
278
        : props.floating
301!
279
        ? props.theme.floatingBtnBgdHover
280
        : props.cta
301✔
281
        ? props.theme.ctaBtnBgdHover
282
        : props.theme.primaryBtnBgdHover};
283
    color: ${props =>
284
      props.negative
462!
285
        ? props.theme.negativeBtnActColor
286
        : props.secondary
462✔
287
        ? props.theme.secondaryBtnActColor
288
        : props.link
338✔
289
        ? props.theme.linkBtnActColor
290
        : props.floating
301!
291
        ? props.theme.floatingBtnActColor
292
        : props.cta
301✔
293
        ? props.theme.ctaBtnActColor
294
        : props.theme.primaryBtnActColor};
295
  }
296

297
  svg {
298
    margin-right: ${props => (props.large ? '10px' : props.small ? '6px' : '8px')};
462✔
299
  }
300
`;
301

302
interface InputProps {
303
  secondary?: boolean;
304
}
305

306
export const Input = styled.input<InputProps>`
10✔
307
  ${props => (props.secondary ? props.theme.secondaryInput : props.theme.input)};
161✔
308
`;
309

310
export const InputLight = styled.input`
10✔
311
  ${props => props.theme.inputLT};
19✔
312
`;
313

314
export const TextArea = styled.textarea<InputProps>`
10✔
UNCOV
315
  ${props => (props.secondary ? props.theme.secondaryInput : props.theme.input)};
×
316
`;
317
export const TextAreaLight = styled.textarea`
10✔
318
  ${props => props.theme.inputLT} height: auto;
9✔
319
  white-space: pre-wrap;
320
`;
321

322
export const InlineInput = styled(Input)`
10✔
323
  ${props => props.theme.inlineInput};
26✔
324
`;
325

326
export interface StyledPanelHeaderProps {
327
  active?: boolean;
328
  labelRCGColorValues?: RGBColor | null;
329
  warning?: boolean;
330
  isValid?: boolean;
331
}
332

333
export const StyledPanelHeader = styled.div<StyledPanelHeaderProps>`
10✔
334
  background-color: ${props =>
335
    props.active ? props.theme.panelBackgroundHover : props.theme.panelBackground};
46✔
336
  border-left: 3px solid
337
    rgb(
338
      ${props => (props.labelRCGColorValues ? props.labelRCGColorValues.join(',') : 'transparent')}
46✔
339
    );
340
  padding: 0 10px 0 0;
341
  height: ${props => props.theme.panelHeaderHeight}px;
46✔
342
  display: flex;
343
  justify-content: space-between;
344
  align-items: center;
345
  border-radius: ${props => props.theme.panelHeaderBorderRadius};
46✔
346
  transition: ${props => props.theme.transition};
46✔
347
`;
348

349
interface StyledPanelDropdownProps {
350
  type?: string;
351
}
352

353
export const StyledPanelDropdown = styled.div<StyledPanelDropdownProps>`
10✔
354
  ${props => props.theme.panelDropdownScrollBar}
18✔
355
  background-color: ${props =>
356
    props.type === 'light' ? props.theme.modalDropdownBackground : props.theme.panelBackground};
18!
357
  overflow-y: auto;
358
  box-shadow: ${props => props.theme.panelBoxShadow};
18✔
359
  border-radius: ${props => props.theme.panelBorderRadius};
18✔
360
  max-height: 500px;
361
  position: relative;
362
  z-index: 999;
363
`;
364

365
export const ButtonGroup = styled.div`
10✔
366
  display: flex;
367
  .button {
368
    border-radius: 0;
369
    margin-left: 2px;
370
  }
371
  .button:first-child {
UNCOV
372
    border-bottom-left-radius: ${props => props.theme.primaryBtnRadius};
×
UNCOV
373
    border-top-left-radius: ${props => props.theme.primaryBtnRadius};
×
374
    margin-left: 0;
375
  }
376
  .button:last-child {
UNCOV
377
    border-bottom-right-radius: ${props => props.theme.primaryBtnRadius};
×
UNCOV
378
    border-top-right-radius: ${props => props.theme.primaryBtnRadius};
×
379
  }
380
`;
381

382
interface DatasetSquareProps {
383
  backgroundColor: RGBColor;
384
}
385

386
export const DatasetSquare = styled.div<DatasetSquareProps>`
10✔
387
  display: inline-block;
388
  width: 10px;
389
  height: 10px;
390
  background-color: rgb(${props => props.backgroundColor.join(',')});
41✔
391
  margin-right: 12px;
392
`;
393

394
interface SelectionButtonProps {
395
  selected?: boolean;
396
}
397

398
export const SelectionButton = styled.div<SelectionButtonProps>`
10✔
399
  position: relative;
400
  border-radius: 2px;
401
  border: 1px solid
402
    ${props =>
403
      props.selected
15✔
404
        ? props.theme.selectionBtnBorderActColor
405
        : props.theme.selectionBtnBorderColor};
406
  color: ${props =>
407
    props.selected ? props.theme.selectionBtnActColor : props.theme.selectionBtnColor};
15✔
408
  background-color: ${props =>
409
    props.selected ? props.theme.selectionBtnActBgd : props.theme.selectionBtnBgd};
15✔
410

411
  cursor: pointer;
412
  font-weight: 500;
413
  margin-right: 6px;
414
  padding: 6px 16px;
415

416
  :hover {
417
    color: ${props => props.theme.selectionBtnActColor};
15✔
418
    border: 1px solid ${props => props.theme.selectionBtnBorderActColor};
15✔
419
  }
420
`;
421

422
export const StyledTable = styled.table`
10✔
423
  width: 100%;
424
  border-spacing: 0;
425

426
  thead {
427
    tr th {
UNCOV
428
      background: ${props => props.theme.panelBackgroundLT};
×
UNCOV
429
      color: ${props => props.theme.titleColorLT};
×
430
      padding: 18px 12px;
431
      text-align: start;
432
    }
433
  }
434

435
  tbody {
436
    tr td {
UNCOV
437
      border-bottom: ${props => props.theme.panelBorderLT};
×
438
      padding: 12px;
439
    }
440
  }
441
`;
442

443
export const StyledModalContent = styled.div`
10✔
444
  background: ${props => props.theme.panelBackgroundLT};
23✔
445
  color: ${props => props.theme.textColorLT};
23✔
446
  display: flex;
447
  flex-direction: row;
448
  font-size: 10px;
449
  padding: 24px ${props => props.theme.modalLateralPadding};
23✔
450
  margin: 0 -${props => props.theme.modalLateralPadding};
23✔
451
  justify-content: space-between;
452
  ${media.portable`
453
    flex-direction: column;
454
    padding: 16px ${props => props.theme.modalPortableLateralPadding};
23✔
455
    margin: 0 -${props => props.theme.modalPortableLateralPadding};
23✔
456
  `};
457
`;
458

459
export const StyledModalVerticalPanel = styled.div.attrs({
10✔
460
  className: 'modal-vertical-panel'
461
})`
462
  display: flex;
463
  flex-direction: column;
464
  justify-content: space-around;
465
  font-size: 12px;
466

467
  .modal-section:first-child {
468
    margin-top: 24px;
469
    ${media.palm`
470
      margin-top: 0;
471
    `};
472
  }
473

474
  input {
475
    margin-right: 8px;
476
  }
477
`;
478

479
export const StyledModalSection = styled.div.attrs(({className}) => ({
18✔
480
  className: classnames('modal-section', className)
481
}))`
482
  margin-bottom: 32px;
483

484
  .modal-section-title {
485
    font-weight: 500;
486
  }
487
  .modal-section-subtitle {
488
    color: ${props => props.theme.subtextColorLT};
18✔
489
  }
490

491
  input {
492
    margin-top: 8px;
493
  }
494

495
  ${media.portable`
496
    margin-bottom: 24px;
497
  `};
498
  ${media.palm`
499
    margin-bottom: 16px;
500
  `};
501
`;
502

503
interface StyledModalInputFootnoteProps {
504
  error?: boolean;
505
}
506

507
export const StyledModalInputFootnote = styled.div.attrs({
10✔
508
  className: 'modal-input__footnote'
509
})<StyledModalInputFootnoteProps>`
510
  display: flex;
511
  justify-content: flex-end;
512
  color: ${props => (props.error ? props.theme.errorColor : props.theme.subtextColorLT)};
9!
513
  font-size: 10px;
514
`;
515
/**
516
 * Newer versions of mapbox.gl display an error message banner on top of the map by default
517
 * which will cause the map to display points in the wrong locations
518
 * This workaround will hide the error banner.
519
 */
520
export const StyledMapContainer = styled.div`
10✔
521
  width: 100%;
522
  height: 100%;
523
  .maplibregl-map {
524
    .maplibregl-missing-css {
525
      display: none;
526
    }
527
    .maplibregl-ctrl-attrib {
528
      display: none;
529
    }
530
  }
531
`;
532

533
export const StyledAttrbution = styled.div.attrs({
10✔
534
  className: 'maplibre-attribution-container'
535
})`
536
  bottom: 0;
537
  right: 0;
538
  position: absolute;
539
  display: block;
540
  margin: 0 10px 6px;
541
  z-index: 1;
542
  .attrition-link {
543
    display: flex;
544
    align-items: center;
545
    margin-left: 10px;
546

547
    a,
548
    .pipe-separator {
549
      margin-right: 2px;
550
      color: ${props => props.theme.labelColor};
28✔
551
    }
552

553
    .pipe-separator {
554
      text-decoration: none;
555
    }
556
  }
557

558
  .attrition-logo {
559
    display: flex;
560
    font-size: 10px;
561
    justify-content: flex-end;
562
    align-items: center;
563
    color: ${props => props.theme.labelColor};
28✔
564

565
    a.maplibregl-ctrl-logo {
566
      width: 72px;
567
      margin-left: 4px;
568
      background-size: contain;
569
    }
570
  }
571
  a,
572
  .pipe-separator {
573
    font-size: 10px;
574
  }
575

576
  ${media.palm`
577
    .attrition-logo a {
578
      width: 60px;
579
    }
580

581
    .attrition-link {
582
      line-height: 1em;
583
    }
584
  `};
585
`;
586

587
export interface StyledExportSectionProps {
588
  disabled?: boolean;
589
}
590

591
export const StyledExportSection = styled.div<StyledExportSectionProps>`
10✔
592
  display: flex;
593
  flex-direction: row;
594
  margin: 35px 0;
595
  width: 100%;
596
  color: ${props => props.theme.textColorLT};
58✔
597
  font-size: 12px;
598
  opacity: ${props => (props.disabled ? 0.3 : 1)};
58✔
599
  pointer-events: ${props => (props.disabled ? 'none' : 'all')};
58✔
600

601
  .description {
602
    width: 185px;
603
    .title {
604
      font-weight: 500;
605
      font-family: ${props => props.theme.fontFamilyMedium ?? props.theme.fontFamily};
58✔
606
    }
607
    .subtitle {
608
      color: ${props => props.theme.subtextColorLT};
58✔
609
      font-size: 11px;
610
    }
611
  }
612
  .warning {
613
    color: ${props => props.theme.errorColor};
58✔
614
    font-weight: 500;
615
  }
616
  .description.full {
617
    width: 100%;
618
  }
619
  .selection {
620
    display: flex;
621
    flex-wrap: wrap;
622
    flex: 1;
623
    padding-left: 50px;
624

625
    select {
626
      background-color: white;
627
      border-radius: 1px;
628
      display: inline-block;
629
      font: inherit;
630
      line-height: 1.5em;
631
      padding: 0.5em 3.5em 0.5em 1em;
632
      margin: 0;
633
      box-sizing: border-box;
634
      appearance: none;
635
      width: 250px;
636
      height: 36px;
637

638
      background-image: linear-gradient(45deg, transparent 50%, gray 50%),
639
        linear-gradient(135deg, gray 50%, transparent 50%), linear-gradient(to right, #ccc, #ccc);
640
      background-position: calc(100% - 20px) calc(1em + 2px), calc(100% - 15px) calc(1em + 2px),
641
        calc(100% - 2.5em) 4.5em;
642
      background-size: 5px 5px, 5px 5px, 1px 1.5em;
643
      background-repeat: no-repeat;
644
    }
645

646
    select:focus {
647
      background-image: linear-gradient(45deg, green 50%, transparent 50%),
648
        linear-gradient(135deg, transparent 50%, green 50%), linear-gradient(to right, #ccc, #ccc);
649
      background-position: calc(100% - 15px) 1em, calc(100% - 20px) 1em, calc(100% - 2.5em) 4.5em;
650
      background-size: 5px 5px, 5px 5px, 1px 1.5em;
651
      background-repeat: no-repeat;
652
      border-color: green;
653
      outline: 0;
654
    }
655
  }
656
`;
657

658
export const StyledFilteredOption = styled(SelectionButton)`
10✔
659
  align-items: center;
660
  display: flex;
661
  flex-direction: column;
662
  justify-content: center;
663
  margin: 4px;
664
  padding: 8px 12px;
665
  width: 140px;
666

667
  .filter-option-title {
UNCOV
668
    color: ${props => props.theme.textColorLT};
×
669
    font-size: 12px;
670
    font-weight: 500;
671
  }
672
  .filter-option-subtitle {
UNCOV
673
    color: ${props => props.theme.subtextColorLT};
×
674
    font-size: 11px;
675
  }
676
`;
677

678
export const StyledType = styled(SelectionButton)`
10✔
679
  height: 100px;
680
  margin: 4px;
681
  padding: 6px 10px;
682
  width: 100px;
683
`;
684

685
export const WidgetContainer = styled.div`
10✔
686
  z-index: 1;
687
`;
688

689
export const BottomWidgetInner = styled.div`
10✔
690
  background-color: ${props => props.theme.bottomWidgetBgd};
10✔
691
  padding: ${props => `${props.theme.bottomInnerPdVert}px ${props.theme.bottomInnerPdSide}px`};
10✔
692
  position: relative;
693
  margin-top: ${props => props.theme.bottomPanelGap}px;
10✔
694

695
  ${media.portable`
696
    border-top: 1px solid ${props => props.theme.panelBorderColor};
10✔
697
    border-left: 1px solid ${props => props.theme.panelBorderColor};
10✔
698
    padding: 12px 12px;
699
    margin-top: 0;
700
  `}
701
`;
702

703
interface MapControlButtonProps {
704
  active?: boolean;
705
}
706

707
export const MapControlButton = styled(Button).attrs(props => ({
218✔
708
  className: classnames('map-control-button', props.className)
709
}))<MapControlButtonProps>`
710
  box-shadow: 0 6px 12px 0 rgba(0, 0, 0, 0.16);
711
  height: 32px;
712
  width: 32px;
713
  padding: 0;
714
  border-radius: 0;
715
  background-color: ${props =>
716
    props.active ? props.theme.floatingBtnBgdHover : props.theme.floatingBtnBgd};
218✔
717
  color: ${props =>
718
    props.active ? props.theme.floatingBtnActColor : props.theme.floatingBtnColor};
218✔
719
  border: ${props =>
720
    props.active ? props.theme.floatingBtnBorderHover : props.theme.floatingBtnBorder};
218✔
721

722
  :hover,
723
  :focus,
724
  :active,
725
  &.active {
726
    background-color: ${props => props.theme.floatingBtnBgdHover};
218✔
727
    color: ${props => props.theme.floatingBtnActColor};
218✔
728
    border: ${props => props.theme.floatingBtnBorderHover};
218✔
729
  }
730
  svg {
731
    margin-right: 0;
732
  }
733
`;
734

735
export const StyledFilterContent = styled.div`
10✔
736
  background-color: ${props => props.theme.panelContentBackground};
5✔
737
  padding: 12px;
738
`;
739

740
export const TruncatedTitleText = styled.div`
10✔
741
  white-space: nowrap;
742
  text-overflow: ellipsis;
743
  overflow: hidden;
744
`;
745

746
export const CheckMark = styled.span.attrs({
10✔
747
  className: 'checkbox-inner'
748
})`
749
  background-color: ${props => props.theme.selectionBtnBorderActColor};
6✔
750
  position: absolute;
751
  top: 0;
752
  right: 0;
753
  display: block;
754
  width: 10px;
755
  height: 10px;
756
  border-top-left-radius: 2px;
757

758
  :after {
759
    position: absolute;
760
    display: table;
761
    border: 1px solid #fff;
762
    border-top: 0;
763
    border-left: 0;
764
    transform: rotate(45deg) scale(1) translate(-50%, -50%);
765
    opacity: 1;
766
    content: ' ';
767
    top: 40%;
768
    left: 30%;
769
    width: 3.2px;
770
    height: 6.22px;
771
  }
772
`;
773

774
export const StyledTimePicker = styled(TimePicker)`
10✔
775
  .react-time-picker {
776
    display: inline-flex;
777
    position: relative;
778
    font-family: ${props => props.theme.fontFamily};
8✔
779
    font-size: ${props => props.theme.inputFontSize};
8✔
780
    background-color: ${props => props.theme.inputBgd};
8✔
781
    color: ${props => props.theme.effectPanelTextMain};
8✔
782
  }
783
  .react-time-picker,
784
  .react-time-picker *,
785
  .react-time-picker *:before,
786
  .react-time-picker *:after {
787
    -moz-box-sizing: border-box;
788
    -webkit-box-sizing: border-box;
789
    box-sizing: border-box;
790
  }
791
  .react-time-picker__wrapper {
792
    display: flex;
793
    flex-grow: 1;
794
    flex-shrink: 0;
795
    background-color: ${props => props.theme.inputBgd};
8✔
796
    border-radius: 4px;
797
    width: 110px;
798
    white-space: nowrap;
799
  }
800
  .react-time-picker__wrapper:hover {
801
    background-color: ${props => props.theme.inputBgdHover};
8✔
802
  }
803
  .react-time-picker__inputGroup {
804
    min-width: calc((4px * 3) + 0.54em * 6 + 0.217em * 2);
805
    flex-grow: 1;
806
    padding: 4px 2px;
807
    box-sizing: content-box;
808
    display: flex;
809
    justify-content: end;
810
    align-items: center;
811
    height: 24px;
812
  }
813
  .react-time-picker__inputGroup__divider {
814
    padding: 1px 0;
815
    white-space: pre;
816
  }
817
  .react-time-picker__inputGroup__divider,
818
  .react-time-picker__inputGroup__leadingZero {
819
    display: inline-block;
820
    color: ${props => props.theme.effectPanelTextMain};
8✔
821
    font-family: ${props => props.theme.fontFamily};
8✔
822
    font-size: ${props => props.theme.inputFontSize};
8✔
823
    font-weight: 400;
824
  }
825
  .react-time-picker__inputGroup__input {
826
    min-width: 0.54em;
827
    height: 100%;
828
    position: relative;
829
    padding: 0 1px;
830
    border: 0;
831
    background: transparent;
832
    color: ${props => props.theme.effectPanelTextMain};
8✔
833
    font-family: ${props => props.theme.fontFamily};
8✔
834
    font-size: ${props => props.theme.inputFontSize};
8✔
835
    box-sizing: content-box;
836
    -webkit-appearance: textfield;
837
    -moz-appearance: textfield;
838
    appearance: textfield;
839
  }
840
  .react-time-picker__inputGroup__input:focus {
841
    outline: none;
842
  }
843
  .react-time-picker__inputGroup__input::-webkit-outer-spin-button,
844
  .react-time-picker__inputGroup__input::-webkit-inner-spin-button {
845
    -webkit-appearance: none;
846
    -moz-appearance: none;
847
    appearance: none;
848
    margin: 0;
849
  }
850
  .react-time-picker__inputGroup__input--hasLeadingZero {
851
    margin-left: -0.54em;
852
    padding-left: calc(1px + 0.54em);
853
  }
854
  .react-time-picker__inputGroup__amPm {
855
    max-width: 37px;
856
    font: inherit;
857
    font-weight: 400;
858
    -webkit-appearance: menulist;
859
    -moz-appearance: menulist;
860
    appearance: menulist;
861
    font-size: ${props => props.theme.inputFontSize};
8✔
862
  }
863
  .react-time-picker__button {
864
    border: 0;
865
    background-color: ${props => props.theme.inputBgd};
8✔
866
    padding: 4px 6px;
867
  }
868
  .react-time-picker__button:enabled {
869
    cursor: pointer;
870
  }
871
  .react-time-picker__button svg {
872
    display: inherit;
873
  }
874
  .react-time-picker__clock--closed,
875
  .react-time-picker__clear-button {
876
    display: none;
877
  }
878
`;
879

880
export const StyledDatePicker = styled(DatePicker)`
10✔
881
  .react-date-picker {
882
    display: inline-flex;
883
    position: relative;
884
    font-family: ${props => props.theme.fontFamily};
8✔
885
    font-size: ${props => props.theme.inputFontSize};
8✔
886
  }
887
  .react-date-picker,
888
  .react-date-picker *,
889
  .react-date-picker *:before,
890
  .react-date-picker *:after {
891
    -moz-box-sizing: border-box;
892
    -webkit-box-sizing: border-box;
893
    box-sizing: border-box;
894
  }
895
  .react-date-picker__wrapper {
896
    display: flex;
897
    flex-grow: 1;
898
    flex-shrink: 0;
899
    width: 108px;
900
    white-space: nowrap;
901
    border-radius: 4px;
902
  }
903
  .react-date-picker__inputGroup {
904
    min-width: calc((4px * 3) + 0.54em * 8 + 0.217em * 2);
905
    flex-grow: 1;
906
    padding: 4px 9px;
907
    box-sizing: content-box;
908
    background-color: ${props => props.theme.inputBgd};
8✔
909
    display: flex;
910
    justify-content: end;
911
    align-items: center;
912
    height: 22px;
913
    border: 1px solid ${props => props.theme.inputBgd};
8✔
914
    border-radius: 4px;
915
  }
916

917
  .react-date-picker__inputGroup:hover {
918
    background-color: ${props => props.theme.inputBgdHover};
8✔
919
  }
920
  .react-date-picker__inputGroup__divider {
921
    padding: 1px 0;
922
    white-space: pre;
923
    color: ${props => props.theme.effectPanelTextMain};
8✔
924
  }
925
  .react-date-picker__inputGroup__divider,
926
  .react-date-picker__inputGroup__leadingZero {
927
    display: inline-block;
928
  }
929
  .react-date-picker__inputGroup__input {
930
    min-width: 0.54em;
931
    height: 100%;
932
    position: relative;
933
    padding: 0 1px;
934
    border: 0;
935
    background: none;
936
    color: ${props => props.theme.effectPanelTextMain};
8✔
937
    font: inherit;
938
    font-size: ${props => props.theme.inputFontSize};
8✔
939
    box-sizing: content-box;
940
    -webkit-appearance: textfield;
941
    -moz-appearance: textfield;
942
    appearance: textfield;
943
  }
944
  .react-date-picker__inputGroup__input:focus {
945
    outline: none;
946
  }
947
  .react-date-picker__inputGroup__input::-webkit-outer-spin-button,
948
  .react-date-picker__inputGroup__input::-webkit-inner-spin-button {
949
    -webkit-appearance: none;
950
    -moz-appearance: none;
951
    appearance: none;
952
    margin: 0;
953
  }
954
  .react-date-picker__inputGroup__input:invalid {
955
    background: ${props => props.theme.inputBgd};
8✔
956
  }
957
  .react-date-picker__inputGroup__input--hasLeadingZero {
958
    margin-left: -0.54em;
959
    padding-left: calc(1px + 0.54em);
960
  }
961
  .react-date-picker__calendar {
962
    width: 257px;
963
    max-width: 100vw;
964
    z-index: 11;
965
    color: ${props => props.theme.effectPanelTextSecondary1};
8✔
966
    inset: auto !important;
967
  }
968
  .react-date-picker__calendar--closed {
969
    display: none;
970
  }
971
  .react-date-picker__calendar .react-calendar {
972
    border-width: thin;
973
  }
974
  .react-date-picker__button {
975
    display: none;
976
  }
977
  .react-calendar {
978
    width: 256px;
979
    max-width: 100%;
980
    color: ${props => props.theme.effectPanelTextSecondary1};
8✔
981
    background: ${props => props.theme.inputBgdHover};
8✔
982
    border-radius: 0px 4px 4px 4px;
983
    font-family: ${props => props.theme.fontFamily};
8✔
984
    line-height: 1.125em;
985
    padding: 16px;
986
  }
987
  .react-calendar,
988
  .react-calendar *,
989
  .react-calendar *:before,
990
  .react-calendar *:after {
991
    -moz-box-sizing: border-box;
992
    -webkit-box-sizing: border-box;
993
    box-sizing: border-box;
994
  }
995
  .react-calendar button {
996
    margin: 0;
997
    border: 0;
998
    outline: none;
999
  }
1000
  .react-calendar buttom:enabled {
1001
    color: ${props => props.theme.effectPanelTextMain};
8✔
1002
  }
1003
  .react-calendar button:enabled:hover {
1004
    cursor: pointer;
1005
  }
1006
  .react-calendar__navigation {
1007
    display: flex;
1008
    height: 25px;
1009
    margin-bottom: 1em;
1010
  }
1011
  .react-calendar__navigation button {
1012
    min-width: 25px;
1013
    background: none;
1014
  }
1015
  .react-calendar__navigation button:enabled:hover,
1016
  .react-calendar__navigation button:enabled:focus {
1017
    background-color: ${props => props.theme.inputBgdActive};
8✔
1018
  }
1019
  .react-calendar__month-view__weekdays {
1020
    text-align: center;
1021
    text-transform: uppercase;
1022
    font-weight: bold;
1023
  }
1024
  .react-calendar__month-view__weekdays__weekday {
1025
    color: ${props => props.theme.effectPanelTextSecondary2};
8✔
1026
    padding: 0.5em;
1027
    font-size: ${props => props.theme.inputFontSize};
8✔
1028
    abbr {
1029
      text-decoration: none;
1030
    }
1031
  }
1032
  .react-calendar__month-view__weekNumbers .react-calendar__tile {
1033
    display: flex;
1034
    align-items: center;
1035
    justify-content: center;
1036
    font-weight: bold;
1037
  }
1038
  .react-calendar__month-view__days__day--weekend {
1039
    color: ${props => props.theme.effectPanelTextSecondary1};
8✔
1040
  }
1041
  .react-calendar__month-view__days__day--neighboringMonth {
1042
    color: ${props => props.theme.effectPanelTextSecondary3};
8✔
1043
    opacity: 0.4;
1044
  }
1045
  .react-calendar__navigation__label__labelText,
1046
  .react-calendar__navigation__arrow {
1047
    color: ${props => props.theme.effectPanelTextMain};
8✔
1048
  }
1049
  .react-calendar__year-view .react-calendar__tile,
1050
  .react-calendar__decade-view .react-calendar__tile,
1051
  .react-calendar__century-view .react-calendar__tile {
1052
    padding: 2em 0.5em;
1053
  }
1054
  .react-calendar__tile {
1055
    color: ${props => props.theme.effectPanelTextSecondary1};
8✔
1056
    max-width: 100%;
1057
    padding: 6px 4px;
1058
    background: none;
1059
    text-align: center;
1060
    font-size: ${props => props.theme.inputFontSize};
8✔
1061
    height: 30px;
1062
  }
1063
  .react-calendar__tile:enabled:hover,
1064
  .react-calendar__tile:enabled:focus {
1065
    background-color: ${props => props.theme.primaryBtnBgd};
8✔
1066
    color: ${props => props.theme.primaryBtnActColor};
8✔
1067
  }
1068
  .react-calendar__tile--now:enabled:hover,
1069
  .react-calendar__tile--now:enabled:focus {
1070
    background: ${props => props.theme.primaryBtnBgd};
8✔
1071
    color: ${props => props.theme.effectPanelTextMain};
8✔
1072
  }
1073
  .react-calendar__tile--hasActive {
1074
    background: ${props => props.theme.primaryBtnActBgd};
8✔
1075
  }
1076
  .react-calendar__tile--hasActive:enabled:hover,
1077
  .react-calendar__tile--hasActive:enabled:focus {
1078
    background: ${props => props.theme.primaryBtnActBgd};
8✔
1079
    color: ${props => props.theme.effectPanelTextMain};
8✔
1080
  }
1081
  .react-calendar__tile--active {
1082
    background: ${props => props.theme.primaryBtnActBgd};
8✔
1083
    color: ${props => props.theme.effectPanelTextMain};
8✔
1084
    border-radius: 4px;
1085
  }
1086
  .react-calendar__tile--active:enabled:hover,
1087
  .react-calendar__tile--active:enabled:focus {
1088
    background: ${props => props.theme.primaryBtnActBgd};
8✔
1089
  }
1090
  .calendar__navigation__label__labelText {
1091
    сolor: ${props => props.theme.effectPanelTextMain};
8✔
1092
  }
1093
`;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc