Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slhmy/daisy UI #34

Merged
merged 8 commits into from
Feb 3, 2024
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: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="/katex-dist/katex.min.css">
<link rel="icon" href="/images/favicon.ico" />
<link rel="icon" href="/images/oj-lab-icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
Expand All @@ -16,7 +16,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="/manifest.json" />
<title>OJ Lab</title>
<title>Online Judge Lab</title>
</head>
<body>
<script type="module" src="/src/index.tsx"></script>
Expand Down
6 changes: 3 additions & 3 deletions src/components/FileUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ const FileUploader: React.FC = () => {

return (
<div
className="flex h-36 cursor-pointer items-center
justify-center rounded-xl border-1.5 border-dashed
className="border-1.5 flex h-36 cursor-pointer
items-center justify-center rounded-xl border-dashed
border-gray-400 bg-gray-100 p-4 text-center"
onDrop={onDrop}
onDragOver={onDragOver}
Expand All @@ -48,7 +48,7 @@ const FileUploader: React.FC = () => {
accept=".zip"
multiple={false}
/>
<p className="text-lg text-gray-500 after:ml-0.5 after:text-xs after:text-danger after:content-['*']">
<p className="after:text-danger text-lg text-gray-500 after:ml-0.5 after:text-xs after:content-['*']">
Drop some files here, or click to select file
</p>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/zh_CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const ZH_CN_TRANSLATIONS: Resource = {
"English (US)": "英语 (美式)",
"Simple Chinese": "简体中文",

Theme: "主题",

Create: "创建",
Cancel: "取消",
"Sign out": "登出",
Expand Down
30 changes: 30 additions & 0 deletions src/layouts/DarkLightToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export default function DarkLightToggle() {
return (
<label className="swap swap-rotate">
{/* this hidden checkbox controls the state */}
<input
type="checkbox"
className="theme-controller h-12 w-12 rounded-full hover:bg-[var(--fallback-bc,oklch(var(--bc)/0.2))]"
value="light"
data-set-theme="light"
data-key="theme"
/>
{/* moon icon */}
<svg
className="swap-off h-6 w-full self-center fill-current"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<path d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z" />
</svg>
{/* sun icon */}
<svg
className="swap-on h-6 w-full self-center fill-current"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" />
</svg>
</label>
);
}
88 changes: 51 additions & 37 deletions src/layouts/LanguageMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,70 @@
import { Menu, Transition } from "@headlessui/react";
import { Fragment } from "react";
import { useTranslation } from "react-i18next";
import { joinClasses } from "../utils/common";
import { LanguageIcon } from "@heroicons/react/24/outline";
import { changeLanguage } from "i18next";
import { LANGUAGE_SELECTIONS } from "../i18n/i18n";
import React from "react";

interface LanguageMenuProps {
className?: string;
}

const LanguageMenu: React.FC<LanguageMenuProps> = (props) => {
const { t } = useTranslation();
const [open, setOpen] = React.useState(false);

React.useEffect(() => {
document?.activeElement instanceof HTMLElement &&
document.activeElement.blur();
}, [open]);

return (
<>
{/* Profile dropdown */}
<Menu as="div" className={joinClasses("relative", props.className)}>
<Menu.Button className="flex items-center p-1.5">
<span className="sr-only">Open user menu</span>
<LanguageIcon className="h-5 w-5" />
</Menu.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
{open && ( // Close the dropdown when clicking outside
<div
className="fixed inset-0 z-[1]"
onClick={() => {
setOpen(false);
}}
/>
)}
<div
className={joinClasses(
"dropdown dropdown-end",
open && "dropdown-open",
props.className,
)}
onClick={() => {
setOpen(!open);
}}
>
<div
tabIndex={0}
className={joinClasses(
"avatar btn btn-circle btn-ghost m-1",
open ? "z-[2]" : "z-[0]",
)}
>
<LanguageIcon className="h-6 w-6" />
</div>
<ul
tabIndex={0}
className="menu dropdown-content z-[2] w-36 rounded-box bg-base-100 p-2 shadow-2xl"
>
<Menu.Items className="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
{LANGUAGE_SELECTIONS.map((item) => (
<Menu.Item key={item.value}>
{({ active }) => (
<div
className={joinClasses(
active ? "bg-gray-100" : "",
"block cursor-pointer px-4 py-2 text-sm text-gray-700",
)}
onClick={() => {
changeLanguage(item.value);
}}
>
{t(item.label)}
</div>
)}
</Menu.Item>
))}
</Menu.Items>
</Transition>
</Menu>
{LANGUAGE_SELECTIONS.map((item, index) => (
<li key={index}>
<span
onClick={() => {
changeLanguage(item.value);
setOpen(false);
}}
>
{t(item.label)}
</span>
</li>
))}
</ul>
</div>
</>
);
};
Expand Down
20 changes: 20 additions & 0 deletions src/layouts/PageMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
interface PageMenuProps {
navigation: Array<{ name: string; href: string; icon: JSX.Element }>;
}

const PageMenu: React.FC<PageMenuProps> = (props) => {
return (
<ul className="menu menu-horizontal rounded-box bg-base-200">
{props.navigation.map((item, index) => (
<li key={index}>
<a href={item.href}>
{item.icon}
<div className="hidden md:block">{item.name}</div>
</a>
</li>
))}
</ul>
);
};

export default PageMenu;
112 changes: 112 additions & 0 deletions src/layouts/ThemeMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { joinClasses } from "@/utils/common";
import React from "react";
import { useTranslation } from "react-i18next";

interface ThemeMenuProps {
className?: string;
}

const ThemeMenu: React.FC<ThemeMenuProps> = (props) => {
const { t } = useTranslation();
const [open, setOpen] = React.useState(false);

React.useEffect(() => {
document?.activeElement instanceof HTMLElement &&
document.activeElement.blur();
}, [open]);

return (
<>
{open && ( // Close the dropdown when clicking outside
<div
className="fixed inset-0 z-[1]"
onClick={() => {
setOpen(false);
}}
/>
)}
<div
className={joinClasses(
"dropdown-end dropdown",
open && "dropdown-open",
props.className,
)}
onClick={() => {
setOpen(!open);
}}
>
<div
tabIndex={0}
role="button"
className={joinClasses(
"avatar btn btn-ghost m-1",
open ? "z-[2]" : "z-[0]",
)}
>
{t("Theme")}
<svg
width="12px"
height="12px"
className="inline-block h-2 w-2 fill-current opacity-60"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 2048 2048"
>
<path d="M1799 349l242 241-1017 1017L7 590l242-241 775 775 775-775z"></path>
</svg>
</div>
<ul
tabIndex={0}
className="menu dropdown-content z-[2] w-32 rounded-box bg-base-100 p-2 shadow-2xl"
>
<li>
<input
type="radio"
name="theme-dropdown"
className="theme-controller btn btn-ghost btn-sm btn-block justify-start font-normal"
aria-label="Default"
value="default"
/>
</li>
<li>
<input
type="radio"
name="theme-dropdown"
className="theme-controller btn btn-ghost btn-sm btn-block justify-start font-normal"
aria-label="Retro"
value="retro"
/>
</li>
<li>
<input
type="radio"
name="theme-dropdown"
className="theme-controller btn btn-ghost btn-sm btn-block justify-start font-normal"
aria-label="Cyberpunk"
value="cyberpunk"
/>
</li>
<li>
<input
type="radio"
name="theme-dropdown"
className="theme-controller btn btn-ghost btn-sm btn-block justify-start font-normal"
aria-label="Valentine"
value="valentine"
/>
</li>
<li>
<input
type="radio"
name="theme-dropdown"
className="theme-controller btn btn-ghost btn-sm btn-block justify-start font-normal"
aria-label="Aqua"
value="aqua"
/>
</li>
</ul>
</div>
</>
);
};

export default ThemeMenu;
Loading
Loading