kyd-shared-badge 0.3.91 → 0.3.93

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kyd-shared-badge",
3
- "version": "0.3.91",
3
+ "version": "0.3.93",
4
4
  "private": false,
5
5
  "main": "./src/index.ts",
6
6
  "module": "./src/index.ts",
@@ -21,7 +21,7 @@
21
21
  "@aws-sdk/lib-dynamodb": "^3.893.0",
22
22
  "@chatscope/chat-ui-kit-react": "^2.1.1",
23
23
  "@chatscope/chat-ui-kit-styles": "^1.4.0",
24
- "@knowyourdeveloper/react-bubble-chart": "^1.0.3",
24
+ "@knowyourdeveloper/react-bubble-chart": "^1.0.5",
25
25
  "@radix-ui/react-slot": "^1.2.3",
26
26
  "@radix-ui/react-tooltip": "^1.2.8",
27
27
  "ai": "5.0.47",
@@ -3,6 +3,7 @@
3
3
  import React, { useMemo, useRef, useState, useEffect } from 'react';
4
4
  import { BubbleChart } from '@knowyourdeveloper/react-bubble-chart';
5
5
  import '@knowyourdeveloper/react-bubble-chart/style.css';
6
+ import { green1, green2, green3, green4, green5 } from '../colors';
6
7
 
7
8
  type SkillsRadarPoint = {
8
9
  axis: string;
@@ -24,29 +25,37 @@ const TooltipBox = ({ state }: { state: HoverTooltipState }) => {
24
25
  if (!state || !state.visible) return null;
25
26
  return (
26
27
  <div
28
+ className="rounded-md border shadow-sm px-3 py-2 text-xs"
27
29
  style={{
28
30
  position: 'absolute',
29
31
  left: state.x,
30
32
  top: state.y,
31
33
  pointerEvents: 'none',
32
34
  background: 'var(--content-card-background)',
33
- border: '1px solid var(--icon-button-secondary)',
35
+ borderColor: 'var(--icon-button-secondary)',
34
36
  color: 'var(--text-main)',
35
- padding: 10,
36
- borderRadius: 6,
37
+ zIndex: 10,
37
38
  minWidth: 250,
38
39
  maxWidth: 320,
39
- zIndex: 10,
40
40
  }}
41
41
  >
42
- <div style={{ fontWeight: 600 }}>{state.title}</div>
42
+ <div className="font-medium" style={{ color: 'var(--text-main)' }}>{state.title}</div>
43
43
  {state.body ? (
44
- <div style={{ fontSize: 12, color: 'var(--text-secondary)' }}>{state.body}</div>
44
+ <div style={{ color: 'var(--text-secondary)' }}>{state.body}</div>
45
45
  ) : null}
46
46
  </div>
47
47
  );
48
48
  };
49
49
 
50
+ const pickGreenByExperience = (experience: number): string => {
51
+ const exp = Math.max(0, Math.min(100, Number(experience || 0)));
52
+ if (exp >= 80) return green1;
53
+ if (exp >= 60) return green2;
54
+ if (exp >= 40) return green3;
55
+ if (exp >= 20) return green4;
56
+ return green5;
57
+ };
58
+
50
59
  export default function SkillsBubble({ skillsCategoryRadar, headless }: { skillsCategoryRadar?: SkillsRadarPoint[]; headless?: boolean }) {
51
60
  const hasRadar = !!(skillsCategoryRadar && skillsCategoryRadar.length > 0);
52
61
  const skillsRadarLimited = (skillsCategoryRadar || []).slice(0, 24);
@@ -78,9 +87,7 @@ export default function SkillsBubble({ skillsCategoryRadar, headless }: { skills
78
87
  const value = seriesAvg(d);
79
88
  const experience = Math.max(0, Math.min(100, Number(d.experience || 0)));
80
89
  const size = Math.max(2, Math.round((value / maxValue) * 100)); // 2..100
81
- // map experience to saturation in HSL; keep hue constant for brand-neutral look
82
- const saturation = Math.max(20, Math.min(100, experience));
83
- const color = `hsl(210 ${saturation}% 45%)`;
90
+ const color = 'var(--content-card-background)';
84
91
  return {
85
92
  label: d.axis,
86
93
  value: size,
@@ -101,8 +108,7 @@ export default function SkillsBubble({ skillsCategoryRadar, headless }: { skills
101
108
  }, [bubbles]);
102
109
 
103
110
  const colorLegend = useMemo(() => {
104
- const steps = [20, 35, 50, 65, 80, 90, 100];
105
- return steps.map((s) => `hsl(210 ${s}% 45%)`);
111
+ return [green5, green4, green3, green2, green1];
106
112
  }, []);
107
113
 
108
114
  const percentLegend = useMemo(() => {
@@ -137,17 +143,54 @@ export default function SkillsBubble({ skillsCategoryRadar, headless }: { skills
137
143
  tooltipFunc={(node, d) => {
138
144
  try {
139
145
  node.innerHTML = '';
146
+ node.className = 'rounded-md border shadow-sm px-3 py-2 text-xs';
147
+ (node as HTMLElement).style.background = 'var(--content-card-background)';
148
+ (node as HTMLElement).style.borderColor = 'var(--icon-button-secondary)';
149
+ (node as HTMLElement).style.color = 'var(--text-main)';
150
+ (node as HTMLElement).style.pointerEvents = 'none';
151
+
152
+ const header = document.createElement('div');
153
+ header.className = 'mb-1';
140
154
  const title = document.createElement('div');
141
- title.style.fontWeight = '600';
155
+ title.className = 'font-medium';
156
+ title.style.color = 'var(--text-main)';
142
157
  title.textContent = String(d.displayText || d._id || '');
143
- const body = document.createElement('div');
144
- body.style.fontSize = '12px';
145
- body.style.color = 'var(--text-secondary)';
158
+ header.appendChild(title);
159
+
160
+ const content = document.createElement('div');
161
+ content.className = 'space-y-1';
146
162
  const ratio = Number(d.value || 0);
147
163
  const experience = Number(d.colorValue || 0);
148
- body.textContent = `${ratio}% ratio • Experience ${experience}`;
149
- node.appendChild(title);
150
- node.appendChild(body);
164
+
165
+ const row1 = document.createElement('div');
166
+ row1.className = 'flex items-center justify-between gap-3';
167
+ const row1Left = document.createElement('span');
168
+ row1Left.style.color = 'var(--text-secondary)';
169
+ row1Left.textContent = 'Ratio';
170
+ const row1Right = document.createElement('span');
171
+ row1Right.className = 'font-medium';
172
+ row1Right.style.color = 'var(--text-main)';
173
+ row1Right.textContent = `${ratio}%`;
174
+ row1.appendChild(row1Left);
175
+ row1.appendChild(row1Right);
176
+
177
+ const row2 = document.createElement('div');
178
+ row2.className = 'flex items-center justify-between gap-3';
179
+ const row2Left = document.createElement('span');
180
+ row2Left.style.color = 'var(--text-secondary)';
181
+ row2Left.textContent = 'Experience';
182
+ const row2Right = document.createElement('span');
183
+ row2Right.className = 'font-medium';
184
+ row2Right.style.color = 'var(--text-main)';
185
+ row2Right.textContent = String(experience);
186
+ row2.appendChild(row2Left);
187
+ row2.appendChild(row2Right);
188
+
189
+ content.appendChild(row1);
190
+ content.appendChild(row2);
191
+
192
+ node.appendChild(header);
193
+ node.appendChild(content);
151
194
  } catch {}
152
195
  }}
153
196
  />
@@ -183,7 +226,7 @@ export default function SkillsBubble({ skillsCategoryRadar, headless }: { skills
183
226
  }}
184
227
  onMouseLeave={() => setLegendTooltip(null)}
185
228
  >
186
- <span className={'inline-block h-2 w-2 rounded-full'} style={{ backgroundColor: `hsl(210 ${Math.max(20, Math.min(100, item.experience))}% 45%)`, flexShrink: 0 }} />
229
+ <span className={'inline-block h-2 w-2 rounded-full'} style={{ backgroundColor: pickGreenByExperience(item.experience), flexShrink: 0 }} />
187
230
  <span className="truncate">{item.label}</span>
188
231
  <span className="ml-auto opacity-80">{item.percent}%</span>
189
232
  </button>
@@ -193,12 +236,12 @@ export default function SkillsBubble({ skillsCategoryRadar, headless }: { skills
193
236
  {/* Legends */}
194
237
  <div className="mt-3 grid grid-cols-1 sm:grid-cols-2 gap-2 text-xs" style={{ color: 'var(--text-secondary)' }}>
195
238
  <div className="flex items-center gap-2">
196
- <span className="inline-block h-3 w-3 rounded-full" style={{ background: 'hsl(210 80% 45%)' }} />
239
+ <span className="inline-block h-3 w-3 rounded-full" style={{ background: green1 }} />
197
240
  <span>Bubble size: relative ratio of observed/self-reported/certified</span>
198
241
  </div>
199
242
  <div className="flex items-center gap-2">
200
- <span className="inline-block h-3 w-3 rounded-full" style={{ background: 'hsl(210 20% 45%)' }} />
201
- <span>Color saturation: experience (darker = more experienced)</span>
243
+ <span className="inline-block h-3 w-3 rounded-full" style={{ background: green5 }} />
244
+ <span>Color shade: experience (darker = more experienced)</span>
202
245
  </div>
203
246
  </div>
204
247
  </div>