Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ef5df9b
feat: 워크스페이스 UI 구현
jjjsun Feb 23, 2026
06b1981
feat: 워크스페이스 생성 모달 UI 구현
jjjsun Feb 24, 2026
5bbf869
Merge remote-tracking branch 'origin/develop' into feature/#50
jjjsun Feb 24, 2026
84dd193
chore: 버튼 최신화진행, 버튼관련 스타일 재조정
jjjsun Feb 24, 2026
0a7e81a
fix: workspaceSetting 라우팅 경로 수정
jjjsun Feb 24, 2026
8933449
fix: 미사용 setting 라우팅 삭제
jjjsun Feb 24, 2026
afbb49a
fix: 코드래빗 수정사항 반영
jjjsun Feb 24, 2026
2276339
fix: 잘못사용한 괄호 수정
jjjsun Feb 24, 2026
dc78595
fix: 워크스페이스 생성할때 url 삭제
jjjsun Feb 24, 2026
02e63ff
chore: dropdownMenu에 아이콘 추가
jjjsun Feb 24, 2026
6d4d764
feat: textarea 컴포넌트로 수정
jjjsun Feb 24, 2026
12f4ba3
fix: 워크스페이스 생성 드롭존을 선택했을시에도 업로드되도록 수정
jjjsun Feb 24, 2026
131ae55
fix: 워크스페이스 생성 모달 타이틀 중복 제거
jjjsun Feb 24, 2026
b67589f
chore: 로고이미지 없을경우 기본 비즈니스빌딩이미지 추가
jjjsun Feb 24, 2026
c019783
fix: 반응형 적용
jjjsun Feb 24, 2026
97e4c35
fix: 코드래빗 수정사항 반영
jjjsun Feb 24, 2026
894b348
fix: build 오류사항 수정
jjjsun Feb 24, 2026
a3bb044
fix: 코드래빗 수정사항반영
jjjsun Feb 24, 2026
0c2b005
fix: 드랍다운 메뉴 cursor-pointer 추가,아이콘 hover 색상 및 기본 컬러 수정
jjjsun Feb 25, 2026
4c69cbf
style: 조직 검색 input 기본 ring 스타일 및 hover/focus 상태 개선
jjjsun Feb 25, 2026
9433b52
fix: 코드래빗 수정사항 반영
jjjsun Feb 25, 2026
09fff8c
fix: build 에러 처리(logoFile 아직 사용전이라 난 에러, 실제사용으로 일단 처리해둠)
jjjsun Feb 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/assets/icon/workspace/Vector.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icon/workspace/building.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icon/workspace/edit-contained.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icon/workspace/message-circle-warning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/icon/workspace/plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/icon/workspace/search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icon/workspace/uploadImg.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icon/workspace/userProfile.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icon/workspace/warning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/components/common/button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export default function Button({
{leftIcon}
</span>
)}
<span>{children}</span>
{children}
</button>
);
}
30 changes: 23 additions & 7 deletions src/components/common/dropdownmenu/DropdownMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from "react";
import React, { useEffect, useId, useRef, useState } from "react";
import { twMerge } from "tailwind-merge";

export type TMenuItem = {
Expand All @@ -12,13 +12,16 @@ export function DropdownMenu({
trigger,
items,
className,
"aria-label": ariaLabel,
}: {
trigger: React.ReactNode;
items: TMenuItem[];
className?: string;
"aria-label"?: string;
}) {
const [open, setOpen] = useState(false);
const ref = useRef<HTMLDivElement | null>(null);
const menuId = useId();

useEffect(() => {
const onDocClick = (e: MouseEvent) => {
Expand All @@ -38,7 +41,8 @@ export function DropdownMenu({
tabIndex={0}
aria-haspopup="menu"
aria-expanded={open}
aria-controls="dropdown-menu"
aria-controls={menuId}
aria-label={ariaLabel}
onClick={() => setOpen((v) => !v)}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
Expand All @@ -51,9 +55,9 @@ export function DropdownMenu({
</div>
{open && (
<div
id="dropdown-menu"
id={menuId}
role="menu"
className="absolute left-0 mt-2 w-72 rounding-15 bg-brand-200 py-3 px-1 shadow-Medium"
className="absolute right-0 mt-2 w-56 max-w-[calc(100vw-40px)] rounding-15 bg-brand-200 py-3 px-1 shadow-Medium z-50"
>
<div className="space-y-1">
{items.map((it, idx) => (
Expand All @@ -66,13 +70,25 @@ export function DropdownMenu({
setOpen(false);
}}
className={twMerge(
"flex w-full items-center gap-3 rounding-15 px-5 py-4 text-left font-body1 transition-fast",
"group flex w-full items-center gap-3 rounding-15 px-5 py-4 text-left font-body1 transition-fast",
it.active
? "bg-brand-300 text-status-blue"
: "text-text-main hover:bg-brand-300",
: "text-text-main hover:bg-brand-300 hover:text-status-blue",
)}
>
{it.icon}
{it.icon ? (
<span
className={twMerge(
"inline-flex h-5 w-5 items-center justify-center text-text-main",
it.active
? "text-status-blue"
: "group-hover:text-status-blue",
)}
aria-hidden="true"
>
{it.icon}
</span>
) : null}
<span
className={twMerge(
"whitespace-nowrap",
Expand Down
15 changes: 6 additions & 9 deletions src/components/common/input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,34 +39,31 @@ const Input = forwardRef<HTMLInputElement, IInputProps>(

return (
<div
className={twMerge(
"flex flex-col w-full gap-2 relative",
wrapperClassName,
)}
className={twMerge("flex flex-col w-full relative", wrapperClassName)}
>
{label && (
<label
htmlFor={inputId}
className="font-label text-brand-900 select-none ml-1 mb-2"
className="text-text-main select-none ml-1 mb-1"
>
{label}
</label>
)}
<div
className={twMerge(
"flex items-center w-full h-input bg-gray-50 border-transparent rounded-component-lg transition-smooth overflow-hidden",
"flex items-center w-full h-input bg-white ring-1 ring-logo-1/30 rounded-component-md transition-colors duration-200 ease-out overflow-hidden",
error
? "ring-2 ring-status-red bg-status-red/5"
: success
? "ring-2 ring-logo-1 bg-white"
: "hover:bg-gray-100 focus-within:bg-white focus-within:ring-2 focus-within:ring-logo-1/30",
? "rubg-2 ring-status-green bg-status-green/5"
: "hover:bg-gray-100 hover:ring-logo-1/40 focus-within:bg-white focus-within:ring-2 focus-within:ring-logo-1/50",
containerClassName,
)}
>
<input
ref={ref}
className={twMerge(
"flex-1 h-full w-full bg-transparent border-none outline-none text-body1 text-brand-900 placeholder:text-text-placeholder px-5",
"flex-1 h-full w-full bg-transparent border-none outline-none text-body1 text-text-main placeholder:text-text-placeholder px-5",
"disabled:bg-gray-100 disabled:cursor-not-allowed disabled:text-text-disabled",
rightElement ? "pr-2" : "",
inputClassName,
Expand Down
55 changes: 55 additions & 0 deletions src/components/common/textarea/TextareaField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import type React from "react";
import { useLayoutEffect, useRef } from "react";
import { twMerge } from "tailwind-merge";

type TProps = {
id: string;
label: string;
value: string;
placeholder?: string;
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
className?: string;
minRows?: number;
};

export default function TextareaField({
id,
label,
value,
placeholder,
onChange,
className,
minRows = 4,
}: TProps) {
const ref = useRef<HTMLTextAreaElement | null>(null);
const resize = () => {
const el = ref.current;
if (!el) return;
el.style.height = "auto";
el.style.height = `${el.scrollHeight}px`;
};
useLayoutEffect(() => {
resize();
}, [value]);

return (
<div className="flex flex-col">
<label className="text-text-main select-none ml-1" htmlFor={id}>
{label}
</label>
<textarea
ref={ref}
id={id}
rows={minRows}
value={value}
className={twMerge(
"w-full resize-none overflow-hidden rounded-component-md bg-gray-50 px-5 py-4 outline-none transition-smooth hover:bg-gray-100 focus:bg-white focus:ring-2 focus:ring-logo-1/30 text-body1 text-text-main placeholder:text-text-placeholder",
className,
)}
placeholder={placeholder}
onChange={onChange}
onInput={resize}
/>
</div>
);
}
56 changes: 56 additions & 0 deletions src/components/workspace/WorkspaceCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import type { TWorkspace } from "@/types/workspace/workspace";

import {
DropdownMenu,
type TMenuItem,
} from "@/components/common/dropdownmenu/DropdownMenu";

import BuildingIcon from "@/assets/icon/workspace/building.svg?react";
import VectorIcon from "@/assets/icon/workspace/Vector.svg?react";

type TProps = {
workspace: TWorkspace;
menuItems: TMenuItem[];
};

export default function WorkspaceCard({ workspace: w, menuItems }: TProps) {
return (
<li className="flex items-center justify-between rounded-component-md bg-white px-6 py-5 shadow-sm border border-gray-100">
<div className="flex items-center gap-5 min-w-0">
<div className="w-20 h-20 bg-gray-100 shrink-0 rounded-component-sm">
{/* TODO: 스타일 확인을 위해 bg-gray-100넣어둠. API연동할때 삭제예정 */}
{w.logoUrl ? (
<img
src={w.logoUrl}
alt={`${w.name} 로고`}
className="w-full h-full object-cover rounded-component-sm"
/>
) : (
<div className="w-full h-full flex items-center justify-center">
<BuildingIcon className="w-12 h-12" />
</div>
)}
</div>

<div className="min-w-0">
<div className="font-heading3 text-text-main truncate">{w.name}</div>
<div className="font-body1 text-text-main mt-1 truncate">
{w.description ?? ""}
</div>
<div className="font-body1 text-text-sub mt-2">
{w.myRole ?? "내 직책 및 역할"}
</div>
</div>
</div>

<div className="flex items-center gap-4 shrink-0">
<DropdownMenu
trigger={<VectorIcon aria-hidden="true" />}
aria-label={`${w.name} 워크스페이스 메뉴`}
className="h-10 w-10 cursor-pointer rounded-xl hover:bg-gray-100 transition-colors flex items-center justify-center"
items={menuItems}
/>
</div>
</li>
);
}
6 changes: 4 additions & 2 deletions src/layout/main/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import Sidebar from "@/components/Sidebar/Sidebar";

export default function MainLayout() {
return (
<div className="flex h-screen p-5 bg-gray-50">
<div className="flex h-screen p-3 bg-gray-50 sm:p-5">
<Sidebar />
<main className="flex-1 overflow-auto">
<Outlet />
<div className="mx-auto w-full max-w-[1600px] py-6 px-4 sm:px-6 lg:px-20">
<Outlet />
</div>
</main>
</div>
);
Expand Down
Loading