Рубрики
Без рубрики

Строительство красочных, пружинные компоненты с использованием реактивной пружины и крошечного

Недавно я решил построить веб-приложение, чтобы позволить дизайнерам и разработчикам генерировать варианты для цветов и проверять доступность цвета. В этом посте я хотел бы дать вам прохождение того, как я построил некоторые компоненты, которые я бы использовал в этом приложении. Полный источник

Недавно я решил построить Веб-приложение Разрешить дизайнерам и разработчикам генерировать варианты для цветов и проверить доступность цвета. В этом посте я хотел бы дать вам прохождение того, как я построил некоторые компоненты, которые я бы использовал в этом приложении.

Полный исходный код для приложения можно найти в конце этой статьи, а также ссылку на экземпляр с рассказами со всеми описанными компонентами.

Зависимости

Чтобы помочь мне построить эти компоненты, которые я использовал Tinycolor. , библиотека с диапазоном цветных полезных функций, которые вы можете использовать для манипулирования, преобразования и представляют собой цвета.

Я также использовал Реагировать весна , которая представляет собой библиотеку на основе пружинной физики, которая позволяет вам действительно легко добавлять анимацию в ваш проект.

Цветовая плитка

Самый простой компонент из нашего списка, цветная плитка будет служить строительным блоком для других компонентов. Ответственность этого компонента – отображение цвета наряду с его именем и шестнадцатеричным значением.

const TILE_SIZES = {
  sm: "2.5rem",
  md: "4rem",
  lg: "6rem"
};

const ColorTile = ({
  color,
  name,
  hideName,
  hideHex,
  size,
  className,
  customTileStyle,
  ...otherProps
}) => {
  const containerClass = cx(styles.container, className);

  const tileClass = cx(styles.tile, {
    "margin-bottom--xxs": !hideName || !hideHex
  });
  const dimension = TILE_SIZES[size];
  const tileStyle = {
    "--color-tile-width": dimension,
    "--color-tile-height": dimension,
    "--color-tile-bg": color,
    "--color-tile-border-color": "transparent",
    ...customTileStyle
  };
  const tile = 
; const nameClass = cx("text--colors-grey-lighten-30", { "margin-bottom--xxs": !hideHex }); const hex = useMemo(() => tinycolor(color).toHexString(), [color]); return (
{tile} {!hideName && {name}} {!hideHex && ( {hex} )}
); }; ColorTile.propTypes = { /** * Color to display */ color: PropTypes.string.isRequired, /** * Name of the color */ name: PropTypes.string, /** * Hide the name text if true */ hideName: PropTypes.bool, /** * Hide the hex color value display if true */ hideHex: PropTypes.bool, /** * Size of the tile */ size: PropTypes.oneOf(["sm", "md", "lg"]), /** * Custom styles to apply to the tile element */ customTileStyle: PropTypes.object }; ColorTile.defaultProps = { size: "md", hideName: true, hideHex: true, customTileStyle: {} };

Примечания по реализации

  1. Линия 17, а линия 19 может выглядеть немного странно, если вы не знакомы с отличным классы библиотека. В основном, библиотека классов позволяет объединять и условно применить классы CSS к вашим элементам.
  2. В строке 36 вы можете видеть, что мы рассчитаем шестигранную строку цвета, передаваемой. Поскольку мы используем цветное отверстие, переданное непосредственно в CSS, он может быть в любом приемлемом цветовом формате CSS, а не только Hex. Это может быть строка RGBA, например. Вот где приходит крон. Мы можем дать ему какие-либо из этих форматов, и он возвращает красиво отформатированную шестигранную строку, которую мы можем отображать вместе с нашей плиткой.
  3. Прилипая с линией 36, вы также можете заметить, что функция для расчета шестигранной строки завернута в Usememo. . Это потому, что мы хотим только вычислить это значение, если цвет изменения цвета. Мы можем избежать пересчета, если какое-либо из других изменений реквизитов, что может вызвать рерандер. Я все еще изучаю новые крючки API, так что это может быть не самое подходящее использование Угемер Поскольку это, вероятно, не особенно дорогая операция, но я думаю, что это был хороший способ справиться с ним независимо. Вы можете узнать больше о Угемер Функция или крючки в целом здесь Отказ
.tile {
  width: var(--color-tile-width);
  height: var(--color-tile-height);
  background-color: var(--color-tile-bg);
  border: 3px solid var(--color-tile-border-color);
  cursor: pointer;
}

.container {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
}

Заметки о стиле

Стайлинг нашей плитки действительно прост. У нас сама плитка, которая принимает свои размеры и цвет из переменных, в которых мы проходим.

Затем у нас есть контейнер, который удерживает плитку, имя цвета и шестнадцатеричное значение. Это простой гибкий контейнер, который поддерживает наши элементы.

Цветовой сборник

Для нашего сборщика цвета мы собираемся повторно использовать компонент цветного плитка, а также с помощью React-Color упаковка.

import React, { useState } from "react";
import PropTypes from "prop-types";
import { ChromePicker } from "react-color";

import ColorTile from "../ColorTile/ColorTile";

import styles from "./ColorPicker.module.scss";

const ColorPicker = ({ color, onChange, className, tileClassName }) => {
  const [isPickerOpen, setPickerOpen] = useState(false);

  const onSwatchClick = () => {
    setPickerOpen(!isPickerOpen);
  };

  const onColorChange = color => {
    onChange(color.hex);
  };

  return (
    
{isPickerOpen && (
)}
); }; ColorPicker.propTypes = { /** * Currently selected color value */ color: PropTypes.string, /** * Callback fn for when the color changes */ onChange: PropTypes.func, /** * Custom classes to apply to the color tile */ tileClassName: PropTypes.string }; ColorPicker.defaultProps = { onChange: () => {} }; export default ColorPicker;

Примечания по реализации

Наш сборщик цвета состоит из Colortile который показывает текущий выбранный цвет, наряду с его шестнадцатеричным значением и A ChromePicker от React-Color Библиотека, которая на самом деле позволяет вам выбрать цвет.

У нас есть какое-то состояние, которое контролирует ли ChromePicker Видно или нет, и функция обратного вызова, чтобы позволить какому компоненту использовать наш сборщик, знал, когда цвет изменяется. React-Color Обеспечивает много информации, когда цвет изменяется, но значение шестнадцатеричное значение было достаточно для моих целей, как вы можете видеть на линии 17.

Цветной список

Компонент нашего списка цветов принимает список цветов и отображает их как список, содержащий цветные плитки. Наш цветной список предназначен для отображения базового цвета как слегка большую плитку, при этом оставшиеся плитки, представляющие варианты основания, показанные в более мелкие плитки. Мы также разрешаем назвать наш список, и это будет использоваться для отображения имени базового цвета.

Наш цветной список также приносит «Спринг» часть этого прохождения. Плитка будет анимирована на входе, используя React Prience?

const ROW_DIRECTION = "row";
const COL_DIRECTION = "col";
const ALL_DIRECTIONS = [ROW_DIRECTION, COL_DIRECTION];

/**
 * Renders a list of colors
 */
const ColorPaletteList = ({
  name,
  colors,
  direction,
  onColorClick,
  onColorDoubleClick,
  animationRef,
  getCustomTileStyle,
  renderTileBy,
  ...otherProps
}) => {
  const headingClass = cx("margin-bottom--xs", {
    "text--align-left": direction === ROW_DIRECTION,
    "text--align-center": direction === COL_DIRECTION
  });

  const containerClass = cx({
    [styles.containerCol]: direction === COL_DIRECTION,
    [styles.containerRow]: direction === ROW_DIRECTION
  });

  const tileClass = cx({
    "margin-bottom--xs": direction === COL_DIRECTION,
    "margin-right--xs": direction === ROW_DIRECTION
  });

  const trailMargin =
    direction === COL_DIRECTION ? "marginBottom" : "marginRight";
  const trails = useTrail(colors.length, {
    from: { [trailMargin]: 20, opacity: 0 },
    to: { [trailMargin]: 0, opacity: 1 },
    ref: animationRef
  });

  return (
    

{name || ""}

{trails.map((trailProps, idx) => { const color = colors[idx]; const onClick = () => onColorClick(color); return ( {renderTileBy(color, tileClass, onClick, false, false)} ); })}
); }; ColorPaletteList.propTypes = { /** * Name of the list */ name: PropTypes.string, /** * The list of colors to display */ colors: PropTypes.arrayOf( PropTypes.shape({ color: PropTypes.string, name: PropTypes.string, isMain: PropTypes.bool }) ).isRequired, /** * Determines the layout of the tiles */ direction: PropTypes.oneOf(ALL_DIRECTIONS), /** * Callback for when a color in the list is clicked */ onColorClick: PropTypes.func, /** * Ref used to hook into the animation */ animationRef: PropTypes.object, /** * Pass custom styles for a particular color tile */ getCustomTileStyle: PropTypes.func, /** * Render prop to render the color tile */ renderTileBy: PropTypes.func }; ColorPaletteList.defaultProps = { direction: COL_DIRECTION, onColorClick: () => {}, onColorDoubleClick: () => {}, getCustomTileStyle: () => ({}), renderTileBy: (color, className, onClick, hideName, hideHex) => ( ) };

Примечания по реализации

  1. По линии 34-40 вы можете увидеть нашу реакцию React Spring, используя поручитель . Вы можете узнать больше о Trails здесь Отказ Мы анимировали маржа на цветовом контейнере для плитки и в зависимости от того, является ли список столбцом выровнен или выровнен строкой, это может быть маржа справа или снизу.
  2. В строке 39 вы можете видеть, что мы проходим нашу анимацию. Это так, чтобы мы могли пройти ссылку на наш цветной список, чтобы задержать анимацию. Это было бы полезно, мы хотели вызвать определенную последовательность анимации из родительского компонента.
.containerCol {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.containerRow {
  display: flex;
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
}

Цветная пара

Компонент Color Pair принимает два цвета и отображает их рядом с какой-либо информацией о доступности. Идея состоит в том, что разработчик или дизайнер соединят цвета, чтобы обеспечить работу вместе при использовании в качестве фона/комбинации переднего плана.

const AccessiblePair = ({
  background,
  foreground,
  hideCloseBtn,
  onCloseBtnClick,
  closeBtnIcon,
  ...otherProps
}) => {
  const title = `${background.name}/${foreground.name}`;

  const bgTileStyle = {
    "--tile-color": background.color
  };

  const fgTileStyle = {
    "--tile-color": foreground.color
  };

  const tileContainerClass = cx(styles.tileContainer, "margin-right--sm");
  const titleContainerClass = cx(
    styles.titleContainer,
    "margin-bottom--xxs",
    "text--colors-grey-lighten-30"
  );

  const isAAPass = tinycolor.isReadable(background.color, foreground.color, {
    level: "AA",
    size: "small"
  });
  const isAAAPass = tinycolor.isReadable(background.color, foreground.color, {
    level: "AAA",
    size: "small"
  });

  const aaDisplayText = "WCAG AA";
  const aaaDisplayText = "WCAG AAA";
  const aaPillType = isAAPass ? "success" : "error";
  const aaaPillType = isAAAPass ? "success" : "error";

  const examplePillStyle = {
    "--pill-background": background.color,
    "--pill-color": foreground.color
  };

  return (
    
{title} {!hideCloseBtn && ( )}
{aaDisplayText} {aaaDisplayText} This is how text will look
); }; AccessiblePair.propTypes = { /** * The background color */ background: colorShape.isRequired, /** * The foreground color */ foreground: colorShape.isRequired, /** * Set to true to hide the close button */ hideCloseBtn: PropTypes.bool, /** * Callback for when the close button is clicked */ onCloseBtnClick: PropTypes.func, /** * FontAwesome icon to use for the close button */ closeBtnIcon: PropTypes.string }; AccessiblePair.defaultProps = { hideCloseBtn: false, onCloseBtnClick: () => {}, closeBtnIcon: "times" };

Примечания по реализации

Как уже упоминалось, наша цветная парная компонент имеет фоновый и цвет переднего плана, а на линии 26-33 вы можете видеть, где мы используем Tinycolor, чтобы определить доступность цветовой пары.

Мы используем простой компонент таблеток для отображения результата с типом таблетки, определяемого результатом. Я не показал источник для таблетки здесь, но это довольно стандартный компонент, который вы найдете в любой библиотеке компонентов (Bootstrap, материал и т. Д.).

Вы можете узнать больше о доступности и WCAG здесь Отказ

Заключение и исходный код

Я надеюсь, что вы узнали что-то из этого прохождения. Я настоятельно рекомендую смотреть в библиотеки, которые я упоминал здесь, в вашем следующем проекте. В частности, мое приложение сделало бы намного дольше, чтобы создать без превосходного пакета Tinycolor.

Если у вас есть какие-либо отзывы о проектах, коде или в целом, я хотел бы услышать это.

Большое спасибо за чтение моей статьи!

Изначально опубликовано здесь .

Оригинал: “https://www.freecodecamp.org/news/building-colorful-springy-components-using-react-spring-and-tinycolor/”