diff --git a/app/pages/project/instances/InstancesPage.tsx b/app/pages/project/instances/InstancesPage.tsx
index 19af2687d..ae59c3dd2 100644
--- a/app/pages/project/instances/InstancesPage.tsx
+++ b/app/pages/project/instances/InstancesPage.tsx
@@ -36,12 +36,12 @@ import { EmptyMessage } from '~/ui/lib/EmptyMessage'
import { PageHeader, PageTitle } from '~/ui/lib/PageHeader'
import { TableActions } from '~/ui/lib/Table'
import { Tooltip } from '~/ui/lib/Tooltip'
+import { Size, ValueUnit } from '~/ui/lib/ValueUnit'
import { setDiff } from '~/util/array'
import { ALL_ISH } from '~/util/consts'
import { toLocaleTimeString } from '~/util/date'
import { pb } from '~/util/path-builder'
import { pluralize } from '~/util/str'
-import { formatBytes } from '~/util/units'
import { useMakeInstanceActions } from './actions'
import { ResizeInstanceModal } from './InstancePage'
@@ -104,22 +104,12 @@ export default function InstancesPage() {
colHelper.accessor('ncpus', {
header: 'CPU',
cell: (info) => (
- <>
- {info.getValue()}{' '}
-
{pluralize('vCPU', info.getValue())}
- >
+
),
}),
colHelper.accessor('memory', {
header: 'Memory',
- cell: (info) => {
- const memory = formatBytes(info.getValue())
- return (
- <>
- {memory.value}
{memory.unit}
- >
- )
- },
+ cell: (info) =>
,
}),
colHelper.accessor(
(i) => ({ runState: i.runState, timeRunStateUpdated: i.timeRunStateUpdated }),
diff --git a/app/pages/system/inventory/sled/SledPage.tsx b/app/pages/system/inventory/sled/SledPage.tsx
index 7947e6c66..1a64da86c 100644
--- a/app/pages/system/inventory/sled/SledPage.tsx
+++ b/app/pages/system/inventory/sled/SledPage.tsx
@@ -18,7 +18,6 @@ import { PropertiesTable } from '~/ui/lib/PropertiesTable'
import { truncate } from '~/ui/lib/Truncate'
import { pb } from '~/util/path-builder'
import type * as PP from '~/util/path-params'
-import { formatBytes } from '~/util/units'
import { ProvisionPolicyBadge, SledKindBadge, SledStateBadge } from './SledBadges'
@@ -38,8 +37,6 @@ export default function SledPage() {
const { sledId } = useSledParams()
const { data: sled } = usePrefetchedQuery(sledView({ sledId }))
- const ram = formatBytes(sled.usablePhysicalRam)
-
return (
<>
@@ -74,10 +71,10 @@ export default function SledPage() {
{sled.rackId}
-
- {ram.value}
- {ram.unit}
-
+
diff --git a/app/table/cells/InstanceResourceCell.tsx b/app/table/cells/InstanceResourceCell.tsx
index a735f54e1..4c4b1e985 100644
--- a/app/table/cells/InstanceResourceCell.tsx
+++ b/app/table/cells/InstanceResourceCell.tsx
@@ -7,20 +7,17 @@
*/
import type { Instance } from '@oxide/api'
-import { formatBytes } from '~/util/units'
+import { Size, ValueUnit } from '~/ui/lib/ValueUnit'
type Props = { value: Pick }
-export const InstanceResourceCell = ({ value }: Props) => {
- const memory = formatBytes(value.memory)
- return (
-
-
- {value.ncpus} vCPU
-
-
- {memory.value} {memory.unit}
-
+export const InstanceResourceCell = ({ value }: Props) => (
+
+)
diff --git a/app/table/columns/common.tsx b/app/table/columns/common.tsx
index 99f0aa8d5..be4678985 100644
--- a/app/table/columns/common.tsx
+++ b/app/table/columns/common.tsx
@@ -11,7 +11,7 @@ import { InstanceStateBadge } from '~/components/StateBadge'
import { DescriptionCell } from '~/table/cells/DescriptionCell'
import { CopyToClipboard } from '~/ui/lib/CopyToClipboard'
import { DateTime } from '~/ui/lib/DateTime'
-import { formatBytes } from '~/util/units'
+import { Size } from '~/ui/lib/ValueUnit'
// the full type of the info arg is CellContext
from RT, but in these
// cells we only care about the return value of getValue
@@ -37,16 +37,6 @@ function instanceStateCell(info: Info) {
return
}
-// not using Info so this can also be used for minitables
-export function sizeCellInner(value: number) {
- const size = formatBytes(value)
- return (
-
- {size.value} {size.unit}
-
- )
-}
-
/** Columns used in a bunch of tables */
export const Columns = {
/** Truncates text if too long, full text in tooltip */
@@ -55,7 +45,7 @@ export const Columns = {
},
id: { header: 'ID', cell: idCell },
instanceState: { header: 'state', cell: instanceStateCell },
- size: { cell: (info: Info) => sizeCellInner(info.getValue()) },
+ size: { cell: (info: Info) => },
timeCreated: { header: 'created', cell: dateCell },
timeModified: { header: 'modified', cell: dateCell },
}
diff --git a/app/ui/lib/PropertiesTable.tsx b/app/ui/lib/PropertiesTable.tsx
index 3322900d3..9f7f96303 100644
--- a/app/ui/lib/PropertiesTable.tsx
+++ b/app/ui/lib/PropertiesTable.tsx
@@ -10,13 +10,13 @@ import type { ReactNode } from 'react'
import { DescriptionCell } from '~/table/cells/DescriptionCell'
import { EmptyCell } from '~/table/cells/EmptyCell'
-import { sizeCellInner } from '~/table/columns/common'
import { isOneOf } from '~/util/children'
import { invariant } from '~/util/invariant'
import { CopyToClipboard } from './CopyToClipboard'
import { DateTime } from './DateTime'
import { Truncate } from './Truncate'
+import { Size } from './ValueUnit'
export interface PropertiesTableProps {
className?: string
@@ -110,7 +110,11 @@ PropertiesTable.SizeRow = ({
}: {
bytes: number
label?: string
-}) => {sizeCellInner(bytes)}
+}) => (
+
+
+
+)
PropertiesTable.CopyableRow = ({ label, text }: { label: string; text: string }) => (
diff --git a/app/ui/lib/ValueUnit.tsx b/app/ui/lib/ValueUnit.tsx
new file mode 100644
index 000000000..05bcb3f84
--- /dev/null
+++ b/app/ui/lib/ValueUnit.tsx
@@ -0,0 +1,28 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * Copyright Oxide Computer Company
+ */
+import type { ReactNode } from 'react'
+
+import { formatBytes } from '~/util/units'
+
+/**
+ * A value with a dimmed unit label, e.g. `4 vCPU` or `16 GiB`: the value renders
+ * in the default text color, the unit in tertiary, separated by a single space.
+ */
+export function ValueUnit({ value, unit }: { value: ReactNode; unit: ReactNode }) {
+ return (
+
+ {value} {unit}
+
+ )
+}
+
+/** Format a byte count with `formatBytes` and render it as a {@link ValueUnit}. */
+export function Size({ bytes }: { bytes: number }) {
+ const { value, unit } = formatBytes(bytes)
+ return
+}