mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-02 08:28:18 +00:00
tabs styling
This commit is contained in:
1 parent
911648f1f0
commit
69f62b8f00
6 files changed
+177
-189
No files matched your search
@@ -1,67 +1,54 @@
|
||||
import {
|
||||
Fragment,
|
||||
useState
|
||||
} from 'react'
|
||||
import { Dialog, Transition } from '@headlessui/react'
|
||||
import {
|
||||
faGears,
|
||||
} from '@fortawesome/pro-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Fragment, useState } from "react";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { faGears } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { Button } from '~/components/Button';
|
||||
import { Button } from "~/components/Button";
|
||||
|
||||
import { SidePanelInner } from './SidePanelInner';
|
||||
import { SidePanelInner } from "./SidePanelInner";
|
||||
|
||||
interface SidePanelPropsI{
|
||||
interface SidePanelPropsI {
|
||||
title?: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const SidePanel =({
|
||||
title,
|
||||
children,
|
||||
}:SidePanelPropsI)=>{
|
||||
|
||||
export const SidePanel = ({ title, children }: SidePanelPropsI) => {
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const handleOpen = ()=> setOpen(true);
|
||||
const handleClose = ()=>setOpen(false);
|
||||
const handleOpen = () => setOpen(true);
|
||||
const handleClose = () => setOpen(false);
|
||||
|
||||
return (<>
|
||||
<Button
|
||||
className='fixed right-0 top-20 mt-2 mr-4'
|
||||
onClick={handleOpen}
|
||||
>
|
||||
<FontAwesomeIcon className="fa-2xl -mx-2" icon={faGears} />
|
||||
</Button>
|
||||
<Transition.Root show={open} as={Fragment}>
|
||||
<Dialog as="div" className="relative z-10" onClose={setOpen}>
|
||||
<div className="fixed inset-0" />
|
||||
return (
|
||||
<>
|
||||
<Button className="fixed right-0 top-20 mr-4 mt-2" onClick={handleOpen}>
|
||||
<FontAwesomeIcon className="fa-2xl -mx-2" icon={faGears} />
|
||||
</Button>
|
||||
<Transition.Root show={open} as={Fragment}>
|
||||
<Dialog as="div" className="relative z-10" onClose={setOpen}>
|
||||
<div className="fixed inset-0" />
|
||||
|
||||
<div className="fixed inset-0 overflow-hidden">
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="pointer-events-none inset-y-0 fixed top-16 mt-2 right-0 flex max-w-full pl-10 sm:pl-16">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="transform transition ease-in-out duration-500 sm:duration-700"
|
||||
enterFrom="translate-x-full"
|
||||
enterTo="translate-x-0"
|
||||
leave="transform transition ease-in-out duration-500 sm:duration-700"
|
||||
leaveFrom="translate-x-0"
|
||||
leaveTo="translate-x-full"
|
||||
>
|
||||
<Dialog.Panel className="pointer-events-auto w-screen lg:max-w-md">
|
||||
<SidePanelInner
|
||||
title={title}
|
||||
closeCallback={handleClose}
|
||||
>
|
||||
{children}
|
||||
</SidePanelInner>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
<div className="fixed inset-0 overflow-hidden">
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="pointer-events-none fixed inset-y-0 right-0 top-16 mt-2 flex max-w-full pl-10 sm:pl-16">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="transform transition ease-in-out duration-500 sm:duration-700"
|
||||
enterFrom="translate-x-full"
|
||||
enterTo="translate-x-0"
|
||||
leave="transform transition ease-in-out duration-500 sm:duration-700"
|
||||
leaveFrom="translate-x-0"
|
||||
leaveTo="translate-x-full"
|
||||
>
|
||||
<Dialog.Panel className="pointer-events-auto lg:max-w-full">
|
||||
<SidePanelInner title={title} closeCallback={handleClose}>
|
||||
{children}
|
||||
</SidePanelInner>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
</>);
|
||||
}
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,35 +1,29 @@
|
||||
import {
|
||||
useCallback,
|
||||
useLayoutEffect,
|
||||
useState
|
||||
} from 'react';
|
||||
import { Dialog } from '@headlessui/react'
|
||||
import { useCallback, useLayoutEffect, useState } from "react";
|
||||
import { Dialog } from "@headlessui/react";
|
||||
|
||||
import {
|
||||
faXmark,
|
||||
} from '@fortawesome/pro-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faXmark } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { TOP_BAR_HEIGHT } from '~/constants';
|
||||
import { TOP_BAR_HEIGHT } from "~/constants";
|
||||
|
||||
export const SidePanelInner = ({
|
||||
title,
|
||||
children,
|
||||
closeCallback
|
||||
}:{
|
||||
closeCallback,
|
||||
}: {
|
||||
title?: string;
|
||||
children: React.ReactNode;
|
||||
closeCallback: ()=>void;
|
||||
})=>{
|
||||
closeCallback: () => void;
|
||||
}) => {
|
||||
const [height, setHeight] = useState(0);
|
||||
const handleWindowResize = useCallback(()=>{
|
||||
if(window){
|
||||
setHeight (Math.ceil(window.innerHeight * 3 / 4) - TOP_BAR_HEIGHT);
|
||||
const handleWindowResize = useCallback(() => {
|
||||
if (window) {
|
||||
setHeight(Math.ceil((window.innerHeight * 3) / 4) - TOP_BAR_HEIGHT);
|
||||
}
|
||||
return 0;
|
||||
},[])
|
||||
}, []);
|
||||
|
||||
useLayoutEffect(()=>{
|
||||
useLayoutEffect(() => {
|
||||
handleWindowResize();
|
||||
window.addEventListener("resize", handleWindowResize);
|
||||
return () => {
|
||||
@@ -37,19 +31,19 @@ export const SidePanelInner = ({
|
||||
};
|
||||
}, [handleWindowResize]);
|
||||
|
||||
return(
|
||||
return (
|
||||
<div
|
||||
className="flex flex-col overflow-y-scroll bg-ui-panel py-6 shadow-xl border-y border-l border-ui-panel-border"
|
||||
style={{height:height+'px'}}
|
||||
className="flex flex-col overflow-y-scroll border-y border-l border-ui-panel-border bg-ui-panel py-6 shadow-xl"
|
||||
style={{ height: height + "px" }}
|
||||
>
|
||||
<div className="px-4 sm:px-6">
|
||||
<div className="flex items-start justify-between">
|
||||
{!title && <span/>}
|
||||
{title &&
|
||||
{!title && <span />}
|
||||
{title && (
|
||||
<Dialog.Title className="text-base font-semibold leading-6 text-white">
|
||||
{title}
|
||||
</Dialog.Title>
|
||||
}
|
||||
)}
|
||||
<div className="ml-3 flex h-7 items-center">
|
||||
<button
|
||||
type="button"
|
||||
@@ -59,7 +53,7 @@ export const SidePanelInner = ({
|
||||
{/* <span className="absolute -inset-2.5" /> */}
|
||||
<span className="sr-only">Close panel</span>
|
||||
<FontAwesomeIcon
|
||||
className="h-6 w-6 mt-1 mx-1"
|
||||
className="mx-1 mt-1 h-6 w-6"
|
||||
aria-hidden="true"
|
||||
icon={faXmark}
|
||||
/>
|
||||
@@ -67,9 +61,7 @@ export const SidePanelInner = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative mt-6 flex-1 px-4 sm:px-6">
|
||||
{children}
|
||||
</div>
|
||||
<div className="relative mt-6 flex-1">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
+22
-33
@@ -1,55 +1,44 @@
|
||||
import { useState } from 'react'
|
||||
import { Tab } from '@headlessui/react'
|
||||
import { useState } from "react";
|
||||
import { Tab } from "@headlessui/react";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { joinClassNames } from '~/helpers';
|
||||
|
||||
export type Tab = {
|
||||
export type TabType = {
|
||||
header: string;
|
||||
children: JSX.Element;
|
||||
}
|
||||
};
|
||||
|
||||
export const Tabs = ({
|
||||
tabs: tabProps
|
||||
}:{
|
||||
tabs:Tab[]
|
||||
}) =>{
|
||||
const [tabs, setTabs] = useState(tabProps);
|
||||
export const Tabs = ({ tabs: tabProps }: { tabs: TabType[] }) => {
|
||||
const [tabs] = useState(tabProps);
|
||||
|
||||
const tabHeaderClassName = (selected: boolean) =>
|
||||
twMerge(
|
||||
"px-4 py-4 text-md font-medium leading-5 focus:outline-none transition duration-150 ease-in-out border-b-[3px] border-white/[.1]",
|
||||
selected
|
||||
? "bg-ui-panel text-white border-brand-primary"
|
||||
: "text-gray-400 hover:bg-ui-panel hover:text-white hover:border-white/[.2]",
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-md px-2 py-16 sm:px-0">
|
||||
<div className="w-full max-w-md px-2 sm:px-0">
|
||||
<Tab.Group>
|
||||
<Tab.List className="flex space-x-1 rounded-xl bg-blue-900/20 p-1">
|
||||
<Tab.List className="flex">
|
||||
{tabs.map((tab, idx) => (
|
||||
<Tab
|
||||
key={idx}
|
||||
className={({ selected }) =>
|
||||
joinClassNames(
|
||||
'w-full rounded-lg py-2.5 text-sm font-medium leading-5',
|
||||
'ring-white/60 ring-offset-2 ring-offset-blue-400 focus:outline-none focus:ring-2',
|
||||
selected
|
||||
? 'bg-white text-blue-700 shadow'
|
||||
: 'text-blue-100 hover:bg-white/[0.12] hover:text-white'
|
||||
)
|
||||
}
|
||||
className={({ selected }) => tabHeaderClassName(selected)}
|
||||
>
|
||||
{tab.header}
|
||||
</Tab>
|
||||
))}
|
||||
</Tab.List>
|
||||
<Tab.Panels className="mt-2">
|
||||
<Tab.Panels>
|
||||
{tabs.map((tab, idx) => (
|
||||
<Tab.Panel
|
||||
key={idx}
|
||||
className={joinClassNames(
|
||||
'rounded-xl bg-white p-3',
|
||||
'ring-white/60 ring-offset-2 ring-offset-blue-400 focus:outline-none focus:ring-2'
|
||||
)}
|
||||
>
|
||||
<Tab.Panel key={idx} className="p-4 text-white focus:outline-none">
|
||||
{tab.children}
|
||||
</Tab.Panel>
|
||||
))}
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
Generated
+17
-6
@@ -27,6 +27,7 @@
|
||||
"isbot": "^4.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"tailwind-merge": "^2.2.2",
|
||||
"three": "^0.162.0",
|
||||
"uuid": "^9.0.1",
|
||||
"webm-writer": "^1.0.0"
|
||||
@@ -722,10 +723,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.23.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
|
||||
"integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
|
||||
"dev": true,
|
||||
"version": "7.24.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz",
|
||||
"integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
},
|
||||
@@ -10600,8 +10600,7 @@
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
||||
},
|
||||
"node_modules/regexp.prototype.flags": {
|
||||
"version": "1.5.2",
|
||||
@@ -11720,6 +11719,18 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwind-merge": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.2.2.tgz",
|
||||
"integrity": "sha512-tWANXsnmJzgw6mQ07nE3aCDkCK4QdT3ThPMCzawoYA2Pws7vSTCvz3Vrjg61jVUGfFZPJzxEP+NimbcW+EdaDw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.24.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/dcastil"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz",
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"isbot": "^4.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"tailwind-merge": "^2.2.2",
|
||||
"three": "^0.162.0",
|
||||
"uuid": "^9.0.1",
|
||||
"webm-writer": "^1.0.0"
|
||||
|
||||
+72
-64
@@ -1,5 +1,5 @@
|
||||
import type { Config } from 'tailwindcss';
|
||||
import colors from 'tailwindcss/colors';
|
||||
import type { Config } from "tailwindcss";
|
||||
import colors from "tailwindcss/colors";
|
||||
|
||||
export default {
|
||||
content: [
|
||||
@@ -8,76 +8,84 @@ export default {
|
||||
"./app/*.{js,jsx,ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
// extend: {},
|
||||
colors:{
|
||||
transparent: 'transparent',
|
||||
current: 'currentColor',
|
||||
extend: {
|
||||
fontFamily: {
|
||||
"custom-font": ["Fira Sans", "sans-serif"],
|
||||
},
|
||||
},
|
||||
colors: {
|
||||
transparent: "transparent",
|
||||
current: "currentColor",
|
||||
|
||||
'brand-primary': { //sunglo
|
||||
DEFAULT: '#e66462', //=500
|
||||
'50': '#fdf3f3',
|
||||
'100': '#fce4e4',
|
||||
'200': '#facfce',
|
||||
'300': '#f6acab',
|
||||
'400': '#ef7c7a',
|
||||
'500': '#e66462',
|
||||
'600': '#cf3533',
|
||||
'700': '#ae2927',
|
||||
'800': '#902624',
|
||||
'900': '#782524',
|
||||
'950': '#410f0e',
|
||||
"brand-primary": {
|
||||
//sunglo
|
||||
DEFAULT: "#e66462", //=500
|
||||
"50": "#fdf3f3",
|
||||
"100": "#fce4e4",
|
||||
"200": "#facfce",
|
||||
"300": "#f6acab",
|
||||
"400": "#ef7c7a",
|
||||
"500": "#e66462",
|
||||
"600": "#cf3533",
|
||||
"700": "#ae2927",
|
||||
"800": "#902624",
|
||||
"900": "#782524",
|
||||
"950": "#410f0e",
|
||||
},
|
||||
'brand-secondary': { //gunpowder
|
||||
DEFAULT: '#39394c', //=950
|
||||
'50': '#f5f6f9',
|
||||
'100': '#e8eaf1',
|
||||
'200': '#d7dbe6',
|
||||
'300': '#bbc1d5',
|
||||
'400': '#9aa2c0',
|
||||
'500': '#8188b0',
|
||||
'600': '#6f74a1',
|
||||
'700': '#636492',
|
||||
'800': '#545579',
|
||||
'900': '#464762',
|
||||
'950': '#39394c',
|
||||
"brand-secondary": {
|
||||
//gunpowder
|
||||
DEFAULT: "#39394c", //=950
|
||||
"50": "#f5f6f9",
|
||||
"100": "#e8eaf1",
|
||||
"200": "#d7dbe6",
|
||||
"300": "#bbc1d5",
|
||||
"400": "#9aa2c0",
|
||||
"500": "#8188b0",
|
||||
"600": "#6f74a1",
|
||||
"700": "#636492",
|
||||
"800": "#545579",
|
||||
"900": "#464762",
|
||||
"950": "#39394c",
|
||||
},
|
||||
danger: { //copper rust
|
||||
DEFAULT: '#8f4951', //=700
|
||||
'50': '#fbf5f5',
|
||||
'100': '#f7ecec',
|
||||
'200': '#efdcdc',
|
||||
'300': '#e2c0bf',
|
||||
'400': '#d19b9c',
|
||||
'500': '#bd7679',
|
||||
'600': '#a5595f',
|
||||
'700': '#8f4951',
|
||||
'800': '#743d45',
|
||||
'900': '#64373f',
|
||||
'950': '#361b1e',
|
||||
danger: {
|
||||
//copper rust
|
||||
DEFAULT: "#8f4951", //=700
|
||||
"50": "#fbf5f5",
|
||||
"100": "#f7ecec",
|
||||
"200": "#efdcdc",
|
||||
"300": "#e2c0bf",
|
||||
"400": "#d19b9c",
|
||||
"500": "#bd7679",
|
||||
"600": "#a5595f",
|
||||
"700": "#8f4951",
|
||||
"800": "#743d45",
|
||||
"900": "#64373f",
|
||||
"950": "#361b1e",
|
||||
},
|
||||
|
||||
success:{ //apple
|
||||
DEFAULT: '#40ad48', //=500
|
||||
'50': '#f2fbf2',
|
||||
'100': '#e2f6e3',
|
||||
'200': '#c5edc7',
|
||||
'300': '#98dd9d',
|
||||
'400': '#64c46b',
|
||||
'500': '#40ad48',
|
||||
'600': '#2f8a35',
|
||||
'700': '#286d2e',
|
||||
'800': '#245728',
|
||||
'900': '#1f4823',
|
||||
'950': '#0c270f',
|
||||
success: {
|
||||
//apple
|
||||
DEFAULT: "#40ad48", //=500
|
||||
"50": "#f2fbf2",
|
||||
"100": "#e2f6e3",
|
||||
"200": "#c5edc7",
|
||||
"300": "#98dd9d",
|
||||
"400": "#64c46b",
|
||||
"500": "#40ad48",
|
||||
"600": "#2f8a35",
|
||||
"700": "#286d2e",
|
||||
"800": "#245728",
|
||||
"900": "#1f4823",
|
||||
"950": "#0c270f",
|
||||
},
|
||||
|
||||
'ui-background': '#1a1a27',
|
||||
'ui-panel': '#242433',
|
||||
'ui-panel-border': '#5e6097',
|
||||
"ui-background": "#1a1a27",
|
||||
"ui-panel": "#242433",
|
||||
"ui-panel-border": "#5e6097",
|
||||
|
||||
gray: colors.gray,
|
||||
white: colors.white
|
||||
}
|
||||
white: colors.white,
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
} satisfies Config
|
||||
} satisfies Config;
|
||||
Reference in new issue
Block a user