mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 01:45:10 +03:00
SQL preview on hover snippet (#20694)
* SQL preview on hover snippet * Fix class name * Fix some styling * Fix some styling * Remove console log * Fix
This commit is contained in:
1 parent
2eb113eadf
commit
ff8b855678
8 files changed
+85
-42
No files matched your search
@@ -39,7 +39,6 @@ export const SelectionDetailedRow = ({
|
||||
</span>
|
||||
{!hideCopy && (
|
||||
<CopyButton
|
||||
bounceIconOnCopy
|
||||
text={value}
|
||||
className="group-hover:opacity-100 opacity-0 my-auto transition col-span-2 h-4 w-4 px-0 py-0"
|
||||
type="text"
|
||||
|
||||
@@ -210,7 +210,7 @@ const SQLEditor = () => {
|
||||
range: new monaco.Range(line, 1, line, 20),
|
||||
options: {
|
||||
isWholeLine: true,
|
||||
inlineClassName: 'bg-amber-600',
|
||||
inlineClassName: 'bg-warning-400',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
@@ -38,7 +38,6 @@ export const SelectionDetailedRow = ({
|
||||
{valueRender ?? value}
|
||||
</span>
|
||||
<CopyButton
|
||||
bounceIconOnCopy
|
||||
text={value}
|
||||
className="group-hover:opacity-100 opacity-0 my-auto transition col-span-2 h-4 w-4 px-0 py-0"
|
||||
type="text"
|
||||
|
||||
@@ -26,12 +26,17 @@ import {
|
||||
IconTrash,
|
||||
IconUnlock,
|
||||
Modal,
|
||||
TooltipContent_Shadcn_,
|
||||
TooltipTrigger_Shadcn_,
|
||||
Tooltip_Shadcn_,
|
||||
} from 'ui'
|
||||
|
||||
import DownloadSnippetModal from 'components/interfaces/SQLEditor/DownloadSnippetModal'
|
||||
import RenameQueryModal from 'components/interfaces/SQLEditor/RenameQueryModal'
|
||||
import { createSqlSnippetSkeleton } from 'components/interfaces/SQLEditor/SQLEditor.utils'
|
||||
import SimpleCodeBlock from 'components/to-be-cleaned/SimpleCodeBlock'
|
||||
import ConfirmationModal from 'components/ui/ConfirmationModal'
|
||||
import CopyButton from 'components/ui/CopyButton'
|
||||
import { useContentDeleteMutation } from 'data/content/content-delete-mutation'
|
||||
import { SqlSnippet } from 'data/content/sql-snippets-query'
|
||||
import { useCheckPermissions, useSelectedProject, useStore } from 'hooks'
|
||||
@@ -46,7 +51,7 @@ export interface QueryItemProps {
|
||||
|
||||
const QueryItem = ({ tabInfo }: QueryItemProps) => {
|
||||
const { ref, id: activeId } = useParams()
|
||||
const { id, name, description } = tabInfo || {}
|
||||
const { id, name, description, content } = tabInfo || {}
|
||||
const isActive = id === activeId
|
||||
const activeItemRef = useRef<HTMLElement | null>(null)
|
||||
|
||||
@@ -61,24 +66,64 @@ const QueryItem = ({ tabInfo }: QueryItemProps) => {
|
||||
})
|
||||
|
||||
return (
|
||||
<div
|
||||
key={id}
|
||||
className={clsx(
|
||||
'flex items-center justify-between rounded-md group',
|
||||
isActive && 'text-foreground bg-surface-300 -active'
|
||||
)}
|
||||
ref={isActive ? (activeItemRef as React.RefObject<HTMLDivElement>) : null}
|
||||
>
|
||||
<Link href={`/project/${ref}/sql/${id}`} className="py-1 px-3 w-full overflow-hidden">
|
||||
<p
|
||||
title={description || name}
|
||||
className="text-sm text-foreground-light group-hover:text-foreground transition overflow-hidden text-ellipsis"
|
||||
<Tooltip_Shadcn_ delayDuration={100}>
|
||||
<TooltipTrigger_Shadcn_ asChild>
|
||||
<div
|
||||
key={id}
|
||||
className={clsx(
|
||||
'flex items-center justify-between rounded-md group',
|
||||
isActive ? 'bg-surface-300' : 'hover:bg-surface-200'
|
||||
)}
|
||||
ref={isActive ? (activeItemRef as React.RefObject<HTMLDivElement>) : null}
|
||||
>
|
||||
{name}
|
||||
</p>
|
||||
</Link>
|
||||
<div className="pr-1">{<QueryItemActions tabInfo={tabInfo} activeId={activeId} />}</div>
|
||||
</div>
|
||||
<Link href={`/project/${ref}/sql/${id}`} className="py-1 px-3 w-full overflow-hidden">
|
||||
<p
|
||||
title={description || name}
|
||||
className={clsx(
|
||||
isActive
|
||||
? 'text-foreground'
|
||||
: 'text-foreground-light group-hover:text-foreground/80',
|
||||
'text-sm transition overflow-hidden text-ellipsis'
|
||||
)}
|
||||
>
|
||||
{name}
|
||||
</p>
|
||||
</Link>
|
||||
<div className="pr-1">{<QueryItemActions tabInfo={tabInfo} activeId={activeId} />}</div>
|
||||
</div>
|
||||
</TooltipTrigger_Shadcn_>
|
||||
{!isActive && (
|
||||
<TooltipContent_Shadcn_
|
||||
side="right"
|
||||
align="start"
|
||||
className="w-96 flex flex-col gap-y-2 py-3 -translate-y-[4px]"
|
||||
>
|
||||
<p className="text-xs">Query preview:</p>
|
||||
<div className="bg-surface-300 py-2 px-3 rounded relative">
|
||||
{content.sql.trim() ? (
|
||||
<SimpleCodeBlock
|
||||
showCopy={false}
|
||||
className="sql"
|
||||
parentClassName="!p-0 [&>div>span]:text-xs [&>div>span]:tracking-tighter"
|
||||
>
|
||||
{content.sql.replaceAll('\n', ' ').replaceAll(/\s+/g, ' ').slice(0, 43) +
|
||||
`${content.sql.length > 43 ? '...' : ''}`}
|
||||
</SimpleCodeBlock>
|
||||
) : (
|
||||
<p className="text-xs text-foreground-lighter">This query is empty</p>
|
||||
)}
|
||||
{content.sql.trim() && (
|
||||
<CopyButton
|
||||
iconOnly
|
||||
type="default"
|
||||
className="px-1 absolute top-1.5 right-1.5"
|
||||
text={content.sql}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</TooltipContent_Shadcn_>
|
||||
)}
|
||||
</Tooltip_Shadcn_>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -225,7 +270,7 @@ const QueryItemActions = observer(({ tabInfo, activeId }: QueryItemActionsProps)
|
||||
<IconChevronDown size="tiny" strokeWidth={2} />
|
||||
</span>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="bottom" align="end">
|
||||
<DropdownMenuContent side="bottom" align="end" className=" w-52 translate-x-[4px]">
|
||||
{isSnippetOwner && (
|
||||
<DropdownMenuItem onClick={onClickRename} className="space-x-2">
|
||||
<IconEdit2 size="tiny" />
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useParams } from 'common'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { Button, cn, IconPlus, IconSearch, IconX, Input, Menu } from 'ui'
|
||||
import { Button, IconPlus, IconSearch, IconX, Input, Menu, cn } from 'ui'
|
||||
|
||||
import { untitledSnippetTitle } from 'components/interfaces/SQLEditor/SQLEditor.constants'
|
||||
import { createSqlSnippetSkeleton } from 'components/interfaces/SQLEditor/SQLEditor.utils'
|
||||
|
||||
@@ -20,6 +20,7 @@ const prism = {
|
||||
}
|
||||
|
||||
interface SimpleCodeBlockProps {
|
||||
parentClassName?: string
|
||||
className?: string
|
||||
metastring?: string
|
||||
showCopy?: boolean
|
||||
@@ -27,6 +28,7 @@ interface SimpleCodeBlockProps {
|
||||
|
||||
const SimpleCodeBlock = ({
|
||||
children,
|
||||
parentClassName,
|
||||
className: languageClassName,
|
||||
metastring,
|
||||
showCopy = true,
|
||||
@@ -67,7 +69,7 @@ const SimpleCodeBlock = ({
|
||||
{({ className, tokens, getLineProps, getTokenProps }) => {
|
||||
return (
|
||||
<div className="Code codeBlockWrapper group">
|
||||
<pre ref={target} className={`codeBlock ${className}`}>
|
||||
<pre ref={target} className={`codeBlock ${className} ${parentClassName}`}>
|
||||
{tokens.map((line, i) => {
|
||||
const lineProps = getLineProps({ line, key: i })
|
||||
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
import { Button, ButtonProps } from 'ui'
|
||||
import { Button, ButtonProps, IconCheck, IconClipboard } from 'ui'
|
||||
import { copyToClipboard } from 'lib/helpers'
|
||||
import { IconClipboard } from 'ui'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
export interface CopyButtonProps extends ButtonProps {
|
||||
text: string
|
||||
// used for text-less feedback
|
||||
bounceIconOnCopy?: boolean
|
||||
iconOnly?: boolean
|
||||
}
|
||||
const CopyButton: React.FC<CopyButtonProps> = ({
|
||||
text,
|
||||
children,
|
||||
onClick,
|
||||
bounceIconOnCopy,
|
||||
...props
|
||||
}) => {
|
||||
const CopyButton = ({ text, iconOnly = false, children, onClick, ...props }: CopyButtonProps) => {
|
||||
const [showCopied, setShowCopied] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -31,16 +23,15 @@ const CopyButton: React.FC<CopyButtonProps> = ({
|
||||
onClick?.(e)
|
||||
}}
|
||||
icon={
|
||||
<IconClipboard
|
||||
size="tiny"
|
||||
className={[showCopied && bounceIconOnCopy ? 'animate-bounce' : '', 'transition'].join(
|
||||
' '
|
||||
)}
|
||||
/>
|
||||
showCopied ? (
|
||||
<IconCheck size="tiny" strokeWidth={2} className="text-brand" />
|
||||
) : (
|
||||
<IconClipboard size="tiny" />
|
||||
)
|
||||
}
|
||||
{...props}
|
||||
>
|
||||
{children ?? (showCopied ? 'Copied' : 'Copy')}
|
||||
{!iconOnly && <>{children ?? (showCopied ? 'Copied' : 'Copy')}</>}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -196,6 +196,13 @@ export {
|
||||
TabsTrigger as TabsTrigger_Shadcn_,
|
||||
} from './src/components/shadcn/ui/tabs/tabs'
|
||||
|
||||
export {
|
||||
TooltipProvider as TooltipProvider_Shadcn_,
|
||||
Tooltip as Tooltip_Shadcn_,
|
||||
TooltipTrigger as TooltipTrigger_Shadcn_,
|
||||
TooltipContent as TooltipContent_Shadcn_,
|
||||
} from './src/components/shadcn/ui/tooltip'
|
||||
|
||||
export { ScrollArea, ScrollBar } from './src/components/shadcn/ui/scroll-area'
|
||||
|
||||
export { Separator } from './src/components/shadcn/ui/separator'
|
||||
|
||||
Reference in new issue
Block a user