😺

【React(Typescript)】ドロップダウンUIの実装例

2023/07/28に公開

作るもの

スクリーンショット 2023-07-28 19.23.10.png
スクリーンショット 2023-07-28 19.23.21.png

実装例

  • Reactの雛形をTypescriptで作成。
terminal
npx create-react-app dropdown --template typescript
  • DropdownList.tsxと、DropdownList.cssをsrc配下に作成する。
DropdownList.tsx
import React, { useState } from 'react';
import './DropdownList.css';

interface Option {
  value: string;
  label: string;
}

const DropdownList: React.FC = () => {
  const [selectedOption, setSelectedOption] = useState<Option | null>(null);
  const [isArrowActive, setArrowActive] = useState(false);

  const options: Option[] = [
    { value: 'option1', label: 'Option 1' },
    { value: 'option2', label: 'Option 2' },
    { value: 'option3', label: 'Option 3' },
  ];

  const handleSelectOption = (event: React.ChangeEvent<HTMLSelectElement>) => {
    const selectedValue = event.target.value;
    const selected = options.find((option) => option.value === selectedValue);
    setSelectedOption(selected || null);
  };

  const arrowClassName = `select-arrow ${isArrowActive ? 'active' : ''}`;

  return (
    <div className="container">
      <h2>ドロップダウンリスト</h2>
      <div className="select-container">
        <select
          value={selectedOption?.value || ''}
          onChange={handleSelectOption}
          onFocus={() => setArrowActive(true)}
          onBlur={() => setArrowActive(false)}
        >
          <option value="">選択してください</option>
          {options.map((option) => (
            <option key={option.value} value={option.value}>
              {option.label}
            </option>
          ))}
        </select>
        <div className={arrowClassName}></div>
      </div>
      {selectedOption && <p>選択されたオプション: {selectedOption.label}</p>}
    </div>
  );
};

export default DropdownList;

DropdownList.css
.container {
  max-width: 300px;
  margin: 0 auto;
  padding: 20px;
  border: 1px solid #ccc;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  background-color: #f9f9f9;
}

h2 {
  margin-bottom: 16px;
  font-size: 24px;
  color: #333;
}

.select-container {
  position: relative;
}

.select-arrow {
  position: absolute;
  top: 50%;
  right: 8px;
  transform: translateY(-50%);
  width: 10px;
  height: 10px;
  border-left: 2px solid #777;
  border-bottom: 2px solid #777;
  transition: transform 0.2s ease-in-out;
  pointer-events: none;
}

.select-arrow.active {
  transform: translateY(-50%) rotate(45deg);
}

select {
  width: 100%;
  padding: 12px;
  border: 2px solid #777;
  border-radius: 8px;
  appearance: none;
  font-size: 16px;
  background-color: #f9f9f9;
  color: #333;
  font-weight: bold;
}

select:focus {
  outline: none;
  border-color: #007bff;
  box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.3);
}

option {
  background-color: #f9f9f9;
}

p {
  margin-top: 12px;
  font-size: 14px;
  color: #777;
}
  • App.tsxで作成したコンポーネントを読み込ませる。
App.tsx
import React from 'react';
import DropdownList from './DropdownList';

const App: React.FC = () => {
  return (
    <div>
      <DropdownList /> {/* DropdownListコンポーネントをここで使用 */}
    </div>
  );
};

export default App;
  • サーバーを起動する。
npm start
  • URLにアクセスすると以下の画面が表示される。
    スクリーンショット 2023-07-28 19.34.38.png

Discussion