Skip to content

Commit

Permalink
Merge pull request #30099 from storybookjs/version-non-patch-from-8.5…
Browse files Browse the repository at this point in the history
….0-beta.2

Release: Prerelease 8.5.0-beta.3
  • Loading branch information
yannbf authored Dec 19, 2024
2 parents 1f6fafa + f1fee6e commit 7a6899f
Show file tree
Hide file tree
Showing 24 changed files with 252 additions and 271 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 8.5.0-beta.3

- Addon A11y: Fix skipped status handling in Testing Module - [#30077](https://github.com/storybookjs/storybook/pull/30077), thanks @valentinpalkovic!
- Core: Float context menu button on top of story titles in sidebar - [#30080](https://github.com/storybookjs/storybook/pull/30080), thanks @ghengeveld!
- Onboarding: Replace `react-confetti` with `@neoconfetti/react` - [#30098](https://github.com/storybookjs/storybook/pull/30098), thanks @ndelangen!

## 8.5.0-beta.2

- Addon Test: Clear coverage data when starting or watching - [#30072](https://github.com/storybookjs/storybook/pull/30072), thanks @ghengeveld!
Expand Down
3 changes: 2 additions & 1 deletion code/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -358,5 +358,6 @@ export const parameters = {
opacity: 0.4,
},
},
tags: ['test', 'vitest', '!a11ytest'],
};

export const tags = ['test', 'vitest', '!a11ytest'];
2 changes: 1 addition & 1 deletion code/addons/onboarding/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@
"prep": "jiti ../../../scripts/prepare/addon-bundle.ts"
},
"devDependencies": {
"@neoconfetti/react": "^1.0.0",
"@radix-ui/react-dialog": "^1.0.5",
"@storybook/icons": "^1.2.12",
"@storybook/react": "workspace:*",
"framer-motion": "^11.0.3",
"react": "^18.2.0",
"react-confetti": "^6.1.0",
"react-dom": "^18.2.0",
"react-joyride": "^2.8.2",
"react-use-measure": "^2.1.1",
Expand Down
12 changes: 1 addition & 11 deletions code/addons/onboarding/src/Onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -268,17 +268,7 @@ export default function Onboarding({ api }: { api: API }) {

return (
<ThemeProvider theme={theme}>
{showConfetti && (
<Confetti
numberOfPieces={800}
recycle={false}
tweenDuration={20000}
onConfettiComplete={(confetti) => {
confetti?.reset();
setShowConfetti(false);
}}
/>
)}
{showConfetti && <Confetti />}
{step === '1:Intro' ? (
<SplashScreen onDismiss={() => setStep('2:Controls')} />
) : (
Expand Down
51 changes: 11 additions & 40 deletions code/addons/onboarding/src/components/Confetti/Confetti.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ const meta: Meta<typeof Confetti> = {
component: Confetti,
parameters: {
chromatic: { disableSnapshot: true },
layout: 'fullscreen',
},
decorators: [
(StoryFn) => (
<div style={{ height: '100vh', width: '100vw' }}>
<button>I am clickable</button>
<div
style={{
height: '100vh',
width: '100vw',
alignContent: 'center',
textAlign: 'center',
}}
>
<span>Falling confetti! 🎉</span>
<StoryFn />
</div>
),
Expand All @@ -23,41 +31,4 @@ export default meta;

type Story = StoryObj<typeof Confetti>;

export const Default: Story = {
args: {
recycle: true,
numberOfPieces: 200,
top: undefined,
left: undefined,
width: undefined,
height: undefined,
friction: 0.99,
wind: 0,
gravity: 0.1,
initialVelocityX: 4,
initialVelocityY: 10,
tweenDuration: 5000,
},
};

export const OneTimeConfetti: Story = {
args: {
...Default.args,
numberOfPieces: 800,
recycle: false,
tweenDuration: 20000,
onConfettiComplete: (confetti) => {
confetti?.reset();
},
},
};

export const Positioned: Story = {
args: {
...Default.args,
top: 100,
left: 300,
width: 300,
height: 250,
},
};
export const Default: Story = {};
149 changes: 26 additions & 123 deletions code/addons/onboarding/src/components/Confetti/Confetti.tsx
Original file line number Diff line number Diff line change
@@ -1,131 +1,34 @@
import React, { useEffect } from 'react';
import { useState } from 'react';
import { createPortal } from 'react-dom';
import React, { type ComponentProps } from 'react';

import { styled } from 'storybook/internal/theming';

import ReactConfetti from 'react-confetti';
import { Confetti as ReactConfetti } from '@neoconfetti/react';

interface ConfettiProps extends Omit<React.ComponentProps<typeof ReactConfetti>, 'drawShape'> {
top?: number;
left?: number;
width?: number;
height?: number;
numberOfPieces?: number;
recycle?: boolean;
colors?: string[];
}
const Wrapper = styled.div({
zIndex: 9999,
position: 'fixed',
top: 0,
left: '50%',
width: '50%',
height: '100%',
});

const Wrapper = styled.div<{
width: number;
height: number;
top: number;
left: number;
}>(({ width, height, left, top }) => ({
width: `${width}px`,
height: `${height}px`,
left: `${left}px`,
top: `${top}px`,
position: 'relative',
overflow: 'hidden',
}));

export function Confetti({
top = 0,
left = 0,
width = window.innerWidth,
height = window.innerHeight,
export const Confetti = React.memo(function Confetti({
timeToFade = 5000,
colors = ['#CA90FF', '#FC521F', '#66BF3C', '#FF4785', '#FFAE00', '#1EA7FD'],
...confettiProps
}: ConfettiProps): React.ReactPortal {
const [confettiContainer] = useState(() => {
const container = document.createElement('div');
container.setAttribute('id', 'confetti-container');
container.setAttribute(
'style',
'position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 9999;'
);

return container;
});

useEffect(() => {
document.body.appendChild(confettiContainer);

return () => {
document.body.removeChild(confettiContainer);
};
}, []);

return createPortal(
<Wrapper top={top} left={left} width={width} height={height}>
<ReactConfetti colors={colors} drawShape={draw} {...confettiProps} />
</Wrapper>,
confettiContainer
}: ComponentProps<typeof ReactConfetti> & { timeToFade?: number }) {
return (
<Wrapper>
<ReactConfetti
colors={colors}
particleCount={200}
duration={5000}
stageHeight={window.innerHeight}
stageWidth={window.innerWidth}
destroyAfterDone
{...confettiProps}
/>
</Wrapper>
);
}

enum ParticleShape {
Circle = 1,
Square = 2,
TShape = 3,
LShape = 4,
Triangle = 5,
QuarterCircle = 6,
}

function getRandomInt(min: number, max: number) {
return Math.floor(Math.random() * (max - min)) + min;
}

function draw(this: any, context: CanvasRenderingContext2D) {
this.shape = this.shape || getRandomInt(1, 6);

switch (this.shape) {
case ParticleShape.Square: {
const cornerRadius = 2;
const width = this.w / 2;
const height = this.h / 2;

context.moveTo(-width + cornerRadius, -height);
context.lineTo(width - cornerRadius, -height);
context.arcTo(width, -height, width, -height + cornerRadius, cornerRadius);
context.lineTo(width, height - cornerRadius);
context.arcTo(width, height, width - cornerRadius, height, cornerRadius);
context.lineTo(-width + cornerRadius, height);
context.arcTo(-width, height, -width, height - cornerRadius, cornerRadius);
context.lineTo(-width, -height + cornerRadius);
context.arcTo(-width, -height, -width + cornerRadius, -height, cornerRadius);

break;
}
case ParticleShape.TShape: {
context.rect(-4, -4, 8, 16);
context.rect(-12, -4, 24, 8);
break;
}
case ParticleShape.LShape: {
context.rect(-4, -4, 8, 16);
context.rect(-4, -4, 24, 8);
break;
}
case ParticleShape.Circle: {
context.arc(0, 0, this.radius, 0, 2 * Math.PI);
break;
}
case ParticleShape.Triangle: {
context.moveTo(16, 4);
context.lineTo(4, 24);
context.lineTo(24, 24);
break;
}
case ParticleShape.QuarterCircle: {
context.arc(4, -4, 4, -Math.PI / 2, 0);
context.lineTo(4, 0);
break;
}
}

context.closePath();
context.fill();
}
});
24 changes: 24 additions & 0 deletions code/addons/test/src/components/TestProviderRender.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ const baseState: TestProviderState<Details, Config> = {
coverage: false,
},
details: {
config: {
a11y: false,
coverage: false,
},
testResults: [
{
endTime: 0,
Expand Down Expand Up @@ -141,6 +145,10 @@ export const WithCoverageNegative: Story = {
...config,
...baseState,
details: {
config: {
a11y: false,
coverage: true,
},
testResults: [],
coverageSummary: {
percentage: 20,
Expand All @@ -162,6 +170,10 @@ export const WithCoverageWarning: Story = {
...baseState,
details: {
testResults: [],
config: {
a11y: false,
coverage: true,
},
coverageSummary: {
percentage: 50,
status: 'warning',
Expand All @@ -182,6 +194,10 @@ export const WithCoveragePositive: Story = {
...baseState,
details: {
testResults: [],
config: {
a11y: false,
coverage: true,
},
coverageSummary: {
percentage: 80,
status: 'positive',
Expand All @@ -206,6 +222,10 @@ export const Editing: Story = {
},
details: {
testResults: [],
config: {
a11y: false,
coverage: false,
},
},
},
},
Expand All @@ -229,6 +249,10 @@ export const EditingAndWatching: Story = {
},
details: {
testResults: [],
config: {
a11y: true,
coverage: true, // should be automatically disabled in the UI
},
},
},
},
Expand Down
29 changes: 22 additions & 7 deletions code/addons/test/src/components/TestProviderRender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,14 @@ export const TestProviderRender: FC<
return 'unknown';
}

if (!a11yResults) {
const definedA11yResults = a11yResults?.filter(Boolean) ?? [];

if (!definedA11yResults || definedA11yResults.length === 0) {
return 'unknown';
}

const failed = a11yResults.some((result) => result?.status === 'failed');
const warning = a11yResults.some((result) => result?.status === 'warning');
const failed = definedA11yResults.some((result) => result?.status === 'failed');
const warning = definedA11yResults.some((result) => result?.status === 'warning');

if (failed) {
return 'negative';
Expand All @@ -154,11 +156,24 @@ export const TestProviderRender: FC<
return 'positive';
}, [state.running, isA11yAddon, config.a11y, a11yResults]);

const a11yNotPassedAmount = a11yResults?.filter(
(result) => result?.status === 'failed' || result?.status === 'warning'
).length;
const a11yNotPassedAmount = state.config?.a11y
? a11yResults?.filter((result) => result?.status === 'failed' || result?.status === 'warning')
.length
: undefined;

const a11ySkippedAmount =
state.running || !state?.details.config?.a11y || !state.config.a11y
? null
: a11yResults?.filter((result) => !result).length;

const a11ySkippedLabel = a11ySkippedAmount
? a11ySkippedAmount === 1 && isStoryEntry
? '(skipped)'
: `(${a11ySkippedAmount} skipped)`
: '';

const storyId = isStoryEntry ? entryId : undefined;

const results = (state.details?.testResults || [])
.flatMap((test) => {
if (!entryId) {
Expand Down Expand Up @@ -333,7 +348,7 @@ export const TestProviderRender: FC<
)}
{isA11yAddon && (
<ListItem
title={<ItemTitle enabled={config.a11y}>Accessibility</ItemTitle>}
title={<ItemTitle enabled={config.a11y}>Accessibility {a11ySkippedLabel}</ItemTitle>}
onClick={
(a11yStatus === 'negative' || a11yStatus === 'warning') && a11yResults.length
? () => {
Expand Down
Loading

0 comments on commit 7a6899f

Please sign in to comment.