@syscore/ui-library 1.11.0 → 1.11.2

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.
@@ -9,7 +9,7 @@ export const UtilityClose: React.FC<UtilityCloseProps> = ({ className }) => {
9
9
  return (
10
10
  <div
11
11
  className={cn(
12
- "size-4 flex items-center justify-center text-gray-500",
12
+ "size-4 flex items-center justify-center text-gray-500 group-hover:text-gray-400",
13
13
  className,
14
14
  )}
15
15
  >
@@ -4,6 +4,7 @@ import * as React from "react";
4
4
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
5
5
 
6
6
  import { cn } from "@/lib/utils";
7
+ import { UtilityClose } from "@/components/icons/UtilityClose";
7
8
 
8
9
  type TriggerMode = "hover" | "click";
9
10
 
@@ -149,8 +150,11 @@ function TooltipContent({
149
150
  side = "bottom",
150
151
  children,
151
152
  alignOffset = 0,
153
+ hideClose = false,
152
154
  ...props
153
- }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
155
+ }: React.ComponentProps<typeof TooltipPrimitive.Content> & {
156
+ hideClose?: boolean;
157
+ }) {
154
158
  const { trigger, close, triggerRef } = React.useContext(TooltipContext);
155
159
  const contentRef = React.useRef<HTMLDivElement>(null);
156
160
 
@@ -193,7 +197,7 @@ function TooltipContent({
193
197
  {...props}
194
198
  >
195
199
  {/* Marker/Arrow */}
196
- <div className="tooltip-arrow" data-side={side}>
200
+ <div className="tooltip-arrow">
197
201
  <svg
198
202
  xmlns="http://www.w3.org/2000/svg"
199
203
  width="10"
@@ -207,10 +211,31 @@ function TooltipContent({
207
211
  />
208
212
  </svg>
209
213
  </div>
214
+ {!hideClose && <ToggleClose className="absolute top-4 right-4" />}
210
215
  {children}
211
216
  </TooltipPrimitive.Content>
212
217
  </TooltipPrimitive.Portal>
213
218
  );
214
219
  }
215
220
 
216
- export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
221
+ function ToggleClose({ className }: { className?: string }) {
222
+ const { close } = React.useContext(TooltipContext);
223
+
224
+ return (
225
+ <button
226
+ data-slot="tooltip-close"
227
+ onClick={close}
228
+ className={cn("group cursor-pointer", className)}
229
+ >
230
+ <UtilityClose />
231
+ </button>
232
+ );
233
+ }
234
+
235
+ export {
236
+ Tooltip,
237
+ TooltipTrigger,
238
+ TooltipContent,
239
+ TooltipProvider,
240
+ ToggleClose,
241
+ };
package/client/global.css CHANGED
@@ -1131,8 +1131,6 @@ body {
1131
1131
  width: 2rem;
1132
1132
  height: 2rem;
1133
1133
  padding: 0;
1134
- background-color: var(--color-white, #fff);
1135
- border: 1px solid var(--color-gray-100, #eff1f2);
1136
1134
  transition: all 0.2s ease-in-out;
1137
1135
  }
1138
1136
 
@@ -1761,13 +1759,13 @@ body {
1761
1759
  }
1762
1760
 
1763
1761
  .tag-general--active {
1764
- background-color: var(--color-cyan-800, #0f748a);
1765
- color: var(--color-white, #fff);
1762
+ background-color: var(--tag-active-bg, var(--color-cyan-800, #0f748a));
1763
+ color: var(--tag-active-fg, var(--color-white, #fff));
1766
1764
  font-weight: 600;
1767
1765
  }
1768
1766
 
1769
1767
  .tag-general--active:hover {
1770
- border-color: var(--color-cyan-800, #0f748a);
1768
+ border-color: var(--tag-active-bg, var(--color-cyan-800, #0f748a));
1771
1769
  }
1772
1770
 
1773
1771
  .tag-general--inactive {
@@ -1896,8 +1894,8 @@ body {
1896
1894
  }
1897
1895
 
1898
1896
  .segmented-control-button--active {
1899
- background-color: var(--color-cyan-800, #0f748a);
1900
- color: var(--color-white, #fff);
1897
+ background-color: var(--toggle-active-bg, var(--color-cyan-800, #0f748a));
1898
+ color: var(--toggle-active-fg, var(--color-white, #fff));
1901
1899
  font-weight: 600;
1902
1900
  }
1903
1901
 
@@ -2020,13 +2018,11 @@ body {
2020
2018
  color: currentColor;
2021
2019
  }
2022
2020
 
2023
-
2024
2021
  /* Tooltip Styles */
2025
2022
  .tooltip-content {
2026
2023
  position: relative;
2027
2024
  background-color: #3e4049;
2028
2025
  z-index: 50;
2029
- width: fit-content;
2030
2026
  border-radius: 0.5rem;
2031
2027
  padding: 1.5rem;
2032
2028
  padding-top: 2rem;
@@ -2087,6 +2083,7 @@ body {
2087
2083
  }
2088
2084
 
2089
2085
  .tooltip-content[data-side="top"] {
2086
+ margin-bottom: 12px;
2090
2087
  animation:
2091
2088
  fade-in 0.15s ease-in-out,
2092
2089
  zoom-in 0.15s ease-in-out,
@@ -2108,23 +2105,23 @@ body {
2108
2105
  justify-content: center;
2109
2106
  }
2110
2107
 
2111
- .tooltip-arrow[data-side="top"] {
2108
+ [data-side="top"] > .tooltip-arrow {
2112
2109
  bottom: 0;
2113
2110
  transform: translateX(-50%) rotate(180deg);
2114
2111
  }
2115
2112
 
2116
- .tooltip-arrow[data-side="bottom"] {
2113
+ [data-side="bottom"] > .tooltip-arrow {
2117
2114
  top: 0;
2118
2115
  transform: translateX(-50%);
2119
2116
  }
2120
2117
 
2121
- .tooltip-arrow[data-side="left"] {
2118
+ [data-side="left"] > .tooltip-arrow {
2122
2119
  right: 0;
2123
2120
  top: 50%;
2124
2121
  transform: translateY(-50%) rotate(-90deg);
2125
2122
  }
2126
2123
 
2127
- .tooltip-arrow[data-side="right"] {
2124
+ [data-side="right"] > .tooltip-arrow {
2128
2125
  left: 0;
2129
2126
  top: 50%;
2130
2127
  transform: translateY(-50%) rotate(90deg);
@@ -6096,7 +6093,7 @@ body {
6096
6093
  top: 0;
6097
6094
  left: 0;
6098
6095
  z-index: 50;
6099
- height: 3.5rem;
6096
+ height: 4rem;
6100
6097
  width: 100%;
6101
6098
  }
6102
6099
 
@@ -6993,7 +6990,8 @@ body {
6993
6990
 
6994
6991
  .page-header-description {
6995
6992
  /* Uses body-large utility */
6996
- max-width: 680px;
6993
+ /* max-width: 680px; */
6994
+ padding-right: 10rem;
6997
6995
  }
6998
6996
 
6999
6997
  /* Navigation Styles */
@@ -7,7 +7,7 @@ import { Tag } from "../components/ui/tag";
7
7
  import { CONCEPT_ICONS, conceptOrder } from "../lib/concept-icons";
8
8
  import { conceptColors } from "../lib/concept-colors";
9
9
  import { Card } from "../components/ui/card";
10
- import { useState } from "react";
10
+ import { useState, type CSSProperties } from "react";
11
11
  import { Label } from "../components/ui/label";
12
12
  import { Toggle } from "../components/ui/toggle";
13
13
 
@@ -37,8 +37,17 @@ const ExploreSidePanelView = (args: any) => {
37
37
  const [hoveredStrategy, setHoveredStrategy] = useState<string | null>(null);
38
38
 
39
39
  // Derived data
40
- const conceptsByKey = new Map(concepts.map((c) => [c.conceptKey, c]));
41
40
  const activeColor = getConceptColor(selectedConcept || "community");
41
+ const displayedConceptKey = hoveredConcept ?? selectedConcept;
42
+ const displayedConceptName = displayedConceptKey
43
+ ? capitalize(
44
+ concepts.find((c) => c.conceptKey === displayedConceptKey)?.name ?? "",
45
+ )
46
+ : "";
47
+ const displayedThemeCode = hoveredTheme ?? selectedTheme;
48
+ const displayedThemeName = displayedThemeCode
49
+ ? capitalize(themes.find((t) => t.code === displayedThemeCode)?.name ?? "")
50
+ : "";
42
51
 
43
52
  return (
44
53
  <LayoutGroup>
@@ -50,22 +59,21 @@ const ExploreSidePanelView = (args: any) => {
50
59
 
51
60
  <div className="relative min-w-0 flex-1 self-stretch">
52
61
  <AnimatePresence mode="wait">
53
- {hoveredConcept && (
62
+ {displayedConceptName && (
54
63
  <motion.div
55
- key={hoveredConcept}
64
+ key={displayedConceptKey ?? "concept-label"}
56
65
  initial={{ opacity: 0, x: -4 }}
57
66
  animate={{ opacity: 1, x: 0 }}
58
67
  exit={{ opacity: 0, x: 4 }}
59
68
  transition={{ duration: 0.15 }}
60
- className="absolute top-1/2 -translate-y-1/2 left-0 right-0 body-small"
69
+ className="absolute top-1/2 -translate-y-1/2 left-0 right-0 body-small max-w-40"
61
70
  style={{ willChange: "opacity, transform" }}
62
71
  >
63
- <span className="line-clamp-1">
64
- ·{" "}
65
- {capitalize(
66
- concepts.find((c) => c.conceptKey === hoveredConcept)
67
- ?.name ?? "",
68
- )}
72
+ <span className="line-clamp-1 text-gray-800">
73
+ <span aria-hidden="true" className="text-gray-300">
74
+ ·{" "}
75
+ </span>
76
+ {displayedConceptName}
69
77
  </span>
70
78
  </motion.div>
71
79
  )}
@@ -104,7 +112,9 @@ const ExploreSidePanelView = (args: any) => {
104
112
  }
105
113
  return undefined;
106
114
  })()}
107
- aria-label={conceptsByKey.get(slug)?.name}
115
+ aria-label={
116
+ concepts.find((c) => c.conceptKey === slug)?.name
117
+ }
108
118
  >
109
119
  <Icon
110
120
  active={isFilled}
@@ -135,22 +145,21 @@ const ExploreSidePanelView = (args: any) => {
135
145
 
136
146
  <div className="relative min-w-0 flex-1 self-stretch">
137
147
  <AnimatePresence mode="wait">
138
- {hoveredTheme && (
148
+ {displayedThemeName && (
139
149
  <motion.div
140
- key={hoveredTheme}
150
+ key={displayedThemeCode ?? "theme-label"}
141
151
  initial={{ opacity: 0, x: -4 }}
142
152
  animate={{ opacity: 1, x: 0 }}
143
153
  exit={{ opacity: 0, x: 4 }}
144
154
  transition={{ duration: 0.15 }}
145
- className="absolute top-1/2 -translate-y-1/2 left-0 right-0 body-small"
155
+ className="absolute top-1/2 -translate-y-1/2 left-0 right-0 body-small max-w-40"
146
156
  style={{ willChange: "opacity, transform" }}
147
157
  >
148
- <span className="line-clamp-1">
149
- ·{" "}
150
- {capitalize(
151
- themes.find((t) => t.code === hoveredTheme)?.name ??
152
- "",
153
- )}
158
+ <span className="block w-[235px] truncate pr-6 text-gray-800">
159
+ <span aria-hidden="true" className="text-gray-300">
160
+ ·{" "}
161
+ </span>
162
+ {displayedThemeName}
154
163
  </span>
155
164
  </motion.div>
156
165
  )}
@@ -240,7 +249,7 @@ const ExploreSidePanelView = (args: any) => {
240
249
  animate={{ opacity: 1, x: 0 }}
241
250
  exit={{ opacity: 0, x: 4 }}
242
251
  transition={{ duration: 0.15 }}
243
- className="absolute top-1/2 -translate-y-1/2 left-0 right-0 body-small"
252
+ className="absolute top-1/2 -translate-y-1/2 left-0 right-0 body-small max-w-40"
244
253
  style={{ willChange: "opacity, transform" }}
245
254
  >
246
255
  <span className="line-clamp-1">
@@ -315,6 +324,9 @@ const ExploreSidePanelView = (args: any) => {
315
324
  { label: "Core", value: "core" },
316
325
  ]}
317
326
  value={scope}
327
+ style={
328
+ { "--toggle-active-bg": "var(--color-cyan-700)" } as CSSProperties
329
+ }
318
330
  onValueChange={(value) =>
319
331
  onScopeChange(value as "non-core" | "core")
320
332
  }
@@ -329,7 +341,10 @@ const ExploreSidePanelView = (args: any) => {
329
341
  className="flex flex-col gap-3 items-start max-w-max"
330
342
  >
331
343
  <Label>PURSUIT</Label>
332
- <div className=" inline-flex gap-3">
344
+ <div
345
+ className=" inline-flex gap-3"
346
+ style={{ "--tag-active-bg": "var(--color-cyan-700)" } as CSSProperties}
347
+ >
333
348
  <Tag
334
349
  variant="text"
335
350
  active={activePursuits.has("certification")}
@@ -6,6 +6,7 @@ import {
6
6
  } from "../components/ui/tooltip";
7
7
  import { Separator } from "../components/ui/separator";
8
8
  import { Button } from "../components/ui/button";
9
+ import { Text } from "../components/ui/typography";
9
10
 
10
11
  const meta = {
11
12
  title: "Review/Tooltip",
@@ -25,15 +26,21 @@ export const Default: Story = {
25
26
  <div className="p-16">
26
27
  <Tooltip>
27
28
  <TooltipTrigger>Hover</TooltipTrigger>
28
- <TooltipContent>
29
+ <TooltipContent className="w-[400px]">
29
30
  <div className="space-y-3">
30
- <h4 className="text-white font-semibold text-base">
31
+ <Text as="h1" variant="body-base" className="text-white">
31
32
  Strategy Details
32
- </h4>
33
+ </Text>
33
34
  <div className="space-y-1">
34
- <p className="text-white/90 text-sm">Status: Active</p>
35
- <p className="text-white/90 text-sm">Score: 12 PTS</p>
36
- <p className="text-white/90 text-sm">Last updated: 2 days ago</p>
35
+ <Text as="p" variant="body-small" className="text-white/90">
36
+ Status: Active
37
+ </Text>
38
+ <Text as="p" variant="body-small" className="text-white/90">
39
+ Score: 12 PTS
40
+ </Text>
41
+ <Text as="p" variant="body-small" className="text-white/90">
42
+ Last updated: 2 days ago
43
+ </Text>
37
44
  </div>
38
45
  </div>
39
46
  </TooltipContent>
@@ -45,15 +52,21 @@ export const Default: Story = {
45
52
  export const WithContent: Story = {
46
53
  render: () => (
47
54
  <div className="p-16">
48
- <Tooltip>
55
+ <Tooltip trigger="click">
49
56
  <TooltipTrigger>Hover with Content</TooltipTrigger>
50
- <TooltipContent className="w-[400px]" alignOffset={500}>
57
+ <TooltipContent className="w-[400px]">
51
58
  <div className="space-y-4">
52
- <h4 className="text-white font-semibold body-base">Header</h4>
59
+ <Text as="h1" variant="body-base" className="text-white">
60
+ Header
61
+ </Text>
53
62
  <div className="space-y-4">
54
- <p className="text-white/90 body-small">Body</p>
63
+ <Text as="p" variant="body-small" className="text-white/90">
64
+ Body
65
+ </Text>
55
66
  <Separator className="my-8" />
56
- <p className="text-white/90 body-small">Body</p>
67
+ <Text as="p" variant="body-small" className="text-white/90">
68
+ Body
69
+ </Text>
57
70
 
58
71
  <div className="flex flex-row gap-4 justify-start items-start">
59
72
  <Button size="utility" variant="tooltip-primary">
@@ -75,18 +88,16 @@ export const Click: Story = {
75
88
  render: () => (
76
89
  <div className="p-16">
77
90
  <Tooltip trigger="click">
78
- <TooltipTrigger >
79
- Click me
80
- </TooltipTrigger>
81
- <TooltipContent>
91
+ <TooltipTrigger>Click me</TooltipTrigger>
92
+ <TooltipContent className="w-[400px]">
82
93
  <div className="space-y-3">
83
- <h4 className="text-white font-semibold text-base">
94
+ <Text as="h1" variant="body-base" className="text-white">
84
95
  Click Tooltip
85
- </h4>
96
+ </Text>
86
97
  <div className="space-y-1">
87
- <p className="text-white/90 text-sm">
98
+ <Text as="p" variant="body-small" className="text-white/90">
88
99
  This tooltip opens on click and closes when clicking outside.
89
- </p>
100
+ </Text>
90
101
  </div>
91
102
  </div>
92
103
  </TooltipContent>