From e087e0353e89f0ad49aaf23fdcaee2f9249e5a64 Mon Sep 17 00:00:00 2001 From: Vlad Furman Date: Fri, 19 Jul 2024 17:27:27 +0300 Subject: [PATCH] fix: api refactoring --- src/components/Reactions/README.md | 58 +++++++-------- src/components/Reactions/Reaction.tsx | 13 ++-- src/components/Reactions/Reactions.tsx | 70 ++++++++++--------- .../__stories__/Reactions.stories.tsx | 21 +++++- .../Reactions/__tests__/Reactions.test.tsx | 11 --- .../Reactions/__tests__/mock/mockHooks.tsx | 16 ++--- src/components/Reactions/context.ts | 4 +- src/components/Reactions/hooks.ts | 4 +- 8 files changed, 104 insertions(+), 93 deletions(-) diff --git a/src/components/Reactions/README.md b/src/components/Reactions/README.md index ad5d410..dd2c7e7 100644 --- a/src/components/Reactions/README.md +++ b/src/components/Reactions/README.md @@ -8,7 +8,7 @@ Component for user reactions (e.g. 👍, 😊, 😎 etc) as new GitHub comments import React from 'react'; import {PaletteOption} from '@gravity-ui/uikit'; -import {ReactionProps, Reactions} from '@gravity-ui/components'; +import {ReactionStateProps, Reactions} from '@gravity-ui/components'; const user = { spongeBob: {name: 'Sponge Bob'}, @@ -30,11 +30,11 @@ const YourComponent = () => { [option.cool.value]: [user.spongeBob], }); - // And then convert that mapping into an array of ReactionProps + // And then convert that mapping into an array of ReactionStateProps const reactions = React.useMemo( () => Object.entries(usersReacted).map( - ([value, users]): ReactionProps => ({ + ([value, users]): ReactionStateProps => ({ value, counter: users.length, selected: users.some(({name}) => name === currentUser.name), @@ -44,8 +44,8 @@ const YourComponent = () => { ); // You can then handle clicking on a reaction with changing the inital mapping, - // and the array of ReactionProps will change accordingly - const onClickReaction = React.useCallback( + // and the array of ReactionStateProps will change accordingly + const onToggle = React.useCallback( (value: string) => { if (!usersReacted[value]) { // If the reaction is not present yet @@ -75,7 +75,7 @@ const YourComponent = () => { ); return ( - + ); }; ``` @@ -86,29 +86,23 @@ For more code examples go to [Reactions.stories.tsx](https://github.com/gravity- **ReactionsProps** (main component props — Reactions' list): -| Property | Type | Required | Default | Description | -| :---------------- | :------------------------ | :------: | :------ | :--------------------------------------------------------------------------------------------- | -| `reactions` | `ReactionProps[]` | `true` | | List of Reactions to display | -| `palette` | `ReactionsPaletteProps` | `true` | | Notifications' palette props — it's a `Palette` component with available reactions to the user | -| `onClickReaction` | `(value: string) => void` | | | Fires when a user clicks on a Reaction (in a Palette or in the Reactions' list) | -| `size` | `ButtonSize` | | `m` | Buttons's size | -| `disabled` | `boolean` | | `false` | If the buttons' are disabled | -| `qa` | `string` | | | `qa` attribute for testing | -| `className` | `string` | | | HTML class attribute | -| `style` | `React.CSSProperties` | | | HTML style attribute | - -**ReactionProps** (single reaction props) extends `Palette`'s `PaletteOption` `disabled` and `value` props: - -| Property | Type | Required | Default | Description | -| :--------- | :--------------------- | :------: | :------ | :------------------------------------------------------------ | -| `selected` | `boolean` | | | Is reaction selected by the user | -| `counter` | `React.ReactNode` | | | How many users used this reaction | -| `tooltip` | `ReactionTooltipProps` | | | Reaction's tooltip with the list of reacted users for example | - -**ReactionTooltipProps** — notification's type extends `Pick`: - -| Property | Type | Required | Default | Description | -| :-------------- | :---------------- | :------: | :------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `content` | `React.ReactNode` | `true` | | Tooltip's content | -| `className` | `string` | | | Tooltip content's HTML class attribute | -| `canClosePopup` | `() => boolean` | | | Fires when the `onMouseLeave` callback is called. Usage example: you have some popup inside a tooltip, you hover on it, you don't want the tooltip to be closed because of that. | +| Property | Type | Required | Default | Description | +| :--------------- | :------------------------ | :------: | :------ | :--------------------------------------------------------------------------------------------- | +| `reactions` | `PaletteOption[]` | `true` | | List of all available reactions | +| `reactionsState` | `ReactionStateProps[]` | `true` | | List of reactions that were used | +| `paletteProps` | `ReactionsPaletteProps` | `true` | | Notifications' palette props — it's a `Palette` component with available reactions to the user | +| `onToggle` | `(value: string) => void` | | | Fires when a user clicks on a Reaction (in a Palette or in the Reactions' list) | +| `size` | `ButtonSize` | | `m` | Buttons's size | +| `readOnly` | `boolean` | | `false` | readOnly state (usage example: only signed in users can react) | +| `qa` | `string` | | | `qa` attribute for testing | +| `className` | `string` | | | HTML class attribute | +| `style` | `React.CSSProperties` | | | HTML style attribute | + +**ReactionStateProps** (single reaction props): + +| Property | Type | Required | Default | Description | +| :--------- | :---------------- | :------: | :------ | :------------------------------------------------------------ | +| `value` | `string` | | | Reaction's unique value (ID) | +| `selected` | `boolean` | | | Is reaction selected by the user | +| `counter` | `React.ReactNode` | | | How many users used this reaction | +| `tooltip` | `React.ReactNode` | | | Reaction's tooltip with the list of reacted users for example | diff --git a/src/components/Reactions/Reaction.tsx b/src/components/Reactions/Reaction.tsx index b8fb789..96a01ca 100644 --- a/src/components/Reactions/Reaction.tsx +++ b/src/components/Reactions/Reaction.tsx @@ -7,7 +7,13 @@ import {block} from '../utils/cn'; import {useReactionsContext} from './context'; import {useReactionsPopup} from './hooks'; -export interface ReactionProps extends Pick { +export type ReactionProps = Pick; + +export interface ReactionStateProps { + /** + * Reaction's unique value (ID). + */ + value: string; /** * Should be true when the user used this reaction. */ @@ -25,7 +31,7 @@ export interface ReactionProps extends Pick } interface ReactionInnerProps extends Pick { - reaction: ReactionProps; + reaction: ReactionStateProps; size: ButtonSize; onClick?: (value: string) => void; } @@ -42,7 +48,7 @@ const popupDefaultPlacement: PopoverProps['placement'] = [ const b = block('reactions'); export function Reaction(props: ReactionInnerProps) { - const {value, disabled, selected, counter, tooltip} = props.reaction; + const {value, selected, counter, tooltip} = props.reaction; const {size, content, onClick} = props; const onClickCallback = React.useCallback(() => onClick?.(value), [onClick, value]); @@ -55,7 +61,6 @@ export function Reaction(props: ReactionInnerProps) {