diff --git a/package.json b/package.json
index 8c1eeddb..61c3cd24 100644
--- a/package.json
+++ b/package.json
@@ -1,61 +1,61 @@
{
- "name": "client",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "tsc -b && vite build",
- "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
- "preview": "vite preview",
- "stylelint": "stylelint './src/**/*.{ts,tsx}' --fix",
- "svgr": "npx @svgr/cli -d src/assets/svg --ignore-existing --typescript --no-dimensions public/svg",
- "storybook": "storybook dev -p 6006",
- "build-storybook": "storybook build"
- },
- "dependencies": {
- "@emotion/react": "^11.11.4",
- "@emotion/styled": "^11.11.5",
- "@svgr/cli": "^8.1.0",
- "react": "^18.3.1",
- "react-dom": "^18.3.1",
- "react-router-dom": "^6.24.1",
- "vite-plugin-svgr": "^4.2.0"
- },
- "devDependencies": {
- "@chromatic-com/storybook": "^1.6.1",
- "@storybook/addon-essentials": "^8.1.11",
- "@storybook/addon-interactions": "^8.1.11",
- "@storybook/addon-links": "^8.1.11",
- "@storybook/addon-onboarding": "^8.1.11",
- "@storybook/blocks": "^8.1.11",
- "@storybook/react": "^8.1.11",
- "@storybook/react-vite": "^8.1.11",
- "@storybook/test": "^8.1.11",
- "@types/react": "^18.3.3",
- "@types/react-dom": "^18.3.0",
- "@typescript-eslint/eslint-plugin": "^7.13.1",
- "@typescript-eslint/parser": "^7.13.1",
- "@vitejs/plugin-react": "^4.3.1",
- "eslint": "^8.57.0",
- "eslint-config-airbnb": "^19.0.4",
- "eslint-config-airbnb-typescript": "^18.0.0",
- "eslint-config-prettier": "^9.1.0",
- "eslint-plugin-import": "^2.25.3",
- "eslint-plugin-jsx-a11y": "^6.5.1",
- "eslint-plugin-prettier": "^5.1.3",
- "eslint-plugin-react": "^7.28.0",
- "eslint-plugin-react-hooks": "^4.6.2",
- "eslint-plugin-react-refresh": "^0.4.7",
- "eslint-plugin-storybook": "^0.8.0",
- "postcss": "^8.4.21",
- "postcss-styled-syntax": "^0.6.4",
- "prettier": "^3.3.2",
- "storybook": "^8.1.11",
- "stylelint": "^16.6.1",
- "stylelint-config-standard": "^36.0.1",
- "stylelint-order": "^6.0.4",
- "typescript": "^5.2.2",
- "vite": "^5.3.1"
- }
+ "name": "client",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview",
+ "stylelint": "stylelint './src/**/*.{ts,tsx}' --fix",
+ "svgr": "npx @svgr/cli -d src/assets/svg --ignore-existing --typescript --no-dimensions public/svg",
+ "storybook": "storybook dev -p 6006",
+ "build-storybook": "storybook build"
+ },
+ "dependencies": {
+ "@emotion/react": "^11.11.4",
+ "@emotion/styled": "^11.11.5",
+ "@svgr/cli": "^8.1.0",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "react-router-dom": "^6.24.1",
+ "vite-plugin-svgr": "^4.2.0"
+ },
+ "devDependencies": {
+ "@chromatic-com/storybook": "^1.6.1",
+ "@storybook/addon-essentials": "^8.1.11",
+ "@storybook/addon-interactions": "^8.1.11",
+ "@storybook/addon-links": "^8.1.11",
+ "@storybook/addon-onboarding": "^8.1.11",
+ "@storybook/blocks": "^8.1.11",
+ "@storybook/react": "^8.1.11",
+ "@storybook/react-vite": "^8.1.11",
+ "@storybook/test": "^8.1.11",
+ "@types/react": "^18.3.3",
+ "@types/react-dom": "^18.3.0",
+ "@typescript-eslint/eslint-plugin": "^7.13.1",
+ "@typescript-eslint/parser": "^7.13.1",
+ "@vitejs/plugin-react": "^4.3.1",
+ "eslint": "^8.57.0",
+ "eslint-config-airbnb": "^19.0.4",
+ "eslint-config-airbnb-typescript": "^18.0.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-import": "^2.25.3",
+ "eslint-plugin-jsx-a11y": "^6.5.1",
+ "eslint-plugin-prettier": "^5.1.3",
+ "eslint-plugin-react": "^7.28.0",
+ "eslint-plugin-react-hooks": "^4.6.2",
+ "eslint-plugin-react-refresh": "^0.4.7",
+ "eslint-plugin-storybook": "^0.8.0",
+ "postcss": "^8.4.21",
+ "postcss-styled-syntax": "^0.6.4",
+ "prettier": "^3.3.2",
+ "storybook": "^8.1.11",
+ "stylelint": "^16.6.1",
+ "stylelint-config-standard": "^36.0.1",
+ "stylelint-order": "^6.0.4",
+ "typescript": "^5.2.2",
+ "vite": "^5.3.1"
+ }
}
diff --git a/src/assets/svg/calendar-minus-01.svg b/src/assets/svg/calendar-minus-01.svg
new file mode 100644
index 00000000..83d2b236
--- /dev/null
+++ b/src/assets/svg/calendar-minus-01.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/svg/clock.svg b/src/assets/svg/clock.svg
new file mode 100644
index 00000000..58dfc083
--- /dev/null
+++ b/src/assets/svg/clock.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/svg/index.ts b/src/assets/svg/index.ts
index 1e23873a..85e6a7e4 100644
--- a/src/assets/svg/index.ts
+++ b/src/assets/svg/index.ts
@@ -1,13 +1,21 @@
import Icn_arrow_narrow_right from '@/assets/svg/arrow-narrow-right.svg?react';
+import Icn_calander from '@/assets/svg/calendar-minus-01.svg?react';
+import Icn_date_clock from '@/assets/svg/clock.svg?react';
import Icn_clock from '@/assets/svg/icn_clock.svg?react';
import Icn_nav_calendar from '@/assets/svg/icn_nav_calendar.svg?react';
import Icn_nav_dashboard from '@/assets/svg/icn_nav_dashboard.svg?react';
import Icn_nav_setting from '@/assets/svg/icn_nav_setting.svg?react';
import Icn_nav_today from '@/assets/svg/icn_nav_today.svg?react';
+import Icn_line from '@/assets/svg/line164.svg?react';
+import IcnXCricle from '@/assets/svg/x-circle.svg?react';
const Icons = {
Icn_clock,
Icn_arrow_narrow_right,
+ Icn_calander,
+ Icn_date_clock,
+ Icn_line,
+ IcnXCricle,
Navbar: {
Icn_nav_calendar,
Icn_nav_dashboard,
diff --git a/src/assets/svg/line164.svg b/src/assets/svg/line164.svg
new file mode 100644
index 00000000..6dafb3d3
--- /dev/null
+++ b/src/assets/svg/line164.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/svg/x-circle.svg b/src/assets/svg/x-circle.svg
new file mode 100644
index 00000000..417c9860
--- /dev/null
+++ b/src/assets/svg/x-circle.svg
@@ -0,0 +1,10 @@
+
diff --git a/src/components/common/BtnDate/BtnDate.tsx b/src/components/common/BtnDate/BtnDate.tsx
new file mode 100644
index 00000000..e6fba4ce
--- /dev/null
+++ b/src/components/common/BtnDate/BtnDate.tsx
@@ -0,0 +1,145 @@
+import { css } from '@emotion/react';
+import styled from '@emotion/styled';
+import { useState } from 'react';
+
+import BtnDateText, { TextWrapper } from './BtnDateText';
+
+import Icons from '@/assets/svg/index';
+
+interface BtnDateProps {
+ date?: string;
+ time?: string;
+ size?: string;
+}
+
+function BtnDate(props: BtnDateProps) {
+ const { date = '마감 기한', time = '마감 시간', size = 'big' } = props;
+ const [isPressed, setIsPressed] = useState(false);
+ const [isClicked, setIsClicked] = useState(false);
+
+ const handleMouseDown = () => {
+ setIsPressed(true);
+ };
+
+ const handleMouseUp = () => {
+ setIsPressed(false);
+ setIsClicked((prev) => !prev);
+ };
+
+ const isDefaultDate = date === '마감 기한';
+ const isDefaultTime = time === '마감 시간';
+
+ return (
+
+ } text={date} isDefault={isDefaultDate} size={size} />
+
+ } text={time} isDefault={isDefaultTime} size={size} />
+
+
+ );
+}
+
+export default BtnDate;
+
+const XIcon = styled((props: React.SVGProps & { isClicked: boolean }) => {
+ const { isClicked, ...rest } = props;
+ return ;
+})<{ isClicked: boolean }>`
+ display: ${({ isClicked }) => (isClicked ? 'flex' : 'none')};
+ width: 2rem;
+ height: 2rem;
+`;
+
+const CalanderIcon = styled(Icons.Icn_calander, { target: 'CalanderIcon' })`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 1.4rem;
+ height: 1.4rem;
+`;
+
+const ClockIcon = styled(Icons.Icn_date_clock, { target: 'ClockIcon' })`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 1.4rem;
+ height: 1.4rem;
+`;
+
+const LineIcon = styled(Icons.Icn_line, { target: 'LineIcon' })<{ size: string }>`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 0.1rem;
+ height: ${({ size }) => (size === 'big' ? '2.2rem' : '1.2rem')};
+`;
+
+const BtnDateLayout = styled.div<{
+ isPressed: boolean;
+ isClicked: boolean;
+ size: string;
+ isDefaultDate: boolean;
+ isDefaultTime: boolean;
+}>`
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+ width: fit-content;
+ min-width: 1.8rem;
+ padding: 0.5rem 1rem;
+
+ background: ${({ theme }) => theme.palette.white};
+ cursor: pointer;
+ border: 1px solid ${({ theme }) => theme.palette.grey3};
+ border-color: ${({ isClicked, theme }) => (isClicked ? theme.palette.primary : theme.palette.grey3)};
+ border-radius: 8px;
+
+ ${({ isClicked, size, theme }) =>
+ isClicked &&
+ css`
+ padding-right: ${size === 'big' ? '0.6rem' : '0.2rem'};
+
+ border-color: ${theme.palette.primary};
+ border-width: 2px;
+ `}
+
+ ${({ isPressed, theme }) =>
+ isPressed &&
+ css`
+ border-width: 0;
+
+ ${TextWrapper} {
+ color: ${theme.palette.white};
+ }
+ `}
+
+ &:hover {
+ color: ${({ isPressed, theme }) => (isPressed ? theme.palette.white : theme.palette.grey6)};
+
+ background: ${({ isPressed, theme }) => (isPressed ? theme.palette.grey5 : theme.palette.grey4)};
+ border-width: 0;
+
+ ${TextWrapper} {
+ color: ${({ isDefaultDate, isDefaultTime, theme }) =>
+ isDefaultDate || isDefaultTime ? theme.palette.grey6 : theme.palette.black};
+ }
+ }
+
+ &:hover ${CalanderIcon}, &:hover ${ClockIcon}, &:hover ${LineIcon} {
+ path {
+ stroke: ${({ isPressed, theme }) => (isPressed ? theme.palette.grey4 : theme.palette.grey5)};
+ }
+
+ line {
+ stroke: ${({ isPressed, theme }) => (isPressed ? theme.palette.grey4 : theme.palette.grey5)};
+ }
+ }
+`;
diff --git a/src/components/common/BtnDate/BtnDateText.tsx b/src/components/common/BtnDate/BtnDateText.tsx
new file mode 100644
index 00000000..fb2c215d
--- /dev/null
+++ b/src/components/common/BtnDate/BtnDateText.tsx
@@ -0,0 +1,38 @@
+import styled from '@emotion/styled';
+
+interface BtnDateTextProps {
+ icon: React.ReactNode;
+ text: string;
+ isDefault: boolean;
+ size: string;
+}
+
+function BtnDateText(props: BtnDateTextProps) {
+ const { icon, text, isDefault, size } = props;
+ return (
+
+ {icon}
+
+ {text}
+
+
+ );
+}
+
+export default BtnDateText;
+
+export const TextWrapper = styled('div', { target: 'TextWrapper' })<{ isDefault: boolean; size: string }>`
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ align-items: flex-start;
+
+ color: ${({ isDefault, theme }) => (isDefault ? theme.palette.grey5 : theme.palette.black)};
+ font-size: ${({ size }) => (size === 'big' ? '1.4rem' : '1.2rem')};
+`;
+
+const BtnDateContainer = styled.div`
+ display: flex;
+ gap: 0.4rem;
+ align-items: center;
+`;
diff --git a/src/components/common/BtnDate/BtnStagingDate.tsx b/src/components/common/BtnDate/BtnStagingDate.tsx
new file mode 100644
index 00000000..38f8fbdd
--- /dev/null
+++ b/src/components/common/BtnDate/BtnStagingDate.tsx
@@ -0,0 +1,47 @@
+import styled from '@emotion/styled';
+
+function BtnStagingDate() {
+ return (
+
+ ⇥ 마감 기한 설정
+
+ );
+}
+
+export default BtnStagingDate;
+
+const BtnStagingDateText = styled('p', { target: 'BtnStagingDateText' })`
+ color: ${({ theme }) => theme.palette.grey5};
+ font-size: 1.2rem;
+ text-align: center;
+`;
+
+const BtnStagingDateLayout = styled('div', { target: 'BtnStagingDateLayout' })`
+ display: flex;
+ gap: 0.8rem;
+ align-items: center;
+ justify-content: center;
+ width: fit-content;
+ height: 2.2rem;
+ padding: 0.3rem 1.2rem;
+
+ background: ${({ theme }) => theme.palette.grey3};
+ cursor: pointer;
+ border-radius: 8px;
+
+ &:hover {
+ background: ${({ theme }) => theme.palette.grey4};
+
+ ${BtnStagingDateText} {
+ color: ${({ theme }) => theme.palette.grey6};
+ }
+ }
+
+ &:active {
+ background: ${({ theme }) => theme.palette.grey5};
+
+ ${BtnStagingDateText} {
+ color: ${({ theme }) => theme.palette.white};
+ }
+ }
+`;
diff --git a/src/pages/Today.tsx b/src/pages/Today.tsx
index c72b5f25..101c7bad 100644
--- a/src/pages/Today.tsx
+++ b/src/pages/Today.tsx
@@ -1,3 +1,5 @@
+import BtnDate from '@/components/common/BtnDate/BtnDate';
+import BtnStagingDate from '@/components/common/BtnDate/BtnStagingDate';
import NavBar from '@/components/common/NavBar';
import TextboxDailydate from '@/components/common/textbox/TextboxDailydate';
import TextboxInput from '@/components/common/textbox/TextboxInput';
@@ -23,6 +25,8 @@ function Today() {
+
+
);
}
diff --git a/src/styles/theme.ts b/src/styles/theme.ts
index c6dbc4d7..f1aa3199 100644
--- a/src/styles/theme.ts
+++ b/src/styles/theme.ts
@@ -29,6 +29,15 @@ const palette = {
GREY_04: '#626273',
GREY_05: '#464656',
GREY_06: '#34343C',
+
+ // 지원 임시색상
+ grey3: '#E9E9EE',
+ grey4: '#C6C6D0',
+ grey5: '#9090A0',
+ grey6: '#626273',
+ black: '#212121',
+ primary: '#3876F6',
+ white: '#FFFFFF',
};
const fonts = {