diff --git a/.changeset/eight-kids-cheer.md b/.changeset/eight-kids-cheer.md new file mode 100644 index 000000000..d71d70666 --- /dev/null +++ b/.changeset/eight-kids-cheer.md @@ -0,0 +1,5 @@ +--- +'website': patch +--- + +Added a max height and radius for hosts on the host map. diff --git a/.changeset/five-bobcats-grin.md b/.changeset/five-bobcats-grin.md new file mode 100644 index 000000000..bb3a721ad --- /dev/null +++ b/.changeset/five-bobcats-grin.md @@ -0,0 +1,5 @@ +--- +'@siafoundation/design-system': minor +--- + +The Dialog now supports providing a title or description that is visually hidden but still announced by assistive technology. diff --git a/.changeset/late-drinks-protect.md b/.changeset/late-drinks-protect.md new file mode 100644 index 000000000..2787ee47f --- /dev/null +++ b/.changeset/late-drinks-protect.md @@ -0,0 +1,5 @@ +--- +'website': patch +--- + +Fixed hydration mismatch warnings related to the random selection of a host on the globe. diff --git a/.changeset/late-readers-play.md b/.changeset/late-readers-play.md new file mode 100644 index 000000000..311fb9c8f --- /dev/null +++ b/.changeset/late-readers-play.md @@ -0,0 +1,5 @@ +--- +'renterd': patch +--- + +Fixed an issue with the uploads list loading and empty states. diff --git a/.changeset/mean-zebras-impress.md b/.changeset/mean-zebras-impress.md new file mode 100644 index 000000000..bcf73e1a4 --- /dev/null +++ b/.changeset/mean-zebras-impress.md @@ -0,0 +1,5 @@ +--- +'@siafoundation/design-system': patch +--- + +Fixed a warning caused by animation props being passed to non-animated graphs. diff --git a/.changeset/perfect-nails-tell.md b/.changeset/perfect-nails-tell.md new file mode 100644 index 000000000..df8968ac5 --- /dev/null +++ b/.changeset/perfect-nails-tell.md @@ -0,0 +1,5 @@ +--- +'website': patch +--- + +Fixed a hydration mismatch warning related to the ThemeRadio in footer. diff --git a/.changeset/quick-horses-love.md b/.changeset/quick-horses-love.md new file mode 100644 index 000000000..7665b16c6 --- /dev/null +++ b/.changeset/quick-horses-love.md @@ -0,0 +1,5 @@ +--- +'@siafoundation/design-system': minor +--- + +Adjusted tooltip to only wrap content with Paragraph if prop is a string or React.Fragment. diff --git a/.changeset/red-kangaroos-nail.md b/.changeset/red-kangaroos-nail.md new file mode 100644 index 000000000..853a95906 --- /dev/null +++ b/.changeset/red-kangaroos-nail.md @@ -0,0 +1,5 @@ +--- +'walletd': patch +--- + +Fixed an issue where the app would try to fetch from an invalid URL when first initializing. diff --git a/.changeset/six-cougars-sell.md b/.changeset/six-cougars-sell.md new file mode 100644 index 000000000..1b93df059 --- /dev/null +++ b/.changeset/six-cougars-sell.md @@ -0,0 +1,6 @@ +--- +'hostd': patch +'renterd': patch +--- + +Added explicit aria descriptions to some primary dialogs. diff --git a/.changeset/stale-windows-walk.md b/.changeset/stale-windows-walk.md new file mode 100644 index 000000000..8155e098e --- /dev/null +++ b/.changeset/stale-windows-walk.md @@ -0,0 +1,5 @@ +--- +'@siafoundation/design-system': patch +--- + +Fixed a 1 pixel gap that would show between the top of the Table and its sticky header when scrolling. diff --git a/.changeset/sweet-timers-fry.md b/.changeset/sweet-timers-fry.md new file mode 100644 index 000000000..bc9cef31a --- /dev/null +++ b/.changeset/sweet-timers-fry.md @@ -0,0 +1,5 @@ +--- +'@siafoundation/design-system': patch +--- + +Fixed warnings caused by the Dialog description prop and aria-describedby. diff --git a/apps/hostd/contexts/volumes/columns.tsx b/apps/hostd/contexts/volumes/columns.tsx index 64e4d4b0f..dd09339cc 100644 --- a/apps/hostd/contexts/volumes/columns.tsx +++ b/apps/hostd/contexts/volumes/columns.tsx @@ -53,7 +53,7 @@ export const columns: VolumesTableColumn[] = [ 'available' ) : ( <> - unavailable + unavailable
{data.errors?.map((reason) => ( diff --git a/apps/hostd/dialogs/VolumeCreateDialog.tsx b/apps/hostd/dialogs/VolumeCreateDialog.tsx index 17121cee2..8a9bf0a90 100644 --- a/apps/hostd/dialogs/VolumeCreateDialog.tsx +++ b/apps/hostd/dialogs/VolumeCreateDialog.tsx @@ -1,5 +1,4 @@ import { - Paragraph, Dialog, GBToSectors, triggerErrorToast, @@ -211,6 +210,7 @@ export function VolumeCreateDialog({ trigger, open, onOpenChange }: Props) { return ( { @@ -230,10 +230,6 @@ export function VolumeCreateDialog({ trigger, open, onOpenChange }: Props) { } >
- - Create a new volume. Select a system directory and specific the size - of the volume. -
diff --git a/apps/renterd/components/Contracts/index.tsx b/apps/renterd/components/Contracts/index.tsx index d656c374d..cf36beb8a 100644 --- a/apps/renterd/components/Contracts/index.tsx +++ b/apps/renterd/components/Contracts/index.tsx @@ -74,7 +74,7 @@ export function Contracts() { height: listHeight, }} > - +
diff --git a/apps/renterd/components/Files/FilesStatsMenuShared/FilesStatsMenuSize.tsx b/apps/renterd/components/Files/FilesStatsMenuShared/FilesStatsMenuSize.tsx index c080bbac6..70a0e2009 100644 --- a/apps/renterd/components/Files/FilesStatsMenuShared/FilesStatsMenuSize.tsx +++ b/apps/renterd/components/Files/FilesStatsMenuShared/FilesStatsMenuSize.tsx @@ -36,8 +36,8 @@ export function FilesStatsMenuSize() { - +
+
size of all files @@ -53,8 +53,8 @@ export function FilesStatsMenuSize() { total storage utilization - - +
+
{humanBytes(stats.data.totalObjectsSize)} {humanBytes(stats.data.totalSectorsSize)} {!!averageRedundancyFactor && ( @@ -64,8 +64,8 @@ export function FilesStatsMenuSize() { )} {humanBytes(stats.data.totalUploadedSize)} - - +
+
} > diff --git a/apps/renterd/components/Hosts/HostMap/HostItem.tsx b/apps/renterd/components/Hosts/HostMap/HostItem.tsx index 443a89959..40c87dfda 100644 --- a/apps/renterd/components/Hosts/HostMap/HostItem.tsx +++ b/apps/renterd/components/Hosts/HostMap/HostItem.tsx @@ -90,26 +90,42 @@ export function HostItem({ - + {countryCodeEmoji(host.country_code)} {host.country_code}
- storage - download - upload + + storage + + + download + + + upload +
- + {humanBytes(host.settings?.total_storage || 0)} - {getDownloadSpeed(host)} - {getUploadSpeed(host)} + + {getDownloadSpeed(host)} + + + {getUploadSpeed(host)} +
- {storageCost} - {downloadCost} - {uploadCost} + + {storageCost} + + + {downloadCost} + + + {uploadCost} +
diff --git a/apps/renterd/components/Keys/KeysCreateDialog.tsx b/apps/renterd/components/Keys/KeysCreateDialog.tsx index d6f7aa564..2002bd726 100644 --- a/apps/renterd/components/Keys/KeysCreateDialog.tsx +++ b/apps/renterd/components/Keys/KeysCreateDialog.tsx @@ -6,7 +6,6 @@ import { FormSubmitButton, ConfigFields, useOnInvalid, - Paragraph, Button, } from '@siafoundation/design-system' import { useCallback, useMemo } from 'react' @@ -159,6 +158,7 @@ export function KeysCreateDialog({ trigger, open, onOpenChange }: Props) { return ( { @@ -178,7 +178,6 @@ export function KeysCreateDialog({ trigger, open, onOpenChange }: Props) { } >
- Create a new S3 authentication key.
diff --git a/apps/renterd/contexts/contracts/columns.tsx b/apps/renterd/contexts/contracts/columns.tsx index a25820b26..ed567e982 100644 --- a/apps/renterd/contexts/contracts/columns.tsx +++ b/apps/renterd/contexts/contracts/columns.tsx @@ -192,37 +192,37 @@ export const columns: ContractsTableColumn[] = [ content={
- + pending - + Contract has been added.
- + active - + Contract has appeared on chain.
- + complete - + Storage proof has appeared on chain.
- + failed - + Storage proof was not submitted before the end of proof window. diff --git a/apps/renterd/contexts/uploads/index.tsx b/apps/renterd/contexts/uploads/index.tsx index 3a4068300..73466f877 100644 --- a/apps/renterd/contexts/uploads/index.tsx +++ b/apps/renterd/contexts/uploads/index.tsx @@ -40,6 +40,11 @@ function useUploadsMain() { const response = useMultipartUploadListUploads({ disabled: !activeBucket, payload: payload as MultipartUploadListUploadsPayload, + config: { + swr: { + keepPreviousData: true, + }, + }, }) const abortAll = useCallback(async () => { @@ -64,9 +69,9 @@ function useUploadsMain() { ) }, [response.data, apiBusUploadAbort, activeBucket, uploadsMap]) - const dataset: ObjectUploadData[] | undefined = useMemo(() => { + const dataset: ObjectUploadData[] = useMemo(() => { if (!response.data?.uploads || !activeBucket?.name) { - return undefined + return [] } return response.data.uploads.map((upload) => { const id = upload.uploadID diff --git a/apps/renterd/dialogs/FilesBucketCreateDialog.tsx b/apps/renterd/dialogs/FilesBucketCreateDialog.tsx index fd10907af..951adb080 100644 --- a/apps/renterd/dialogs/FilesBucketCreateDialog.tsx +++ b/apps/renterd/dialogs/FilesBucketCreateDialog.tsx @@ -1,5 +1,4 @@ import { - Paragraph, Dialog, triggerErrorToast, triggerSuccessToast, @@ -77,6 +76,7 @@ export function FilesBucketCreateDialog({ return ( { @@ -91,9 +91,6 @@ export function FilesBucketCreateDialog({ onSubmit={form.handleSubmit(onSubmit, onInvalid)} >
- - A bucket is an isolated collection of files. - Create bucket
diff --git a/apps/walletd/components/Wallet/WalletActionsMenu.tsx b/apps/walletd/components/Wallet/WalletActionsMenu.tsx index 24eb62289..e53bd3440 100644 --- a/apps/walletd/components/Wallet/WalletActionsMenu.tsx +++ b/apps/walletd/components/Wallet/WalletActionsMenu.tsx @@ -22,6 +22,7 @@ export function WalletActionsMenu() { const { openDialog } = useDialog() const walletId = router.query.id as string const balance = useWalletBalance({ + disabled: !walletId, params: { id: walletId, }, diff --git a/apps/website/components/HostMap/Globe.tsx b/apps/website/components/HostMap/Globe.tsx index 9fff16dc7..a983bb85f 100644 --- a/apps/website/components/HostMap/Globe.tsx +++ b/apps/website/components/HostMap/Globe.tsx @@ -17,7 +17,7 @@ import { useTheme } from 'next-themes' import { useElementSize } from 'usehooks-ts' type Props = { - activeHost: SiaCentralPartialHost + activeHost?: SiaCentralPartialHost selectActiveHost: (public_key: string) => void hosts: SiaCentralPartialHost[] rates: { @@ -56,7 +56,9 @@ function GlobeComponent({ activeHost, hosts, rates, selectActiveHost }: Props) { }, []) const moveToActiveHost = useCallback(() => { - moveToHost(activeHost) + if (activeHost) { + moveToHost(activeHost) + } }, [moveToHost, activeHost]) useEffect(() => { @@ -110,6 +112,9 @@ function GlobeComponent({ activeHost, hosts, rates, selectActiveHost }: Props) { }, [hosts]) const activeRoutes = useMemo(() => { + if (!activeHost) { + return [] + } let routes: Route[] = [] for (let i = 0; i < hosts.length; i++) { const host = hosts[i] @@ -212,8 +217,11 @@ function distanceBetweenHosts( function doesIncludeActiveHost( route: Route, - activeHost: SiaCentralPartialHost + activeHost?: SiaCentralPartialHost ) { + if (!activeHost) { + return false + } return ( route.dst.public_key === activeHost.public_key || route.src.public_key === activeHost.public_key diff --git a/apps/website/components/HostMap/HostItem.tsx b/apps/website/components/HostMap/HostItem.tsx index e16469034..3d8eabcb4 100644 --- a/apps/website/components/HostMap/HostItem.tsx +++ b/apps/website/components/HostMap/HostItem.tsx @@ -22,7 +22,7 @@ import { type Props = { host: SiaCentralPartialHost - activeHost: SiaCentralPartialHost + activeHost?: SiaCentralPartialHost setRef?: (el: HTMLButtonElement) => void selectActiveHost: (public_key: string) => void rates: { @@ -90,7 +90,12 @@ export function HostItem({ content={
- + {countryCodeEmoji(host.country_code)} {host.country_code}
- storage - download - upload + + storage + + + download + + + upload +
- + {humanBytes(host.settings.total_storage)} - {getDownloadSpeed(host)} - {getUploadSpeed(host)} + + {getDownloadSpeed(host)} + + + {getUploadSpeed(host)} +
- {storageCost} - {downloadCost} - {uploadCost} + + {storageCost} + + + {downloadCost} + + + {uploadCost} +
diff --git a/apps/website/components/HostMap/index.tsx b/apps/website/components/HostMap/index.tsx index 62f231abf..e868e1e7f 100644 --- a/apps/website/components/HostMap/index.tsx +++ b/apps/website/components/HostMap/index.tsx @@ -32,9 +32,14 @@ export function HostMap({ className, hosts, rates }: Props) { const scrollRef = useRef() const refs = useRef([]) // to store refs for all items - const [activeIndex, setActiveIndex] = useState( - random(0, hosts.length - 1) - ) + const [activeIndex, setActiveIndex] = useState() + + // Once page loads set a random active index. This avoids hydration issues. + useEffect(() => { + setActiveIndex(random(0, hosts.length - 1)) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + const activeHost = useMemo(() => hosts[activeIndex], [hosts, activeIndex]) const [reset, setReset] = useState() const selectActiveHostByIndex = useCallback( diff --git a/apps/website/components/Layout/Footer.tsx b/apps/website/components/Layout/Footer.tsx index fb70ac22a..f738bc883 100644 --- a/apps/website/components/Layout/Footer.tsx +++ b/apps/website/components/Layout/Footer.tsx @@ -1,4 +1,5 @@ import { + ClientSideOnly, Link, Logo, SiteMap, @@ -64,7 +65,11 @@ export function Footer() { {webLinks.email}
- +
} + > + +
diff --git a/apps/website/components/Map/Globe.tsx b/apps/website/components/Map/Globe.tsx index d2504e1d9..c90d42479 100644 --- a/apps/website/components/Map/Globe.tsx +++ b/apps/website/components/Map/Globe.tsx @@ -149,7 +149,9 @@ export function Globe({ pointAltitude={(h: SiaCentralPartialHost) => { let radius = 0 radius = h.settings.total_storage / 1e15 - return Math.max(radius, 0.005) + const minSize = 0.005 + const maxSize = 0.1 + return Math.min(Math.max(radius, minSize), maxSize) }} pointsTransitionDuration={0} pointColor={(h: SiaCentralPartialHost) => @@ -160,7 +162,9 @@ export function Globe({ pointRadius={(h: SiaCentralPartialHost) => { let radius = 0 radius = h.settings.total_storage / 1e13 / 3 - return Math.max(radius, 0.2) + const minSize = 0.2 + const maxSize = 2 + return Math.min(Math.max(radius, minSize), maxSize) }} onPointHover={(h: SiaCentralPartialHost) => { if (!h) { diff --git a/libs/design-system/package.json b/libs/design-system/package.json index f4f3e6041..b2deff040 100644 --- a/libs/design-system/package.json +++ b/libs/design-system/package.json @@ -12,6 +12,7 @@ "@siafoundation/units": "^3.2.0", "@siafoundation/types": "^0.6.0", "@siafoundation/next": "^0.1.3", + "@radix-ui/react-visually-hidden": "^1.1.0", "swr": "^2.1.1", "class-variance-authority": "^0.7.0", "bignumber.js": "^9.0.2", diff --git a/libs/design-system/src/app/SyncerConnectPeerDialog.tsx b/libs/design-system/src/app/SyncerConnectPeerDialog.tsx index 057ff5c37..544414703 100644 --- a/libs/design-system/src/app/SyncerConnectPeerDialog.tsx +++ b/libs/design-system/src/app/SyncerConnectPeerDialog.tsx @@ -1,6 +1,5 @@ 'use client' -import { Paragraph } from '../core/Paragraph' import { triggerErrorToast, triggerSuccessToast } from '../lib/toast' import { Response } from '@siafoundation/react-core' import { Dialog } from '../core/Dialog' @@ -80,6 +79,7 @@ export function SyncerConnectPeerDialog({
- Connect to a peer by IP address.
diff --git a/libs/design-system/src/app/WalletBalanceTip.tsx b/libs/design-system/src/app/WalletBalanceTip.tsx index 03b5af568..bda24841b 100644 --- a/libs/design-system/src/app/WalletBalanceTip.tsx +++ b/libs/design-system/src/app/WalletBalanceTip.tsx @@ -29,8 +29,10 @@ export function WalletBalanceTip({
- spendable - All confirmed outputs not in-use. + spendable + + All confirmed outputs not in-use. +
- immature - + immature + All confirmed but still locked outputs.
@@ -63,8 +65,10 @@ export function WalletBalanceTip({
- confirmed - All confirmed outputs. + confirmed + + All confirmed outputs. +
- unconfirmed - All unconfirmed outputs not in-use. + unconfirmed + + All unconfirmed outputs not in-use. +
({ id, width, height, accessors, + useAnimatedComponents, animationTrajectory, curve, data, @@ -104,11 +106,15 @@ export function ChartXYGraph({ ) })} {renderBarStack && ( @@ -190,10 +196,14 @@ export function ChartXYGraph({ )} humanDate(d)} tickLength={12} tickLabelProps={(p) => ({ @@ -206,7 +216,12 @@ export function ChartXYGraph({ })} /> ({ numTicks={numTicks} tickLength={12} // rangePadding={0} - animationTrajectory={animationTrajectory} // values don't make sense in stream graph // tickFormat={stackOffset === 'wiggle' ? () => '' : undefined} tickFormat={config.formatTickY} @@ -402,3 +416,22 @@ export function getColor( ? `url(#pattern-${idKey})` : `url(#gradient-${idKey})` } + +function getAnimationProps({ + key, + useAnimatedComponents, + animationTrajectory, +}: { + key: string + useAnimatedComponents: boolean + animationTrajectory?: AnimationTrajectory +}) { + return useAnimatedComponents && animationTrajectory + ? { + key: `${key}-${animationTrajectory}`, + animationTrajectory, + } + : { + key, + } +} diff --git a/libs/design-system/src/components/ChartXY/useChartXY.tsx b/libs/design-system/src/components/ChartXY/useChartXY.tsx index 9d926783f..0ccb1e87c 100644 --- a/libs/design-system/src/components/ChartXY/useChartXY.tsx +++ b/libs/design-system/src/components/ChartXY/useChartXY.tsx @@ -250,6 +250,7 @@ export function useChartXY( return { id, accessors, + useAnimatedComponents, animationTrajectory, config, scales, diff --git a/libs/design-system/src/components/Table/index.tsx b/libs/design-system/src/components/Table/index.tsx index c79ace26e..3af57d12c 100644 --- a/libs/design-system/src/components/Table/index.tsx +++ b/libs/design-system/src/components/Table/index.tsx @@ -201,7 +201,7 @@ export function Table< > diff --git a/libs/design-system/src/core/Dialog.tsx b/libs/design-system/src/core/Dialog.tsx index c9070500d..d604e48b1 100644 --- a/libs/design-system/src/core/Dialog.tsx +++ b/libs/design-system/src/core/Dialog.tsx @@ -5,6 +5,7 @@ import { cva, cx } from 'class-variance-authority' import { panelStyles } from './Panel' import { useOpen } from '../hooks/useOpen' import React, { useEffect, useLayoutEffect, useRef, useState } from 'react' +import * as VisuallyHidden from '@radix-ui/react-visually-hidden' import * as DialogPrimitive from '@radix-ui/react-dialog' import { Close24 } from '@siafoundation/react-icons' import { Button } from './Button' @@ -54,7 +55,9 @@ export const Dialog = React.forwardRef< onOpenChange: _onOpenChange, onSubmit, title, + titleVisuallyHidden, description, + descriptionVisuallyHidden, containerVariants, contentVariants, controls, @@ -90,7 +93,16 @@ export const Dialog = React.forwardRef< {open ? ( - +
onOpenChange(false)} @@ -155,6 +167,8 @@ type ContentProps = { onSubmit?: React.FormEventHandler title?: React.ReactNode description?: React.ReactNode + titleVisuallyHidden?: boolean + descriptionVisuallyHidden?: boolean controls?: React.ReactNode children?: React.ReactNode contentVariants?: VariantProps @@ -170,6 +184,8 @@ const Content = React.forwardRef( onSubmit, title, description, + titleVisuallyHidden, + descriptionVisuallyHidden, controls, contentVariants, closeClassName, @@ -195,13 +211,19 @@ const Content = React.forwardRef( // eslint-disable-next-line @typescript-eslint/no-explicit-any className={contentStyles(contentVariants as any)} > - {title && ( - - {title} - - )} + {title ? ( + titleVisuallyHidden ? ( + + {title} + + ) : ( + + {title} + + ) + ) : null} ( }} >
- {description && ( - - {description} - - )} + {description ? ( + descriptionVisuallyHidden ? ( + + + {description} + + + ) : ( + + {description} + + ) + ) : null} {children}
diff --git a/libs/design-system/src/core/Tooltip.tsx b/libs/design-system/src/core/Tooltip.tsx index e6d7e102f..d8e9d47b3 100644 --- a/libs/design-system/src/core/Tooltip.tsx +++ b/libs/design-system/src/core/Tooltip.tsx @@ -14,6 +14,8 @@ type TooltipProps = Omit< 'content' > & { children: React.ReactElement + /** The content to display in the tooltip. + * If a string or React.Fragment is passed the content will be wrapped in a Paragraph. */ content: React.ReactNode } @@ -44,6 +46,7 @@ export function Tooltip({ open: _open, onOpenChange: _onOpenChange, }) + return ( - {content} + {typeof content === 'string' || Array.isArray(content) ? ( + {content} + ) : ( + content + )}
diff --git a/package-lock.json b/package-lock.json index a6a59c544..34e4b5b6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "@radix-ui/react-switch": "^1.1.1", "@radix-ui/react-tabs": "^1.1.1", "@radix-ui/react-tooltip": "1.0.0", + "@radix-ui/react-visually-hidden": "^1.1.0", "@react-spring/web": "^9.7.3", "@siacentral/ledgerjs-sia": "^1.1.0", "@tailwindcss/container-queries": "^0.1.1", diff --git a/package.json b/package.json index 8e189face..9fdbf3e88 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@radix-ui/react-switch": "^1.1.1", "@radix-ui/react-tabs": "^1.1.1", "@radix-ui/react-tooltip": "1.0.0", + "@radix-ui/react-visually-hidden": "^1.1.0", "@react-spring/web": "^9.7.3", "@siacentral/ledgerjs-sia": "^1.1.0", "@tailwindcss/container-queries": "^0.1.1",