Skip to content

Commit

Permalink
feat: responsive screen size hook and css var (#548)
Browse files Browse the repository at this point in the history
  • Loading branch information
artmsilva authored Jan 10, 2024
1 parent 16b4b71 commit 5768e9c
Show file tree
Hide file tree
Showing 8 changed files with 450 additions and 51 deletions.
50 changes: 0 additions & 50 deletions .github/workflows/interaction-tests.yml

This file was deleted.

6 changes: 5 additions & 1 deletion .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ function DarkPanel(props) {
export const decorators = [
(Story, Context) => {
if (Context.story.includes("Interactions")) {
return <Story theme="light" />;
return (
<GlobalStyles>
<Story theme="light" />;
</GlobalStyles>
);
}

return (
Expand Down
38 changes: 38 additions & 0 deletions build.washingtonpost.com/docs/foundations/breakpoints.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,41 @@ export default function Example() {
);
}
```

### Using the Responsive Screen Size React Hook

The `useResponsiveScreenSize` hook can be used to get the current screen size and use it in your components.

<Alert variant="info">
<p>
The hook is only available in the browser and will return{" "}
<code>unknown</code> on the server.
</p>
</Alert>

#### An example using the hook

Our Spectrum render engine uses the hook to render a drawer on small screens and a dialog on larger screens. This is a simplified version of the code used in the Spectrum render engine.

```jsx
import {
useResponsiveScreenSize,
screenSizesEnums,
Dialog,
Drawer,
} from "@washingtonpost/wpds-ui-kit";

export default function Example() {
const screenSize = useResponsiveScreenSize();

return (
<div>
{screenSize === screenSizesEnums.small ? (
<Drawer>{/* Drawer content */}</Drawer>
) : (
<Dialog>{/* Dialog content */}</Dialog>
)}
</div>
);
}
```
1 change: 1 addition & 0 deletions ui/theme/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./stitches.config";
export * from "./useResponsiveScreenSize";
19 changes: 19 additions & 0 deletions ui/theme/src/stitches.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,25 @@ export const globalStyles = globalCss({
":root": {
"--base": `${tokens.base}`,
lineHeight: "$meta",
$$screenSize: "unknown",
"@sm": {
$$screenSize: "small",
},
"@md": {
$$screenSize: "medium",
},
"@lg": {
$$screenSize: "large",
},
"@xl": {
$$screenSize: "xlarge",
},
"@xxl": {
$$screenSize: "xxlarge",
},
"@minXxl": {
$$screenSize: "infinity", // temporary name cause we don't have a name for this
},
},
"*": {
boxSizing: "border-box",
Expand Down
225 changes: 225 additions & 0 deletions ui/theme/src/useResponsiveScreenSize.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
import * as React from "react";
import { Meta, Story } from "@storybook/react";
import { within } from "@storybook/testing-library";
import { expect } from "@storybook/jest";
import { Box } from "@washingtonpost/wpds-box";
import { useResponsiveScreenSize } from "./useResponsiveScreenSize";

const allModes = {
sm: {
viewport: "small",
},
md: {
viewport: "medium",
},
lg: {
viewport: "large",
},
xl: {
viewport: "xlarge",
},
xxl: {
viewport: "xxlarge",
},
minXxl: {
viewport: "infinity",
},
};

export default {
title: "useResponsiveScreenSize",
parameters: {
viewport: {
viewports: {
small: {
name: "Small",
styles: {
height: "590px",
width: "767px",
},
type: "mobile",
},
medium: {
name: "Medium",
styles: {
height: "590px",
width: "900px",
},
type: "tablet",
},
large: {
name: "Large",
styles: {
height: "590px",
width: "1024px",
},
type: "tablet",
},
xlarge: {
name: "Extra Large",
styles: {
height: "590px",
width: "1280px",
},
type: "desktop",
},
xxlarge: {
name: "Extra Extra Large",
styles: {
height: "590px",
width: "1440px",
},
type: "desktop",
},
infinity: {
name: "Infinity",
styles: {
height: "590px",
width: "1442px",
},
type: "desktop",
},
},
defaultViewport: "responsive",
},
},
} as Meta;

const Template: Story<typeof Box> = () => {
const screenSize = useResponsiveScreenSize();

return (
<div>
<h1>Responsive Screen Size</h1>
<p>Current screen size: {screenSize}</p>
</div>
);
};

// Function to emulate pausing between interactions
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

export const InteractionsSmall = Template.bind({});

InteractionsSmall.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
await sleep(500);

const screenSize = canvas.getByText("Current screen size: small");
expect(screenSize).toBeInTheDocument();
};

InteractionsSmall.parameters = {
viewport: {
defaultViewport: "small",
},
chromatic: {
modes: {
mobile: allModes["sm"],
},
},
};

export const InteractionsMedium = Template.bind({});
InteractionsMedium.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
await sleep(500);

const screenSize = canvas.getByText("Current screen size: medium");
expect(screenSize).toBeInTheDocument();
};

InteractionsMedium.parameters = {
viewport: {
defaultViewport: "medium",
},
chromatic: {
modes: {
tablet: allModes["md"],
},
},
};

export const InteractionsLarge = Template.bind({});
InteractionsLarge.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
await sleep(500);

const screenSize = canvas.getByText("Current screen size: large");
expect(screenSize).toBeInTheDocument();
};

InteractionsLarge.parameters = {
viewport: {
defaultViewport: "large",
},
chromatic: {
modes: {
tablet: allModes["lg"],
},
},
};

export const InteractionsXLarge = Template.bind({});
InteractionsXLarge.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
await sleep(500);

const screenSize = canvas.getByText("Current screen size: xlarge");
expect(screenSize).toBeInTheDocument();
};

InteractionsXLarge.parameters = {
viewport: {
defaultViewport: "xlarge",
},
chromatic: {
modes: {
desktop: allModes["xl"],
},
},
};

export const InteractionsXXLarge = Template.bind({});

InteractionsXXLarge.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
await sleep(500);

const screenSize = canvas.getByText("Current screen size: xxlarge");
expect(screenSize).toBeInTheDocument();
};

InteractionsXXLarge.parameters = {
viewport: {
defaultViewport: "xxlarge",
},
chromatic: {
modes: {
desktop: allModes["xxl"],
},
},
};

export const InteractionsInfinity = Template.bind({});

InteractionsInfinity.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
await sleep(500);

const screenSize = canvas.getByText("Current screen size: infinity");
expect(screenSize).toBeInTheDocument();
};

InteractionsInfinity.parameters = {
viewport: {
defaultViewport: "responsive",
},
chromatic: {
modes: {
desktop: allModes["minXxl"],
},
},
};
Loading

2 comments on commit 5768e9c

@vercel
Copy link

@vercel vercel bot commented on 5768e9c Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

wpds-ui-kit – ./build.washingtonpost.com

wpds-ui-kit-git-main.preview.now.washingtonpost.com
build.washingtonpost.com
wpds-ui-kit.preview.now.washingtonpost.com

@vercel
Copy link

@vercel vercel bot commented on 5768e9c Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

wpds-ui-kit-storybook – ./

wpds-ui-kit-storybook-git-main.preview.now.washingtonpost.com
wpds-ui-kit-storybook.preview.now.washingtonpost.com

Please sign in to comment.