Skip to content

Commit

Permalink
feat: scroll to last announcement, add clear button
Browse files Browse the repository at this point in the history
  • Loading branch information
AriPerkkio committed Jan 7, 2024
1 parent 1e97e97 commit f9a6e86
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 13 deletions.
34 changes: 33 additions & 1 deletion .storybook/Example.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { useLayoutEffect, useMemo, useReducer, useRef } from 'react';
import React, {
useLayoutEffect,
useMemo,
useReducer,
useRef,
useState,
} from 'react';

export default {
title: 'Example',
Expand Down Expand Up @@ -65,6 +71,32 @@ export function ShadowDOM() {
);
}

export function Intervals() {
const [isVisible, toggleVisible] = useReducer((s) => !s, false);
const [interval, setIntervalState] = useState<ReturnType<
typeof setInterval
> | null>();

function onClick() {
if (interval != null) {
clearInterval(interval);
setIntervalState(null);
return;
}

setIntervalState(setInterval(toggleVisible, 500));
}

return (
<>
<button onClick={onClick}>{interval == null ? 'Start' : 'Stop'}</button>

<div role="status">{isVisible && 'Notification'}</div>
<div role="alert">{isVisible && 'Alert'}</div>
</>
);
}

function Toggle({
children,
}: {
Expand Down
76 changes: 64 additions & 12 deletions src/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { useAddonState, useChannel } from "@storybook/manager-api";
import React, { useRef } from 'react';
import { useAddonState, useChannel } from '@storybook/manager-api';
import { AddonPanel } from '@storybook/components';
import { STORY_CHANGED } from '@storybook/core-events';
import { styled } from '@storybook/theming';
Expand All @@ -12,6 +12,12 @@ interface Announcement {
politenessSetting: PolitenessSetting;
}

const Wrapper = styled.div`
position: relative;
max-height: 100%;
overflow: auto;
`;

const List = styled.ol`
list-style: none;
margin: 0;
Expand All @@ -23,6 +29,20 @@ const ListItem = styled.li`
margin: 0.5rem 0;
`;

const Button = styled.button`
margin: 0;
padding: 0;
background: transparent;
border: 0;
height: 2rem;
width: 2rem;
cursor: pointer;
position: absolute;
top: 0.5rem;
right: 1rem;
z-index: 2;
`;

const PolitenessLabel = styled.span<Announcement>`
font-weight: 600;
text-transform: uppercase;
Expand All @@ -46,16 +66,48 @@ export const Panel: React.FC<{ active: boolean }> = (props) => {

return (
<AddonPanel {...props}>
<List>
{captures.map((capture, index) => (
<ListItem key={index}>
<PolitenessLabel {...capture}>
[{capture.politenessSetting}]
</PolitenessLabel>{' '}
{capture.textContent}
</ListItem>
))}
</List>
<Button
onClick={() => setCaptures([])}
title="Clear announcements"
aria-label="Clear announcements"
>
<RestartIcon aria-hidden />
</Button>

<Wrapper>
<List>
{captures.map((capture, index) => (
<ListItem
key={index}
ref={(ref) => {
// Automatically scroll to last item
if (ref && index === captures.length - 1) {
ref.scrollIntoView();
}
}}
>
<PolitenessLabel {...capture}>
[{capture.politenessSetting}]
</PolitenessLabel>{' '}
{capture.textContent}
</ListItem>
))}
</List>
</Wrapper>
</AddonPanel>
);
};

// https://akveo.github.io/eva-icons/#/?searchKey=refresh&type=outline
function RestartIcon() {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#029CFD">
<g data-name="Layer 2">
<g data-name="refresh">
<rect width="24" height="24" opacity="0" />
<path d="M20.3 13.43a1 1 0 0 0-1.25.65A7.14 7.14 0 0 1 12.18 19 7.1 7.1 0 0 1 5 12a7.1 7.1 0 0 1 7.18-7 7.26 7.26 0 0 1 4.65 1.67l-2.17-.36a1 1 0 0 0-1.15.83 1 1 0 0 0 .83 1.15l4.24.7h.17a1 1 0 0 0 .34-.06.33.33 0 0 0 .1-.06.78.78 0 0 0 .2-.11l.09-.11c0-.05.09-.09.13-.15s0-.1.05-.14a1.34 1.34 0 0 0 .07-.18l.75-4a1 1 0 0 0-2-.38l-.27 1.45A9.21 9.21 0 0 0 12.18 3 9.1 9.1 0 0 0 3 12a9.1 9.1 0 0 0 9.18 9A9.12 9.12 0 0 0 21 14.68a1 1 0 0 0-.7-1.25z" />
</g>
</g>
</svg>
);
}

0 comments on commit f9a6e86

Please sign in to comment.