diff --git a/front/packages/primitives/src/menu.tsx b/front/packages/primitives/src/menu.tsx index 9c4a509c..ffc52b86 100644 --- a/front/packages/primitives/src/menu.tsx +++ b/front/packages/primitives/src/menu.tsx @@ -27,10 +27,11 @@ import Close from "@material-symbols/svg-400/rounded/close-fill.svg"; import { Icon, IconButton } from "./icons"; import { PressableFeedback } from "./links"; import { P } from "./text"; -import { ContrastArea } from "./themes"; +import { ContrastArea, SwitchVariant } from "./themes"; import { ts } from "./utils"; import Check from "@material-symbols/svg-400/rounded/check-fill.svg"; import { useRouter } from "solito/router"; +import { SvgProps } from "react-native-svg"; const MenuContext = createContext<((open: boolean) => void) | undefined>(undefined); @@ -60,48 +61,50 @@ const Menu = ({ {isOpen && ( - {({ css, theme }) => ( - - setOpen(false)} - focusable={false} - {...css({ ...StyleSheet.absoluteFillObject, flexGrow: 1, bg: "transparent" })} - /> - theme.background, - position: "absolute", - bottom: 0, - width: percent(100), - alignSelf: "center", - borderTopLeftRadius: px(26), - borderTopRightRadius: { xs: px(26), xl: 0 }, - paddingTop: { xs: px(26), xl: 0 }, - marginTop: { xs: px(72), xl: 0 }, - }, - sm({ - maxWidth: px(640), - marginHorizontal: px(56), - }), - xl({ - top: 0, - right: 0, - marginRight: 0, - borderBottomLeftRadius: px(26), - }), - ])} - > - + {({ css, theme }) => ( + + setOpen(false)} - {...css({ alignSelf: "flex-end", display: { xs: "none", xl: "flex" } })} + focusable={false} + {...css({ ...StyleSheet.absoluteFillObject, flexGrow: 1, bg: "transparent" })} /> - {children} - - - )} + theme.background, + position: "absolute", + bottom: 0, + width: percent(100), + alignSelf: "center", + borderTopLeftRadius: px(26), + borderTopRightRadius: { xs: px(26), xl: 0 }, + paddingTop: { xs: px(26), xl: 0 }, + marginTop: { xs: px(72), xl: 0 }, + }, + sm({ + maxWidth: px(640), + marginHorizontal: px(56), + }), + xl({ + top: 0, + right: 0, + marginRight: 0, + borderBottomLeftRadius: px(26), + }), + ])} + > + setOpen(false)} + {...css({ alignSelf: "flex-end", display: { xs: "none", xl: "flex" } })} + /> + {children} + + + )} + )} @@ -114,10 +117,12 @@ const MenuItem = ({ selected, onSelect, href, + icon, ...props }: { label: string; selected?: boolean; + icon?: ComponentType; } & ({ onSelect: () => void; href?: undefined } | { href: string; onSelect?: undefined })) => { const { css, theme } = useYoshiki(); const setOpen = useContext(MenuContext); @@ -141,7 +146,7 @@ const MenuItem = ({ props as any, )} > - {selected && } + {selected && }

{label}

); diff --git a/front/packages/primitives/src/menu.web.tsx b/front/packages/primitives/src/menu.web.tsx index e062a942..1ffcd47c 100644 --- a/front/packages/primitives/src/menu.web.tsx +++ b/front/packages/primitives/src/menu.web.tsx @@ -25,10 +25,11 @@ import { PressableProps } from "react-native"; import { useYoshiki } from "yoshiki/web"; import { px, useYoshiki as useNativeYoshiki } from "yoshiki/native"; import { P } from "./text"; -import { ContrastArea } from "./themes"; +import { ContrastArea, SwitchVariant } from "./themes"; import { Icon } from "./icons"; import Dot from "@material-symbols/svg-400/rounded/fiber_manual_record-fill.svg"; -import { focusReset } from "./utils"; +import { focusReset, ts } from "./utils"; +import { SvgProps } from "react-native-svg"; type YoshikiFunc = (props: ReturnType) => T; const YoshikiProvider = ({ children }: { children: YoshikiFunc }) => { @@ -68,26 +69,28 @@ const Menu = ({ - - {({ css }) => ( - - e.stopImmediatePropagation()} - {...css({ - bg: (theme) => theme.background, - overflow: "hidden", - minWidth: "220px", - borderRadius: "8px", - boxShadow: - "0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2)", - zIndex: 2, - })} - > - {children} - - - )} - + + + {({ css }) => ( + + e.stopImmediatePropagation()} + {...css({ + bg: (theme) => theme.background, + overflow: "hidden", + minWidth: "220px", + borderRadius: "8px", + boxShadow: + "0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2)", + zIndex: 2, + })} + > + {children} + + + )} + + ); @@ -122,7 +125,7 @@ const MenuItem = ({ ...props }: { label: string; - icon?: JSX.Element; + icon?: ComponentType; selected?: boolean; } & ({ onSelect: () => void; href?: undefined } | { href: string; onSelect?: undefined })) => { const { css: nCss } = useNativeYoshiki(); @@ -132,7 +135,7 @@ const MenuItem = ({ <> {selected && ( )} - {

{label}

} + {

{label}

}
); diff --git a/front/packages/ui/src/browse/header.tsx b/front/packages/ui/src/browse/header.tsx index 157996cc..eeefadfd 100644 --- a/front/packages/ui/src/browse/header.tsx +++ b/front/packages/ui/src/browse/header.tsx @@ -24,82 +24,12 @@ import { useYoshiki } from "yoshiki/native"; import GridView from "@material-symbols/svg-400/rounded/grid_view.svg"; import ViewList from "@material-symbols/svg-400/rounded/view_list.svg"; import Sort from "@material-symbols/svg-400/rounded/sort.svg"; +import ArrowUpward from "@material-symbols/svg-400/rounded/arrow_upward.svg"; +import ArrowDownward from "@material-symbols/svg-400/rounded/arrow_downward.svg"; import { Layout, SortBy, SortOrd } from "./types"; import { forwardRef } from "react"; import { View, PressableProps } from "react-native"; -// const SortByMenu = ({ -// sortKey, -// setSort, -// sortOrd, -// setSortOrd, -// anchor, -// onClose, -// }: { -// sortKey: SortBy; -// setSort: (sort: SortBy) => void; -// sortOrd: SortOrd; -// setSortOrd: (sort: SortOrd) => void; -// anchor: HTMLElement; -// onClose: () => void; -// }) => { -// const router = useRouter(); -// const { t } = useTranslation("browse"); -// -// return ( -// -// {Object.values(SortBy).map((x) => ( -// setSort(x)} -// component={Link} -// to={{ query: { ...router.query, sortBy: `${sortKey}-${sortOrd}` } }} -// shallow -// replace -// > -// {t(`browse.sortkey.${x}`)} -// -// ))} -// -// setSortOrd(SortOrd.Asc)} -// component={Link} -// to={{ query: { ...router.query, sortBy: `${sortKey}-${sortOrd}` } }} -// shallow -// replace -// > -// -// -// -// {t("browse.sortord.asc")} -// -// setSortOrd(SortOrd.Desc)} -// component={Link} -// to={{ query: { ...router.query, sortBy: `${sortKey}-${sortOrd}` } }} -// shallow -// replace -// > -// -// -// -// {t("browse.sortord.desc")} -// -// -// ); -// }; - const SortTrigger = forwardRef(function _SortTrigger( { sortKey, ...props }, ref, @@ -121,20 +51,17 @@ const SortTrigger = forwardRef(funct export const BrowseSettings = ({ sortKey, - setSort, sortOrd, - setSortOrd, + setSort, layout, setLayout, }: { sortKey: SortBy; - setSort: (sort: SortBy) => void; sortOrd: SortOrd; - setSortOrd: (sort: SortOrd) => void; + setSort: (sort: SortBy, ord: SortOrd) => void; layout: Layout; setLayout: (layout: Layout) => void; }) => { - // const [sortAnchor, setSortAnchor] = useState(null); const { css, theme } = useYoshiki(); const { t } = useTranslation(); @@ -148,10 +75,10 @@ export const BrowseSettings = ({ key={x} label={t(`browse.sortkey.${x}`)} selected={sortKey === x} - onSelect={() => setSort(x)} - // component={Link} - // to={{ query: { ...router.query, sortBy: `${sortKey}-${sortOrd}` } }} - // TODO: Set query param for sort. + icon={sortOrd === SortOrd.Asc ? ArrowUpward : ArrowDownward} + onSelect={() => + setSort(x, sortKey === x && sortOrd === SortOrd.Asc ? SortOrd.Desc : SortOrd.Asc) + } /> ))} @@ -173,40 +100,4 @@ export const BrowseSettings = ({ ); - - // return ( - // <> - // - // - // - // - // - // - // - // - // {sortAnchor && ( - // setSortAnchor(null)} - // /> - // )} - // - // ); }; diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx index 28f10635..2f5cd96b 100644 --- a/front/packages/ui/src/browse/index.tsx +++ b/front/packages/ui/src/browse/index.tsx @@ -18,7 +18,6 @@ * along with Kyoo. If not, see . */ -import { ComponentProps, useState } from "react"; import { QueryIdentifier, QueryPage, @@ -27,6 +26,8 @@ import { ItemType, getDisplayDate, } from "@kyoo/models"; +import { ComponentProps, useState } from "react"; +import { createParam } from "solito"; import { DefaultLayout } from "../layout"; import { WithLoading } from "../fetch"; import { InfiniteFetch } from "../fetch-infinite"; @@ -35,6 +36,8 @@ import { ItemList } from "./list"; import { SortBy, SortOrd, Layout } from "./types"; import { BrowseSettings } from "./header"; +const { useParam } = createParam<{ sortBy?: string }>(); + export const itemMap = ( item: WithLoading, ): WithLoading & ComponentProps> => { @@ -72,33 +75,32 @@ const query = ( }); export const BrowsePage: QueryPage<{ slug?: string }> = ({ slug }) => { - const [sortKey, setSort] = useState(SortBy.Name); - const [sortOrd, setSortOrd] = useState(SortOrd.Asc); + const [sort, setSort] = useParam("sortBy"); + const sortKey = (sort?.split(":")[0] as SortBy) || SortBy.Name; + const sortOrd = (sort?.split(":")[1] as SortOrd) || SortOrd.Asc; const [layout, setLayout] = useState(Layout.Grid); const LayoutComponent = layout === Layout.Grid ? ItemGrid : ItemList; - // TODO list header to seet sort things, filter and layout. return ( - <> - - } - > - {(item) => } - - + { + setSort(`${key}:${ord}`); + }} + layout={layout} + setLayout={setLayout} + /> + } + > + {(item) => } + ); };