Skip to content

Commit

Permalink
refactor: rename toast components (#1520)
Browse files Browse the repository at this point in the history
Relates to #1301

As discussed with Jannick, we aligned the naming between UX and dev
  • Loading branch information
larsrickert authored Jul 6, 2024
1 parent d4d35c9 commit 7b72cbc
Show file tree
Hide file tree
Showing 69 changed files with 550 additions and 535 deletions.
8 changes: 8 additions & 0 deletions .changeset/funny-roses-prove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"sit-onyx": major
---

refactor: rename toast components

- renamed `OnyxToast` to `OnyxToastMessage`
- renamed `OnyxToastProvider` to `OnyxToast`
4 changes: 2 additions & 2 deletions apps/demo-app/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
OnyxMenuItem,
OnyxNavBar,
OnyxNavButton,
OnyxToastProvider,
OnyxToast,
OnyxUserMenu,
type OnyxNavButtonProps,
} from "sit-onyx";
Expand Down Expand Up @@ -92,6 +92,6 @@ watch(

<RouterView />

<OnyxToastProvider />
<OnyxToast />
</OnyxAppLayout>
</template>
3 changes: 1 addition & 2 deletions apps/docs/src/.vitepress/components/IconLibraryItem.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts" setup>
import OnyxIcon from "~components/OnyxIcon/OnyxIcon.vue";
import { useToast } from "~components/OnyxToastProvider/useToast";
import { useToast } from "~components/OnyxToast/useToast";
import OnyxTooltip from "~components/OnyxTooltip/OnyxTooltip.vue";
import type { EnrichedIcon } from "../utils-icons";
Expand All @@ -20,7 +20,6 @@ const handleCopy = async () => {
headline: "Copied to clipboard!",
description: `Import for icon "${importName}" has been copied to your clipboard.`,
color: "success",
duration: 3000,
});
};
</script>
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/src/.vitepress/theme/TheLayout.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<script lang="ts" setup>
import DefaultTheme from "vitepress/theme";
import OnyxToastProvider from "~components/OnyxToastProvider/OnyxToastProvider.vue";
import OnyxToast from "~components/OnyxToast/OnyxToast.vue";
const { Layout } = DefaultTheme;
</script>

<template>
<Layout>
<template #layout-bottom>
<OnyxToastProvider />
<OnyxToast />

<footer class="footer">
<p class="footer__message">Released under the Apache-2.0 License.</p>
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
94 changes: 23 additions & 71 deletions packages/sit-onyx/src/components/OnyxToast/OnyxToast.ct.tsx
Original file line number Diff line number Diff line change
@@ -1,79 +1,31 @@
import { DENSITIES } from "../../composables/density";
import { test } from "../../playwright/a11y";
import { executeMatrixScreenshotTest } from "../../playwright/screenshots";
import type { OnyxColor } from "../../types";
import OnyxToast from "./OnyxToast.vue";
import { expect, test } from "../../playwright/a11y";
import { ONYX_BREAKPOINTS } from "../../types";
import PlaywrightTestWrapper from "./PlaywrightTestWrapper.vue";

const TOAST_COLORS = ["neutral", "danger", "warning", "success"] satisfies OnyxColor[];
Object.entries(ONYX_BREAKPOINTS).forEach(([breakpoint, width]) => {
test(`should render (${breakpoint})`, async ({ mount, makeAxeBuilder, page }) => {
await page.setViewportSize({ width, height: 512 });

test.beforeEach(async ({ page }) => {
await page.addStyleTag({
content: `.onyx-toast__progress-bar {
width: 100%
}`,
});
});
// ARRANGE
const component = await mount(<PlaywrightTestWrapper />);

test.describe("Screenshot tests", () => {
for (const mode of ["default", "clickable", "manual-close"] as const) {
executeMatrixScreenshotTest({
name: `Toast (${mode})`,
columns: DENSITIES,
rows: TOAST_COLORS,
// ASSERT
await expect(page).toHaveScreenshot(`breakpoint-${breakpoint}.png`);

// ACT
const accessibilityScanResults = await makeAxeBuilder()
// TODO: remove when contrast issues are fixed in https://github.com/SchwarzIT/onyx/issues/410
disabledAccessibilityRules: ["color-contrast"],
component: (column, row) => (
<OnyxToast
headline="Test toast"
color={row}
density={column}
duration={mode === "manual-close" ? 0 : undefined}
clickable={mode === "clickable"}
// margin is used to not cut off the box shadow in the screenshot
style={{ margin: "1rem" }}
/>
),
});
}
});
.disableRules(["color-contrast"])
.analyze();

test.describe("Screenshot tests (description)", () => {
executeMatrixScreenshotTest({
name: "Toast (description)",
columns: DENSITIES,
rows: TOAST_COLORS,
// TODO: remove when contrast issues are fixed in https://github.com/SchwarzIT/onyx/issues/410
disabledAccessibilityRules: ["color-contrast"],
component: (column, row) => (
<OnyxToast
headline="Test toast"
color={row}
density={column}
description="Lorem ipsum dolor sit amet consectetur. Non in felis erat velit consectetur. Sed integer non hac viverra nibh vehicula risus ultrices. Molestie cras lobortis vitae gravida et ut. Turpis nisl pharetra amet ante eu sagittis sit elementum ut."
// margin is used to not cut off the box shadow in the screenshot
style={{ margin: "1rem" }}
/>
),
});
});
// ASSERT
expect(accessibilityScanResults.violations).toEqual([]);
await expect(component).toContainText("Example toast 1");

// ACT
await component.getByLabel("Close").nth(4).click();

test.describe("Screenshot tests (truncation)", () => {
executeMatrixScreenshotTest({
name: "Toast (truncation)",
columns: ["default"],
rows: ["default"],
component: () => (
<OnyxToast
headline={"Test".repeat(32)}
description={"Test".repeat(96)}
// margin is used to not cut off the box shadow in the screenshot
style={{ margin: "1rem" }}
/>
),
beforeScreenshot: async (component) => {
await component.getByRole("paragraph").evaluate((element) => {
element.scrollBy({ top: element.scrollHeight });
});
},
// ASSERT
await expect(component).not.toContainText("Example toast 1");
});
});
121 changes: 47 additions & 74 deletions packages/sit-onyx/src/components/OnyxToast/OnyxToast.stories.ts
Original file line number Diff line number Diff line change
@@ -1,85 +1,58 @@
import { defineStorybookActionsAndVModels } from "@sit-onyx/storybook-utils";
import type { Meta, StoryObj } from "@storybook/vue3";
import { defineIconSelectArgType } from "../../utils/storybook";
import OnyxToast from "./OnyxToast.vue";
import StorybookExample from "./StorybookExample.vue";
import StorybookExampleSourceCode from "./StorybookExample.vue?raw";

/**
* Single toast component. Is mainly intended to be used with the [OnyxToastProvider](/docs/feedback-toastprovider--docs).
* The toast is used to display toast messages to the user.
* For a full list of toast examples, you can check out the [OnyxToastMessage](/docs/support-toastmessage--docs) component.
*
* For a good user experience, make sure to not display too many toasts at the same time (we recommend a limit of 5 toasts).
*
* ### Setup
*
* #### Step 1: Use the `<OnyxToast />` component
*
* Place the `<OnyxToast />` component once anywhere in your application (e.g. in your App.vue file).
* It will take care of displaying the toasts correctly.
*
* #### Step 2: Create the toast provider
*
* **If you are using the `createOnyx()` Vue plugin, you can skip this step since this will already be set up for you.**
*
* The toast works with Vue's [provide/inject](https://vuejs.org/guide/components/provide-inject) API so you need to create a toast provider once.
* To do so, add the following code to your `main.ts` file to set up the toasts globally:
*
* ```ts
* import { createToastProvider, TOAST_PROVIDER_INJECTION_KEY } from "sit-onyx";
*
* app.provide(TOAST_PROVIDER_INJECTION_KEY, createToastProvider());
* ```
*
* Afterwards, toasts can be shown using the `useToast()` composable as shown in the example below.
*/
const meta: Meta<typeof OnyxToast> = {
title: "Support/Toast",
const meta: Meta<typeof StorybookExample> = {
title: "Feedback/Toast",
...defineStorybookActionsAndVModels({
component: OnyxToast,
events: ["click", "close"],
argTypes: {
icon: defineIconSelectArgType(),
},
component: StorybookExample,
events: [],
decorators: [
(story) => ({
components: { story },
template: `<div style="height: 24rem;"> <story /> </div>`,
}),
],
}),
parameters: {
docs: {
source: {
code: StorybookExampleSourceCode.replace('from "../.."', 'from "sit-onyx"'),
},
},
},
};

export default meta;
type Story = StoryObj<typeof OnyxToast>;

export const Default = {
args: {
headline: "Example toast",
description: "Lorem ipsum dolor sit amet consectetur. Non in felis erat velit consectetur.",
},
} satisfies Story;

export const Danger = {
args: {
...Default.args,
color: "danger",
},
} satisfies Story;

export const Warning = {
args: {
...Default.args,
color: "warning",
},
} satisfies Story;

export const Success = {
args: {
...Default.args,
color: "success",
},
} satisfies Story;
type Story = StoryObj<typeof StorybookExample>;

export const Clickable = {
args: {
...Default.args,
clickable: true,
},
} satisfies Story;

export const ManualClose = {
args: {
...Default.args,
duration: 0,
},
} satisfies Story;

/**
* This example shows a toast with a very long description that is limited to 3 lines.
* The user can scroll to see the rest of the description.
*/
export const LongDescription = {
args: {
...Default.args,
description:
"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
},
} satisfies Story;

/**
* This example shows a toast with the minimal amount of data.
*/
export const MinimalData = {
args: {
headline: Default.args.headline,
icon: false,
},
} satisfies Story;
export const Default = { args: {} } satisfies Story;
Loading

0 comments on commit 7b72cbc

Please sign in to comment.