Fleet UI: Allow DataSet value to wrap, apply to policy (#46733)

This commit is contained in:
RachelElysia
2026-06-03 15:17:27 -04:00
committed by GitHub
parent 3663475263
commit 1d44256b17
6 changed files with 89 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
* Long policy resolution text now wraps on the policy details page instead of being truncated.
@@ -1,3 +1,4 @@
import React from "react";
import { Meta, StoryObj } from "@storybook/react";
import DataSet from "./DataSet";
@@ -22,3 +23,19 @@ export const HorizontalOrientation: Story = {
orientation: "horizontal",
},
};
// Multiline values wrap instead of truncating with an ellipsis. Use for
// free-form prose like "Resolve" or "Description".
export const Multiline: Story = {
args: {
title: "Resolve",
value:
"Re-enable FileVault on the device. Open System Settings, navigate to Privacy & Security, and turn on FileVault. Store the recovery key in a safe place.",
multiline: true,
},
decorators: [
(Story) => (
<div style={{ maxWidth: "320px", padding: "16px" }}>{Story()}</div>
),
],
};
@@ -0,0 +1,56 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import DataSet from "./DataSet";
describe("DataSet", () => {
it("renders title and value", () => {
render(<DataSet title="Author" value="Alice" />);
expect(screen.getByText("Author")).toBeInTheDocument();
expect(screen.getByText("Alice")).toBeInTheDocument();
});
it("uses vertical orientation by default (no horizontal class, no colon)", () => {
const { container } = render(<DataSet title="Author" value="Alice" />);
expect(container.querySelector(".data-set__horizontal")).toBeNull();
expect(container.querySelector("dt")?.textContent).toBe("Author");
});
it("applies horizontal orientation class and appends a colon to the title", () => {
const { container } = render(
<DataSet title="Author" value="Alice" orientation="horizontal" />
);
expect(
container.querySelector(".data-set__horizontal")
).toBeInTheDocument();
expect(container.querySelector("dt")?.textContent).toBe("Author:");
});
it("applies the text-only modifier when textOnly is set", () => {
const { container } = render(
<DataSet title="Author" value="Alice" textOnly />
);
expect(container.querySelector(".data-set--text-only")).toBeInTheDocument();
});
it("applies the multiline modifier when multiline is set", () => {
const { container } = render(
<DataSet title="Resolve" value="Long remediation text." multiline />
);
expect(container.querySelector(".data-set--multiline")).toBeInTheDocument();
});
it("does not apply the multiline modifier by default", () => {
const { container } = render(<DataSet title="Author" value="Alice" />);
expect(container.querySelector(".data-set--multiline")).toBeNull();
});
it("merges a custom className alongside the base class", () => {
const { container } = render(
<DataSet title="Author" value="Alice" className="custom-class" />
);
const root = container.firstChild as HTMLElement;
expect(root).toHaveClass("data-set");
expect(root).toHaveClass("custom-class");
});
});
+8
View File
@@ -13,6 +13,12 @@ interface IDataSetProps {
* baseline. Do NOT use when the value contains icons, buttons, or status
* indicators that need vertical centering. */
textOnly?: boolean;
/** When true, the value wraps onto multiple lines instead of truncating
* with an ellipsis. Use for free-form prose like "Resolve" or
* "Description" where the full text needs to be readable. Default behavior
* (single-line truncation with ellipsis) assumes the consumer wraps the
* value in a tooltip-on-truncate helper. */
multiline?: boolean;
className?: string;
}
@@ -21,11 +27,13 @@ const DataSet = ({
value,
orientation = "vertical",
textOnly = false,
multiline = false,
className,
}: IDataSetProps) => {
const classNames = classnames(baseClass, className, {
[`${baseClass}__horizontal`]: orientation === "horizontal",
[`${baseClass}--text-only`]: textOnly,
[`${baseClass}--multiline`]: multiline,
});
return (
+6
View File
@@ -23,6 +23,12 @@
align-items: baseline;
}
&--multiline dd {
white-space: pre-wrap;
overflow: visible;
overflow-wrap: anywhere;
}
&__horizontal {
flex-direction: row;
}
@@ -426,6 +426,7 @@ const PolicyDetailsPage = ({
className={`${baseClass}__resolve`}
title="Resolve"
value={lastEditedQueryResolution}
multiline
/>
)}
{renderAuthor()}