From ea1b2e3079dc0545fcd9ade15d1636c396398580 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 14 Jan 2025 07:05:21 +1100
Subject: [PATCH 1/3] Bump the dependencies group with 4 updates (#8889)

Bumps the dependencies group with 4 updates: [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action), [actions/upload-artifact](https://github.com/actions/upload-artifact), [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `docker/setup-qemu-action` from 3.2.0 to 3.3.0
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...53851d14592bedcffcf25ea515637cff71ef929a)

Updates `actions/upload-artifact` from 4.5.0 to 4.6.0
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/6f51ac03b9356f520e9adb1b1b7802705f340c2b...65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08)

Updates `stefanzweifel/git-auto-commit-action` from 5.0.1 to 5.1.0
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/8621497c8c39c72f3e2a999a26b4ca1b5058a842...e348103e9026cc0eee72ae06630dbe30c8bf7a79)

Updates `github/codeql-action` from 3.28.0 to 3.28.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/48ab28a6f5dbc2a99bf1e0131198dd8f1df78169...b6a472f63d85b9c78a3ac5e89422239fc15e9b3c)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependencies
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 .github/workflows/docker.yaml    |  2 +-
 .github/workflows/qc_checks.yaml | 10 +++++-----
 .github/workflows/scorecard.yaml |  4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml
index 74601e87fa..22255fd655 100644
--- a/.github/workflows/docker.yaml
+++ b/.github/workflows/docker.yaml
@@ -130,7 +130,7 @@ jobs:
           rm -rf InvenTree/_testfolder
       - name: Set up QEMU
         if: github.event_name != 'pull_request'
-        uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # pin@v3.2.0
+        uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # pin@v3.3.0
       - name: Set up Docker Buildx
         if: github.event_name != 'pull_request'
         uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # pin@v3.8.0
diff --git a/.github/workflows/qc_checks.yaml b/.github/workflows/qc_checks.yaml
index a4a6f7bb37..d41a886449 100644
--- a/.github/workflows/qc_checks.yaml
+++ b/.github/workflows/qc_checks.yaml
@@ -148,7 +148,7 @@ jobs:
       - name: Export API Documentation
         run: invoke dev.schema --ignore-warnings --filename src/backend/InvenTree/schema.yml
       - name: Upload schema
-        uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # pin@v4.5.0
+        uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # pin@v4.6.0
         with:
           name: schema.yml
           path: src/backend/InvenTree/schema.yml
@@ -219,7 +219,7 @@ jobs:
           echo "Version: $version"
           mkdir export/${version}
           mv schema.yml export/${version}/api.yaml
-      - uses: stefanzweifel/git-auto-commit-action@8621497c8c39c72f3e2a999a26b4ca1b5058a842 # pin@v5.0.1
+      - uses: stefanzweifel/git-auto-commit-action@e348103e9026cc0eee72ae06630dbe30c8bf7a79 # pin@v5.1.0
         name: Commit schema changes
         with:
           commit_message: "Update API schema for ${{ env.version }} / ${{ github.sha }}"
@@ -550,7 +550,7 @@ jobs:
       - name: Run Playwright tests
         id: tests
         run: cd src/frontend && npx nyc playwright test
-      - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # pin@v4.5.0
+      - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # pin@v4.6.0
         if: ${{ !cancelled() && steps.tests.outcome == 'failure' }}
         with:
           name: playwright-report
@@ -597,7 +597,7 @@ jobs:
         run: |
           cd src/backend/InvenTree/web/static
           zip -r frontend-build.zip web/ web/.vite
-      - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # pin@v4.5.0
+      - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # pin@v4.6.0
         with:
           name: frontend-build
           path: src/backend/InvenTree/web/static/web
@@ -622,7 +622,7 @@ jobs:
         env:
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
       - name: Upload SARIF file
-        uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # pin@v3
+        uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # pin@v3
         with:
           sarif_file: results.sarif
           category: zizmor
diff --git a/.github/workflows/scorecard.yaml b/.github/workflows/scorecard.yaml
index c15d99301a..a5c408cb82 100644
--- a/.github/workflows/scorecard.yaml
+++ b/.github/workflows/scorecard.yaml
@@ -59,7 +59,7 @@ jobs:
       # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
       # format to the repository Actions tab.
       - name: "Upload artifact"
-        uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
+        uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
         with:
           name: SARIF file
           path: results.sarif
@@ -67,6 +67,6 @@ jobs:
 
       # Upload the results to GitHub's code scanning dashboard.
       - name: "Upload to code-scanning"
-        uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
+        uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
         with:
           sarif_file: results.sarif

From 46f6450ee156b0c14e5d14d3772a83f084f41e2b Mon Sep 17 00:00:00 2001
From: Oliver <oliver.henry.walters@gmail.com>
Date: Tue, 14 Jan 2025 10:38:48 +1100
Subject: [PATCH 2/3] [UI] Responsiveness Improvements (#8885)

* Shorten string in page title

* Style fixes

* Adjust cell width props

* Refactor <PageDetail> component

- Improve responsiveness

* Simplify <ItemDetailsGrid />

* Refactor <DetailsImage>
---
 .../src/components/details/Details.tsx        | 11 ++-
 .../src/components/details/DetailsImage.tsx   | 59 +++++++-----
 .../src/components/details/ItemDetails.tsx    | 13 ++-
 .../src/components/nav/PageDetail.tsx         | 92 ++++++++++++++-----
 src/frontend/src/pages/build/BuildDetail.tsx  | 18 ++--
 .../src/pages/company/CompanyDetail.tsx       | 30 +++---
 .../pages/company/ManufacturerPartDetail.tsx  | 24 +++--
 .../src/pages/company/SupplierPartDetail.tsx  | 22 ++---
 src/frontend/src/pages/part/PartDetail.tsx    | 37 ++++----
 .../pages/purchasing/PurchaseOrderDetail.tsx  | 18 ++--
 .../src/pages/sales/ReturnOrderDetail.tsx     | 18 ++--
 .../src/pages/sales/SalesOrderDetail.tsx      | 18 ++--
 .../pages/sales/SalesOrderShipmentDetail.tsx  | 30 +++---
 src/frontend/src/pages/stock/StockDetail.tsx  | 23 ++---
 14 files changed, 224 insertions(+), 189 deletions(-)

diff --git a/src/frontend/src/components/details/Details.tsx b/src/frontend/src/components/details/Details.tsx
index 5395033a05..52883d1242 100644
--- a/src/frontend/src/components/details/Details.tsx
+++ b/src/frontend/src/components/details/Details.tsx
@@ -380,16 +380,15 @@ export function DetailsTableField({
     <Table.Tr style={{ verticalAlign: 'top' }}>
       <Table.Td
         style={{
-          width: '50',
           maxWidth: '50'
         }}
       >
         <InvenTreeIcon icon={field.icon ?? (field.name as InvenTreeIconType)} />
       </Table.Td>
-      <Table.Td style={{ maxWidth: '65%', lineBreak: 'auto' }}>
+      <Table.Td style={{ minWidth: 75, lineBreak: 'auto', flex: 2 }}>
         <Text>{field.label}</Text>
       </Table.Td>
-      <Table.Td style={{ lineBreak: 'anywhere' }}>
+      <Table.Td style={{ lineBreak: 'anywhere', minWidth: 100, flex: 10 }}>
         <FieldType field_data={field} field_value={fieldValue} />
       </Table.Td>
       <Table.Td style={{ width: '50' }}>
@@ -409,7 +408,11 @@ export function DetailsTable({
   title?: string;
 }>) {
   return (
-    <Paper p='xs' withBorder radius='xs'>
+    <Paper
+      p='xs'
+      withBorder
+      style={{ overflowX: 'hidden', width: '100%', minWidth: 200 }}
+    >
       <Stack gap='xs'>
         {title && <StylishText size='lg'>{title}</StylishText>}
         <Table striped verticalSpacing={5} horizontalSpacing='sm'>
diff --git a/src/frontend/src/components/details/DetailsImage.tsx b/src/frontend/src/components/details/DetailsImage.tsx
index 09104900e5..89a61f4159 100644
--- a/src/frontend/src/components/details/DetailsImage.tsx
+++ b/src/frontend/src/components/details/DetailsImage.tsx
@@ -2,6 +2,7 @@ import { Trans, t } from '@lingui/macro';
 import {
   AspectRatio,
   Button,
+  Grid,
   Group,
   Image,
   Overlay,
@@ -421,31 +422,39 @@ export function DetailsImage(props: Readonly<DetailImageProps>) {
   return (
     <>
       {downloadImage.modal}
-      <AspectRatio ref={ref} maw={IMAGE_DIMENSION} ratio={1} pos='relative'>
-        <>
-          <ApiImage
-            src={img}
-            mah={IMAGE_DIMENSION}
-            maw={IMAGE_DIMENSION}
-            onClick={expandImage}
-          />
-          {permissions.hasChangeRole(props.appRole) &&
-            hasOverlay &&
-            hovered && (
-              <Overlay color='black' opacity={0.8} onClick={expandImage}>
-                <ImageActionButtons
-                  visible={hovered}
-                  actions={props.imageActions}
-                  apiPath={props.apiPath}
-                  hasImage={!!props.src}
-                  pk={props.pk}
-                  setImage={setAndRefresh}
-                  downloadImage={downloadImage.open}
-                />
-              </Overlay>
-            )}
-        </>
-      </AspectRatio>
+      <Grid.Col span={{ base: 12, sm: 4 }}>
+        <AspectRatio
+          ref={ref}
+          maw={IMAGE_DIMENSION}
+          ratio={1}
+          pos='relative'
+          visibleFrom='xs'
+        >
+          <>
+            <ApiImage
+              src={img}
+              mah={IMAGE_DIMENSION}
+              maw={IMAGE_DIMENSION}
+              onClick={expandImage}
+            />
+            {permissions.hasChangeRole(props.appRole) &&
+              hasOverlay &&
+              hovered && (
+                <Overlay color='black' opacity={0.8} onClick={expandImage}>
+                  <ImageActionButtons
+                    visible={hovered}
+                    actions={props.imageActions}
+                    apiPath={props.apiPath}
+                    hasImage={!!props.src}
+                    pk={props.pk}
+                    setImage={setAndRefresh}
+                    downloadImage={downloadImage.open}
+                  />
+                </Overlay>
+              )}
+          </>
+        </AspectRatio>
+      </Grid.Col>
     </>
   );
 }
diff --git a/src/frontend/src/components/details/ItemDetails.tsx b/src/frontend/src/components/details/ItemDetails.tsx
index 77750caf7e..1d0b79d7da 100644
--- a/src/frontend/src/components/details/ItemDetails.tsx
+++ b/src/frontend/src/components/details/ItemDetails.tsx
@@ -1,16 +1,15 @@
 import { Paper, SimpleGrid } from '@mantine/core';
-import { useElementSize } from '@mantine/hooks';
 import type React from 'react';
-import { useMemo } from 'react';
 
 export function ItemDetailsGrid(props: React.PropsWithChildren<{}>) {
-  const { ref, width } = useElementSize();
-
-  const cols = useMemo(() => (width > 700 ? 2 : 1), [width]);
-
   return (
     <Paper p='xs'>
-      <SimpleGrid cols={cols} spacing='xs' verticalSpacing='xs' ref={ref}>
+      <SimpleGrid
+        cols={{ base: 1, '900px': 2 }}
+        type='container'
+        spacing='xs'
+        verticalSpacing='xs'
+      >
         {props.children}
       </SimpleGrid>
     </Paper>
diff --git a/src/frontend/src/components/nav/PageDetail.tsx b/src/frontend/src/components/nav/PageDetail.tsx
index 28cfecd037..0382516068 100644
--- a/src/frontend/src/components/nav/PageDetail.tsx
+++ b/src/frontend/src/components/nav/PageDetail.tsx
@@ -1,7 +1,8 @@
-import { Group, Paper, Space, Stack, Text } from '@mantine/core';
+import { Group, Paper, SimpleGrid, Stack, Text } from '@mantine/core';
 import { useHotkeys } from '@mantine/hooks';
-import { Fragment, type ReactNode } from 'react';
+import { Fragment, type ReactNode, useMemo } from 'react';
 
+import { shortenString } from '../../functions/tables';
 import { ApiImage } from '../images/ApiImage';
 import { StylishText } from '../items/StylishText';
 import { type Breadcrumb, BreadcrumbList } from './BreadcrumbList';
@@ -51,9 +52,41 @@ export function PageDetail({
     ]
   ]);
 
+  const pageTitleString = useMemo(
+    () =>
+      shortenString({
+        str: title,
+        len: 50
+      }),
+    [title]
+  );
+
+  const description = useMemo(
+    () =>
+      shortenString({
+        str: subtitle,
+        len: 75
+      }),
+    [subtitle]
+  );
+
+  const maxCols = useMemo(() => {
+    let cols = 1;
+
+    if (!!detail) {
+      cols++;
+    }
+
+    if (!!badges) {
+      cols++;
+    }
+
+    return cols;
+  }, [detail, badges]);
+
   return (
     <>
-      <PageTitle title={title} />
+      <PageTitle title={pageTitleString} />
       <Stack gap='xs'>
         {breadcrumbs && breadcrumbs.length > 0 && (
           <BreadcrumbList
@@ -62,8 +95,19 @@ export function PageDetail({
           />
         )}
         <Paper p='xs' radius='xs' shadow='xs'>
-          <Stack gap='xs'>
-            <Group justify='space-between' wrap='nowrap'>
+          <Group
+            justify='space-between'
+            gap='xs'
+            wrap='nowrap'
+            align='flex-start'
+          >
+            <SimpleGrid
+              cols={{
+                base: 1,
+                md: Math.min(2, maxCols),
+                lg: Math.min(3, maxCols)
+              }}
+            >
               <Group justify='left' wrap='nowrap'>
                 {imageUrl && (
                   <ApiImage
@@ -72,6 +116,7 @@ export function PageDetail({
                     miw={42}
                     mah={42}
                     maw={42}
+                    visibleFrom='sm'
                   />
                 )}
                 <Stack gap='xs'>
@@ -79,30 +124,33 @@ export function PageDetail({
                   {subtitle && (
                     <Group gap='xs'>
                       {icon}
-                      <Text size='sm' truncate>
-                        {subtitle}
-                      </Text>
+                      <Text size='sm'>{description}</Text>
                     </Group>
                   )}
                 </Stack>
               </Group>
-              <Space />
-              {detail}
-              <Group justify='right' gap='xs' wrap='nowrap'>
-                {badges?.map((badge, idx) => (
-                  <Fragment key={idx}>{badge}</Fragment>
-                ))}
-              </Group>
-              <Space />
-              {actions && (
-                <Group gap={5} justify='right'>
-                  {actions.map((action, idx) => (
-                    <Fragment key={idx}>{action}</Fragment>
+              {detail && <div>{detail}</div>}
+              {badges && (
+                <Group
+                  justify='center'
+                  gap='xs'
+                  align='flex-start'
+                  wrap='nowrap'
+                >
+                  {badges?.map((badge, idx) => (
+                    <Fragment key={idx}>{badge}</Fragment>
                   ))}
                 </Group>
               )}
-            </Group>
-          </Stack>
+            </SimpleGrid>
+            {actions && (
+              <Group gap={5} justify='right' wrap='nowrap' align='flex-start'>
+                {actions.map((action, idx) => (
+                  <Fragment key={idx}>{action}</Fragment>
+                ))}
+              </Group>
+            )}
+          </Group>
         </Paper>
       </Stack>
     </>
diff --git a/src/frontend/src/pages/build/BuildDetail.tsx b/src/frontend/src/pages/build/BuildDetail.tsx
index ec0bbecd4d..c28090d6bd 100644
--- a/src/frontend/src/pages/build/BuildDetail.tsx
+++ b/src/frontend/src/pages/build/BuildDetail.tsx
@@ -239,16 +239,14 @@ export default function BuildDetail() {
 
     return (
       <ItemDetailsGrid>
-        <Grid>
-          <Grid.Col span={4}>
-            <DetailsImage
-              appRole={UserRoles.part}
-              apiPath={ApiEndpoints.part_list}
-              src={build.part_detail?.image ?? build.part_detail?.thumbnail}
-              pk={build.part}
-            />
-          </Grid.Col>
-          <Grid.Col span={8}>
+        <Grid grow>
+          <DetailsImage
+            appRole={UserRoles.part}
+            apiPath={ApiEndpoints.part_list}
+            src={build.part_detail?.image ?? build.part_detail?.thumbnail}
+            pk={build.part}
+          />
+          <Grid.Col span={{ base: 12, sm: 8 }}>
             <DetailsTable fields={tl} item={build} />
           </Grid.Col>
         </Grid>
diff --git a/src/frontend/src/pages/company/CompanyDetail.tsx b/src/frontend/src/pages/company/CompanyDetail.tsx
index 56c4b3ecff..11e4c8dce6 100644
--- a/src/frontend/src/pages/company/CompanyDetail.tsx
+++ b/src/frontend/src/pages/company/CompanyDetail.tsx
@@ -145,22 +145,20 @@ export default function CompanyDetail(props: Readonly<CompanyDetailProps>) {
 
     return (
       <ItemDetailsGrid>
-        <Grid>
-          <Grid.Col span={4}>
-            <DetailsImage
-              appRole={UserRoles.purchase_order}
-              apiPath={apiUrl(ApiEndpoints.company_list, company.pk)}
-              src={company.image}
-              pk={company.pk}
-              refresh={refreshInstance}
-              imageActions={{
-                uploadFile: true,
-                downloadImage: true,
-                deleteFile: true
-              }}
-            />
-          </Grid.Col>
-          <Grid.Col span={8}>
+        <Grid grow>
+          <DetailsImage
+            appRole={UserRoles.purchase_order}
+            apiPath={apiUrl(ApiEndpoints.company_list, company.pk)}
+            src={company.image}
+            pk={company.pk}
+            refresh={refreshInstance}
+            imageActions={{
+              uploadFile: true,
+              downloadImage: true,
+              deleteFile: true
+            }}
+          />
+          <Grid.Col span={{ base: 12, sm: 8 }}>
             <DetailsTable item={company} fields={tl} />
           </Grid.Col>
         </Grid>
diff --git a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx
index c68136fe01..6b8350eab9 100644
--- a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx
+++ b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx
@@ -133,19 +133,17 @@ export default function ManufacturerPartDetail() {
 
     return (
       <ItemDetailsGrid>
-        <Grid>
-          <Grid.Col span={4}>
-            <DetailsImage
-              appRole={UserRoles.part}
-              src={manufacturerPart?.part_detail?.image}
-              apiPath={apiUrl(
-                ApiEndpoints.part_list,
-                manufacturerPart?.part_detail?.pk
-              )}
-              pk={manufacturerPart?.part_detail?.pk}
-            />
-          </Grid.Col>
-          <Grid.Col span={8}>
+        <Grid grow>
+          <DetailsImage
+            appRole={UserRoles.part}
+            src={manufacturerPart?.part_detail?.image}
+            apiPath={apiUrl(
+              ApiEndpoints.part_list,
+              manufacturerPart?.part_detail?.pk
+            )}
+            pk={manufacturerPart?.part_detail?.pk}
+          />
+          <Grid.Col span={{ base: 12, sm: 8 }}>
             <DetailsTable title={t`Part Details`} fields={tl} item={data} />
           </Grid.Col>
         </Grid>
diff --git a/src/frontend/src/pages/company/SupplierPartDetail.tsx b/src/frontend/src/pages/company/SupplierPartDetail.tsx
index e3e4bec417..f5c9c51f0d 100644
--- a/src/frontend/src/pages/company/SupplierPartDetail.tsx
+++ b/src/frontend/src/pages/company/SupplierPartDetail.tsx
@@ -217,18 +217,16 @@ export default function SupplierPartDetail() {
 
     return (
       <ItemDetailsGrid>
-        <Grid>
-          <Grid.Col span={4}>
-            <DetailsImage
-              appRole={UserRoles.part}
-              src={supplierPart?.part_detail?.image}
-              apiPath={apiUrl(
-                ApiEndpoints.part_list,
-                supplierPart?.part_detail?.pk
-              )}
-              pk={supplierPart?.part_detail?.pk}
-            />
-          </Grid.Col>
+        <Grid grow>
+          <DetailsImage
+            appRole={UserRoles.part}
+            src={supplierPart?.part_detail?.image}
+            apiPath={apiUrl(
+              ApiEndpoints.part_list,
+              supplierPart?.part_detail?.pk
+            )}
+            pk={supplierPart?.part_detail?.pk}
+          />
           <Grid.Col span={8}>
             <DetailsTable title={t`Part Details`} fields={tl} item={data} />
           </Grid.Col>
diff --git a/src/frontend/src/pages/part/PartDetail.tsx b/src/frontend/src/pages/part/PartDetail.tsx
index 248298612d..90953b271f 100644
--- a/src/frontend/src/pages/part/PartDetail.tsx
+++ b/src/frontend/src/pages/part/PartDetail.tsx
@@ -5,7 +5,6 @@ import {
   Grid,
   Loader,
   Skeleton,
-  Space,
   Stack,
   Text
 } from '@mantine/core';
@@ -439,23 +438,21 @@ export default function PartDetail() {
 
     return part ? (
       <ItemDetailsGrid>
-        <Grid>
-          <Grid.Col span={4}>
-            <DetailsImage
-              appRole={UserRoles.part}
-              imageActions={{
-                selectExisting: true,
-                downloadImage: true,
-                uploadFile: true,
-                deleteFile: true
-              }}
-              src={part.image}
-              apiPath={apiUrl(ApiEndpoints.part_list, part.pk)}
-              refresh={refreshInstance}
-              pk={part.pk}
-            />
-          </Grid.Col>
-          <Grid.Col span={8}>
+        <Grid grow>
+          <DetailsImage
+            appRole={UserRoles.part}
+            imageActions={{
+              selectExisting: true,
+              downloadImage: true,
+              uploadFile: true,
+              deleteFile: true
+            }}
+            src={part.image}
+            apiPath={apiUrl(ApiEndpoints.part_list, part.pk)}
+            refresh={refreshInstance}
+            pk={part.pk}
+          />
+          <Grid.Col span={{ base: 12, sm: 8 }}>
             <DetailsTable fields={tl} item={data} />
           </Grid.Col>
         </Grid>
@@ -1040,9 +1037,7 @@ export default function PartDetail() {
                     }}
                   />
                 </Stack>
-              ) : (
-                <Space />
-              )
+              ) : null
             }
           />
           <PanelGroup
diff --git a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx
index 2d5e13e719..dec6fa689f 100644
--- a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx
+++ b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx
@@ -263,16 +263,14 @@ export default function PurchaseOrderDetail() {
 
     return (
       <ItemDetailsGrid>
-        <Grid>
-          <Grid.Col span={4}>
-            <DetailsImage
-              appRole={UserRoles.purchase_order}
-              apiPath={ApiEndpoints.company_list}
-              src={order.supplier_detail?.image}
-              pk={order.supplier}
-            />
-          </Grid.Col>
-          <Grid.Col span={8}>
+        <Grid grow>
+          <DetailsImage
+            appRole={UserRoles.purchase_order}
+            apiPath={ApiEndpoints.company_list}
+            src={order.supplier_detail?.image}
+            pk={order.supplier}
+          />
+          <Grid.Col span={{ base: 12, sm: 8 }}>
             <DetailsTable fields={tl} item={order} />
           </Grid.Col>
         </Grid>
diff --git a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx
index d598134805..e63f484dd3 100644
--- a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx
+++ b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx
@@ -233,16 +233,14 @@ export default function ReturnOrderDetail() {
 
     return (
       <ItemDetailsGrid>
-        <Grid>
-          <Grid.Col span={4}>
-            <DetailsImage
-              appRole={UserRoles.purchase_order}
-              apiPath={ApiEndpoints.company_list}
-              src={order.customer_detail?.image}
-              pk={order.customer}
-            />
-          </Grid.Col>
-          <Grid.Col span={8}>
+        <Grid grow>
+          <DetailsImage
+            appRole={UserRoles.purchase_order}
+            apiPath={ApiEndpoints.company_list}
+            src={order.customer_detail?.image}
+            pk={order.customer}
+          />
+          <Grid.Col span={{ base: 12, sm: 8 }}>
             <DetailsTable fields={tl} item={order} />
           </Grid.Col>
         </Grid>
diff --git a/src/frontend/src/pages/sales/SalesOrderDetail.tsx b/src/frontend/src/pages/sales/SalesOrderDetail.tsx
index c0b7e0fa23..282dcf2d49 100644
--- a/src/frontend/src/pages/sales/SalesOrderDetail.tsx
+++ b/src/frontend/src/pages/sales/SalesOrderDetail.tsx
@@ -243,16 +243,14 @@ export default function SalesOrderDetail() {
 
     return (
       <ItemDetailsGrid>
-        <Grid>
-          <Grid.Col span={4}>
-            <DetailsImage
-              appRole={UserRoles.purchase_order}
-              apiPath={ApiEndpoints.company_list}
-              src={order.customer_detail?.image}
-              pk={order.customer}
-            />
-          </Grid.Col>
-          <Grid.Col span={8}>
+        <Grid grow>
+          <DetailsImage
+            appRole={UserRoles.purchase_order}
+            apiPath={ApiEndpoints.company_list}
+            src={order.customer_detail?.image}
+            pk={order.customer}
+          />
+          <Grid.Col span={{ base: 12, sm: 8 }}>
             <DetailsTable fields={tl} item={order} />
           </Grid.Col>
         </Grid>
diff --git a/src/frontend/src/pages/sales/SalesOrderShipmentDetail.tsx b/src/frontend/src/pages/sales/SalesOrderShipmentDetail.tsx
index 1a5e3631b6..a40c1b9b49 100644
--- a/src/frontend/src/pages/sales/SalesOrderShipmentDetail.tsx
+++ b/src/frontend/src/pages/sales/SalesOrderShipmentDetail.tsx
@@ -175,22 +175,20 @@ export default function SalesOrderShipmentDetail() {
     return (
       <>
         <ItemDetailsGrid>
-          <Grid>
-            <Grid.Col span={4}>
-              <DetailsImage
-                appRole={UserRoles.sales_order}
-                apiPath={ApiEndpoints.company_list}
-                src={customer?.image}
-                pk={customer?.pk}
-                imageActions={{
-                  selectExisting: false,
-                  downloadImage: false,
-                  uploadFile: false,
-                  deleteFile: false
-                }}
-              />
-            </Grid.Col>
-            <Grid.Col span={8}>
+          <Grid grow>
+            <DetailsImage
+              appRole={UserRoles.sales_order}
+              apiPath={ApiEndpoints.company_list}
+              src={customer?.image}
+              pk={customer?.pk}
+              imageActions={{
+                selectExisting: false,
+                downloadImage: false,
+                uploadFile: false,
+                deleteFile: false
+              }}
+            />
+            <Grid.Col span={{ base: 12, sm: 8 }}>
               <DetailsTable fields={tl} item={data} />
             </Grid.Col>
           </Grid>
diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx
index a4ffb6c3ad..3b069e99f4 100644
--- a/src/frontend/src/pages/stock/StockDetail.tsx
+++ b/src/frontend/src/pages/stock/StockDetail.tsx
@@ -346,19 +346,16 @@ export default function StockDetail() {
 
     return (
       <ItemDetailsGrid>
-        <Grid>
-          <Grid.Col span={4}>
-            <DetailsImage
-              appRole={UserRoles.part}
-              apiPath={ApiEndpoints.part_list}
-              src={
-                stockitem.part_detail?.image ??
-                stockitem?.part_detail?.thumbnail
-              }
-              pk={stockitem.part}
-            />
-          </Grid.Col>
-          <Grid.Col span={8}>
+        <Grid grow>
+          <DetailsImage
+            appRole={UserRoles.part}
+            apiPath={ApiEndpoints.part_list}
+            src={
+              stockitem.part_detail?.image ?? stockitem?.part_detail?.thumbnail
+            }
+            pk={stockitem.part}
+          />
+          <Grid.Col span={{ base: 12, sm: 8 }}>
             <DetailsTable fields={tl} item={data} />
           </Grid.Col>
         </Grid>

From 412bba50babdf20ac4008e1896f5e7a438ef8505 Mon Sep 17 00:00:00 2001
From: Oliver <oliver.henry.walters@gmail.com>
Date: Tue, 14 Jan 2025 13:42:03 +1100
Subject: [PATCH 3/3] Slight tweak to <DetailsTable> (#8890)

* Slight tweak to <DetailsTable>

* Responsive layout for user settings

* Make menu links responsive

* Update <FactCollection />

* Update part pricing panels
---
 .../src/components/details/Details.tsx        | 19 ++++++++++++-------
 .../src/components/items/MenuLinks.tsx        |  7 ++++++-
 .../components/settings/FactCollection.tsx    | 10 +++++++++-
 .../Settings/AccountSettings/UserPanel.tsx    |  2 +-
 .../src/pages/part/PartSchedulingDetail.tsx   |  2 +-
 .../src/pages/part/PartStocktakeDetail.tsx    |  2 +-
 .../pages/part/pricing/BomPricingPanel.tsx    |  2 +-
 .../pages/part/pricing/PriceBreakPanel.tsx    |  2 +-
 .../part/pricing/PricingOverviewPanel.tsx     |  2 +-
 .../part/pricing/PurchaseHistoryPanel.tsx     |  2 +-
 .../pages/part/pricing/SaleHistoryPanel.tsx   |  2 +-
 .../part/pricing/SupplierPricingPanel.tsx     |  2 +-
 .../part/pricing/VariantPricingPanel.tsx      |  2 +-
 13 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/src/frontend/src/components/details/Details.tsx b/src/frontend/src/components/details/Details.tsx
index 52883d1242..531317f31b 100644
--- a/src/frontend/src/components/details/Details.tsx
+++ b/src/frontend/src/components/details/Details.tsx
@@ -378,17 +378,22 @@ export function DetailsTableField({
 
   return (
     <Table.Tr style={{ verticalAlign: 'top' }}>
+      <Table.Td style={{ minWidth: 75, lineBreak: 'auto', flex: 2 }}>
+        <Group gap='xs' wrap='nowrap'>
+          <InvenTreeIcon
+            icon={field.icon ?? (field.name as InvenTreeIconType)}
+          />
+          <Text style={{ paddingLeft: 10 }}>{field.label}</Text>
+        </Group>
+      </Table.Td>
       <Table.Td
         style={{
-          maxWidth: '50'
+          lineBreak: 'anywhere',
+          minWidth: 100,
+          flex: 10,
+          display: 'inline-block'
         }}
       >
-        <InvenTreeIcon icon={field.icon ?? (field.name as InvenTreeIconType)} />
-      </Table.Td>
-      <Table.Td style={{ minWidth: 75, lineBreak: 'auto', flex: 2 }}>
-        <Text>{field.label}</Text>
-      </Table.Td>
-      <Table.Td style={{ lineBreak: 'anywhere', minWidth: 100, flex: 10 }}>
         <FieldType field_data={field} field_value={fieldValue} />
       </Table.Td>
       <Table.Td style={{ width: '50' }}>
diff --git a/src/frontend/src/components/items/MenuLinks.tsx b/src/frontend/src/components/items/MenuLinks.tsx
index 9f882e22a5..531b2a81bc 100644
--- a/src/frontend/src/components/items/MenuLinks.tsx
+++ b/src/frontend/src/components/items/MenuLinks.tsx
@@ -53,7 +53,12 @@ export function MenuLinks({
         <Divider />
         <StylishText size='md'>{title}</StylishText>
         <Divider />
-        <SimpleGrid cols={2} spacing={0} p={3}>
+        <SimpleGrid
+          cols={{ base: 1, '400px': 2 }}
+          type='container'
+          spacing={0}
+          p={3}
+        >
           {visibleLinks.map((item) => (
             <Tooltip
               key={`menu-link-tooltip-${item.id}`}
diff --git a/src/frontend/src/components/settings/FactCollection.tsx b/src/frontend/src/components/settings/FactCollection.tsx
index 633a92c6d4..ac0e9e2a93 100644
--- a/src/frontend/src/components/settings/FactCollection.tsx
+++ b/src/frontend/src/components/settings/FactCollection.tsx
@@ -10,7 +10,15 @@ export function FactCollection({
   minItems?: number;
 }>) {
   return (
-    <SimpleGrid cols={minItems} spacing='xs'>
+    <SimpleGrid
+      cols={{
+        base: 1,
+        sm: Math.min(2, minItems),
+        md: Math.min(3, minItems),
+        lg: minItems
+      }}
+      spacing='xs'
+    >
       {items.map((item, index) => (
         <FactItem
           key={`${index}-${item.value}`}
diff --git a/src/frontend/src/pages/Index/Settings/AccountSettings/UserPanel.tsx b/src/frontend/src/pages/Index/Settings/AccountSettings/UserPanel.tsx
index ffea0c136e..918418452c 100644
--- a/src/frontend/src/pages/Index/Settings/AccountSettings/UserPanel.tsx
+++ b/src/frontend/src/pages/Index/Settings/AccountSettings/UserPanel.tsx
@@ -9,7 +9,7 @@ export function AccountContent() {
 
   return (
     <div>
-      <SimpleGrid cols={2} spacing='md'>
+      <SimpleGrid cols={{ base: 1, md: 2 }} spacing='md'>
         <Container w='100%'>
           <AccountDetailPanel />
         </Container>
diff --git a/src/frontend/src/pages/part/PartSchedulingDetail.tsx b/src/frontend/src/pages/part/PartSchedulingDetail.tsx
index bf5caa310d..1ec87409d4 100644
--- a/src/frontend/src/pages/part/PartSchedulingDetail.tsx
+++ b/src/frontend/src/pages/part/PartSchedulingDetail.tsx
@@ -243,7 +243,7 @@ export default function PartSchedulingDetail({
           <Text>{t`There is no scheduling information available for the selected part`}</Text>
         </Alert>
       )}
-      <SimpleGrid cols={2}>
+      <SimpleGrid cols={{ base: 1, md: 2 }}>
         <InvenTreeTable
           url={apiUrl(ApiEndpoints.part_scheduling, part.pk)}
           tableState={table}
diff --git a/src/frontend/src/pages/part/PartStocktakeDetail.tsx b/src/frontend/src/pages/part/PartStocktakeDetail.tsx
index b51c3f32d0..3c56f45ac2 100644
--- a/src/frontend/src/pages/part/PartStocktakeDetail.tsx
+++ b/src/frontend/src/pages/part/PartStocktakeDetail.tsx
@@ -209,7 +209,7 @@ export default function PartStocktakeDetail({
       {generateReport.modal}
       {editStocktakeEntry.modal}
       {deleteStocktakeEntry.modal}
-      <SimpleGrid cols={2}>
+      <SimpleGrid cols={{ base: 1, md: 2 }}>
         <InvenTreeTable
           url={apiUrl(ApiEndpoints.part_stocktake_list)}
           tableState={table}
diff --git a/src/frontend/src/pages/part/pricing/BomPricingPanel.tsx b/src/frontend/src/pages/part/pricing/BomPricingPanel.tsx
index 4127c4f033..e628b838fd 100644
--- a/src/frontend/src/pages/part/pricing/BomPricingPanel.tsx
+++ b/src/frontend/src/pages/part/pricing/BomPricingPanel.tsx
@@ -219,7 +219,7 @@ export default function BomPricingPanel({
 
   return (
     <Stack gap='xs'>
-      <SimpleGrid cols={2}>
+      <SimpleGrid cols={{ base: 1, md: 2 }}>
         <InvenTreeTable
           tableState={table}
           url={apiUrl(ApiEndpoints.bom_list)}
diff --git a/src/frontend/src/pages/part/pricing/PriceBreakPanel.tsx b/src/frontend/src/pages/part/pricing/PriceBreakPanel.tsx
index 85710b4946..48b6621574 100644
--- a/src/frontend/src/pages/part/pricing/PriceBreakPanel.tsx
+++ b/src/frontend/src/pages/part/pricing/PriceBreakPanel.tsx
@@ -151,7 +151,7 @@ export default function PriceBreakPanel({
       {newPriceBreak.modal}
       {editPriceBreak.modal}
       {deletePriceBreak.modal}
-      <SimpleGrid cols={2}>
+      <SimpleGrid cols={{ base: 1, md: 2 }}>
         <InvenTreeTable
           tableState={table}
           url={tableUrl}
diff --git a/src/frontend/src/pages/part/pricing/PricingOverviewPanel.tsx b/src/frontend/src/pages/part/pricing/PricingOverviewPanel.tsx
index 720b639db3..04e014fefc 100644
--- a/src/frontend/src/pages/part/pricing/PricingOverviewPanel.tsx
+++ b/src/frontend/src/pages/part/pricing/PricingOverviewPanel.tsx
@@ -240,7 +240,7 @@ export default function PricingOverviewPanel({
     <>
       {editPricing.modal}
       <Stack gap='xs'>
-        <SimpleGrid cols={2}>
+        <SimpleGrid cols={{ base: 1, md: 2 }}>
           <Stack gap='xs'>
             <Paper p='xs'>
               <Group justify='space-between' wrap='nowrap'>
diff --git a/src/frontend/src/pages/part/pricing/PurchaseHistoryPanel.tsx b/src/frontend/src/pages/part/pricing/PurchaseHistoryPanel.tsx
index ce3ea98e33..aeec576b76 100644
--- a/src/frontend/src/pages/part/pricing/PurchaseHistoryPanel.tsx
+++ b/src/frontend/src/pages/part/pricing/PurchaseHistoryPanel.tsx
@@ -103,7 +103,7 @@ export default function PurchaseHistoryPanel({
   }, [table.records]);
 
   return (
-    <SimpleGrid cols={2}>
+    <SimpleGrid cols={{ base: 1, md: 2 }}>
       <InvenTreeTable
         tableState={table}
         url={apiUrl(ApiEndpoints.purchase_order_line_list)}
diff --git a/src/frontend/src/pages/part/pricing/SaleHistoryPanel.tsx b/src/frontend/src/pages/part/pricing/SaleHistoryPanel.tsx
index 7bbee81ed7..442686fb44 100644
--- a/src/frontend/src/pages/part/pricing/SaleHistoryPanel.tsx
+++ b/src/frontend/src/pages/part/pricing/SaleHistoryPanel.tsx
@@ -63,7 +63,7 @@ export default function SaleHistoryPanel({
   }, [table.records]);
 
   return (
-    <SimpleGrid cols={2}>
+    <SimpleGrid cols={{ base: 1, md: 2 }}>
       <InvenTreeTable
         tableState={table}
         url={apiUrl(ApiEndpoints.sales_order_line_list)}
diff --git a/src/frontend/src/pages/part/pricing/SupplierPricingPanel.tsx b/src/frontend/src/pages/part/pricing/SupplierPricingPanel.tsx
index a4ad956816..4a3b7a2718 100644
--- a/src/frontend/src/pages/part/pricing/SupplierPricingPanel.tsx
+++ b/src/frontend/src/pages/part/pricing/SupplierPricingPanel.tsx
@@ -45,7 +45,7 @@ export default function SupplierPricingPanel({
   }, [table.records]);
 
   return (
-    <SimpleGrid cols={2}>
+    <SimpleGrid cols={{ base: 1, md: 2 }}>
       <InvenTreeTable
         url={apiUrl(ApiEndpoints.supplier_part_pricing_list)}
         columns={columns}
diff --git a/src/frontend/src/pages/part/pricing/VariantPricingPanel.tsx b/src/frontend/src/pages/part/pricing/VariantPricingPanel.tsx
index 224736929d..69ed90d60e 100644
--- a/src/frontend/src/pages/part/pricing/VariantPricingPanel.tsx
+++ b/src/frontend/src/pages/part/pricing/VariantPricingPanel.tsx
@@ -73,7 +73,7 @@ export default function VariantPricingPanel({
 
   return (
     <Stack gap='xs'>
-      <SimpleGrid cols={2}>
+      <SimpleGrid cols={{ base: 1, md: 2 }}>
         <InvenTreeTable
           tableState={table}
           url={apiUrl(ApiEndpoints.part_list)}