Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/design-system/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { createBrowserRouter, Navigate, RouterProvider } from 'react-router-dom'
import ViewPreview from '@/pages/view-preview/view-preview'
import { useThemeStore } from '@utils/theme-utils'

import { TooltipProvider } from '@harnessio/ui/components'
import { ThemeProvider, TranslationProvider } from '@harnessio/ui/context'

import AppRouterProvider from './AppRouterProvider'
Expand All @@ -24,7 +25,9 @@ const App: FC = () => {
return (
<ThemeProvider {...themeStore}>
<TranslationProvider>
<RouterProvider router={router} />
<TooltipProvider>
<RouterProvider router={router} />
</TooltipProvider>
</TranslationProvider>
</ThemeProvider>
)
Expand Down
26 changes: 24 additions & 2 deletions apps/design-system/src/AppRouterProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,31 @@ import {
useSearchParams
} from 'react-router-dom'

import { Button, SplitButton } from '@harnessio/ui/components'
import { Button, RbacButtonProps, SplitButton, toButtonProps, Tooltip } from '@harnessio/ui/components'
import { ComponentProvider, RouterContextProvider } from '@harnessio/ui/context'

const RbacButton = ({ rbac: _, tooltip, ...rest }: RbacButtonProps) => {
const hasPermission = true

const button = (
<Button
{...toButtonProps({
...rest,
ignoreIconOnlyTooltip: true
})}
disabled={!hasPermission}
/>
)

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

const AppRouterProvider: FC = () => {
const navigate = useNavigate()
const location = useLocation()
Expand All @@ -28,7 +50,7 @@ const AppRouterProvider: FC = () => {
useMatches={useMatches}
useParams={useParams}
>
<ComponentProvider components={{ RbacButton: Button, RbacSplitButton: SplitButton }}>
<ComponentProvider components={{ RbacButton, RbacSplitButton: SplitButton }}>
<Outlet />
</ComponentProvider>
</RouterContextProvider>
Expand Down
6 changes: 3 additions & 3 deletions apps/design-system/src/pages/view-preview/view-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ import TableV2Demo from '@subjects/views/table-v2-demo'
import { ViewOnlyView } from '@subjects/views/templates/view-only'
import UnifiedPipelineStudioWrapper from '@subjects/views/unified-pipeline-studio/unified-pipeline-studio'

import { ChatEmptyPreviewWrapper, ChatPreviewWrapper, TooltipProvider } from '@harnessio/ui/components'
import { ChatEmptyPreviewWrapper, ChatPreviewWrapper } from '@harnessio/ui/components'
import { NotFoundPage } from '@harnessio/ui/views'

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

const ViewPreview: FC = () => {
return (
<TooltipProvider>
<>
<Routes>
{Object.entries(viewPreviews).map(([_, group]) =>
Object.entries(group.items).map(([route, { element }]) => (
Expand All @@ -616,7 +616,7 @@ const ViewPreview: FC = () => {
<Route path="/" element={<Navigate to={Object.keys(viewPreviews)[0]} />} />
</Routes>
<ViewSettings routes={Object.keys(viewPreviews)} />
</TooltipProvider>
</>
)
}

Expand Down
3 changes: 3 additions & 0 deletions apps/design-system/src/pages/view-preview/view-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ const ViewSettings: FC<ViewSettingsProps> = ({ routes }) => {
onClick={() => setShowSettings(current => !current)}
className={css.showHideButton}
title={showSettings ? 'Hide view settings' : 'Show view settings'}
tooltipProps={{
content: showSettings ? 'Hide view settings' : 'Show view settings'
}}
>
<IconV2 name={showSettings ? 'xmark' : 'settings'} />
</Button>
Expand Down
12 changes: 6 additions & 6 deletions apps/design-system/src/subjects/views/templates/view-only.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ export const ViewOnlyView = () => {
/>
</Table.Cell>
<Table.Cell align="right" width="40">
<Toggle prefixIcon="pin" iconOnly />
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
</Table.Cell>
</Table.Row>
<Table.Row>
Expand All @@ -281,7 +281,7 @@ export const ViewOnlyView = () => {
/>
</Table.Cell>
<Table.Cell align="right" width="40">
<Toggle prefixIcon="pin" iconOnly />
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
</Table.Cell>
</Table.Row>
<Table.Row>
Expand All @@ -305,7 +305,7 @@ export const ViewOnlyView = () => {
/>
</Table.Cell>
<Table.Cell align="right" width="40">
<Toggle prefixIcon="pin" iconOnly />
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
</Table.Cell>
</Table.Row>
<Table.Row>
Expand All @@ -329,7 +329,7 @@ export const ViewOnlyView = () => {
/>
</Table.Cell>
<Table.Cell align="right" width="40">
<Toggle prefixIcon="pin" iconOnly />
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
</Table.Cell>
</Table.Row>
<Table.Row>
Expand All @@ -353,7 +353,7 @@ export const ViewOnlyView = () => {
/>
</Table.Cell>
<Table.Cell align="right" width="40">
<Toggle prefixIcon="pin" iconOnly />
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
</Table.Cell>
</Table.Row>
<Table.Row>
Expand All @@ -377,7 +377,7 @@ export const ViewOnlyView = () => {
/>
</Table.Cell>
<Table.Cell align="right" width="40">
<Toggle prefixIcon="pin" iconOnly />
<Toggle prefixIcon="pin" iconOnly tooltipProps={{ content: 'Toggle Pin' }} />
</Table.Cell>
</Table.Row>
</Table.Body>
Expand Down
12 changes: 10 additions & 2 deletions apps/gitness/src/framework/rbac/rbac-button.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, RbacButtonProps, Resource, Tooltip } from '@harnessio/ui/components'
import { Button, RbacButtonProps, Resource, toButtonProps, Tooltip } from '@harnessio/ui/components'

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

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

const button = <Button {...rest} disabled={!hasPermission} />
const button = (
<Button
{...toButtonProps({
...rest,
ignoreIconOnlyTooltip: true
})}
disabled={!hasPermission}
/>
)

return !hasPermission ? (
<Tooltip title={tooltip?.title ?? 'You are missing the permission for this action.'} content={tooltip?.content}>
Expand Down
60 changes: 32 additions & 28 deletions apps/portal/src/components/docs-page/example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,41 +75,45 @@ const Example: FC<ExampleProps> = ({
element: (
<RouterContextProvider Link={Link} NavLink={NavLink} Outlet={Outlet}>
<TranslationProvider>
<TooltipProvider>
<LivePreview />
</TooltipProvider>
<LivePreview />
</TranslationProvider>
</RouterContextProvider>
),
},
]);

return (
<div className="bg-cn-background-1 not-content my-12 overflow-hidden rounded-md border">
<LiveProvider code={currentCode} scope={scopeWithLayout} enableTypeScript>
<div className={cn("grid place-items-center p-12", contentClassName)}>
<RouterProvider router={router} />
</div>
{!hideCode && (
<details className="relative example-expand bg-cn-background-2 border-t p-3">
<CopyButton
buttonVariant="transparent"
className="absolute top-3 right-3"
name={currentCode}
/>
<summary className="flex cursor-pointer select-none items-center gap-1 text-sm">
<IconV2 name="nav-arrow-right" className="disclosure-icon" />
Show code
</summary>
<LiveEditor
theme={isLightTheme ? themes.vsLight : themes.vsDark}
className="font-body-code line-numbers p-1 text-sm leading-6"
onChange={setCurrentCode}
/>
</details>
)}
</LiveProvider>
</div>
<TooltipProvider>
<div className="bg-cn-background-1 not-content my-12 overflow-hidden rounded-md border">
<LiveProvider
code={currentCode}
scope={scopeWithLayout}
enableTypeScript
>
<div className={cn("grid place-items-center p-12", contentClassName)}>
<RouterProvider router={router} />
</div>
{!hideCode && (
<details className="relative example-expand bg-cn-background-2 border-t p-3">
<CopyButton
buttonVariant="transparent"
className="absolute top-3 right-3"
name={currentCode}
/>
<summary className="flex cursor-pointer select-none items-center gap-1 text-sm">
<IconV2 name="nav-arrow-right" className="disclosure-icon" />
Show code
</summary>
<LiveEditor
theme={isLightTheme ? themes.vsLight : themes.vsDark}
className="font-body-code line-numbers p-1 text-sm leading-6"
onChange={setCurrentCode}
/>
</details>
)}
</LiveProvider>
</div>
</TooltipProvider>
);
};

Expand Down
35 changes: 22 additions & 13 deletions apps/portal/src/components/layout/ThemeSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
IconV2,
ThemeDialog,
type ThemeDialogProps,
TooltipProvider,
} from "@harnessio/ui/components";
import { useEffect, useState } from "react";

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

return (
<ThemeDialog
open={open}
onOpenChange={setOpen}
setTheme={setTheme}
theme={theme}
>
<Button iconOnly onClick={() => setOpen(true)}>
<IconV2 name="theme" />
</Button>
</ThemeDialog>
<TooltipProvider>
<ThemeDialog
open={open}
onOpenChange={setOpen}
setTheme={setTheme}
theme={theme}
>
<Button
iconOnly
onClick={() => setOpen(true)}
tooltipProps={{ content: "Appearance settings" }}
>
<IconV2 name="theme" />
</Button>
</ThemeDialog>
</TooltipProvider>
);
}

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

return (
<Button iconOnly>
<IconV2 name="theme" />
</Button>
<TooltipProvider>
<Button iconOnly ignoreIconOnlyTooltip>
<IconV2 name="theme" />
</Button>
</TooltipProvider>
);
}
40 changes: 30 additions & 10 deletions apps/portal/src/content/docs/components/button.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ Secondary buttons can be styled with different themes for various contexts.
Success Loading
</Button>
</div>

<div className="flex gap-3">
<Button variant="secondary" theme="danger" disabled>
Danger Disabled
Expand Down Expand Up @@ -428,34 +428,38 @@ Transparent buttons have no background or border and don't accept theme props.

## Additional Features

When the `iconOnly` prop is used, you must also provide `tooltipProps` to display content in the tooltip.

If you need to skip showing the tooltip, you should set `ignoreIconOnlyTooltip`.

<DocsPage.ComponentExample
client:only
code={`<div className="flex flex-col items-start min-w-[600px] gap-8">
<h4>Icon Only Buttons</h4>

<div className="flex gap-3">
<Button iconOnly>
<Button iconOnly tooltipProps={{ content: "Add" }}>
<IconV2 name="plus" skipSize />
</Button>
<Button variant="secondary" size="sm" iconOnly>
<Button variant="secondary" size="sm" iconOnly ignoreIconOnlyTooltip>
<IconV2 name="git-branch" skipSize />
</Button>
<Button variant="transparent" size="sm" iconOnly>
<Button variant="transparent" size="sm" iconOnly ignoreIconOnlyTooltip>
<IconV2 name="xmark" skipSize />
</Button>
<Button variant="outline" size="xs" iconOnly>
<Button variant="outline" size="xs" iconOnly ignoreIconOnlyTooltip>
<IconV2 name="check" skipSize />
</Button>
<Button variant="outline" size="2xs" iconOnly>
<Button variant="outline" size="2xs" iconOnly ignoreIconOnlyTooltip>
<IconV2 name="check" skipSize />
</Button>
<Button variant="outline" size="3xs" iconOnly>
<Button variant="outline" size="3xs" iconOnly ignoreIconOnlyTooltip>
<IconV2 name="check" skipSize />
</Button>
<Button variant="outline" size="2xs" iconOnly>
<Button variant="outline" size="2xs" iconOnly ignoreIconOnlyTooltip>
<IconV2 name="xmark" skipSize />
</Button>
<Button variant="outline" size="3xs" iconOnly>
<Button variant="outline" size="3xs" iconOnly ignoreIconOnlyTooltip>
<IconV2 name="xmark" skipSize />
</Button>
</div>
Expand Down Expand Up @@ -515,7 +519,7 @@ import { Button } from '@harnessio/ui/components'
<Button rounded>Rounded Button</Button>

// Icon only button
<Button iconOnly>
<Button iconOnly tooltipProps={{ content: 'Add' }}>
<IconV2 name="plus" />
</Button>

Expand Down Expand Up @@ -618,5 +622,21 @@ This ensures type safety and provides proper development-time feedback on invali
required: true,
value: "ReactNode",
},
{
name: "tooltipProps",
description:
"If provided, wraps the Button in a tooltip with the specified properties.",
required: false,
defaultValue: "undefined",
value: "Pick<TooltipProps, 'title' | 'content' | 'side'>",
},
{
name: "ignoreIconOnlyTooltip",
description:
"Allows skipping the required tooltipProps when using iconOnly.",
required: false,
value: "boolean",
defaultValue: "undefined",
},
]}
/>
2 changes: 1 addition & 1 deletion apps/portal/src/content/docs/components/toggle-group.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ The `Item` component is used to define each toggle button within the group.
{
name: "tooltipProps",
description:
"If provided, wraps the ToggleItem in a tooltip with the specified properties.",
"If provided, wraps the Button in a tooltip with the specified properties.",
required: false,
defaultValue: "undefined",
value: "Pick<TooltipProps, 'title' | 'content' | 'side' | 'align'>",
Expand Down
Loading