mirror of
https://github.com/zoriya/Kyoo.git
synced 2026-06-08 15:25:15 -04:00
Finish sort menu
This commit is contained in:
@@ -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 = <AsProps,>({
|
||||
{isOpen && (
|
||||
<Portal>
|
||||
<ContrastArea mode="user">
|
||||
{({ css, theme }) => (
|
||||
<MenuContext.Provider value={setOpen}>
|
||||
<Pressable
|
||||
onPress={() => setOpen(false)}
|
||||
focusable={false}
|
||||
{...css({ ...StyleSheet.absoluteFillObject, flexGrow: 1, bg: "transparent" })}
|
||||
/>
|
||||
<ScrollView
|
||||
{...css([
|
||||
{
|
||||
bg: (theme) => 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),
|
||||
}),
|
||||
])}
|
||||
>
|
||||
<IconButton
|
||||
icon={Close}
|
||||
color={theme.colors.black}
|
||||
<SwitchVariant>
|
||||
{({ css, theme }) => (
|
||||
<MenuContext.Provider value={setOpen}>
|
||||
<Pressable
|
||||
onPress={() => setOpen(false)}
|
||||
{...css({ alignSelf: "flex-end", display: { xs: "none", xl: "flex" } })}
|
||||
focusable={false}
|
||||
{...css({ ...StyleSheet.absoluteFillObject, flexGrow: 1, bg: "transparent" })}
|
||||
/>
|
||||
{children}
|
||||
</ScrollView>
|
||||
</MenuContext.Provider>
|
||||
)}
|
||||
<ScrollView
|
||||
{...css([
|
||||
{
|
||||
bg: (theme) => 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),
|
||||
}),
|
||||
])}
|
||||
>
|
||||
<IconButton
|
||||
icon={Close}
|
||||
color={theme.colors.black}
|
||||
onPress={() => setOpen(false)}
|
||||
{...css({ alignSelf: "flex-end", display: { xs: "none", xl: "flex" } })}
|
||||
/>
|
||||
{children}
|
||||
</ScrollView>
|
||||
</MenuContext.Provider>
|
||||
)}
|
||||
</SwitchVariant>
|
||||
</ContrastArea>
|
||||
</Portal>
|
||||
)}
|
||||
@@ -114,10 +117,12 @@ const MenuItem = ({
|
||||
selected,
|
||||
onSelect,
|
||||
href,
|
||||
icon,
|
||||
...props
|
||||
}: {
|
||||
label: string;
|
||||
selected?: boolean;
|
||||
icon?: ComponentType<SvgProps>;
|
||||
} & ({ 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 && <Icon icon={Check} color={theme.paragraph} size={24} />}
|
||||
{selected && <Icon icon={icon ?? Check} color={theme.paragraph} size={24} />}
|
||||
<P {...css({ paddingLeft: ts(2) + +!selected * px(24) })}>{label}</P>
|
||||
</PressableFeedback>
|
||||
);
|
||||
|
||||
@@ -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<T> = (props: ReturnType<typeof useYoshiki>) => T;
|
||||
const YoshikiProvider = ({ children }: { children: YoshikiFunc<ReactNode> }) => {
|
||||
@@ -68,26 +69,28 @@ const Menu = <AsProps extends { onPress: PressableProps["onPress"] }>({
|
||||
<InternalTriger Component={Trigger} ComponentProps={props} />
|
||||
</DropdownMenu.Trigger>
|
||||
<ContrastArea mode="user">
|
||||
<YoshikiProvider>
|
||||
{({ css }) => (
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content
|
||||
onFocusOutside={(e) => 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}
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
)}
|
||||
</YoshikiProvider>
|
||||
<SwitchVariant>
|
||||
<YoshikiProvider>
|
||||
{({ css }) => (
|
||||
<DropdownMenu.Portal>
|
||||
<DropdownMenu.Content
|
||||
onFocusOutside={(e) => 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}
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Portal>
|
||||
)}
|
||||
</YoshikiProvider>
|
||||
</SwitchVariant>
|
||||
</ContrastArea>
|
||||
</DropdownMenu.Root>
|
||||
);
|
||||
@@ -122,7 +125,7 @@ const MenuItem = ({
|
||||
...props
|
||||
}: {
|
||||
label: string;
|
||||
icon?: JSX.Element;
|
||||
icon?: ComponentType<SvgProps>;
|
||||
selected?: boolean;
|
||||
} & ({ onSelect: () => void; href?: undefined } | { href: string; onSelect?: undefined })) => {
|
||||
const { css: nCss } = useNativeYoshiki();
|
||||
@@ -132,7 +135,7 @@ const MenuItem = ({
|
||||
<>
|
||||
<style jsx global>{`
|
||||
[data-highlighted] {
|
||||
background: ${theme.alternate.accent};
|
||||
background: ${theme.variant.accent};
|
||||
}
|
||||
`}</style>
|
||||
<Item
|
||||
@@ -151,13 +154,13 @@ const MenuItem = ({
|
||||
>
|
||||
{selected && (
|
||||
<Icon
|
||||
icon={Dot}
|
||||
icon={icon ?? Dot}
|
||||
color={theme.paragraph}
|
||||
size={px(8)}
|
||||
{...nCss({ paddingRight: px(8) })}
|
||||
size={ts(icon ? 2 : 1)}
|
||||
{...nCss({ paddingRight: ts(1) })}
|
||||
/>
|
||||
)}
|
||||
{<P {...nCss(!selected && { paddingLeft: px(8 * 2) })}>{label}</P>}
|
||||
{<P {...nCss(!selected && { paddingLeft: ts(1 + (icon ? 2 : 1)) })}>{label}</P>}
|
||||
</Item>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user