All files / lib/components/Inventory/Tag index.tsx

100% Statements 21/21
92.85% Branches 13/14
100% Functions 7/7
100% Lines 18/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80          2x                       1x       23x   23x   23x     60x       23x 23x   14x 13x           1x   1x         23x 23x   14x         23x                     23x                   2x  
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import { css } from '@emotion/react';
import React from 'react';
 
export const TAG_ONCLICK_TEST_ID = 'tag-onclick-component';
 
interface TagProps {
  name: string;
  color: string;
  size?: 'small' | 'medium';
  isSelected?: boolean;
  onClick?: () => void;
}
 
// RGB를 받아서 밝기를 계산하는 함수
function getBrightness(r: number, g: number, b: number): number {
  return (r * 299 + g * 587 + b * 114) / 1000;
}
 
export function Tag(props: TagProps) {
  const { name, color, size, isSelected, onClick } = props;
 
  const rgbColor = React.useMemo(
    () =>
      color
        ?.substring(1)
        .split(/(?=(?:..)*$)/)
        .map((n) => parseInt(n, 16)),
    [color]
  );
 
  const tagTextColor = React.useMemo(() => {
    if (!rgbColor) return css``;
 
    if (!isSelected) {
      return css`
        color: rgb(${rgbColor[0]}, ${rgbColor[1]}, ${rgbColor[2]});
      `;
    }
 
    // 밝기에 따라 텍스트 색상 결정
    const brightness = getBrightness(rgbColor[0], rgbColor[1], rgbColor[2]);
 
    return css`
      color: ${brightness > 127 ? 'black' : 'white'};
    `;
  }, [rgbColor, isSelected]);
 
  const tagBackgroundColor = React.useMemo(() => {
    if (!rgbColor) return css``;
 
    return css`
      background: rgba(${rgbColor[0]}, ${rgbColor[1]}, ${rgbColor[2]}, ${isSelected ? 1 : 0.1});
    `;
  }, [rgbColor, isSelected]);
 
  return (
    <div
      css={[tag({ size }), tagTextColor, tagBackgroundColor, isSelected && selectedTag]}
      onClick={onClick}
      data-testid={TAG_ONCLICK_TEST_ID}
    >
      {name}
    </div>
  );
}
 
const tag = (props: { size: 'small' | 'medium' | undefined }) => css`
  display: flex;
  padding: 0 12px;
  height: 30px;
  justify-content: center;
  align-items: center;
  border-radius: 15px;
  font-size: ${props.size === 'small' ? '12px' : '15px'};
`;
 
const selectedTag = css``;