1
0
Fork 0

local and theme pickers working with headless ui

This commit is contained in:
Enoch Riese 2022-07-01 15:58:39 -05:00
parent 5766f274c0
commit c1b53465cf
5 changed files with 163 additions and 54 deletions

View file

@ -138,6 +138,7 @@
],
"version": "0.0.0",
"dependencies": {
"@headlessui/react": "^1.6.5",
"autoprefixer": "^10.4.0",
"handlebars": "^4.7.7",
"jsonfile": "^6.1.0",

View file

@ -3,38 +3,59 @@ import LocaleIcon from 'shared/components/icons/i18n.js'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
import Link from 'next/link'
import Picker, {PickerLink} from './picker';
import { Menu } from '@headlessui/react'
const LocalePicker = ({ app, iconOnly=false }) => {
const { t } = useTranslation(['locales'])
const router = useRouter()
const pickerProps = {
iconOnly,
Icon: LocaleIcon,
selectedItem: t(router.locale)
}
return (
<div className="dropdown dropdown-end w-auto">
<div tabIndex="0" className={ iconOnly
? 'btn btn-sm'
: `m-0 btn btn-neutral flex flex-row gap-2 btn-outline
md:btn-ghost
hover:bg-neutral hover:border-neutral-content
`
}>
<LocaleIcon />
{!iconOnly && <span>{t(router.locale)}</span>}
</div>
<ul tabIndex="0" className="p-2 shadow menu dropdown-content bg-base-100 rounded-box w-52">
<Picker {...pickerProps} >
{router.locales.map(locale => (
<li key={locale}>
<Link href={router.asPath} locale={locale}>
<a className="btn btn-ghost text-base-content hover:bg-base-200">
<span className="text-base-content">
<PickerLink
locale={locale}
href={router.asPath}
key={locale}>
{t(locale)}
</span>
</a>
</Link>
</li>
</PickerLink>
))}
</ul>
</div>
</Picker>
)
// return (
// <div className="dropdown dropdown-end w-auto">
// <div tabIndex="0" className={ iconOnly
// ? 'btn btn-sm'
// : `m-0 btn btn-neutral flex flex-row gap-2 btn-outline
// md:btn-ghost
// hover:bg-neutral hover:border-neutral-content
// `
// }>
// <LocaleIcon />
// {!iconOnly && <span>{t(router.locale)}</span>}
// </div>
// <ul tabIndex="0" className="p-2 shadow menu dropdown-content bg-base-100 rounded-box w-52">
// {router.locales.map(locale => (
// <li key={locale}>
// <Link href={router.asPath} locale={locale}>
// <a className="btn btn-ghost text-base-content hover:bg-base-200">
// <span className="text-base-content">
// {t(locale)}
// </span>
// </a>
// </Link>
// </li>
// ))}
// </ul>
// </div>
// )
}
export default LocalePicker

View file

@ -0,0 +1,56 @@
import {useRef, forwardRef} from 'react'
import { Menu } from '@headlessui/react'
import Link from 'next/link'
const Picker = ({Icon, className, selectedItem, iconOnly=false, children}) => {
return (<Menu as="div" className={`dropdown dropdown-end ${className} w-auto`}>
<Menu.Button className={iconOnly
? `btn btn-sm`
: `m-0 btn btn-neutral flex flex-row gap-2 btn-outline
md:btn-ghost
hover:bg-neutral hover:border-neutral-content
`}
aria-label="Choose Theme">
<Icon />
{!iconOnly && <span>{selectedItem}</span>}
</Menu.Button>
<Menu.Items as="ul" className="p-2 shadow menu dropdown-content bg-base-100 rounded-box w-52">
{children}
</Menu.Items>
</Menu>)
}
export default Picker
const itemClass = (active) => "btn btn-ghost " + (active ? 'bg-base-200' : '')
export const PickerLink = (props) => {
return (<li role="menuitem">
<Menu.Item>
{({active}) => (<ForwardLink active={active} {...props}></ForwardLink>)}
</Menu.Item>
</li>)
}
const ForwardLink = forwardRef(({href, locale, active, children, ...rest}, ref) => (
<Link href={href} locale={locale}>
<a className={itemClass(active)} {...rest} role={undefined} ref={ref}>
<span className="text-base-content">
{children}
</span>
</a>
</Link>
))
export const PickerButton = ({onClick, children}) => {
return (<Menu.Item as="li" onClick={onClick}>
{({ active }) => (
<button className={itemClass(active)}>
<span className="text-base-content">
{children}
</span>
</button>
)}
</Menu.Item>)
}

View file

@ -1,41 +1,67 @@
import themes from 'shared/themes/index.js'
import ThemeIcon from 'shared/components/icons/theme.js'
import {useRef} from 'react'
import { useTranslation } from 'next-i18next'
import Picker, {PickerButton} from './picker';
import { Menu } from '@headlessui/react'
const ThemePicker = ({ app, className, iconOnly=false }) => {
const { t } = useTranslation(['themes'])
return (
<div className={`dropdown dropdown-end ${className} w-auto`}>
<div tabIndex="0" className={iconOnly
? `btn btn-sm`
: `m-0 btn btn-neutral flex flex-row gap-2 btn-outline
md:btn-ghost
hover:bg-neutral hover:border-neutral-content
`}
>
<ThemeIcon />
{!iconOnly && <span>{t(`${app.theme}Theme`)}</span>}
</div>
<ul
tabIndex="0"
className="p-2 shadow menu dropdown-content bg-base-100 rounded-box w-52"
>
const items = {};
for (var k in themes){
items[k] = {...themes[k], key: k}
}
const pickerProps = {
className,
iconOnly,
Icon: ThemeIcon,
selectedItem: t(`${app.theme}Theme`)
}
return (<Picker {...pickerProps}>
{Object.keys(themes).map(theme => (
<li key={theme}>
<button
onClick={() => app.setTheme(theme)}
className="btn btn-ghost hover:bg-base-200"
>
<span className="text-base-content">
<PickerButton onClick={() =>
app.setTheme(theme)} key={theme}>
{t(`${theme}Theme`)}
</span>
</button>
</li>
</PickerButton>
))}
</ul>
</div>
)
</Picker>)
// return (
// <div className={`dropdown dropdown-end ${className} w-auto`}>
// <div tabIndex="0" className={iconOnly
// ? `btn btn-sm`
// : `m-0 btn btn-neutral flex flex-row gap-2 btn-outline
// md:btn-ghost
// hover:bg-neutral hover:border-neutral-content
// `}
// >
// <ThemeIcon />
// {!iconOnly && <span>{t(`${app.theme}Theme`)}</span>}
// </div>
// <ul
// tabIndex="0"
// className="p-2 shadow menu dropdown-content bg-base-100 rounded-box w-52"
// >
// {Object.keys(themes).map(theme => (
// <li key={theme}>
// <button
// onClick={() => app.setTheme(theme)}
// className="btn btn-ghost hover:bg-base-200"
// >
// <span className="text-base-content">
// {t(`${theme}Theme`)}
// </span>
// </button>
// </li>
// ))}
// </ul>
// </div>
// )
// return null;
}
export default ThemePicker

View file

@ -1909,6 +1909,11 @@
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
"@headlessui/react@^1.6.5":
version "1.6.5"
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.6.5.tgz#5587c537de809cf3146eb2ff263e5e940b1bf69c"
integrity sha512-3VkKteDxlxf3fE0KbfO9t60KC1lM7YNpZggLpwzVNg1J/zwL+h+4N7MBlFDVpInZI3rKlZGpNx0PWsG/9c2vQg==
"@heroicons/react@^1.0.5":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.6.tgz#35dd26987228b39ef2316db3b1245c42eb19e324"