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
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
"@stackflow/plugin-renderer-basic": "^1.1.13",
"@stackflow/react": "^1.5.2",
"@tailwindcss/vite": "^4.1.7",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"jotai": "^2.12.4",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-hook-form": "^7.56.4",
"tailwind-merge": "^3.3.0",
"tailwindcss": "^4.1.7"
},
"devDependencies": {
Expand Down
40 changes: 40 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 32 additions & 2 deletions src/app/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,26 @@
--color-grad1: #5ba5f8;
--color-grad2: #7c81ff;

--text-3xl: 32px;
--text-4xl: 32px;
--text-3xl: 28px;
--text-2xl: 24px;

--text-xl: 20px;

--text-lg: 18px;
--text-md: 16px;
--text-sm: 14px;

--spacing-normal: 20px;
--spacing-normal-half: 10px;

--radius-lg: 20px;
--radius-md: 12px;
}

@font-face {
font-family: 'Fredoka';
src: url('../assets/font/fredoka-variable.ttf') format('truetype');
font-weight: 600;
}

:root {
Expand All @@ -47,6 +57,18 @@
color: #111;
}

/* Chrome, Safari, Edge, Opera */
input[type='number']::-webkit-outer-spin-button,
input[type='number']::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}

/* Firefox */
input[type='number'] {
-moz-appearance: textfield;
}

@layer utilities {
.container-mobile {
max-width: 402px;
Expand All @@ -61,4 +83,12 @@
-ms-overflow-style: none;
scrollbar-width: none;
}

.logo {
font-family: Fredoka;
}

.shadow-login {
box-shadow: 0px 4px 20px 0px rgba(55, 127, 248, 0.04);
}
}
1 change: 1 addition & 0 deletions src/app/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './global.css';
import '@stackflow/plugin-basic-ui/index.css';
import App from './App';

createRoot(document.getElementById('root')!).render(
Expand Down
14 changes: 7 additions & 7 deletions src/app/stackflow/Stack.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { basicUIPlugin } from "@stackflow/plugin-basic-ui";
import { basicRendererPlugin } from "@stackflow/plugin-renderer-basic";
import { stackflow } from "@stackflow/react";
import { HomeScreen } from "../../screen/home/ui";
import { basicUIPlugin } from '@stackflow/plugin-basic-ui';
import { basicRendererPlugin } from '@stackflow/plugin-renderer-basic';
import { stackflow } from '@stackflow/react';
import { LoginScreen } from '@/screen/login/ui';

export const { Stack, useFlow } = stackflow({
transitionDuration: 350,
activities: { HomeScreen },
activities: { LoginScreen },
plugins: [
basicRendererPlugin(),
basicUIPlugin({
theme: "cupertino",
theme: 'cupertino',
}),
],
initialActivity: () => "HomeScreen",
initialActivity: () => 'LoginScreen',
});
Binary file added src/assets/font/fredoka-variable.ttf
Binary file not shown.
Binary file added src/assets/image/bg-login.png
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/image/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import LoginBg from './bg-login.png';

export { LoginBg };
23 changes: 23 additions & 0 deletions src/features/login/ui/LoginForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Button, Input } from '@/shared/ui';

export default function LoginForm() {
return (
<form className="flex w-full flex-col gap-y-15">
<div className="flex w-full flex-col gap-[10px]">
<Input
intent="login"
placeholder="학번 8자리"
className="no-spinner"
type="number"
/>
<Input placeholder="패스워드" intent="login" type="password" />
</div>
<div className="flex w-full flex-col gap-3">
<Button>학생으로 로그인</Button>
<Button intent="textmain" size="fit">
관리자로 로그인
</Button>
</div>
</form>
);
}
1 change: 1 addition & 0 deletions src/features/login/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as LoginForm } from './LoginForm';
5 changes: 0 additions & 5 deletions src/screen/home/ui/HomeScreen.tsx

This file was deleted.

1 change: 0 additions & 1 deletion src/screen/home/ui/index.ts

This file was deleted.

17 changes: 17 additions & 0 deletions src/screen/login/ui/LoginScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { AppScreen } from '@stackflow/plugin-basic-ui';

import { LoginBg } from '@/assets/image';
import { BasicAppBar } from '@/shared/ui';
import { LoginContainer } from '@/widgets/login/ui';

export default function LoginScreen() {
return (
<AppScreen
preventSwipeBack
backgroundImage={`url(${LoginBg})`}
appBar={BasicAppBar}
>
<LoginContainer />
</AppScreen>
);
}
1 change: 1 addition & 0 deletions src/screen/login/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as LoginScreen } from './LoginScreen';
11 changes: 11 additions & 0 deletions src/shared/ui/AppBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { LoginBg } from '@/assets/image';

const baseStyle = { height: '58px', border: false };

export const BasicAppBar = {
...baseStyle,
backgroundImage: `url(${LoginBg})`,
renderLeft: () => (
<span className="logo text-m ml-[4px] text-3xl">took!</span>
),
};
48 changes: 48 additions & 0 deletions src/shared/ui/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { ButtonHTMLAttributes } from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/shared/utils';

interface ButtonsProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof ButtonVariants> {
children?: React.ReactNode;
}

const ButtonVariants = cva(
'rounded-md cursor-pointer font-medium focus:outline-none hover:brightness-90',
{
variants: {
intent: {
primary: 'bg-md text-white',
textmain: 'text-m',
},
size: {
fit: 'w-full h-fit text-lg',
sm: '',
md: '',
lg: 'w-full h-14 text-xl',
},
},
defaultVariants: {
intent: 'primary',
size: 'lg',
},
},
);

export default function Button({
intent,
size,
children,
className,
...props
}: ButtonsProps) {
return (
<button
className={cn(ButtonVariants({ intent, size }), className)}
{...props}
>
{children}
</button>
);
}
39 changes: 39 additions & 0 deletions src/shared/ui/Input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { InputHTMLAttributes } from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/shared/utils';

type InputProps = InputHTMLAttributes<HTMLInputElement> &
VariantProps<typeof InputVariants>;

const InputVariants = cva('w-full focus:outline-none', {
variants: {
intent: {
login: 'rounded-md border-[1px] border-s',
primary: '',
},
size: {
fit: 'w-full h-fit text-lg',
sm: '',
md: '',
lg: 'w-full h-14 px-6 py-4',
},
},
defaultVariants: {
intent: 'primary',
size: 'lg',
},
});

export default function Input({
intent,
className,
size,
...props
}: InputProps) {
return (
<input
className={cn(InputVariants({ intent, size }), className)}
{...props}
/>
);
}
3 changes: 3 additions & 0 deletions src/shared/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './AppBar';
export { default as Button } from './Button';
export { default as Input } from './Input';
1 change: 1 addition & 0 deletions src/shared/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './string';
6 changes: 6 additions & 0 deletions src/shared/utils/string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
19 changes: 19 additions & 0 deletions src/widgets/login/ui/LoginContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { LoginForm } from '@/features/login/ui';

export default function LoginContainer() {
return (
<div className="p-normal grid size-full place-items-center">
<div className="shadow-login box-border grid h-[530px] w-full place-items-center rounded-lg border-[1px] border-white bg-white/50 p-6 backdrop-blur-sm">
<div className="flex w-full flex-col gap-y-15">
<div className="flex w-full flex-col">
<span className="text-md text-4xl font-semibold">로그인 후</span>
<span className="text-md text-4xl font-semibold">
간편하게 투표하세요!
</span>
</div>
<LoginForm />
</div>
</div>
</div>
);
}
1 change: 1 addition & 0 deletions src/widgets/login/ui/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as LoginContainer } from './LoginContainer';
Loading