();
+
+ return (
+
+ setSelectedId(value as string)}
+ />
+
+ );
+ },
+};
diff --git a/src/components/Dropdown/DropdownV3.tsx b/src/components/Dropdown/DropdownV3.tsx
new file mode 100644
index 0000000..33734ec
--- /dev/null
+++ b/src/components/Dropdown/DropdownV3.tsx
@@ -0,0 +1,227 @@
+import React, { useState, useEffect, useRef } from 'react';
+import classNames from 'classnames';
+import { styled } from '@mui/material/styles';
+import Box from '@mui/material/Box';
+import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
+import KeyboardArrowUp from '@mui/icons-material/KeyboardArrowUp';
+import { Popper as MuIPopper } from '@mui/material';
+import { DropDownItem, DropDownProps } from './Dropdown.type';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import Icon from '../Icon/Icon';
+import CheckSvg from '../../assets/image/svg/check.svg';
+
+const Root = styled(Box)(({ theme }) => ({
+ fontFamily: '"Noto Sans TC", "Noto Sans"',
+ fontSize: '0.875rem',
+ lineHeight: 1.5,
+ minWidth: 220,
+ height: 40,
+ userSelect: 'none',
+ cursor: 'pointer',
+ display: 'flex',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ color: theme.color.secondary.$80,
+ backgroundColor: '#FFF',
+ padding: '8px 0px 8px 16px',
+ borderRadius: 4,
+ // Ellipsis for selected text
+ '.Dropdown-selected-text': {
+ overflow: 'hidden',
+ whiteSpace: 'nowrap',
+ textOverflow: 'ellipsis',
+ flex: 1,
+ minWidth: 0,
+ marginRight: 8,
+ display: 'block',
+ fontFamily: '"Noto Sans TC", "Noto Sans"',
+ fontSize: '0.875rem',
+ lineHeight: 1.5,
+ },
+ '&.dark': {
+ color: 'white',
+ backgroundColor: 'rgba(0, 0 ,0, 0.2)',
+ },
+ '&.Dropdown-empty': {
+ color: theme.color.secondary.$60,
+ '&.dark': {
+ color: theme.color.secondary.$80,
+ },
+ },
+ '&.Dropdown--disabled': {
+ opacity: 0.3,
+ pointerEvents: 'none',
+ },
+}));
+
+const List = styled(Box)(({ theme }) => ({
+ backgroundColor: '#FFF',
+ margin: '8px auto',
+ borderRadius: 4,
+ boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.1)',
+ '&.dark': {
+ color: 'white',
+ backgroundColor: theme.color.secondary.$100,
+ },
+}));
+
+const Popper = styled(MuIPopper)(({ theme }) => ({
+ maxHeight: '200px',
+ overflow: 'auto',
+}));
+
+const Item = styled(Box, { label: 'Dropdown-item' })(({ theme }) => ({
+ fontFamily: '"Noto Sans TC", "Noto Sans"',
+ fontSize: '0.875rem',
+ lineHeight: 1.5,
+ cursor: 'pointer',
+ display: 'flex',
+ alignItems: 'center',
+
+ width: '100%', // Ensure item fills parent width
+ '&:hover': {
+ backgroundColor: 'rgba(0, 0, 0, .05)',
+ },
+
+ '.Dropdown-icon': {
+ width: 24,
+ minWidth: 24,
+ maxWidth: 24,
+ flexShrink: 0,
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginRight: 8,
+ },
+ '.Dropdown-item-text': {
+ overflow: 'hidden',
+ whiteSpace: 'nowrap',
+ textOverflow: 'ellipsis',
+ flex: 1,
+ minWidth: 0,
+ width: '100%', // Ensure text fills available space
+ fontFamily: '"Noto Sans TC", "Noto Sans"',
+ fontSize: '0.875rem',
+ lineHeight: 1.5,
+ },
+}));
+
+const DropdownV3: React.FC = (props) => {
+ const {
+ list,
+ itemProps,
+ placeholder,
+ selectedId,
+ disabled,
+ onSelect,
+ popperProps,
+ selectionId,
+ mode = 'light',
+ ...otherProps
+ } = props;
+ const selectRef = useRef(null);
+ const [selectedItem, setSelectedItem] = useState(null);
+ const [isOpen, setIsOpen] = useState(false);
+
+ useEffect(() => {
+ if (selectedId && selectedId !== selectedItem?.id) {
+ for (let i = 0; i < list.length; i++) {
+ if (selectedId === list[i].id) {
+ setSelectedItem(list[i]);
+ break;
+ }
+ }
+ } else if (selectedId === undefined) {
+ setSelectedItem(null);
+ }
+ }, [selectedId]);
+
+ useEffect(() => {
+ for (let i = 0; i < list.length; i++) {
+ if (selectedId === list[i].id) {
+ setSelectedItem(list[i]);
+ break;
+ }
+ }
+ }, [list]);
+
+ const handleOnClickSelect = () => {
+ setIsOpen(true);
+ };
+
+ const handleOnClickAway = () => {
+ setIsOpen(false);
+ };
+
+ const handleOnClick = (item: DropDownItem) => {
+ setIsOpen(false);
+ onSelect(item.value, item);
+ };
+
+ const items = list
+ .filter((item) => item.id !== selectionId)
+ .map((item) => (
+ - handleOnClick(item)}
+ {...itemProps}
+ >
+
+ {selectedItem?.id === item.id &&
}
+
+ {item.name}
+
+ ));
+
+ return (
+ <>
+
+
+ {selectedItem?.name ?? placeholder}
+
+
+ {isOpen ? : }
+
+
+
+
+
+ {items}
+
+
+
+ >
+ );
+};
+
+export default DropdownV3;
diff --git a/src/components/Tooltip/Tooltip.stories.tsx b/src/components/Tooltip/Tooltip.stories.tsx
new file mode 100644
index 0000000..fadd6eb
--- /dev/null
+++ b/src/components/Tooltip/Tooltip.stories.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { Meta, StoryObj } from '@storybook/react';
+import TooltipIcon from './TooltipIcon';
+
+const meta: Meta = {
+ title: 'Components/TooltipIcon',
+ component: TooltipIcon,
+};
+
+export default meta;
+
+type Story = StoryObj;
+export const Default: Story = {
+ render: () => (
+
+ ),
+};
diff --git a/src/components/Tooltip/TooltipIcon.tsx b/src/components/Tooltip/TooltipIcon.tsx
new file mode 100644
index 0000000..3a2cdc0
--- /dev/null
+++ b/src/components/Tooltip/TooltipIcon.tsx
@@ -0,0 +1,50 @@
+import React from 'react';
+import Tooltip from '@mui/material/Tooltip';
+import InfoCircleSolidSvgIcon from '../../assets/SvgIcon/InfoCircleSolidSvgIcon';
+import { styled } from '@mui/material';
+
+const ContainerTooltip = styled('div')({
+ display: 'flex',
+ alignItems: 'center',
+ gap: '4px',
+ fontFamily: '"Noto Sans TC", "Noto Sans"',
+ fontSize: '0.875rem',
+ lineHeight: 1.5,
+});
+
+const IconWrapper = styled('span')({
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: '100%',
+});
+
+const TooltipIcon = ({ title, text }: { title: string; text: string }) => {
+ return (
+
+ {text}
+ ({
+ '& .MuiTooltip-tooltip': {
+ color: '#fff',
+ backgroundColor: theme.externalColor?.secondary?.$140 || '#333',
+ borderRadius: '4px',
+ boxShadow: '0px 2px 2px rgba(0, 0, 0, 0.1)',
+ maxWidth: '250px',
+ padding: '10px',
+ },
+ }),
+ }}
+ >
+
+
+
+
+
+ );
+};
+
+export default TooltipIcon;