WangShuXian6 / blog

FE-BLOG
https://wangshuxian6.github.io/blog/
MIT License
46 stars 10 forks source link

React Examples / React Components 组件 #121

Open WangShuXian6 opened 3 years ago

WangShuXian6 commented 3 years ago

React Examples

WangShuXian6 commented 3 years ago

Drag

https://developer.mozilla.org/zh-CN/docs/Web/API/Document/drag_event

基本拖动

import React, {
  useState,
  useMemo,
  useEffect,
  useRef,
  useCallback,
  DragEvent,
} from "react";
import logo from "./logo.svg";
import styles from "./App.module.css";

function App() {
  const onDragStart = (e: DragEvent<HTMLDivElement>) => {
    console.log("onDragStart:", e.target);
  };
  const onDragEnd = (e: DragEvent<HTMLDivElement>) => {
    console.log("onDragEnd:", e.target);
  };
  const onDrop = (e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    console.log("onDrop:", e.target);
  };
  const onDragOver = (e: DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    //console.log("onDragOver:", e.target);
  };
  return (
    <>
      <div className={styles.wrapper}>
        <div className={styles.left}>
          <div
            // 可拖动模块
            onDragStart={onDragStart}
            onDragEnd={onDragEnd}
            draggable="true"
            className={styles.item}
          ></div>
        </div>
        <div onDrop={onDrop} onDragOver={onDragOver} className={styles.right}>
          {/* 拖动目标区域 */}
          <div className={styles.item}></div>
        </div>
      </div>
    </>
  );
}

export default App;
WangShuXian6 commented 2 weeks ago

可变色 SVG React 组件

注意,如果同级有绝对定位的元素,必须在父级设置svg为固定定位。否则svf将被隐藏。


interface Props {
  bActive?: boolean
  fill: string
}

export const Accessibility = ({ bActive, fill }: Props) => {
  return (
    <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
      <g>
        <path
          id="icon-1"
          d="M13.0847 1.125C10.9933 1.125 9.29215 2.82397 9.29215 4.91751C9.29215 7.00888 10.7906 8.71001 12.882 8.71001C14.9712 8.71001 16.875 7.00888 16.875 4.91966C16.875 2.82613 15.176 1.125 13.0847 1.125ZM13.0847 7.39266C11.7199 7.39266 10.6073 6.28229 10.6073 4.91751C10.6073 3.55272 11.7199 2.43804 13.0847 2.43804C14.4494 2.43804 15.562 3.55056 15.562 4.91535C15.5598 6.28013 14.4473 7.39266 13.0847 7.39266ZM6.8364 1.32767H2.59112C1.78044 1.32767 1.125 1.98311 1.125 2.79379V7.03907C1.125 7.84974 1.78044 8.50518 2.59112 8.50518H6.8364C7.64707 8.50518 8.30252 7.84974 8.30252 7.03907V2.79163C8.30252 1.98527 7.64707 1.32767 6.8364 1.32767ZM6.98732 7.03907C6.98732 7.12315 6.91833 7.18999 6.8364 7.18999H2.59112C2.50703 7.18999 2.4402 7.121 2.4402 7.03907V2.79163C2.4402 2.70755 2.50919 2.64071 2.59112 2.64071H6.8364C6.92048 2.64071 6.98732 2.7097 6.98732 2.79163V7.03907ZM6.8364 9.69748H2.59112C1.78044 9.69748 1.125 10.3529 1.125 11.1636V15.4089C1.125 16.2196 1.78044 16.875 2.59112 16.875H6.8364C7.64707 16.875 8.30252 16.2196 8.30252 15.4089V11.1658C8.30252 10.3551 7.64707 9.69748 6.8364 9.69748ZM6.98732 15.411C6.98732 15.4951 6.91833 15.562 6.8364 15.562H2.59112C2.50703 15.562 2.4402 15.493 2.4402 15.411V11.1658C2.4402 11.0817 2.50919 11.0148 2.59112 11.0148H6.8364C6.92048 11.0148 6.98732 11.0838 6.98732 11.1658V15.411ZM15.2084 9.69748H10.9609C10.1503 9.69748 9.49481 10.3529 9.49481 11.1636V15.4089C9.49481 16.2196 10.1503 16.875 10.9609 16.875H15.2062C16.0169 16.875 16.6723 16.2196 16.6723 15.4089V11.1658C16.6723 10.3551 16.0169 9.69748 15.2084 9.69748ZM15.2084 15.562H10.9609C10.8768 15.562 10.81 15.493 10.81 15.411V11.1658C10.81 11.0817 10.879 11.0148 10.9609 11.0148H15.2062C15.2903 11.0148 15.3571 11.0838 15.3571 11.1658V15.411H15.3593C15.3593 15.4951 15.2903 15.562 15.2084 15.562Z"
          fill={bActive ? fill : '#666'}
        />
      </g>
    </svg>
  )
}
WangShuXian6 commented 2 weeks ago

Tabs 组件

image


import React, { useState } from 'react'
import clsx from 'clsx'
import styles from './index.module.less'

import ActiveBackground from './assets/tab-active-bg.png'
import DisableBackground from './assets/tab-disable-bg.png'

interface Tab {
  icon?: React.ReactNode
  iconDisable?: React.ReactNode
  label: string
  key: string
  content: React.ReactNode
}

interface TabsProps {
  tabs: Tab[]
  onTabChange?: (key: string) => void
  defaultActiveKey?: string
}

export const FTabs: React.FC<TabsProps> = ({ tabs, onTabChange, defaultActiveKey }) => {
  const [activeKey, setActiveKey] = useState(defaultActiveKey || tabs[0]?.key)

  const handleTabClick = (key: string) => {
    setActiveKey(key)
    if (onTabChange) {
      onTabChange(key)
    }
  }

  return (
    <div className={styles.tabsWrapper}>
      <div className={styles.tabList}>
        {tabs.map((tab) => (
          <div
            key={tab.key}
            className={clsx(styles.tabItem, {
              [styles.activeTab]: tab.key === activeKey
            })}
            onClick={() => handleTabClick(tab.key)}
          >
            <img
              src={tab.key === activeKey ? ActiveBackground : DisableBackground}
              alt="bg"
              className={styles.background}
            />
            {/* {tab.icon && <img src={tab.icon} alt="icon" className={styles.icon} />} */}
            {tab.key === activeKey ? tab.icon : tab.iconDisable}
            {tab.label && <span className={styles.label}>{tab.label}</span>}
          </div>
        ))}
      </div>
      <div className={styles.tabContent}>
        {tabs.map((tab) => (
          <div key={tab.key} style={{ display: tab.key === activeKey ? 'block' : 'none' }}>
            {tab.content}
          </div>
        ))}
      </div>
    </div>
  )
}
.tabsWrapper {
  display: flex;
  flex-direction: column;
  //width: calc(100% + 14px);
  //overflow: hidden;
}

.tabList {
  display: flex;
  //border-bottom: 1px solid #e8e8e8;
  //background-color: #f5f5f5;
  //padding: 8px 16px;
  //width: calc(100% + 14px);
}

.tabItem {
  z-index: 1;
  position: relative;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  padding: 8px 16px;
  cursor: pointer;
  transition: color 0.3s, background-color 0.3s;
  color: #555;
  margin-right: 8px;

  width: calc(164px - 28px);
  height: 56px;
  flex-shrink: 0;
  & > .background {
    position: absolute;
    top: 0;
    left: 0;
    width: 164px;
    height: 100%;
    flex-shrink: 0;
  }

  svg {
    position: relative;
    margin-right: 8px;
  }
  & > .icon {
    position: relative;
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    margin-right: 8px;

    filter: grayscale(100%);
    opacity: 0.5;
  }
  & > .label {
    position: relative;
    color: #5e5e5e;
    text-align: center;

    /* Body/Large */
    font-family: 'PingFang SC';
    font-size: 16px;
    font-style: normal;
    font-weight: 400;
    line-height: 24px; /* 150% */
  }
}

.tabItem:hover {
  color: #1890ff;
}

.tabItem.activeTab {
  z-index: 5;
  font-weight: bold;
  color: #1890ff;
  //border-bottom: 2px solid #1890ff;
  & > .icon {
    filter: none;
    opacity: 1;
  }
  & > .label {
    color: var(--main-color, #75287f);
    text-align: center;

    /* Title/Medium */
    font-family: 'PingFang SC';
    font-size: 16px;
    font-style: normal;
    font-weight: 600;
    line-height: 24px; /* 150% */
  }
}

.tabContent {
  z-index: 4;
  //padding: 16px;
  //background-color: #ffffff;
  //border: 1px solid #e8e8e8;
  //border-top: none;
  box-sizing: border-box;
  background-color: #fff;
  transform: translateY(-2px);
  //width: 632px;
}

tab-active-bg tab-disable-bg

使用


const ExamplePage3 = () => {
  const mainColor = useCSSVariable('--main-color')

  const tabs = [
    {
      label: '诊断模版',
      key: 'diagnosis_template',
      content: <div className={styles['content-wrapper']}>诊断模版</div>,
      icon: <DiagnosticTemplates bActive={true} fill={mainColor} />,
      iconDisable: <DiagnosticTemplates bActive={false} fill={mainColor} />
    },
    {
      label: '到检队列',
      key: 'arrival_queue',
      content: <div className={styles['content-wrapper']}>到检队列</div>,
      icon: <CheckInQueue bActive={true} fill={mainColor} />,
      iconDisable: <CheckInQueue bActive={false} fill={mainColor} />
    },
    {
      label: '辅助功能',
      key: 'auxiliary',
      content: <div className={styles['content-wrapper']}>辅助功能</div>,
      icon: <Accessibility bActive={true} fill={mainColor} />,
      iconDisable: <Accessibility bActive={false} fill={mainColor} />
    }
  ]

  const handleTabChange = (key: string) => {
    console.log('Active Tab:', key)
  }

  return (
    <div className={styles['wrapper']}>

        <FTabs tabs={tabs} onTabChange={handleTabChange} defaultActiveKey="diagnosis_template" />

    </div>
  )
}

export default ExamplePage3