Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(summary-detail): add package (#3727)
* feat(summary-detail): add package * chore: add missing package * chore: minor fixes * fix: many improvements * chore: add changeset * chore: pr fixes * chore: lockfile
- Loading branch information
Showing
23 changed files
with
940 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
"@twilio-paste/summary-detail": major | ||
"@twilio-paste/core": minor | ||
--- | ||
|
||
[Summary Detail] Add new SummaryDetail component package. | ||
|
||
A Summary Detail is a collapsible container that can be used to hide or show content. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,4 @@ | |
--- | ||
|
||
[Codemods] added a new package: page-header | ||
[Codemods] added a new package: SummaryDetail |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
272 changes: 272 additions & 0 deletions
272
packages/paste-core/components/summary-detail/__tests__/index.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
import { render, screen, waitFor } from "@testing-library/react"; | ||
import userEvent from "@testing-library/user-event"; | ||
import { CustomizationProvider } from "@twilio-paste/customization"; | ||
import { Theme } from "@twilio-paste/theme"; | ||
import * as React from "react"; | ||
|
||
import { | ||
SummaryDetail, | ||
SummaryDetailContent, | ||
SummaryDetailHeading, | ||
SummaryDetailHeadingContent, | ||
type SummaryDetailProps, | ||
SummaryDetailToggleButton, | ||
useSummaryDetailState, | ||
} from "../src"; | ||
|
||
const MockSummaryDetail: React.FC<{ | ||
visible?: SummaryDetailProps["visible"]; | ||
}> = ({ visible }) => { | ||
return ( | ||
<Theme.Provider theme="default"> | ||
<SummaryDetail baseId="summary-detail" visible={visible} data-testid="summary-detail"> | ||
<SummaryDetailHeading data-testid="summary-detail-heading"> | ||
<SummaryDetailToggleButton data-testid="summary-detail-toggle-button" /> | ||
<SummaryDetailHeadingContent data-testid="summary-detail-heading-content"> | ||
Inbound Call | ||
</SummaryDetailHeadingContent> | ||
</SummaryDetailHeading> | ||
<SummaryDetailContent data-testid="summary-detail-content">Agent: John Doe</SummaryDetailContent> | ||
</SummaryDetail> | ||
</Theme.Provider> | ||
); | ||
}; | ||
|
||
const MockDefaultElementSummaryDetail = (): JSX.Element => { | ||
return ( | ||
<SummaryDetail baseId="summary-detail" data-testid="summary-detail"> | ||
<SummaryDetailHeading data-testid="summary-detail-heading"> | ||
<SummaryDetailToggleButton aria-label="BOOP" data-testid="summary-detail-toggle-button" /> | ||
<SummaryDetailHeadingContent data-testid="summary-detail-heading-content"> | ||
Inbound Call | ||
</SummaryDetailHeadingContent> | ||
</SummaryDetailHeading> | ||
<SummaryDetailContent data-testid="summary-detail-content">Agent: John Doe</SummaryDetailContent> | ||
</SummaryDetail> | ||
); | ||
}; | ||
|
||
const MockCustomElementSummaryDetail = (): JSX.Element => { | ||
return ( | ||
<SummaryDetail element="MY_SUMMARY_DETAIL" baseId="summary-detail" data-testid="summary-detail"> | ||
<SummaryDetailHeading element="MY_SUMMARY_DETAIL_HEADING" data-testid="summary-detail-heading"> | ||
<SummaryDetailToggleButton | ||
element="MY_SUMMARY_DETAIL_TOGGLE_BUTTON" | ||
aria-label="BOOP" | ||
data-testid="summary-detail-toggle-button" | ||
/> | ||
<SummaryDetailHeadingContent | ||
element="MY_SUMMARY_DETAIL_HEADING_CONTENT" | ||
data-testid="summary-detail-heading-content" | ||
> | ||
Inbound Call | ||
</SummaryDetailHeadingContent> | ||
</SummaryDetailHeading> | ||
<SummaryDetailContent element="MY_SUMMARY_DETAIL_CONTENT" data-testid="summary-detail-content"> | ||
Agent: John Doe | ||
</SummaryDetailContent> | ||
</SummaryDetail> | ||
); | ||
}; | ||
|
||
const StateHookMock = (): JSX.Element => { | ||
const summaryDetail = useSummaryDetailState(); | ||
return ( | ||
<Theme.Provider theme="default"> | ||
<button | ||
onClick={() => { | ||
summaryDetail.toggle(); | ||
}} | ||
type="button" | ||
data-testid="external-toggle" | ||
> | ||
Toggle summaryDetail | ||
</button> | ||
<SummaryDetail state={summaryDetail} baseId="summary-detail" data-testid="summary-detail"> | ||
<SummaryDetailHeading element="FOO_HEADING" data-testid="summary-detail-heading"> | ||
<SummaryDetailToggleButton | ||
element="FOO_TOGGLE_BUTTON" | ||
aria-label="BOOP" | ||
data-testid="summary-detail-toggle-button" | ||
/> | ||
<SummaryDetailHeadingContent element="FOO_HEADING_CONTENT" data-testid="summary-detail-heading-content"> | ||
Inbound Call | ||
</SummaryDetailHeadingContent> | ||
</SummaryDetailHeading> | ||
<SummaryDetailContent element="FOO_CONTENT" data-testid="summary-detail-content"> | ||
Agent: John Doe | ||
</SummaryDetailContent> | ||
</SummaryDetail> | ||
</Theme.Provider> | ||
); | ||
}; | ||
|
||
describe("SummaryDetail", () => { | ||
describe("Render", () => { | ||
it("should render a summary-detail button with aria attributes", () => { | ||
render(<MockDefaultElementSummaryDetail />); | ||
const renderedSummaryDetailButton = screen.getByTestId("summary-detail-toggle-button"); | ||
expect(renderedSummaryDetailButton.getAttribute("aria-expanded")).toEqual("false"); | ||
expect(renderedSummaryDetailButton.getAttribute("aria-controls")).toEqual("summary-detail"); | ||
expect(renderedSummaryDetailButton.getAttribute("aria-label")).toEqual("BOOP"); | ||
expect(renderedSummaryDetailButton.getAttribute("aria-labelledby")).toBe(null); | ||
}); | ||
it("should overwrite aria-labelledby if passing an aria-label", () => { | ||
render(<MockSummaryDetail />); | ||
const renderedSummaryDetailButton = screen.getByTestId("summary-detail-toggle-button"); | ||
expect(renderedSummaryDetailButton.getAttribute("aria-label")).toEqual(null); | ||
expect(renderedSummaryDetailButton.getAttribute("aria-labelledby")).not.toBe(null); | ||
}); | ||
|
||
it("should render a summary-detail open", async () => { | ||
await waitFor(() => { | ||
render(<MockSummaryDetail visible />); | ||
}); | ||
const renderedSummaryDetailButton = screen.getByRole("button"); | ||
const summaryDetailContent = screen.getByTestId("summary-detail-content"); | ||
expect(renderedSummaryDetailButton.getAttribute("aria-expanded")).toEqual("true"); | ||
expect(summaryDetailContent).toBeVisible(); | ||
}); | ||
|
||
it("should toggle open state correctly", async () => { | ||
render(<MockSummaryDetail />); | ||
const summaryDetailButton = screen.getByTestId("summary-detail-toggle-button"); | ||
const summaryDetailContent = screen.getByTestId("summary-detail-content"); | ||
expect(summaryDetailButton.getAttribute("aria-expanded")).toEqual("false"); | ||
expect(summaryDetailContent).not.toBeVisible(); | ||
userEvent.click(summaryDetailButton); | ||
expect(summaryDetailButton.getAttribute("aria-expanded")).toEqual("true"); | ||
waitFor(() => { | ||
expect(summaryDetailContent).toBeVisible(); | ||
}); | ||
}); | ||
|
||
it("should toggle open state correctly when using a state hook", async () => { | ||
render(<StateHookMock />); | ||
const toggleButton = screen.getByTestId("external-toggle"); | ||
const summaryDetailButton = screen.getByTestId("summary-detail-toggle-button"); | ||
const summaryDetailContent = screen.getByTestId("summary-detail-content"); | ||
expect(summaryDetailButton.getAttribute("aria-expanded")).toEqual("false"); | ||
expect(summaryDetailContent).not.toBeVisible(); | ||
userEvent.click(toggleButton); | ||
expect(summaryDetailButton.getAttribute("aria-expanded")).toEqual("true"); | ||
waitFor(() => { | ||
expect(summaryDetailContent).toBeVisible(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("Customization", () => { | ||
it("should set an element data attribute for SummaryDetail components", () => { | ||
render( | ||
<Theme.Provider theme="default"> | ||
<MockDefaultElementSummaryDetail /> | ||
</Theme.Provider>, | ||
); | ||
|
||
const renderedSummaryDetailHeading = screen.getByTestId("summary-detail-heading"); | ||
const renderedSummaryDetail = screen.getByTestId("summary-detail"); | ||
const renderedSummaryDetailContent = screen.getByTestId("summary-detail-content"); | ||
const renderedSummaryDetailHeadingContent = screen.getByTestId("summary-detail-heading-content"); | ||
const renderedSummaryDetailToggleButton = screen.getByTestId("summary-detail-toggle-button"); | ||
|
||
expect(renderedSummaryDetail.getAttribute("data-paste-element")).toEqual("SUMMARY_DETAIL"); | ||
expect(renderedSummaryDetailHeading.getAttribute("data-paste-element")).toEqual("SUMMARY_DETAIL_HEADING"); | ||
expect(renderedSummaryDetailContent.getAttribute("data-paste-element")).toEqual("SUMMARY_DETAIL_CONTENT"); | ||
expect(renderedSummaryDetailHeadingContent.getAttribute("data-paste-element")).toEqual( | ||
"SUMMARY_DETAIL_HEADING_CONTENT", | ||
); | ||
expect(renderedSummaryDetailToggleButton.getAttribute("data-paste-element")).toEqual( | ||
"SUMMARY_DETAIL_TOGGLE_BUTTON", | ||
); | ||
}); | ||
|
||
it("should set a custom element data attribute for custom named SummaryDetail components", () => { | ||
render( | ||
<Theme.Provider theme="default"> | ||
<MockCustomElementSummaryDetail /> | ||
</Theme.Provider>, | ||
); | ||
|
||
const renderedSummaryDetailHeading = screen.getByTestId("summary-detail-heading"); | ||
const renderedSummaryDetail = screen.getByTestId("summary-detail"); | ||
const renderedSummaryDetailContent = screen.getByTestId("summary-detail-content"); | ||
const renderedSummaryDetailHeadingContent = screen.getByTestId("summary-detail-heading-content"); | ||
const renderedSummaryDetailToggleButton = screen.getByTestId("summary-detail-toggle-button"); | ||
|
||
expect(renderedSummaryDetail.getAttribute("data-paste-element")).toEqual("MY_SUMMARY_DETAIL"); | ||
expect(renderedSummaryDetailHeading.getAttribute("data-paste-element")).toEqual("MY_SUMMARY_DETAIL_HEADING"); | ||
expect(renderedSummaryDetailContent.getAttribute("data-paste-element")).toEqual("MY_SUMMARY_DETAIL_CONTENT"); | ||
expect(renderedSummaryDetailHeadingContent.getAttribute("data-paste-element")).toEqual( | ||
"MY_SUMMARY_DETAIL_HEADING_CONTENT", | ||
); | ||
expect(renderedSummaryDetailToggleButton.getAttribute("data-paste-element")).toEqual( | ||
"MY_SUMMARY_DETAIL_TOGGLE_BUTTON", | ||
); | ||
}); | ||
|
||
it("should add custom styles to SummaryDetail components", () => { | ||
render( | ||
<CustomizationProvider | ||
baseTheme="default" | ||
theme={TestTheme} | ||
elements={{ | ||
SUMMARY_DETAIL: { padding: "space100" }, | ||
SUMMARY_DETAIL_CONTENT: { color: "colorTextErrorStrong" }, | ||
SUMMARY_DETAIL_HEADING: { color: "colorTextWeakest", backgroundColor: "colorBackgroundDestructiveStrong" }, | ||
SUMMARY_DETAIL_HEADING_CONTENT: { color: "colorTextIconError" }, | ||
SUMMARY_DETAIL_TOGGLE_BUTTON: { borderColor: "colorBorderError" }, | ||
}} | ||
> | ||
<MockDefaultElementSummaryDetail /> | ||
</CustomizationProvider>, | ||
); | ||
|
||
const renderedSummaryDetailHeading = screen.getByTestId("summary-detail-heading"); | ||
const renderedSummaryDetail = screen.getByTestId("summary-detail"); | ||
const renderedSummaryDetailContent = screen.getByTestId("summary-detail-content"); | ||
const renderedSummaryDetailHeadingContent = screen.getByTestId("summary-detail-heading-content"); | ||
const renderedSummaryDetailToggleButton = screen.getByTestId("summary-detail-toggle-button"); | ||
|
||
expect(renderedSummaryDetail).toHaveStyleRule("padding", "2.25rem"); | ||
expect(renderedSummaryDetailHeading).toHaveStyleRule("color", "rgb(255, 255, 255)"); | ||
expect(renderedSummaryDetailHeading).toHaveStyleRule("background-color", "rgb(117, 12, 12)"); | ||
expect(renderedSummaryDetailContent).toHaveStyleRule("color", "rgb(173, 17, 17)"); | ||
expect(renderedSummaryDetailHeadingContent).toHaveStyleRule("color", "rgb(214, 31, 31)"); | ||
expect(renderedSummaryDetailToggleButton).toHaveStyleRule("border-color", "rgb(214, 31, 31)"); | ||
}); | ||
|
||
it("should add custom styles to custom named SummaryDetail components", () => { | ||
render( | ||
<CustomizationProvider | ||
baseTheme="default" | ||
theme={TestTheme} | ||
elements={{ | ||
MY_SUMMARY_DETAIL: { padding: "space100" }, | ||
MY_SUMMARY_DETAIL_CONTENT: { color: "colorTextErrorStrong" }, | ||
MY_SUMMARY_DETAIL_HEADING: { | ||
color: "colorTextWeakest", | ||
backgroundColor: "colorBackgroundDestructiveStrong", | ||
}, | ||
MY_SUMMARY_DETAIL_HEADING_CONTENT: { color: "colorTextIconError" }, | ||
MY_SUMMARY_DETAIL_TOGGLE_BUTTON: { borderColor: "colorBorderError" }, | ||
}} | ||
> | ||
<MockCustomElementSummaryDetail /> | ||
</CustomizationProvider>, | ||
); | ||
const renderedSummaryDetailHeading = screen.getByTestId("summary-detail-heading"); | ||
const renderedSummaryDetail = screen.getByTestId("summary-detail"); | ||
const renderedSummaryDetailContent = screen.getByTestId("summary-detail-content"); | ||
const renderedSummaryDetailHeadingContent = screen.getByTestId("summary-detail-heading-content"); | ||
const renderedSummaryDetailToggleButton = screen.getByTestId("summary-detail-toggle-button"); | ||
|
||
expect(renderedSummaryDetail).toHaveStyleRule("padding", "2.25rem"); | ||
expect(renderedSummaryDetailHeading).toHaveStyleRule("color", "rgb(255, 255, 255)"); | ||
expect(renderedSummaryDetailHeading).toHaveStyleRule("background-color", "rgb(117, 12, 12)"); | ||
expect(renderedSummaryDetailContent).toHaveStyleRule("color", "rgb(173, 17, 17)"); | ||
expect(renderedSummaryDetailHeadingContent).toHaveStyleRule("color", "rgb(214, 31, 31)"); | ||
expect(renderedSummaryDetailToggleButton).toHaveStyleRule("border-color", "rgb(214, 31, 31)"); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const { build } = require("../../../../tools/build/esbuild"); | ||
|
||
build(require("./package.json")); |
77 changes: 77 additions & 0 deletions
77
packages/paste-core/components/summary-detail/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
{ | ||
"name": "@twilio-paste/summary-detail", | ||
"version": "0.0.1", | ||
"category": "interaction", | ||
"status": "production", | ||
"description": "A Summary Detail is a collapsible container that can be used to hide or show content.", | ||
"author": "Twilio Inc.", | ||
"license": "MIT", | ||
"main:dev": "src/index.tsx", | ||
"main": "dist/index.js", | ||
"module": "dist/index.es.js", | ||
"types": "dist/index.d.ts", | ||
"sideEffects": false, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"build": "yarn clean && NODE_ENV=production node build.js && tsc", | ||
"build:js": "NODE_ENV=development node build.js", | ||
"build:typedocs": "tsx ../../../../tools/build/generate-type-docs", | ||
"clean": "rm -rf ./dist", | ||
"tsc": "tsc" | ||
}, | ||
"peerDependencies": { | ||
"@twilio-paste/anchor": "^12.0.0", | ||
"@twilio-paste/animation-library": "^2.0.0", | ||
"@twilio-paste/box": "^10.3.0", | ||
"@twilio-paste/button": "^14.0.0", | ||
"@twilio-paste/card": "^9.1.0", | ||
"@twilio-paste/color-contrast-utils": "^5.0.0", | ||
"@twilio-paste/customization": "^8.0.0", | ||
"@twilio-paste/design-tokens": "^10.0.0", | ||
"@twilio-paste/disclosure-primitive": "^2.1.1", | ||
"@twilio-paste/icons": "^12.0.0", | ||
"@twilio-paste/reakit-library": "^2.0.0", | ||
"@twilio-paste/spinner": "^14.0.0", | ||
"@twilio-paste/stack": "^8.0.0", | ||
"@twilio-paste/style-props": "^9.0.0", | ||
"@twilio-paste/styling-library": "^3.0.0", | ||
"@twilio-paste/theme": "^11.0.0", | ||
"@twilio-paste/types": "^6.0.0", | ||
"@twilio-paste/uid-library": "^2.0.0", | ||
"@types/react": "^16.8.6 || ^17.0.2 || ^18.0.27", | ||
"@types/react-dom": "^16.8.6 || ^17.0.2 || ^18.0.10", | ||
"react": "^16.8.6 || ^17.0.2 || ^18.0.0", | ||
"react-dom": "^16.8.6 || ^17.0.2 || ^18.0.0" | ||
}, | ||
"devDependencies": { | ||
"@twilio-paste/anchor": "^12.0.0", | ||
"@twilio-paste/animation-library": "^2.0.0", | ||
"@twilio-paste/box": "^10.3.0", | ||
"@twilio-paste/button": "^14.0.0", | ||
"@twilio-paste/card": "^9.1.0", | ||
"@twilio-paste/color-contrast-utils": "^5.0.0", | ||
"@twilio-paste/customization": "^8.1.1", | ||
"@twilio-paste/design-tokens": "^10.4.0", | ||
"@twilio-paste/disclosure-primitive": "^2.1.1", | ||
"@twilio-paste/icons": "^12.0.0", | ||
"@twilio-paste/reakit-library": "^2.0.0", | ||
"@twilio-paste/spinner": "^14.0.0", | ||
"@twilio-paste/stack": "^8.0.0", | ||
"@twilio-paste/style-props": "^9.1.1", | ||
"@twilio-paste/styling-library": "^3.0.0", | ||
"@twilio-paste/theme": "^11.0.0", | ||
"@twilio-paste/types": "^6.0.0", | ||
"@twilio-paste/uid-library": "^2.0.0", | ||
"@types/react": "^18.0.27", | ||
"@types/react-dom": "^18.0.10", | ||
"react": "^18.0.0", | ||
"react-dom": "^18.0.0", | ||
"tsx": "^4.0.0", | ||
"typescript": "^4.9.4" | ||
} | ||
} |
Oops, something went wrong.