Skip to content

Commit 522ba11

Browse files
committed
Added mandatory tooltip support for the iconOnly button
1 parent 0996cc0 commit 522ba11

File tree

61 files changed

+475
-232
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+475
-232
lines changed

apps/design-system/src/App.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { createBrowserRouter, Navigate, RouterProvider } from 'react-router-dom'
44
import ViewPreview from '@/pages/view-preview/view-preview'
55
import { useThemeStore } from '@utils/theme-utils'
66

7+
import { TooltipProvider } from '@harnessio/ui/components'
78
import { ThemeProvider, TranslationProvider } from '@harnessio/ui/context'
89

910
import AppRouterProvider from './AppRouterProvider'
@@ -24,7 +25,9 @@ const App: FC = () => {
2425
return (
2526
<ThemeProvider {...themeStore}>
2627
<TranslationProvider>
27-
<RouterProvider router={router} />
28+
<TooltipProvider>
29+
<RouterProvider router={router} />
30+
</TooltipProvider>
2831
</TranslationProvider>
2932
</ThemeProvider>
3033
)

apps/design-system/src/AppRouterProvider.tsx

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,31 @@ import {
1010
useSearchParams
1111
} from 'react-router-dom'
1212

13-
import { Button, SplitButton } from '@harnessio/ui/components'
13+
import { Button, RbacButtonProps, SplitButton, toButtonProps, Tooltip } from '@harnessio/ui/components'
1414
import { ComponentProvider, RouterContextProvider } from '@harnessio/ui/context'
1515

16+
const RbacButton = ({ rbac: _, tooltip, ...rest }: RbacButtonProps) => {
17+
const hasPermission = true
18+
19+
const button = (
20+
<Button
21+
{...toButtonProps({
22+
...rest,
23+
ignoreIconOnlyTooltip: true
24+
})}
25+
disabled={!hasPermission}
26+
/>
27+
)
28+
29+
return !hasPermission ? (
30+
<Tooltip title={tooltip?.title ?? 'You are missing the permission for this action.'} content={tooltip?.content}>
31+
{button}
32+
</Tooltip>
33+
) : (
34+
button
35+
)
36+
}
37+
1638
const AppRouterProvider: FC = () => {
1739
const navigate = useNavigate()
1840
const location = useLocation()
@@ -28,7 +50,7 @@ const AppRouterProvider: FC = () => {
2850
useMatches={useMatches}
2951
useParams={useParams}
3052
>
31-
<ComponentProvider components={{ RbacButton: Button, RbacSplitButton: SplitButton }}>
53+
<ComponentProvider components={{ RbacButton, RbacSplitButton: SplitButton }}>
3254
<Outlet />
3355
</ComponentProvider>
3456
</RouterContextProvider>

apps/design-system/src/pages/view-preview/view-preview.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import TableV2Demo from '@subjects/views/table-v2-demo'
5959
import { ViewOnlyView } from '@subjects/views/templates/view-only'
6060
import UnifiedPipelineStudioWrapper from '@subjects/views/unified-pipeline-studio/unified-pipeline-studio'
6161

62-
import { ChatEmptyPreviewWrapper, ChatPreviewWrapper, TooltipProvider } from '@harnessio/ui/components'
62+
import { ChatEmptyPreviewWrapper, ChatPreviewWrapper } from '@harnessio/ui/components'
6363
import { NotFoundPage } from '@harnessio/ui/views'
6464

6565
import { AppViewWrapper } from './app-view-wrapper'
@@ -606,7 +606,7 @@ export const viewPreviews: Record<string, ViewPreviewGroup> = {
606606

607607
const ViewPreview: FC = () => {
608608
return (
609-
<TooltipProvider>
609+
<>
610610
<Routes>
611611
{Object.entries(viewPreviews).map(([_, group]) =>
612612
Object.entries(group.items).map(([route, { element }]) => (
@@ -616,7 +616,7 @@ const ViewPreview: FC = () => {
616616
<Route path="/" element={<Navigate to={Object.keys(viewPreviews)[0]} />} />
617617
</Routes>
618618
<ViewSettings routes={Object.keys(viewPreviews)} />
619-
</TooltipProvider>
619+
</>
620620
)
621621
}
622622

apps/design-system/src/pages/view-preview/view-settings.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ const ViewSettings: FC<ViewSettingsProps> = ({ routes }) => {
5656
onClick={() => setShowSettings(current => !current)}
5757
className={css.showHideButton}
5858
title={showSettings ? 'Hide view settings' : 'Show view settings'}
59+
tooltipProps={{
60+
content: showSettings ? 'Hide view settings' : 'Show view settings'
61+
}}
5962
>
6063
<IconV2 name={showSettings ? 'xmark' : 'settings'} />
6164
</Button>

apps/design-system/src/subjects/views/templates/view-only.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ export const ViewOnlyView = () => {
257257
/>
258258
</Table.Cell>
259259
<Table.Cell align="right" width="40">
260-
<Toggle prefixIcon="pin" iconOnly />
260+
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
261261
</Table.Cell>
262262
</Table.Row>
263263
<Table.Row>
@@ -281,7 +281,7 @@ export const ViewOnlyView = () => {
281281
/>
282282
</Table.Cell>
283283
<Table.Cell align="right" width="40">
284-
<Toggle prefixIcon="pin" iconOnly />
284+
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
285285
</Table.Cell>
286286
</Table.Row>
287287
<Table.Row>
@@ -305,7 +305,7 @@ export const ViewOnlyView = () => {
305305
/>
306306
</Table.Cell>
307307
<Table.Cell align="right" width="40">
308-
<Toggle prefixIcon="pin" iconOnly />
308+
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
309309
</Table.Cell>
310310
</Table.Row>
311311
<Table.Row>
@@ -329,7 +329,7 @@ export const ViewOnlyView = () => {
329329
/>
330330
</Table.Cell>
331331
<Table.Cell align="right" width="40">
332-
<Toggle prefixIcon="pin" iconOnly />
332+
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
333333
</Table.Cell>
334334
</Table.Row>
335335
<Table.Row>
@@ -353,7 +353,7 @@ export const ViewOnlyView = () => {
353353
/>
354354
</Table.Cell>
355355
<Table.Cell align="right" width="40">
356-
<Toggle prefixIcon="pin" iconOnly />
356+
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
357357
</Table.Cell>
358358
</Table.Row>
359359
<Table.Row>
@@ -377,7 +377,7 @@ export const ViewOnlyView = () => {
377377
/>
378378
</Table.Cell>
379379
<Table.Cell align="right" width="40">
380-
<Toggle prefixIcon="pin" iconOnly />
380+
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
381381
</Table.Cell>
382382
</Table.Row>
383383
</Table.Body>

apps/gitness/src/framework/rbac/rbac-button.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Button, RbacButtonProps, Resource, Tooltip } from '@harnessio/ui/components'
1+
import { Button, RbacButtonProps, Resource, toButtonProps, Tooltip } from '@harnessio/ui/components'
22

33
import { useMFEContext } from '../hooks/useMFEContext'
44

@@ -16,7 +16,15 @@ export const RbacButton = ({ rbac, tooltip, ...rest }: RbacButtonProps) => {
1616
})
1717
?.some(Boolean) ?? true
1818

19-
const button = <Button {...rest} disabled={!hasPermission} />
19+
const button = (
20+
<Button
21+
{...toButtonProps({
22+
...rest,
23+
ignoreIconOnlyTooltip: true
24+
})}
25+
disabled={!hasPermission}
26+
/>
27+
)
2028

2129
return !hasPermission ? (
2230
<Tooltip title={tooltip?.title ?? 'You are missing the permission for this action.'} content={tooltip?.content}>

apps/portal/src/components/docs-page/example.tsx

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -75,41 +75,45 @@ const Example: FC<ExampleProps> = ({
7575
element: (
7676
<RouterContextProvider Link={Link} NavLink={NavLink} Outlet={Outlet}>
7777
<TranslationProvider>
78-
<TooltipProvider>
79-
<LivePreview />
80-
</TooltipProvider>
78+
<LivePreview />
8179
</TranslationProvider>
8280
</RouterContextProvider>
8381
),
8482
},
8583
]);
8684

8785
return (
88-
<div className="bg-cn-background-1 not-content my-12 overflow-hidden rounded-md border">
89-
<LiveProvider code={currentCode} scope={scopeWithLayout} enableTypeScript>
90-
<div className={cn("grid place-items-center p-12", contentClassName)}>
91-
<RouterProvider router={router} />
92-
</div>
93-
{!hideCode && (
94-
<details className="relative example-expand bg-cn-background-2 border-t p-3">
95-
<CopyButton
96-
buttonVariant="transparent"
97-
className="absolute top-3 right-3"
98-
name={currentCode}
99-
/>
100-
<summary className="flex cursor-pointer select-none items-center gap-1 text-sm">
101-
<IconV2 name="nav-arrow-right" className="disclosure-icon" />
102-
Show code
103-
</summary>
104-
<LiveEditor
105-
theme={isLightTheme ? themes.vsLight : themes.vsDark}
106-
className="font-body-code line-numbers p-1 text-sm leading-6"
107-
onChange={setCurrentCode}
108-
/>
109-
</details>
110-
)}
111-
</LiveProvider>
112-
</div>
86+
<TooltipProvider>
87+
<div className="bg-cn-background-1 not-content my-12 overflow-hidden rounded-md border">
88+
<LiveProvider
89+
code={currentCode}
90+
scope={scopeWithLayout}
91+
enableTypeScript
92+
>
93+
<div className={cn("grid place-items-center p-12", contentClassName)}>
94+
<RouterProvider router={router} />
95+
</div>
96+
{!hideCode && (
97+
<details className="relative example-expand bg-cn-background-2 border-t p-3">
98+
<CopyButton
99+
buttonVariant="transparent"
100+
className="absolute top-3 right-3"
101+
name={currentCode}
102+
/>
103+
<summary className="flex cursor-pointer select-none items-center gap-1 text-sm">
104+
<IconV2 name="nav-arrow-right" className="disclosure-icon" />
105+
Show code
106+
</summary>
107+
<LiveEditor
108+
theme={isLightTheme ? themes.vsLight : themes.vsDark}
109+
className="font-body-code line-numbers p-1 text-sm leading-6"
110+
onChange={setCurrentCode}
111+
/>
112+
</details>
113+
)}
114+
</LiveProvider>
115+
</div>
116+
</TooltipProvider>
113117
);
114118
};
115119

apps/portal/src/components/layout/ThemeSelector.tsx

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
IconV2,
44
ThemeDialog,
55
type ThemeDialogProps,
6+
TooltipProvider,
67
} from "@harnessio/ui/components";
78
import { useEffect, useState } from "react";
89

@@ -25,16 +26,22 @@ export function ThemeSelector() {
2526
}, [theme]);
2627

2728
return (
28-
<ThemeDialog
29-
open={open}
30-
onOpenChange={setOpen}
31-
setTheme={setTheme}
32-
theme={theme}
33-
>
34-
<Button iconOnly onClick={() => setOpen(true)}>
35-
<IconV2 name="theme" />
36-
</Button>
37-
</ThemeDialog>
29+
<TooltipProvider>
30+
<ThemeDialog
31+
open={open}
32+
onOpenChange={setOpen}
33+
setTheme={setTheme}
34+
theme={theme}
35+
>
36+
<Button
37+
iconOnly
38+
onClick={() => setOpen(true)}
39+
tooltipProps={{ content: "Appearance settings" }}
40+
>
41+
<IconV2 name="theme" />
42+
</Button>
43+
</ThemeDialog>
44+
</TooltipProvider>
3845
);
3946
}
4047

@@ -44,8 +51,10 @@ export default function ThemeSelectorWrapper() {
4451
}
4552

4653
return (
47-
<Button iconOnly>
48-
<IconV2 name="theme" />
49-
</Button>
54+
<TooltipProvider>
55+
<Button iconOnly ignoreIconOnlyTooltip>
56+
<IconV2 name="theme" />
57+
</Button>
58+
</TooltipProvider>
5059
);
5160
}

apps/portal/src/content/docs/components/button.mdx

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ Secondary buttons can be styled with different themes for various contexts.
179179
Success Loading
180180
</Button>
181181
</div>
182-
182+
183183
<div className="flex gap-3">
184184
<Button variant="secondary" theme="danger" disabled>
185185
Danger Disabled
@@ -428,34 +428,38 @@ Transparent buttons have no background or border and don't accept theme props.
428428

429429
## Additional Features
430430

431+
When the `iconOnly` prop is used, you must also provide `tooltipProps` to display content in the tooltip.
432+
433+
If you need to skip showing the tooltip, you should set `ignoreIconOnlyTooltip`.
434+
431435
<DocsPage.ComponentExample
432436
client:only
433437
code={`<div className="flex flex-col items-start min-w-[600px] gap-8">
434438
<h4>Icon Only Buttons</h4>
435439
436440
<div className="flex gap-3">
437-
<Button iconOnly>
441+
<Button iconOnly tooltipProps={{ content: "Add" }}>
438442
<IconV2 name="plus" skipSize />
439443
</Button>
440-
<Button variant="secondary" size="sm" iconOnly>
444+
<Button variant="secondary" size="sm" iconOnly ignoreIconOnlyTooltip>
441445
<IconV2 name="git-branch" skipSize />
442446
</Button>
443-
<Button variant="transparent" size="sm" iconOnly>
447+
<Button variant="transparent" size="sm" iconOnly ignoreIconOnlyTooltip>
444448
<IconV2 name="xmark" skipSize />
445449
</Button>
446-
<Button variant="outline" size="xs" iconOnly>
450+
<Button variant="outline" size="xs" iconOnly ignoreIconOnlyTooltip>
447451
<IconV2 name="check" skipSize />
448452
</Button>
449-
<Button variant="outline" size="2xs" iconOnly>
453+
<Button variant="outline" size="2xs" iconOnly ignoreIconOnlyTooltip>
450454
<IconV2 name="check" skipSize />
451455
</Button>
452-
<Button variant="outline" size="3xs" iconOnly>
456+
<Button variant="outline" size="3xs" iconOnly ignoreIconOnlyTooltip>
453457
<IconV2 name="check" skipSize />
454458
</Button>
455-
<Button variant="outline" size="2xs" iconOnly>
459+
<Button variant="outline" size="2xs" iconOnly ignoreIconOnlyTooltip>
456460
<IconV2 name="xmark" skipSize />
457461
</Button>
458-
<Button variant="outline" size="3xs" iconOnly>
462+
<Button variant="outline" size="3xs" iconOnly ignoreIconOnlyTooltip>
459463
<IconV2 name="xmark" skipSize />
460464
</Button>
461465
</div>
@@ -515,7 +519,7 @@ import { Button } from '@harnessio/ui/components'
515519
<Button rounded>Rounded Button</Button>
516520

517521
// Icon only button
518-
<Button iconOnly>
522+
<Button iconOnly tooltipProps={{ content: 'Add' }}>
519523
<IconV2 name="plus" />
520524
</Button>
521525

@@ -618,5 +622,21 @@ This ensures type safety and provides proper development-time feedback on invali
618622
required: true,
619623
value: "ReactNode",
620624
},
625+
{
626+
name: "tooltipProps",
627+
description:
628+
"If provided, wraps the Button in a tooltip with the specified properties.",
629+
required: false,
630+
defaultValue: "undefined",
631+
value: "Pick<TooltipProps, 'title' | 'content' | 'side'>",
632+
},
633+
{
634+
name: "ignoreIconOnlyTooltip",
635+
description:
636+
"Allows skipping the required tooltipProps when using iconOnly.",
637+
required: false,
638+
value: "boolean",
639+
defaultValue: "undefined",
640+
},
621641
]}
622642
/>

apps/portal/src/content/docs/components/toggle-group.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ The `Item` component is used to define each toggle button within the group.
429429
{
430430
name: "tooltipProps",
431431
description:
432-
"If provided, wraps the ToggleItem in a tooltip with the specified properties.",
432+
"If provided, wraps the Button in a tooltip with the specified properties.",
433433
required: false,
434434
defaultValue: "undefined",
435435
value: "Pick<TooltipProps, 'title' | 'content' | 'side' | 'align'>",

0 commit comments

Comments
 (0)