Skip to content

Commit

Permalink
Fix tooltips and Start Modal (#10294)
Browse files Browse the repository at this point in the history
  • Loading branch information
MrFlashAccount authored Jun 16, 2024
1 parent 04551f4 commit 20998e3
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const BUTTON_STYLES = twv.tv({
fullWidth: { true: 'w-full' },
fullWidthText: { true: { text: 'w-full' } },
size: {
custom: { base: '', extraClickZone: 'after:inset-[-12px]', icon: 'h-full' },
custom: { base: '', extraClickZone: '', icon: 'h-full' },
hero: { base: 'px-8 py-4 text-lg font-bold', content: 'gap-[0.75em]' },
large: {
base: text.TEXT_STYLE({
Expand Down Expand Up @@ -181,7 +181,6 @@ export const BUTTON_STYLES = twv.tv({
showIconOnHover: {
true: { icon: 'opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100' },
},
noExtraClickZone: { true: { extraClickZone: 'after:inset-0' } },
},
slots: {
extraClickZone: 'flex relative after:absolute after:cursor-pointer',
Expand Down Expand Up @@ -261,7 +260,6 @@ export const Button = React.forwardRef(function Button(
showIconOnHover,
iconPosition,
size,
noExtraClickZone,
fullWidth,
fullWidthText,
rounded,
Expand All @@ -287,7 +285,15 @@ export const Button = React.forwardRef(function Button(
'data-testid': testId ?? (isLink ? 'link' : 'button'),
}
const isIconOnly = (children == null || children === '' || children === false) && icon != null
const shouldShowTooltip = isIconOnly || tooltip !== false
const shouldShowTooltip = (() => {
if (tooltip === false) {
return false
} else if (isIconOnly) {
return true
} else {
return tooltip != null
}
})()
const tooltipElement = shouldShowTooltip ? tooltip ?? ariaProps['aria-label'] : null

const isLoading = loading || implicitlyLoading
Expand Down Expand Up @@ -340,7 +346,6 @@ export const Button = React.forwardRef(function Button(
} = BUTTON_STYLES({
isDisabled,
loading: isLoading,
noExtraClickZone,
fullWidth,
fullWidthText,
size,
Expand Down Expand Up @@ -413,6 +418,7 @@ export const Button = React.forwardRef(function Button(
) : (
<ariaComponents.TooltipTrigger delay={0} closeDelay={0}>
{button}

<ariaComponents.Tooltip
{...(tooltipPlacement != null ? { placement: tooltipPlacement } : {})}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ import * as variants from './variants'
/**
* Props for the {@link Dialog} component.
*/
export interface DialogProps extends types.DialogProps, twv.VariantProps<typeof DIALOG_STYLES> {}
export interface DialogProps
extends types.DialogProps,
Omit<twv.VariantProps<typeof DIALOG_STYLES>, 'scrolledToTop'> {}

const OVERLAY_STYLES = twv.tv({
base: 'fixed inset-0 isolate flex items-center justify-center bg-black/[25%]',
Expand All @@ -47,14 +49,30 @@ const DIALOG_STYLES = twv.tv({
base: '',
variants: {
type: {
modal: 'w-full max-w-md min-h-[100px] max-h-[90vh]',
fullscreen: 'w-full h-full max-w-full max-h-full bg-clip-border',
modal: {
base: 'w-full max-w-md min-h-[100px] max-h-[90vh]',
header: 'px-3.5 pt-[3px] pb-0.5',
},
fullscreen: {
base: 'w-full h-full max-w-full max-h-full bg-clip-border',
header: 'px-4 pt-[5px] pb-1.5',
},
},
hideCloseButton: { true: { closeButton: 'hidden' } },
closeButton: {
normal: { base: '', closeButton: '' },
floating: {
base: '',
closeButton: 'absolute left-4 top-4 visible z-1 transition-all duration-150',
header: 'invisible p-0 h-0 border-0 z-1',
content: 'isolate',
},
},
scrolledToTop: { true: { header: 'border-transparent' } },
},
slots: {
header:
'sticky grid grid-cols-[1fr_auto_1fr] items-center border-b border-primary/10 px-3.5 pt-[3px] pb-0.5',
'sticky grid grid-cols-[1fr_auto_1fr] items-center border-b border-primary/10 transition-[border-color] duration-150',
closeButton: 'col-start-1 col-end-1 mr-auto',
heading: 'col-start-2 col-end-2 my-0',
content: 'relative flex-auto overflow-y-auto p-3.5',
Expand All @@ -72,7 +90,7 @@ export function Dialog(props: DialogProps) {
children,
title,
type = 'modal',
closeButton = 'none',
closeButton = 'normal',
isDismissable = true,
isKeyboardDismissDisabled = false,
hideCloseButton = false,
Expand All @@ -84,12 +102,32 @@ export function Dialog(props: DialogProps) {
...ariaDialogProps
} = props

const [isScrolledToTop, setIsScrolledToTop] = React.useState(true)

/**
* Handles the scroll event on the dialog content.
*/
const handleScroll = (scrollTop: number) => {
if (scrollTop > 0) {
setIsScrolledToTop(false)
} else {
setIsScrolledToTop(true)
}
}

const dialogId = aria.useId()
const dialogRef = React.useRef<HTMLDivElement>(null)
const overlayState = React.useRef<aria.OverlayTriggerState | null>(null)
const root = portal.useStrictPortalContext()
const shouldRenderTitle = typeof title === 'string'
const dialogSlots = DIALOG_STYLES({ className, type, rounded, hideCloseButton })

const dialogSlots = DIALOG_STYLES({
className,
type,
rounded,
hideCloseButton,
closeButton,
scrolledToTop: isScrolledToTop,
})

utlities.useInteractOutside({
ref: dialogRef,
Expand Down Expand Up @@ -152,10 +190,12 @@ export function Dialog(props: DialogProps) {
className={dialogSlots.base()}
{...ariaDialogProps}
>
{opts => (
<dialogProvider.DialogProvider value={{ close: opts.close, dialogId }}>
{shouldRenderTitle && (
<aria.Header className={dialogSlots.header()}>
{opts => {
return (
<dialogProvider.DialogProvider value={{ close: opts.close, dialogId }}>
<aria.Header
className={dialogSlots.header({ scrolledToTop: isScrolledToTop })}
>
<ariaComponents.CloseButton
className={dialogSlots.closeButton()}
onPress={opts.close}
Expand All @@ -169,22 +209,27 @@ export function Dialog(props: DialogProps) {
{title}
</ariaComponents.Text.Heading>
</aria.Header>
)}

<div className={dialogSlots.content()}>
<errorBoundary.ErrorBoundary>
<React.Suspense fallback={<loader.Loader minHeight="h32" />}>
{typeof children === 'function' ? children(opts) : children}
</React.Suspense>
</errorBoundary.ErrorBoundary>
</div>
{closeButton === 'floating' && (
<div className="absolute m-[19px] flex gap-1">
<ariaComponents.CloseButton onPress={opts.close} />

<div
ref={ref => {
if (ref) {
handleScroll(ref.scrollTop)
}
}}
className={dialogSlots.content()}
onScroll={event => {
handleScroll(event.currentTarget.scrollTop)
}}
>
<errorBoundary.ErrorBoundary>
<React.Suspense fallback={<loader.Loader minHeight="h32" />}>
{typeof children === 'function' ? children(opts) : children}
</React.Suspense>
</errorBoundary.ErrorBoundary>
</div>
)}
</dialogProvider.DialogProvider>
)}
</dialogProvider.DialogProvider>
)
}}
</aria.Dialog>
</dialogStackProvider.DialogStackRegistrar>
</aria.Modal>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
/** @file Types for the Dialog component. */
import type * as aria from '#/components/aria'

/** The type of close button for the Dialog.
* Note that Dialogs with a title have a regular close button by default. */
export type DialogCloseButtonType = 'floating' | 'none'

/** Props for the Dialog component. */
export interface DialogProps extends aria.DialogProps {
readonly closeButton?: DialogCloseButtonType
readonly title?: string
readonly isDismissable?: boolean
readonly onOpenChange?: (isOpen: boolean) => void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const DIALOG_BACKGROUND = twv.tv({

export const DIALOG_STYLES = twv.tv({
extend: DIALOG_BACKGROUND,
base: 'flex flex-col overflow-hidden text-left align-middle shadow-xl',
base: 'flex flex-col text-left align-middle shadow-xl',
variants: {
rounded: {
none: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ export default function ProjectIcon(props: ProjectIconProps) {
<ariaComponents.Button
size="custom"
variant="custom"
noExtraClickZone
icon={PlayIcon}
aria-label={getText('openInEditor')}
tooltipPlacement="left"
Expand All @@ -309,7 +308,6 @@ export default function ProjectIcon(props: ProjectIconProps) {
<ariaComponents.Button
size="custom"
variant="custom"
noExtraClickZone
isDisabled={isOtherUserUsingProject}
icon={StopIcon}
aria-label={getText('stopExecution')}
Expand Down Expand Up @@ -337,7 +335,6 @@ export default function ProjectIcon(props: ProjectIconProps) {
<ariaComponents.Button
size="custom"
variant="custom"
noExtraClickZone
isDisabled={isOtherUserUsingProject}
icon={StopIcon}
aria-label={getText('stopExecution')}
Expand All @@ -363,7 +360,6 @@ export default function ProjectIcon(props: ProjectIconProps) {
<ariaComponents.Button
size="custom"
variant="custom"
noExtraClickZone
className="size-project-icon border-0"
icon={ArrowUpIcon}
aria-label={getText('openInEditor')}
Expand Down
3 changes: 2 additions & 1 deletion app/ide-desktop/lib/dashboard/src/layouts/Samples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,11 @@ export default function Samples(props: SamplesProps) {
const { getText } = textProvider.useText()

return (
<div data-testid="samples" className="flex flex-col gap-subheading px-home-section-x">
<div data-testid="samples" className="flex flex-col gap-subheading px-[5px]">
<aria.Heading level={2} className="text-subheading font-normal">
{getText('sampleAndCommunityProjects')}
</aria.Heading>

<div className="grid grid-cols-fill-samples gap-samples">
{SAMPLES.map(sample => (
<ProjectTile key={sample.id} sample={sample} createProject={createProject} />
Expand Down
21 changes: 11 additions & 10 deletions app/ide-desktop/lib/dashboard/src/layouts/StartModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import * as textProvider from '#/providers/TextProvider'
import Samples from '#/layouts/Samples'
import WhatsNew from '#/layouts/WhatsNew'

import * as aria from '#/components/aria'
import * as ariaComponents from '#/components/AriaComponents'

// ==================
Expand All @@ -24,18 +23,20 @@ export default function StartModal(props: StartModalProps) {
const { getText } = textProvider.useText()

return (
<ariaComponents.Dialog type="fullscreen" closeButton="floating">
<ariaComponents.Dialog type="fullscreen" title={getText('selectTemplate')}>
{opts => (
<div className="relative mb-4 flex flex-1 flex-col gap-home text-xs text-primary">
<aria.Heading
level={2}
className="py-banner-item mx-10 mt-16 self-center text-center text-3xl font-light leading-snug"
<div className="mb-4 flex flex-1 flex-col gap-home text-xs text-primary">
<ariaComponents.Text
elementType="p"
variant="custom"
balance
className="mx-10 my-12 max-w-[45rem] self-center text-center text-3xl font-light leading-snug"
>
<aria.Text className="inline-block max-w-[45rem]">
{getText('welcomeSubtitle')}
</aria.Text>
</aria.Heading>
{getText('welcomeSubtitle')}
</ariaComponents.Text>

<WhatsNew />

<Samples
createProject={(templateId, templateName) => {
createProjectRaw(templateId, templateName)
Expand Down
2 changes: 1 addition & 1 deletion app/ide-desktop/lib/dashboard/src/layouts/WhatsNew.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function WhatsNew() {
const { getText } = textProvider.useText()

return (
<div className="flex flex-col gap-subheading px-home-section-x">
<div className="flex flex-col gap-subheading px-[5px]">
<aria.Heading level={2} className="text-subheading font-normal">
{getText('discoverWhatsNew')}
</aria.Heading>
Expand Down
1 change: 1 addition & 0 deletions app/ide-desktop/lib/dashboard/src/text/english.json
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@
"confirmNewPasswordLabel": "Confirm new password",
"confirmNewPasswordPlaceholder": "Confirm your new password",

"selectTemplate": "Select a template",
"welcomeSubtitle": "Explore templates, plugins, and data sources to kickstart your next big idea.",
"newsItem3Beta": "Read what’s new in Enso 3.0 Beta",
"newsItem3BetaDescription": "Learn about Enso Cloud, new data libraries, and Enso AI.",
Expand Down

0 comments on commit 20998e3

Please sign in to comment.