Merge pull request #77 from tloncorp/po/fix-radix-upgrade-issues

Update uses of Dropdown and Dialog from radix to conform with upgrade
This commit is contained in:
Patrick O'Sullivan 2023-02-08 10:01:08 -06:00 committed by GitHub
commit f37cb1613f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 241 additions and 203 deletions

View File

@ -74,7 +74,7 @@ export const AppInfo: FC<AppInfoProps> = ({ docket, pike, className }) => {
// TODO: maybe replace spinner with skeletons
return (
<div className="dialog-inner-container flex justify-center text-black">
<Spinner className="w-10 h-10" />
<Spinner className="h-10 w-10" />
</div>
);
}
@ -82,7 +82,7 @@ export const AppInfo: FC<AppInfoProps> = ({ docket, pike, className }) => {
return (
<div className={cn('text-black', className)}>
<DocketHeader docket={docket}>
<div className="col-span-2 md:col-span-1 flex items-center space-x-4">
<div className="col-span-2 flex items-center space-x-4 md:col-span-1">
{installStatus === 'installed' && (
<PillButton
variant="alt-primary"
@ -97,32 +97,39 @@ export const AppInfo: FC<AppInfoProps> = ({ docket, pike, className }) => {
)}
{installStatus !== 'installed' && (
<Dialog>
<DialogTrigger as={PillButton} disabled={installing} variant="alt-primary">
{installing ? (
<>
<Spinner />
<span className="sr-only">Installing...</span>
</>
) : (
'Get App'
)}
<DialogTrigger asChild>
<PillButton variant="alt-primary" disabled={installing}>
{installing ? (
<>
<Spinner />
<span className="sr-only">Installing...</span>
</>
) : (
'Get App'
)}
</PillButton>
</DialogTrigger>
<DialogContent
showClose={false}
className="space-y-6"
containerClass="w-full max-w-md"
>
<h2 className="h4">Install &ldquo;{getAppName(docket)}&rdquo;</h2>
<p className="tracking-tight pr-6">
This application will be able to view and interact with the contents of your
Urbit. Only install if you trust the developer.
<h2 className="h4">
Install &ldquo;{getAppName(docket)}&rdquo;
</h2>
<p className="pr-6 tracking-tight">
This application will be able to view and interact with the
contents of your Urbit. Only install if you trust the
developer.
</p>
<div className="flex space-x-6">
<DialogClose as={Button} variant="secondary">
Cancel
<DialogClose asChild>
<Button variant="secondary">Cancel</Button>
</DialogClose>
<DialogClose as={Button} onClick={installApp}>
Get &ldquo;{getAppName(docket)}&rdquo;
<DialogClose asChild onClick={installApp}>
<Button onClick={installApp}>
Get &ldquo;{getAppName(docket)}&rdquo;
</Button>
</DialogClose>
</div>
</DialogContent>
@ -137,13 +144,13 @@ export const AppInfo: FC<AppInfoProps> = ({ docket, pike, className }) => {
<div className="space-y-6">
{pike ? (
<>
<hr className="-mx-5 sm:-mx-8 border-gray-50" />
<hr className="-mx-5 border-gray-50 sm:-mx-8" />
<PikeMeta pike={pike} />
</>
) : null}
{!treaty ? null : (
<>
<hr className="-mx-5 sm:-mx-8 border-gray-50" />
<hr className="-mx-5 border-gray-50 sm:-mx-8" />
<TreatyMeta treaty={treaty} />
</>
)}

View File

@ -26,12 +26,16 @@ const SubmitIssue = ({ error }: { error: Error }) => {
);
};
export const ErrorAlert = ({ error, resetErrorBoundary, className }: ErrorAlertProps) => {
export const ErrorAlert = ({
error,
resetErrorBoundary,
className,
}: ErrorAlertProps) => {
return (
<Dialog defaultOpen modal onOpenChange={() => resetErrorBoundary()}>
<DialogContent
showClose={false}
className={cn('pr-8 space-y-6', className)}
className={cn('space-y-6 pr-8', className)}
containerClass="w-full max-w-3xl"
>
<h2 className="h4">
@ -39,15 +43,17 @@ export const ErrorAlert = ({ error, resetErrorBoundary, className }: ErrorAlertP
<span className="font-mono">{error.message}</span>
</h2>
{error.stack && (
<div className="w-full p-2 bg-gray-50 overflow-x-auto rounded">
<div className="w-full overflow-x-auto rounded bg-gray-50 p-2">
<pre>{error.stack}</pre>
</div>
)}
<div className="flex space-x-6">
<DialogClose as={Button} variant="secondary">
Try Again
<DialogClose asChild>
<Button variant="secondary">Try Again</Button>
</DialogClose>
<DialogClose asChild>
<SubmitIssue error={error} />
</DialogClose>
<DialogClose as={SubmitIssue} error={error} />
</div>
</DialogContent>
</Dialog>

View File

@ -77,7 +77,6 @@ const AppLink = ({ link, title, description, image, color }: App) => {
function LandscapeDescription() {
const charges = useCharges();
console.log({ charges });
return (
<div className="flex flex-col leading-5">
<h1 className="my-8 text-2xl font-bold">Where am I?</h1>

View File

@ -1,7 +1,13 @@
import { DialogContent } from '@radix-ui/react-dialog';
import * as Portal from '@radix-ui/react-portal';
import classNames from 'classnames';
import React, { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react';
import React, {
FunctionComponent,
useCallback,
useEffect,
useRef,
useState,
} from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import {
Link,
@ -189,7 +195,7 @@ export const Nav: FunctionComponent<NavProps> = ({ menu }) => {
<DialogContent
onInteractOutside={preventClose}
onOpenAutoFocus={onOpen}
className="scroll-left-50 scroll-full-width outline-none fixed bottom-0 flex h-full max-h-full max-w-[882px] -translate-x-1/2 flex-col justify-end px-4 text-gray-400 sm:top-0 sm:bottom-auto sm:h-auto sm:justify-start sm:pb-4"
className="scroll-left-50 scroll-full-width outline-none fixed bottom-0 z-50 flex h-full max-h-full max-w-[882px] -translate-x-1/2 flex-col justify-end px-4 text-gray-400 sm:top-0 sm:bottom-auto sm:h-auto sm:justify-start sm:pb-4"
role="combobox"
aria-controls="leap-items"
aria-owns="leap-items"

View File

@ -22,7 +22,12 @@ function getHash(pike: Pike): string {
return parts[parts.length - 1];
}
export const SystemMenu = ({ className, open, subMenuOpen, shouldDim }: SystemMenuProps) => {
export const SystemMenu = ({
className,
open,
subMenuOpen,
shouldDim,
}: SystemMenuProps) => {
const { push } = useHistory();
const [copied, setCopied] = useState(false);
const garden = usePike(window.desk);
@ -67,7 +72,7 @@ export const SystemMenu = ({ className, open, subMenuOpen, shouldDim }: SystemMe
<Link
to={open || subMenuOpen ? '/' : '/system-menu'}
className={classNames(
'relative appearance-none circle-button default-ring',
'circle-button default-ring relative appearance-none',
open && 'text-gray-300',
shouldDim && 'opacity-60',
className
@ -76,13 +81,13 @@ export const SystemMenu = ({ className, open, subMenuOpen, shouldDim }: SystemMe
>
{!open && !subMenuOpen && (
<>
<Adjust className="w-6 h-6 fill-current text-gray" />
<Adjust className="text-gray h-6 w-6 fill-current" />
<span className="sr-only">System Menu</span>
</>
)}
{(open || subMenuOpen) && (
<>
<Cross className="w-3 h-3 fill-current" />
<Cross className="h-3 w-3 fill-current" />
<span className="sr-only">Close</span>
</>
)}
@ -97,47 +102,49 @@ export const SystemMenu = ({ className, open, subMenuOpen, shouldDim }: SystemMe
onPointerDownOutside={preventFlash}
side={isMobile ? 'top' : 'bottom'}
sideOffset={12}
className="dropdown relative z-40 min-w-64 p-4 font-semibold text-gray-500 bg-white"
className="dropdown relative z-40 min-w-64 bg-white p-4 font-semibold text-gray-500"
>
<DropdownMenu.Group>
<DropdownMenu.Item
as={Link}
to="/leap/system-preferences"
className="flex items-center p-2 mb-2 space-x-2 focus:bg-blue-200 focus:outline-none rounded"
onSelect={handleDropdownLink()}
>
<span className="w-5 h-5 bg-gray-100 rounded-full" />
<span className="h4">System Preferences</span>
<DropdownMenu.Item onSelect={handleDropdownLink()}>
<Link
to="/leap/system-preferences"
className="focus:outline-none mb-2 flex items-center space-x-2 rounded p-2 focus:bg-blue-200"
>
<span className="h-5 w-5 rounded-full bg-gray-100" />
<span className="h4">System Preferences</span>
</Link>
</DropdownMenu.Item>
<DropdownMenu.Item
as={Link}
to="/leap/help-and-support"
className="flex items-center p-2 mb-2 space-x-2 focus:bg-blue-200 focus:outline-none rounded"
onSelect={handleDropdownLink()}
>
<span className="w-5 h-5 bg-gray-100 rounded-full" />
<span className="h4">Help and Support</span>
<DropdownMenu.Item asChild onSelect={handleDropdownLink()}>
<Link
to="/leap/help-and-support"
className="focus:outline-none mb-2 flex items-center space-x-2 rounded p-2 focus:bg-blue-200"
>
<span className="h-5 w-5 rounded-full bg-gray-100" />
<span className="h4">Help and Support</span>
</Link>
</DropdownMenu.Item>
<DropdownMenu.Item
as={Link}
to={`/app/${window.desk}`}
className="flex items-center p-2 mb-2 space-x-2 focus:bg-blue-200 focus:outline-none rounded"
onSelect={handleDropdownLink()}
>
<span className="w-5 h-5 bg-gray-100 rounded-full" />
<span className="h4">About</span>
<DropdownMenu.Item asChild onSelect={handleDropdownLink()}>
<Link
to={`/app/${window.desk}`}
className="focus:outline-none mb-2 flex items-center space-x-2 rounded p-2 focus:bg-blue-200"
>
<span className="h-5 w-5 rounded-full bg-gray-100" />
<span className="h4">About</span>
</Link>
</DropdownMenu.Item>
{hash && (
<DropdownMenu.Item
as="button"
className="inline-flex items-center py-2 px-3 m-2 h4 text-black bg-gray-100 rounded focus:bg-blue-200 focus:outline-none"
onSelect={copyHash}
>
<span className="sr-only">Base Hash</span>
<code>
{!copied && <span aria-label={hash.split('').join('-')}>{hash}</span>}
{copied && 'copied!'}
</code>
<DropdownMenu.Item asChild onSelect={copyHash}>
<button className="h4 focus:outline-none m-2 inline-flex items-center rounded bg-gray-100 py-2 px-3 text-black focus:bg-blue-200">
<span className="sr-only">Base Hash</span>
<code>
{!copied && (
<span aria-label={hash.split('').join('-')}>
{hash}
</span>
)}
{copied && 'copied!'}
</code>
</button>
</DropdownMenu.Item>
)}
</DropdownMenu.Group>
@ -148,7 +155,7 @@ export const SystemMenu = ({ className, open, subMenuOpen, shouldDim }: SystemMe
<Route path="/system-menu">
<div
id="system-menu-overlay"
className="fixed z-30 right-0 bottom-0 w-screen h-screen bg-black opacity-30"
className="fixed right-0 bottom-0 z-30 h-screen w-screen bg-black opacity-30"
/>
</Route>
</>

View File

@ -44,7 +44,7 @@ export const Grid: FunctionComponent = () => {
return (
<div className="flex h-screen w-full flex-col">
{!disableWayfinding && <LandscapeWayfinding />}
{/* !disableWayfinding && <LandscapeWayfinding /> */}
<header className="fixed bottom-0 left-0 z-30 flex w-full justify-center px-4 sm:sticky sm:bottom-auto sm:top-0">
<Nav menu={menu} />
</header>

View File

@ -2,7 +2,12 @@ import { Pike } from '@urbit/api';
import React from 'react';
import { AppList } from '../../components/AppList';
import { Button } from '../../components/Button';
import { Dialog, DialogClose, DialogContent, DialogTrigger } from '../../components/Dialog';
import {
Dialog,
DialogClose,
DialogContent,
DialogTrigger,
} from '../../components/Dialog';
import { FullTlon16Icon } from '../../components/icons/FullTlon16Icon';
import { useSystemUpdate } from '../../logic/useSystemUpdate';
import { useCharge } from '../../state/docket';
@ -19,107 +24,115 @@ export const AboutSystem = () => {
const basePike = usePike('base');
const { systemBlocked, blockedCharges, blockedCount, freezeApps } =
useSystemUpdate();
const gardenBlocked = null != blockedCharges.find(charge => charge.desk == 'garden');
const gardenBlocked =
null != blockedCharges.find((charge) => charge.desk == 'garden');
const hash = basePike && getHash(basePike);
const lag = useLag();
return (
<>
<div className="inner-section space-y-8 relative mb-4">
<div className="inner-section relative mb-4 space-y-8">
<div className="flex items-center justify-between">
<h2 className="h4">About System</h2>
{systemBlocked && (
<span className="bg-orange-50 text-orange-500 text-sm font-semibold px-2 py-1 rounded-md">
<span className="rounded-md bg-orange-50 px-2 py-1 text-sm font-semibold text-orange-500">
System Update Blocked
</span>
)}
</div>
<div className="leading-5 space-y-4">
<div className="space-y-4 leading-5">
<FullTlon16Icon className="h-4" />
<div>
<p>
Urbit Kernel Version ({hash})
</p>
<p>Urbit Kernel Version ({hash})</p>
</div>
{systemBlocked ? (
<>
{lag ? (
<>
<p className="text-orange-500">
System update failed because your runtime was out of date.
</p>
<p>
Update your runtime or contact your hosting provider.
</p>
<p>
Once your runtime is up to date, click retry below.
</p>
<Button variant="caution" onClick={freezeApps}>
Retry System Update
</Button>
</>
) : (blockedCount == 0) ? (
<>
<p className="text-orange-500">
System update failed.
</p>
<p>
For additional debugging output, open the terminal and click retry below.
</p>
<Button variant="caution" onClick={freezeApps}>
Retry System Update
</Button>
</>
) : (
<>
<p className="text-orange-500">
Update is currently blocked by the following {pluralize('app', blockedCount)}:
</p>
<AppList
apps={blockedCharges}
labelledBy="blocked-apps"
size="xs"
className="font-medium"
/>
{gardenBlocked ? (
{lag ? (
<>
<p>
Landscape is the application launcher and system interface.
It needs an update before you can apply the System Update.
</p>
<p className="text-orange-500">
System update failed because your runtime was out of date.
</p>
<p>Update your runtime or contact your hosting provider.</p>
<p>Once your runtime is up to date, click retry below.</p>
<Button variant="caution" onClick={freezeApps}>
Retry System Update
</Button>
</>
) : blockedCount == 0 ? (
<>
<p className="text-orange-500">System update failed.</p>
<p>
For additional debugging output, open the terminal and click
retry below.
</p>
<Button variant="caution" onClick={freezeApps}>
Retry System Update
</Button>
</>
) : (
<Dialog>
<DialogTrigger as={Button} variant="caution">
Suspend {blockedCount} {pluralize('App', blockedCount)} and Apply Update
</DialogTrigger>
<DialogContent
showClose={false}
onOpenAutoFocus={disableDefault}
className="space-y-6 tracking-tight"
containerClass="w-full max-w-md"
>
<h2 className="h4">
Suspend {blockedCount} {pluralize('App', blockedCount)} and Apply System Update
</h2>
<p>
The following {pluralize('app', blockedCount)} will be suspended until their
developer provides an update.
</p>
<AppList apps={blockedCharges} labelledBy="blocked-apps" size="xs" />
<div className="flex space-x-6">
<DialogClose as={Button} variant="secondary">
Cancel
</DialogClose>
<DialogClose as={Button} variant="caution" onClick={freezeApps}>
Suspend {pluralize('App', blockedCount)} and Update
</DialogClose>
</div>
</DialogContent>
</Dialog>
<>
<p className="text-orange-500">
Update is currently blocked by the following{' '}
{pluralize('app', blockedCount)}:
</p>
<AppList
apps={blockedCharges}
labelledBy="blocked-apps"
size="xs"
className="font-medium"
/>
{gardenBlocked ? (
<>
<p>
Landscape is the application launcher and system
interface. It needs an update before you can apply the
System Update.
</p>
</>
) : (
<Dialog>
<DialogTrigger asChild>
<Button variant="caution">
Suspend {blockedCount}{' '}
{pluralize('App', blockedCount)} and Apply Update
</Button>
</DialogTrigger>
<DialogContent
showClose={false}
onOpenAutoFocus={disableDefault}
className="space-y-6 tracking-tight"
containerClass="w-full max-w-md"
>
<h2 className="h4">
Suspend {blockedCount}{' '}
{pluralize('App', blockedCount)} and Apply System
Update
</h2>
<p>
The following {pluralize('app', blockedCount)} will be
suspended until their developer provides an update.
</p>
<AppList
apps={blockedCharges}
labelledBy="blocked-apps"
size="xs"
/>
<div className="flex space-x-6">
<DialogClose asChild>
<Button variant="secondary">Cancel</Button>
</DialogClose>
<DialogClose asChild>
<Button variant="caution" onClick={freezeApps}>
Suspend {pluralize('App', blockedCount)} and
Update
</Button>
</DialogClose>
</div>
</DialogContent>
</Dialog>
)}
</>
)}
</>
)}
</>
) : (
<p>Your urbit is up to date.</p>

View File

@ -21,22 +21,27 @@ export const RemoveApp = () => {
return (
<Dialog open onOpenChange={(open) => !open && history.push('/')}>
<DialogContent showClose={false} className="space-y-6" containerClass="w-full max-w-md">
<DialogContent
showClose={false}
className="space-y-6"
containerClass="w-full max-w-md"
>
<h1 className="h4">Uninstall &ldquo;{getAppName(docket)}&rdquo;?</h1>
<p className="tracking-tight pr-6">
The app tile will be removed from Landscape, all processes will be stopped and their data
archived, and the app will stop receiving updates.
<p className="pr-6 tracking-tight">
The app tile will be removed from Landscape, all processes will be
stopped and their data archived, and the app will stop receiving
updates.
</p>
<p className="tracking-tight pr-6">
If the app is reinstalled, the archived data will be restored and you&apos;ll be able to
pick up where you left off.
<p className="pr-6 tracking-tight">
If the app is reinstalled, the archived data will be restored and
you&apos;ll be able to pick up where you left off.
</p>
<div className="flex space-x-6">
<DialogClose as={Button} variant="secondary">
Cancel
<DialogClose asChild>
<Button variant="secondary">Cancel</Button>
</DialogClose>
<DialogClose as={Button} onClick={handleRemoveApp}>
Uninstall
<DialogClose asChild>
<Button onClick={handleRemoveApp}>Uninstall</Button>
</DialogClose>
</div>
</DialogContent>

View File

@ -24,22 +24,26 @@ export const SuspendApp = () => {
return (
<Dialog open onOpenChange={(open) => !open && history.push('/')}>
<DialogContent showClose={false} className="space-y-6" containerClass="w-full max-w-md">
<DialogContent
showClose={false}
className="space-y-6"
containerClass="w-full max-w-md"
>
<h1 className="h4">Suspend &ldquo;{getAppName(charge)}&rdquo;</h1>
<p className="tracking-tight pr-6">
All processes will be stopped and data archived. The app will continue to receive updates
from its publisher.
<p className="pr-6 tracking-tight">
All processes will be stopped and data archived. The app will continue
to receive updates from its publisher.
</p>
<p className="tracking-tight pr-6">
When unsuspended, archived data will be loaded and all processes will resume running, so
you can pick up where you left off.
<p className="pr-6 tracking-tight">
When unsuspended, archived data will be loaded and all processes will
resume running, so you can pick up where you left off.
</p>
<div className="flex space-x-6">
<DialogClose as={Button} variant="secondary">
Cancel
<DialogClose asChild>
<Button variant="secondary">Cancel</Button>
</DialogClose>
<DialogClose as={Button} onClick={handleSuspendApp}>
Suspend
<DialogClose asChild>
<Button onClick={handleSuspendApp}>Suspend</Button>
</DialogClose>
</div>
</DialogContent>

View File

@ -1,4 +1,4 @@
import React, { useCallback, useState } from 'react';
import React, { ReactElement, useCallback, useState } from 'react';
import type * as Polymorphic from '@radix-ui/react-polymorphic';
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import classNames from 'classnames';
@ -24,20 +24,17 @@ const MenuIcon = ({ className }: { className: string }) => (
</svg>
);
type ItemComponent = Polymorphic.ForwardRefComponent<
Polymorphic.IntrinsicElement<typeof DropdownMenu.Item>,
Polymorphic.OwnProps<typeof DropdownMenu.Item>
>;
const Item = React.forwardRef(({ children, ...props }, ref) => (
<DropdownMenu.Item
ref={ref}
{...props}
className="default-ring block w-full select-none rounded px-4 py-3 leading-none mix-blend-hard-light ring-gray-600"
>
{children}
</DropdownMenu.Item>
)) as ItemComponent;
const Item = React.forwardRef<HTMLDivElement, DropdownMenu.MenuItemProps>(
({ children, ...props }, ref) => (
<DropdownMenu.Item
ref={ref}
{...props}
className="default-ring block w-full select-none rounded px-4 py-3 leading-none mix-blend-hard-light ring-gray-600"
>
{children}
</DropdownMenu.Item>
)
);
export const TileMenu = ({
desk,
@ -77,40 +74,34 @@ export const TileMenu = ({
<DropdownMenu.Content
onCloseAutoFocus={disableDefault}
className={classNames(
'dropdown py-2 font-semibold',
'dropdown py-2 font-semibold z-40',
lightText ? 'text-gray-100' : 'text-gray-800'
)}
style={menuBg}
>
<DropdownMenu.Group>
<Item
as={Link}
to={`/app/${desk}`}
onSelect={isMobile ? (e) => e.preventDefault() : linkOnSelect}
>
App Info
<Item onSelect={isMobile ? (e) => e.preventDefault() : linkOnSelect}>
<Link to={`/app/${desk}`}>App Info</Link>
</Item>
</DropdownMenu.Group>
<DropdownMenu.Separator className="-mx-4 my-2 border-t-2 border-solid border-gray-600 mix-blend-soft-light" />
<DropdownMenu.Group>
{active && (
<Item
as={Link}
to={`/app/${desk}/suspend`}
asChild
onSelect={isMobile ? (e) => e.preventDefault() : linkOnSelect}
>
Suspend App
<Link to={`/app/${desk}/suspend`}>Suspend App</Link>
</Item>
)}
{suspended && (
<Item onSelect={() => toggleDocket(desk)}>Resume App</Item>
)}
<Item
as={Link}
to={`/app/${desk}/remove`}
asChild
onSelect={isMobile ? (e) => e.preventDefault() : linkOnSelect}
>
Uninstall App
<Link to={`/app/${desk}/remove`}>Uninstall App</Link>
</Item>
</DropdownMenu.Group>
<DropdownMenu.Arrow