@tsiky/components-r19 1.0.0 → 1.2.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.
Files changed (61) hide show
  1. package/index.ts +35 -33
  2. package/package.json +1 -1
  3. package/src/components/AnnouncementPanel/FlexRowContainer.css +17 -17
  4. package/src/components/AnnouncementPanel/FlexRowContainer.stories.tsx +329 -329
  5. package/src/components/AnnouncementPanel/FlexRowContainer.tsx +24 -24
  6. package/src/components/AnnouncementPanel/ListBox/CounterListBox.css +56 -56
  7. package/src/components/AnnouncementPanel/ListBox/CounterListBox.stories.tsx +292 -292
  8. package/src/components/AnnouncementPanel/ListBox/CounterListBox.tsx +106 -106
  9. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.css +57 -57
  10. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.stories.tsx +189 -189
  11. package/src/components/AnnouncementPanel/ListBox/SimpleListBox.tsx +138 -138
  12. package/src/components/AnnouncementPanel/ListBox/TrendListBox.css +61 -61
  13. package/src/components/AnnouncementPanel/ListBox/TrendListBox.stories.tsx +257 -257
  14. package/src/components/AnnouncementPanel/ListBox/TrendListBox.tsx +90 -90
  15. package/src/components/AnnouncementPanel/ListBox/index.ts +3 -3
  16. package/src/components/AnnouncementPanel/ListContentContainer.css +23 -23
  17. package/src/components/AnnouncementPanel/ListContentContainer.stories.tsx +212 -212
  18. package/src/components/AnnouncementPanel/ListContentContainer.tsx +33 -33
  19. package/src/components/AnnouncementPanel/index.ts +3 -3
  20. package/src/components/Charts/area-chart-admission/AreaChartAdmission.tsx +129 -89
  21. package/src/components/Charts/bar-chart/BarChart.tsx +171 -132
  22. package/src/components/Charts/boxplot-chart/BoxPlotChart.tsx +114 -114
  23. package/src/components/Charts/mixed-chart/MixedChart.tsx +65 -9
  24. package/src/components/Charts/sankey-adaptation/sankey.tsx +70 -70
  25. package/src/components/Charts/sankey-chart/SankeyChart.tsx +183 -155
  26. package/src/components/Confirmationpopup/ConfirmationPopup.module.css +88 -0
  27. package/src/components/Confirmationpopup/ConfirmationPopup.stories.tsx +94 -0
  28. package/src/components/Confirmationpopup/ConfirmationPopup.tsx +47 -0
  29. package/src/components/Confirmationpopup/index.ts +6 -0
  30. package/src/components/Confirmationpopup/useConfirmationPopup.ts +48 -0
  31. package/src/components/DayStatCard/DayStatCard.tsx +96 -69
  32. package/src/components/DraggableSwitcher/DraggableSwitcherButton.tsx +58 -58
  33. package/src/components/DraggableSwitcher/context/useDraggableSwitcher.tsx +45 -45
  34. package/src/components/DraggableSwitcher/index.ts +2 -2
  35. package/src/components/DynamicInput/input/SelectInput.tsx +75 -75
  36. package/src/components/DynamicInput/input/assets/SelectInput.module.css +95 -95
  37. package/src/components/DynamicTable/TableCell.tsx +38 -30
  38. package/src/components/DynamicTable/TableHeader.tsx +39 -34
  39. package/src/components/DynamicTable/TableauDynamique.module.css +1333 -1287
  40. package/src/components/DynamicTable/TableauDynamique.tsx +154 -154
  41. package/src/components/DynamicTable/tools/tableTypes.ts +63 -63
  42. package/src/components/Grid/Grid.tsx +5 -0
  43. package/src/components/Grid/grid.css +285 -285
  44. package/src/components/Header/Header.tsx +4 -2
  45. package/src/components/Header/header.css +61 -31
  46. package/src/components/MetricsPanel/MetricsPanel.module.css +688 -636
  47. package/src/components/MetricsPanel/MetricsPanel.tsx +220 -282
  48. package/src/components/MetricsPanel/renderers/CompactRenderer.tsx +148 -125
  49. package/src/components/NavBar/NavBar.tsx +1 -1
  50. package/src/components/NavItem/NavItem.tsx +58 -58
  51. package/src/components/PeriodRange/PeriodRange.module.css +158 -158
  52. package/src/components/PeriodRange/PeriodRange.tsx +130 -130
  53. package/src/components/SearchBar/SearchBar.css +40 -40
  54. package/src/components/SelectFilter/SelectFilter.module.css +249 -0
  55. package/src/components/SelectFilter/SelectFilter.stories.tsx +321 -0
  56. package/src/components/SelectFilter/SelectFilter.tsx +219 -0
  57. package/src/components/SelectFilter/index.ts +2 -0
  58. package/src/components/SelectFilter/types.ts +19 -0
  59. package/src/components/TranslationKey/TranslationKey.css +272 -272
  60. package/src/components/TranslationKey/TranslationKey.tsx +266 -245
  61. package/src/components/TrendList/TrendList.tsx +72 -45
@@ -1,158 +1,158 @@
1
- .wrapper {
2
- box-sizing: border-box;
3
- display: flex;
4
- align-items: center;
5
- gap: 12px;
6
- padding: 10px 16px;
7
- background: var(--color-card-background);
8
- border-radius: 10px;
9
- border: 1px solid rgba(16, 24, 40, 0.06);
10
- box-shadow: 0 1px 0 rgba(16, 24, 40, 0.03);
11
- width: 100%;
12
- }
13
-
14
- .label {
15
- display: inline-flex;
16
- align-items: center;
17
- gap: 8px;
18
- color: var(--color-text);
19
- font-size: 14px;
20
- flex: 0 0 auto;
21
- }
22
-
23
- .labelText {
24
- display: inline-block;
25
- color: var(--color-text);
26
- }
27
-
28
- .calendarIcon {
29
- opacity: 0.75;
30
- display: block;
31
- }
32
-
33
- .rangeRow {
34
- display: flex;
35
- align-items: center;
36
- gap: 10px;
37
- width: 100%;
38
- flex-wrap: nowrap;
39
- }
40
-
41
- .dateWrap {
42
- display: flex;
43
- flex-direction: column;
44
- gap: 6px;
45
- min-width: 0;
46
- flex: 1 1 0;
47
- }
48
-
49
- .innerLabel {
50
- font-size: 12px;
51
- color: #6b7280;
52
- display: block;
53
- }
54
-
55
- .dateInput {
56
- -webkit-appearance: none;
57
- appearance: none;
58
- border: 1px solid;
59
- padding: 8px 10px;
60
- border-radius: 8px;
61
- border-color: var(--color-border);
62
- font-size: 14px;
63
- background: transparent;
64
- width: 100%;
65
- box-sizing: border-box;
66
- color: var(--color-text);
67
- }
68
-
69
- .sepWrap {
70
- display: flex;
71
- align-items: center;
72
- justify-content: center;
73
- padding: 0 6px;
74
- }
75
-
76
- .separator {
77
- color: #9ca3af;
78
- font-weight: 600;
79
- user-select: none;
80
- }
81
-
82
- .samplingWrap {
83
- display: flex;
84
- /* position: absolute; */
85
- flex-direction: column;
86
- gap: 6px;
87
- min-width: 160px;
88
- flex: 0 0 auto;
89
- }
90
-
91
- .samplingLabel {
92
- font-size: 12px;
93
- color: #374151;
94
- }
95
-
96
- .samplingSelect {
97
- padding: 8px 10px;
98
- border-radius: 8px;
99
- border: 1px solid rgba(16, 24, 40, 0.06);
100
- background: var(--color-background);
101
- font-size: 14px;
102
- box-sizing: border-box;
103
- width: 100%;
104
- border-color: var(--color-border);
105
- color: var(--color-text);
106
- cursor: pointer;
107
- }
108
-
109
- /* Responsive: stack on smaller screens */
110
- @media (max-width: 720px) {
111
- .wrapper {
112
- padding: 10px;
113
- }
114
- .rangeRow {
115
- gap: 8px;
116
- }
117
- .label {
118
- font-size: 13px;
119
- }
120
- .samplingWrap {
121
- min-width: 140px;
122
- }
123
- }
124
-
125
- @media (max-width: 520px) {
126
- .wrapper {
127
- flex-direction: column;
128
- align-items: stretch;
129
- gap: 10px;
130
- }
131
-
132
- .label {
133
- order: 0;
134
- }
135
- .rangeRow {
136
- flex-direction: row;
137
- flex-wrap: wrap;
138
- align-items: flex-start;
139
- }
140
-
141
- .dateWrap {
142
- flex: 1 1 48%;
143
- }
144
- .sepWrap {
145
- display: none;
146
- }
147
-
148
- .samplingWrap {
149
- flex: 1 1 100%;
150
- min-width: 0;
151
- }
152
- }
153
-
154
- @media (max-width: 360px) {
155
- .dateWrap {
156
- flex: 1 1 100%;
157
- }
158
- }
1
+ .wrapper {
2
+ box-sizing: border-box;
3
+ display: flex;
4
+ align-items: center;
5
+ gap: 12px;
6
+ padding: 10px 16px;
7
+ background: var(--color-card-background);
8
+ border-radius: 10px;
9
+ border: 1px solid rgba(16, 24, 40, 0.06);
10
+ box-shadow: 0 1px 0 rgba(16, 24, 40, 0.03);
11
+ width: 100%;
12
+ }
13
+
14
+ .label {
15
+ display: inline-flex;
16
+ align-items: center;
17
+ gap: 8px;
18
+ color: var(--color-text);
19
+ font-size: 14px;
20
+ flex: 0 0 auto;
21
+ }
22
+
23
+ .labelText {
24
+ display: inline-block;
25
+ color: var(--color-text);
26
+ }
27
+
28
+ .calendarIcon {
29
+ opacity: 0.75;
30
+ display: block;
31
+ }
32
+
33
+ .rangeRow {
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 10px;
37
+ width: 100%;
38
+ flex-wrap: nowrap;
39
+ }
40
+
41
+ .dateWrap {
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: 6px;
45
+ min-width: 0;
46
+ flex: 1 1 0;
47
+ }
48
+
49
+ .innerLabel {
50
+ font-size: 12px;
51
+ color: #6b7280;
52
+ display: block;
53
+ }
54
+
55
+ .dateInput {
56
+ -webkit-appearance: none;
57
+ appearance: none;
58
+ border: 1px solid;
59
+ padding: 8px 10px;
60
+ border-radius: 8px;
61
+ border-color: var(--color-border);
62
+ font-size: 14px;
63
+ background: transparent;
64
+ width: 100%;
65
+ box-sizing: border-box;
66
+ color: var(--color-text);
67
+ }
68
+
69
+ .sepWrap {
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: center;
73
+ padding: 0 6px;
74
+ }
75
+
76
+ .separator {
77
+ color: #9ca3af;
78
+ font-weight: 600;
79
+ user-select: none;
80
+ }
81
+
82
+ .samplingWrap {
83
+ display: flex;
84
+ /* position: absolute; */
85
+ flex-direction: column;
86
+ gap: 6px;
87
+ min-width: 160px;
88
+ flex: 0 0 auto;
89
+ }
90
+
91
+ .samplingLabel {
92
+ font-size: 12px;
93
+ color: #374151;
94
+ }
95
+
96
+ .samplingSelect {
97
+ padding: 8px 10px;
98
+ border-radius: 8px;
99
+ border: 1px solid rgba(16, 24, 40, 0.06);
100
+ background: var(--color-background);
101
+ font-size: 14px;
102
+ box-sizing: border-box;
103
+ width: 100%;
104
+ border-color: var(--color-border);
105
+ color: var(--color-text);
106
+ cursor: pointer;
107
+ }
108
+
109
+ /* Responsive: stack on smaller screens */
110
+ @media (max-width: 720px) {
111
+ .wrapper {
112
+ padding: 10px;
113
+ }
114
+ .rangeRow {
115
+ gap: 8px;
116
+ }
117
+ .label {
118
+ font-size: 13px;
119
+ }
120
+ .samplingWrap {
121
+ min-width: 140px;
122
+ }
123
+ }
124
+
125
+ @media (max-width: 520px) {
126
+ .wrapper {
127
+ flex-direction: column;
128
+ align-items: stretch;
129
+ gap: 10px;
130
+ }
131
+
132
+ .label {
133
+ order: 0;
134
+ }
135
+ .rangeRow {
136
+ flex-direction: row;
137
+ flex-wrap: wrap;
138
+ align-items: flex-start;
139
+ }
140
+
141
+ .dateWrap {
142
+ flex: 1 1 48%;
143
+ }
144
+ .sepWrap {
145
+ display: none;
146
+ }
147
+
148
+ .samplingWrap {
149
+ flex: 1 1 100%;
150
+ min-width: 0;
151
+ }
152
+ }
153
+
154
+ @media (max-width: 360px) {
155
+ .dateWrap {
156
+ flex: 1 1 100%;
157
+ }
158
+ }
@@ -1,130 +1,130 @@
1
- /* File: components/PeriodRange/PeriodRange.tsx */
2
- 'use client';
3
- import { useEffect, useRef, useState } from 'react';
4
- import styles from './PeriodRange.module.css';
5
-
6
- export type Sampling = 'Par jour' | 'Par semaine' | 'Par mois' | 'Par heure';
7
-
8
- export interface PeriodRangeProps {
9
- start?: string; // 'YYYY-MM-DD' or 'YYYY-MM-DDTHH:mm'
10
- end?: string;
11
- onChange?: (range: { start: string; end: string }) => void;
12
- sampling?: Sampling;
13
- onSamplingChange?: (s: Sampling) => void;
14
- className?: string;
15
- }
16
-
17
- export default function PeriodRange({
18
- start = '',
19
- end = '',
20
- onChange,
21
- sampling = 'Par jour',
22
- onSamplingChange,
23
- className = '',
24
- }: PeriodRangeProps) {
25
- const [from, setFrom] = useState<string>(start);
26
- const [to, setTo] = useState<string>(end);
27
- const [localSampling, setLocalSampling] = useState<Sampling>(sampling);
28
- const containerRef = useRef<HTMLDivElement | null>(null);
29
-
30
- // keep local state in sync if parent changes props
31
- useEffect(() => setFrom(start), [start]);
32
- useEffect(() => setTo(end), [end]);
33
- useEffect(() => setLocalSampling(sampling), [sampling]);
34
-
35
- useEffect(() => {
36
- function handleClickOutside(e: MouseEvent) {
37
- const t = e.target as Node | null;
38
- if (containerRef.current && t && !containerRef.current.contains(t)) {
39
- // keep behaviour simple: we don't show custom popovers here
40
- }
41
- }
42
- document.addEventListener('mousedown', handleClickOutside);
43
- return () => document.removeEventListener('mousedown', handleClickOutside);
44
- }, []);
45
-
46
- useEffect(() => {
47
- onChange?.({ start: from, end: to });
48
- }, [from, to, onChange]);
49
-
50
- const handleSamplingChange = (s: Sampling) => {
51
- setLocalSampling(s);
52
- onSamplingChange?.(s);
53
- };
54
-
55
- return (
56
- <div className={`${styles.wrapper} ${className}`} ref={containerRef}>
57
- <label className={styles.label} aria-hidden>
58
- <svg
59
- className={styles.calendarIcon}
60
- xmlns='http://www.w3.org/2000/svg'
61
- viewBox='0 0 24 24'
62
- width='18'
63
- height='18'
64
- aria-hidden
65
- >
66
- <path fill='currentColor' d='M7 10h5v5H7z' opacity='0' />
67
- <path
68
- fill='currentColor'
69
- d='M19 4h-1V2h-2v2H8V2H6v2H5a2 2 0 00-2 2v12a2 2 0 002 2h14a2 2 0 002-2V6a2 2 0 00-2-2zM5 20V9h14l.002 11H5z'
70
- />
71
- </svg>
72
- <span className={styles.labelText}>Période</span>
73
- </label>
74
-
75
- <div className={styles.rangeRow}>
76
- <div className={styles.dateWrap}>
77
- <label className={styles.innerLabel} htmlFor='period-from'>
78
- Début
79
- </label>
80
- <input
81
- id='period-from'
82
- className={styles.dateInput}
83
- type='date'
84
- value={from}
85
- onChange={(e) => setFrom(e.target.value)}
86
- aria-label='Date de début'
87
- />
88
- </div>
89
-
90
- <div className={styles.sepWrap} aria-hidden>
91
- <span className={styles.separator}>—</span>
92
- </div>
93
-
94
- <div className={styles.dateWrap}>
95
- <label className={styles.innerLabel} htmlFor='period-to'>
96
- Fin
97
- </label>
98
- <div className={styles.inputWithIcon}>
99
- <input
100
- id='period-to'
101
- className={styles.dateInput}
102
- type='date'
103
- value={to}
104
- onChange={(e) => setTo(e.target.value)}
105
- aria-label='Date de fin'
106
- />
107
- </div>
108
- </div>
109
-
110
- <div className={styles.samplingWrap}>
111
- <label className={styles.samplingLabel} htmlFor='period-sampling'>
112
- Échantillonnage
113
- </label>
114
- <select
115
- id='period-sampling'
116
- className={styles.samplingSelect}
117
- value={localSampling}
118
- onChange={(e) => handleSamplingChange(e.target.value as Sampling)}
119
- aria-label='Échantillonnage'
120
- >
121
- <option>Par jour</option>
122
- <option>Par semaine</option>
123
- <option>Par mois</option>
124
- <option>Par heure</option>
125
- </select>
126
- </div>
127
- </div>
128
- </div>
129
- );
130
- }
1
+ /* File: components/PeriodRange/PeriodRange.tsx */
2
+ 'use client';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import styles from './PeriodRange.module.css';
5
+
6
+ export type Sampling = 'Par jour' | 'Par semaine' | 'Par mois' | 'Par heure';
7
+
8
+ export interface PeriodRangeProps {
9
+ start?: string; // 'YYYY-MM-DD' or 'YYYY-MM-DDTHH:mm'
10
+ end?: string;
11
+ onChange?: (range: { start: string; end: string }) => void;
12
+ sampling?: Sampling;
13
+ onSamplingChange?: (s: Sampling) => void;
14
+ className?: string;
15
+ }
16
+
17
+ export default function PeriodRange({
18
+ start = '',
19
+ end = '',
20
+ onChange,
21
+ sampling = 'Par jour',
22
+ onSamplingChange,
23
+ className = '',
24
+ }: PeriodRangeProps) {
25
+ const [from, setFrom] = useState<string>(start);
26
+ const [to, setTo] = useState<string>(end);
27
+ const [localSampling, setLocalSampling] = useState<Sampling>(sampling);
28
+ const containerRef = useRef<HTMLDivElement | null>(null);
29
+
30
+ // keep local state in sync if parent changes props
31
+ useEffect(() => setFrom(start), [start]);
32
+ useEffect(() => setTo(end), [end]);
33
+ useEffect(() => setLocalSampling(sampling), [sampling]);
34
+
35
+ useEffect(() => {
36
+ function handleClickOutside(e: MouseEvent) {
37
+ const t = e.target as Node | null;
38
+ if (containerRef.current && t && !containerRef.current.contains(t)) {
39
+ // keep behaviour simple: we don't show custom popovers here
40
+ }
41
+ }
42
+ document.addEventListener('mousedown', handleClickOutside);
43
+ return () => document.removeEventListener('mousedown', handleClickOutside);
44
+ }, []);
45
+
46
+ useEffect(() => {
47
+ onChange?.({ start: from, end: to });
48
+ }, [from, to, onChange]);
49
+
50
+ const handleSamplingChange = (s: Sampling) => {
51
+ setLocalSampling(s);
52
+ onSamplingChange?.(s);
53
+ };
54
+
55
+ return (
56
+ <div className={`${styles.wrapper} ${className}`} ref={containerRef}>
57
+ <label className={styles.label} aria-hidden>
58
+ <svg
59
+ className={styles.calendarIcon}
60
+ xmlns='http://www.w3.org/2000/svg'
61
+ viewBox='0 0 24 24'
62
+ width='18'
63
+ height='18'
64
+ aria-hidden
65
+ >
66
+ <path fill='currentColor' d='M7 10h5v5H7z' opacity='0' />
67
+ <path
68
+ fill='currentColor'
69
+ d='M19 4h-1V2h-2v2H8V2H6v2H5a2 2 0 00-2 2v12a2 2 0 002 2h14a2 2 0 002-2V6a2 2 0 00-2-2zM5 20V9h14l.002 11H5z'
70
+ />
71
+ </svg>
72
+ <span className={styles.labelText}>Période</span>
73
+ </label>
74
+
75
+ <div className={styles.rangeRow}>
76
+ <div className={styles.dateWrap}>
77
+ <label className={styles.innerLabel} htmlFor='period-from'>
78
+ Début
79
+ </label>
80
+ <input
81
+ id='period-from'
82
+ className={styles.dateInput}
83
+ type='date'
84
+ value={from}
85
+ onChange={(e) => setFrom(e.target.value)}
86
+ aria-label='Date de début'
87
+ />
88
+ </div>
89
+
90
+ <div className={styles.sepWrap} aria-hidden>
91
+ <span className={styles.separator}>—</span>
92
+ </div>
93
+
94
+ <div className={styles.dateWrap}>
95
+ <label className={styles.innerLabel} htmlFor='period-to'>
96
+ Fin
97
+ </label>
98
+ <div className={styles.inputWithIcon}>
99
+ <input
100
+ id='period-to'
101
+ className={styles.dateInput}
102
+ type='date'
103
+ value={to}
104
+ onChange={(e) => setTo(e.target.value)}
105
+ aria-label='Date de fin'
106
+ />
107
+ </div>
108
+ </div>
109
+
110
+ <div className={styles.samplingWrap}>
111
+ <label className={styles.samplingLabel} htmlFor='period-sampling'>
112
+ Échantillonnage
113
+ </label>
114
+ <select
115
+ id='period-sampling'
116
+ className={styles.samplingSelect}
117
+ value={localSampling}
118
+ onChange={(e) => handleSamplingChange(e.target.value as Sampling)}
119
+ aria-label='Échantillonnage'
120
+ >
121
+ <option>Par jour</option>
122
+ <option>Par semaine</option>
123
+ <option>Par mois</option>
124
+ <option>Par heure</option>
125
+ </select>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ );
130
+ }
@@ -1,40 +1,40 @@
1
- .search-container {
2
- position: relative;
3
- width: 100%;
4
- }
5
-
6
- .search-icon {
7
- position: absolute;
8
- left: 1rem;
9
- top: 50%;
10
- transform: translateY(-50%);
11
- width: 1.25rem;
12
- height: 1.25rem;
13
- color: #9ca3af;
14
- pointer-events: none;
15
- }
16
-
17
- .search-input {
18
- width: 100%;
19
- padding: 1rem 1rem 1rem 3rem; /* top right bottom left */
20
- border: 1px solid #d1d5db;
21
- border-radius: 0.5rem;
22
- outline: none;
23
- background-color: white;
24
- color: var(--color-text);
25
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
26
- box-sizing: border-box;
27
- border: 1px solid var(--color-border);
28
- background-color: var(--color-card-background);
29
- }
30
-
31
- .search-input::placeholder {
32
- color: #9ca3af;
33
- font-family: var(--font-primary);
34
- font-size: var(--text-paragraph);
35
- font-weight: var(--font-normal);
36
- }
37
-
38
- .search-input:focus {
39
- border-color: #d1d5db;
40
- }
1
+ .search-container {
2
+ position: relative;
3
+ width: 100%;
4
+ }
5
+
6
+ .search-icon {
7
+ position: absolute;
8
+ left: 1rem;
9
+ top: 50%;
10
+ transform: translateY(-50%);
11
+ width: 1.25rem;
12
+ height: 1.25rem;
13
+ color: #9ca3af;
14
+ pointer-events: none;
15
+ }
16
+
17
+ .search-input {
18
+ width: 100%;
19
+ padding: 1rem 1rem 1rem 3rem; /* top right bottom left */
20
+ border: 1px solid #d1d5db;
21
+ border-radius: 0.5rem;
22
+ outline: none;
23
+ background-color: white;
24
+ color: var(--color-text);
25
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
26
+ box-sizing: border-box;
27
+ border: 1px solid var(--color-border);
28
+ background-color: var(--color-card-background);
29
+ }
30
+
31
+ .search-input::placeholder {
32
+ color: #9ca3af;
33
+ font-family: var(--font-primary);
34
+ font-size: var(--text-paragraph);
35
+ font-weight: var(--font-normal);
36
+ }
37
+
38
+ .search-input:focus {
39
+ border-color: #d1d5db;
40
+ }