diff --git a/webui/bun.lockb b/webui/bun.lockb
index e11c602..97e6b19 100755
Binary files a/webui/bun.lockb and b/webui/bun.lockb differ
diff --git a/webui/package.json b/webui/package.json
index de00117..2686332 100644
--- a/webui/package.json
+++ b/webui/package.json
@@ -21,6 +21,7 @@
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-toast": "^1.1.5",
+ "@radix-ui/react-tooltip": "^1.1.2",
"@tailwindcss/typography": "^0.5.10",
"@tanstack/react-query": "^5.22.2",
"class-variance-authority": "^0.7.0",
diff --git a/webui/src/app/(atlas)/[bundle].tsx b/webui/src/app/(atlas)/[bundle].tsx
index 0e6e3c3..dc0f290 100644
--- a/webui/src/app/(atlas)/[bundle].tsx
+++ b/webui/src/app/(atlas)/[bundle].tsx
@@ -3,6 +3,7 @@ import { keepPreviousData, useQuery } from '@tanstack/react-query';
import type { ModuleGraphResponse } from '~/app/--/bundles/[bundle]/modules/graph+api';
import { BundleGraph } from '~/components/BundleGraph';
import { BundleSelectForm } from '~/components/BundleSelectForm';
+import { FileSize } from '~/components/FileSize';
import { ModuleFiltersForm } from '~/components/ModuleFilterForm';
import { PropertySummary } from '~/components/PropertySummary';
import {
@@ -17,7 +18,6 @@ import { Layout, LayoutHeader, LayoutNavigation, LayoutTitle } from '~/ui/Layout
import { Tag } from '~/ui/Tag';
import { fetchApi, handleApiError } from '~/utils/api';
import { type ModuleFilters, moduleFiltersToParams } from '~/utils/filters';
-import { formatFileSize } from '~/utils/formatString';
export default function BundlePage() {
const { bundle } = useBundle();
@@ -40,14 +40,14 @@ export default function BundlePage() {
{!!modules.data && {modules.data.bundle.moduleFiles} modules}
- {!!modules.data && {formatFileSize(modules.data.bundle.moduleSize)}}
+ {!!modules.data && }
{!!modules.data && modulesAreFiltered && (
visible:}
>
{modules.data.filtered.moduleFiles} modules
- {formatFileSize(modules.data.filtered.moduleSize)}
+
)}
diff --git a/webui/src/app/(atlas)/[bundle]/folders/[path].tsx b/webui/src/app/(atlas)/[bundle]/folders/[path].tsx
index 9da9ea3..04e1440 100644
--- a/webui/src/app/(atlas)/[bundle]/folders/[path].tsx
+++ b/webui/src/app/(atlas)/[bundle]/folders/[path].tsx
@@ -5,6 +5,7 @@ import type { ModuleGraphResponse } from '~/app/--/bundles/[bundle]/modules/grap
import { BreadcrumbLinks } from '~/components/BreadcrumbLinks';
import { BundleGraph } from '~/components/BundleGraph';
import { BundleSelectForm } from '~/components/BundleSelectForm';
+import { FileSize } from '~/components/FileSize';
import { ModuleFiltersForm } from '~/components/ModuleFilterForm';
import { PropertySummary } from '~/components/PropertySummary';
import {
@@ -19,7 +20,6 @@ import { Layout, LayoutHeader, LayoutNavigation, LayoutTitle } from '~/ui/Layout
import { Tag } from '~/ui/Tag';
import { fetchApi, handleApiError } from '~/utils/api';
import { type ModuleFilters, moduleFiltersToParams } from '~/utils/filters';
-import { formatFileSize } from '~/utils/formatString';
export default function FolderPage() {
const { path: relativePath } = useLocalSearchParams<{ path: string }>();
@@ -47,7 +47,7 @@ export default function FolderPage() {
)}
{!!modules.data?.filtered.moduleSize && (
- {formatFileSize(modules.data.filtered.moduleSize)}
+
)}
diff --git a/webui/src/app/(atlas)/[bundle]/modules/[path].tsx b/webui/src/app/(atlas)/[bundle]/modules/[path].tsx
index 4003d9e..e0c50c0 100644
--- a/webui/src/app/(atlas)/[bundle]/modules/[path].tsx
+++ b/webui/src/app/(atlas)/[bundle]/modules/[path].tsx
@@ -3,6 +3,7 @@ import { useLocalSearchParams } from 'expo-router';
import { BreadcrumbLinks } from '~/components/BreadcrumbLinks';
import { BundleSelectForm } from '~/components/BundleSelectForm';
+import { FileSize } from '~/components/FileSize';
import { ModuleCode } from '~/components/ModuleCode';
import { ModuleReference } from '~/components/ModuleReference';
import { PropertySummary } from '~/components/PropertySummary';
@@ -12,7 +13,6 @@ import { Layout, LayoutHeader, LayoutNavigation, LayoutTitle } from '~/ui/Layout
import { Skeleton } from '~/ui/Skeleton';
import { Tag } from '~/ui/Tag';
import { fetchApi, handleApiError } from '~/utils/api';
-import { formatFileSize } from '~/utils/formatString';
import { type AtlasModule } from '~core/data/types';
export default function ModulePage() {
@@ -32,7 +32,7 @@ export default function ModulePage() {
{!!module.data?.package && {module.data.package}}
{!!module.data && {getModuleType(module.data)}}
- {!!module.data && {formatFileSize(module.data.size)}}
+ {!!module.data && }
diff --git a/webui/src/components/BundleGraph.tsx b/webui/src/components/BundleGraph.tsx
index 3560533..4fdc2e9 100644
--- a/webui/src/components/BundleGraph.tsx
+++ b/webui/src/components/BundleGraph.tsx
@@ -8,7 +8,7 @@ import EchartsReact from 'echarts-for-react/lib/core';
import { useRouter } from 'expo-router';
import { useMemo } from 'react';
-import { formatFileSize } from '~/utils/formatString';
+import { formatByteSize } from '~/components/FileSize';
import type { TreemapNode } from '~/utils/treemap';
import type { PartialAtlasBundle } from '~core/data/types';
@@ -195,7 +195,7 @@ function getBundleGraphTooltip(
${formatNodeValue(node)}
- Size: ${formatFileSize(size)}
+ Size: ${formatByteSize(size)}
${
files === 1
? `Files: ${files}`
diff --git a/webui/src/components/FileSize.tsx b/webui/src/components/FileSize.tsx
new file mode 100644
index 0000000..e95d581
--- /dev/null
+++ b/webui/src/components/FileSize.tsx
@@ -0,0 +1,54 @@
+// @ts-expect-error
+import AsteriskIcon from 'lucide-react/dist/esm/icons/asterisk';
+
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '~/ui/Tooltip';
+
+type BundleFileSizeProps = {
+ /** The size of the files or bundle, in bytes */
+ byteSize: number;
+};
+
+export function FileSize(props: BundleFileSizeProps) {
+ return (
+
+ {formatByteSize(props.byteSize)}
+
+
+
+
+
+
+
+ All file sizes are calculated based on the transpiled JavaScript byte size.
+
+
+ While these sizes might differ from actual bundle size when using{' '}
+
+ Hermes Bytecode (HBC)
+
+ , the relative proportions are still correct.
+
+
+
+
+
+ );
+}
+
+/** Format files or bundle size, from bytes to the nearest unit */
+export function formatByteSize(size: number) {
+ if (size < 1024) {
+ return size + 'B';
+ } else if (size < 1024 * 1024) {
+ return (size / 1024).toFixed(1) + 'KB';
+ } else {
+ return (size / 1024 / 1024).toFixed(1) + 'MB';
+ }
+}
diff --git a/webui/src/ui/Tooltip.tsx b/webui/src/ui/Tooltip.tsx
new file mode 100644
index 0000000..9daff07
--- /dev/null
+++ b/webui/src/ui/Tooltip.tsx
@@ -0,0 +1,30 @@
+// see: https://ui.shadcn.com/docs/components/tooltip
+
+import * as TooltipPrimitive from '@radix-ui/react-tooltip';
+import { cx } from 'class-variance-authority';
+import { type ComponentPropsWithoutRef, type ElementRef, forwardRef } from 'react';
+
+export const TooltipProvider = TooltipPrimitive.Provider;
+
+export const Tooltip = TooltipPrimitive.Root;
+
+export const TooltipTrigger = TooltipPrimitive.Trigger;
+
+export const TooltipContent = forwardRef<
+ ElementRef,
+ ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+));
+
+TooltipContent.displayName = TooltipPrimitive.Content.displayName;
diff --git a/webui/src/utils/formatString.ts b/webui/src/utils/formatString.ts
deleted file mode 100644
index a54bbd1..0000000
--- a/webui/src/utils/formatString.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export function formatFileSize(size: number) {
- if (size < 1024) {
- return size + 'B';
- } else if (size < 1024 * 1024) {
- return (size / 1024).toFixed(1) + 'KB';
- } else {
- return (size / 1024 / 1024).toFixed(1) + 'MB';
- }
-}