Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 3 additions & 8 deletions jobdri/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,11 @@ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-

## Getting Started

First, run the development server:
First, install dependencies and run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
corepack pnpm install
corepack pnpm dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
Expand Down
24 changes: 24 additions & 0 deletions jobdri/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,27 @@
font-family: "Pretendard-Variable", sans-serif;
}
}

:is(
button,
a[href],
summary,
label[for],
[role="button"],
input[type="button"],
input[type="submit"],
input[type="reset"]
):not(:disabled):not([aria-disabled="true"]) {
cursor: pointer !important;
}

:is(
button,
[role="button"],
input[type="button"],
input[type="submit"],
input[type="reset"]
):disabled,
[aria-disabled="true"] {
cursor: not-allowed !important;
}
15 changes: 3 additions & 12 deletions jobdri/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { Metadata } from "next";
import "./globals.css";
import Lnb from "@/components/common/lnb/Lnb";
import PageHeader from "@/components/common/PageHeader";
import AppShell from "@/components/common/AppShell";

export const metadata: Metadata = {
title: "JobDri",
Expand All @@ -15,16 +14,8 @@ export default function RootLayout({
}) {
return (
<html lang="ko" className="h-full antialiased">
<body className="min-h-full flex bg-line-neutral-assistive">
<aside className="h-screen fixed top-0 shrink-0">
<Lnb />
</aside>
<main className="flex-1 min-w-0 flex flex-col content-center max-w-270 h-screen mx-auto py-11 px-10 scroll-auto">
<div>
<PageHeader />
{children}
</div>
</main>
<body className="min-h-full">
<AppShell>{children}</AppShell>
</body>
</html>
);
Expand Down
5 changes: 5 additions & 0 deletions jobdri/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { EmailLoginScreen } from "@/components/login";

export default function LoginPage() {
return <EmailLoginScreen />;
}
16 changes: 14 additions & 2 deletions jobdri/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import IconBox from "@/components/common/icons/IconBox";
import CheckBox from "@/components/common/icons/CheckBox";
import Header from "@/components/common/header/Header";
import { Lnb } from "@/components/common/lnb";
import {
Button,
ButtonCta,
ButtonCtaModal,
IconButton,
IconOnlyButton,
TextButton,
TextOnlyButton,
} from "@/components/common/buttons";
import { Toast, ToastFrame } from "@/components/common/toast";
import { ChipRound, ChipRoundSelected, ChipQnumber } from "@/components/common/chips";
import {
ChipRound,
ChipRoundSelected,
ChipQnumber,
} from "@/components/common/chips";
import ChipMainDemo from "@/components/common/chips/ChipMainDemo";
import ModalLinkInputDemo from "@/components/common/modal/ModalLinkInputDemo";
import { CompleteBadge } from "@/components/common/badges";
Expand Down Expand Up @@ -211,6 +215,14 @@ export default function Home() {
<TextButton size="large" styleType="secondary" iconPosition="left" />
</div>
</Section>
<Section title="Button/TextOnly">
<div className="flex items-center gap-8">
<TextOnlyButton size="small" styleType="primary" />
<TextOnlyButton size="large" styleType="primary" />
<TextOnlyButton size="small" styleType="secondary" />
<TextOnlyButton size="large" styleType="secondary" />
</div>
</Section>
<Section title="IconBox">
<IconBox type="TRASH" />
<IconBox type="HOME_M" />
Expand Down
30 changes: 30 additions & 0 deletions jobdri/components/common/AppShell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"use client";

import type { ReactNode } from "react";
import { usePathname } from "next/navigation";
import Lnb from "@/components/common/lnb/Lnb";
import PageHeader from "@/components/common/PageHeader";

const standaloneRoutes = new Set(["/login"]);

export default function AppShell({ children }: { children: ReactNode }) {
const pathname = usePathname();

if (standaloneRoutes.has(pathname)) {
return <>{children}</>;
}

return (
<div className="flex min-h-screen bg-line-neutral-assistive">
<aside className="fixed top-0 h-screen shrink-0">
<Lnb />
</aside>
<main className="mx-auto flex h-screen max-w-270 flex-1 content-center flex-col overflow-auto px-10 py-11">
<div>
<PageHeader />
{children}
</div>
</main>
</div>
);
}
6 changes: 4 additions & 2 deletions jobdri/components/common/buttons/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const styleTypeStyles: Record<ButtonStyle, string> = {
};

const inactiveStyle =
"bg-fill-disabled text-text-neutral-disabled hover:bg-fill-disabled";
"cursor-not-allowed bg-fill-disabled text-text-neutral-disabled hover:bg-fill-disabled";

const iconColorStyles: Record<ButtonStyle, string> = {
primary: "text-icon-neutral-white",
Expand Down Expand Up @@ -80,7 +80,9 @@ export default function Button({
: "gap-1",
sizeStyles[size],
radiusStyles[size],
isInactive ? inactiveStyle : styleTypeStyles[resolvedStyleType],
isInactive
? inactiveStyle
: clsx("cursor-pointer", styleTypeStyles[resolvedStyleType]),
className,
)}
aria-disabled={isInactive || undefined}
Expand Down
2 changes: 1 addition & 1 deletion jobdri/components/common/buttons/ButtonCtaModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function ModalIconButton({ label, iconType }: Stack3Item) {
return (
<button
type="button"
className="flex h-[46px] w-full items-center justify-center gap-1 self-stretch rounded-cta-s bg-fill-quaternary-assistive p-3 text-btn16-semibold text-text-neutral-description [font-feature-settings:'liga'_off,'clig'_off]"
className="flex h-[46px] w-full cursor-pointer items-center justify-center gap-1 self-stretch rounded-cta-s bg-fill-quaternary-assistive p-3 text-btn16-semibold text-text-neutral-description [font-feature-settings:'liga'_off,'clig'_off]"
>
<Icon
type={iconType}
Expand Down
1 change: 1 addition & 0 deletions jobdri/components/common/buttons/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default function IconButton({
aria-label={direction === "left" ? "이전" : "다음"}
className={clsx(
"flex h-12 w-12 items-center justify-center gap-2.5 rounded-icon-round bg-bg-white p-2.5",
buttonProps.disabled ? "cursor-not-allowed" : "cursor-pointer",
active ? "text-icon-neutral-heavy" : "text-icon-neutral-assistive",
className,
)}
Expand Down
1 change: 1 addition & 0 deletions jobdri/components/common/buttons/IconOnlyButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default function IconOnlyButton({
aria-label="아이콘 버튼"
className={clsx(
"flex h-[30px] w-[30px] items-center justify-center rounded-[10px] p-[3px]",
buttonProps.disabled ? "cursor-not-allowed" : "cursor-pointer",
toneStyles[tone],
className,
)}
Expand Down
1 change: 1 addition & 0 deletions jobdri/components/common/buttons/TextButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default function TextButton({
type={type}
className={clsx(
"inline-flex items-center gap-1 rounded-toast-s [font-feature-settings:'liga'_off,'clig'_off] hover:bg-fill-hover",
buttonProps.disabled ? "cursor-not-allowed" : "cursor-pointer",
isLeftLarge
? "py-1.5 pr-3 pl-2 text-b16-med"
: isRightLarge
Expand Down
56 changes: 56 additions & 0 deletions jobdri/components/common/buttons/TextOnlyButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import type { ButtonHTMLAttributes } from "react";
import clsx from "clsx";

export type TextOnlyButtonSize = "small" | "large";
export type TextOnlyButtonStyle = "primary" | "secondary";

interface TextOnlyButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
label?: string;
size?: TextOnlyButtonSize;
styleType?: TextOnlyButtonStyle;
}

const typographyStyles: Record<
TextOnlyButtonSize,
Record<TextOnlyButtonStyle, string>
> = {
small: {
primary: "text-sub14-med",
secondary: "text-sub14-reg",
},
large: {
primary: "text-b16-med",
secondary: "text-b16-med",
},
};

const colorStyles: Record<TextOnlyButtonStyle, string> = {
primary: "text-text-primary-default hover:text-fill-primary-pressed-default",
secondary:
"text-text-neutral-caption hover:text-fill-tertiary-default-pressed",
};

export default function TextOnlyButton({
label = "전체보기",
size = "small",
styleType = "primary",
className,
type = "button",
...buttonProps
}: TextOnlyButtonProps) {
return (
<button
type={type}
className={clsx(
"inline-flex items-center rounded-toast-s [font-feature-settings:'liga'_off,'clig'_off] transition-colors",
buttonProps.disabled ? "cursor-not-allowed" : "cursor-pointer",
typographyStyles[size][styleType],
colorStyles[styleType],
className,
)}
{...buttonProps}
>
{label}
</button>
);
}
5 changes: 5 additions & 0 deletions jobdri/components/common/buttons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,10 @@ export { default as ButtonCtaModal } from "./ButtonCtaModal";
export { default as IconButton } from "./IconButton";
export { default as IconOnlyButton } from "./IconOnlyButton";
export { default as TextButton } from "./TextButton";
export { default as TextOnlyButton } from "./TextOnlyButton";
export type { ButtonSize, ButtonStyle } from "./Button";
export type { TextButtonSize, TextButtonStyle } from "./TextButton";
export type {
TextOnlyButtonSize,
TextOnlyButtonStyle,
} from "./TextOnlyButton";
52 changes: 33 additions & 19 deletions jobdri/components/common/input/InputMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ interface InputMainProps {
placeholder?: string;
value?: string;
onChange?: (value: string) => void;
inputType?: React.HTMLInputTypeAttribute;
name?: string;
autoComplete?: string;
maxLength?: number;
disabled?: boolean;
hasError?: boolean;
error?: string;
rightContent?: React.ReactNode;
className?: string;
Expand All @@ -24,7 +29,12 @@ export function InputMain({
placeholder,
value: externalValue,
onChange,
inputType,
name,
autoComplete,
maxLength,
disabled = false,
hasError = false,
error,
rightContent,
className,
Expand All @@ -34,6 +44,10 @@ export function InputMain({
const [focused, setFocused] = useState(false);

const value = externalValue ?? internalValue;
const iconType = type === "PASSWORD" ? "PASSWORD" : "PROFILE";
const resolvedInputType =
inputType ?? (type === "PASSWORD" ? "password" : "text");
const isError = hasError || !!error;

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInternalValue(e.target.value);
Expand All @@ -42,30 +56,30 @@ export function InputMain({

return (
<div className={clsx("flex flex-col gap-1.5", className)}>
<span className="text-label14-semibold text-text-neutral-title">
{label}
{required && <span className="text-text-system-fail ml-0.5">•</span>}
</span>
{label && (
<span className="text-label14-semibold text-text-neutral-title">
{label}
{required && <span className="text-text-system-fail ml-0.5">•</span>}
</span>
)}

<div className={getWrapperClass(focused, disabled, !!error)}>
<div className={getWrapperClass(focused, disabled, isError)}>
<div className={clsx("flex items-center gap-2")}>
{!focused &&
!value &&
(disabled && type === "PASSWORD" ? (
<Icon
type="PASSWORD"
className="text-icon-neutral-assistive shrink-0"
/>
) : (
<Icon
type="PROFILE"
className="text-icon-neutral-assistive shrink-0"
/>
))}
{!focused && !value && (
<Icon
type={iconType}
className="text-icon-neutral-assistive shrink-0"
/>
)}
<input
type={resolvedInputType}
name={name}
autoComplete={autoComplete}
maxLength={maxLength}
className={clsx(
getFieldClass(disabled),
"flex-1 min-w-0 text-sub14-reg",
type === "PASSWORD" && value && "text-[60px] tracking-[3px]",
)}
placeholder={placeholder}
value={value}
Expand All @@ -78,7 +92,7 @@ export function InputMain({
<div
className={clsx(
"shrink-0 text-cap12-med",
error ? "text-text-system-fail" : "text-text-neutral-caption",
isError ? "text-text-system-fail" : "text-text-neutral-caption",
)}
>
{rightContent}
Expand Down
Loading