From 95eb703788c9bfa0aba91e217df72b67b01cd656 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 3 Jan 2023 22:34:17 +0900 Subject: [PATCH] Make search bar collapse on small screen --- front/packages/primitives/src/input.tsx | 27 ++++----- front/packages/primitives/src/links.tsx | 3 +- front/packages/ui/src/navbar/index.tsx | 78 ++++++++++++++++++------- 3 files changed, 72 insertions(+), 36 deletions(-) diff --git a/front/packages/primitives/src/input.tsx b/front/packages/primitives/src/input.tsx index 1e23083f..6a86244c 100644 --- a/front/packages/primitives/src/input.tsx +++ b/front/packages/primitives/src/input.tsx @@ -18,30 +18,31 @@ * along with Kyoo. If not, see . */ +import { forwardRef } from "react"; import { TextInput } from "react-native"; import { px, Stylable, useYoshiki } from "yoshiki/native"; import { ts } from "./utils"; -export const Input = ({ - onChange, - value, - placeholder, - placeholderTextColor, - ...props -}: { - onChange: (value: string) => void; - value?: string; - placeholder?: string; - placeholderTextColor?: string; -} & Stylable) => { +export const Input = forwardRef< + TextInput, + { + onChange: (value: string) => void; + value?: string; + placeholder?: string; + placeholderTextColor?: string; + onBlur?: (value: string | undefined) => void; + } & Stylable +>(function _Input({ onChange, value, placeholder, placeholderTextColor, onBlur, ...props }, ref) { const { css, theme } = useYoshiki(); return ( onBlur?.call(null, value)} {...css( { borderColor: (theme) => theme.accent, @@ -53,4 +54,4 @@ export const Input = ({ )} /> ); -}; +}); diff --git a/front/packages/primitives/src/links.tsx b/front/packages/primitives/src/links.tsx index 2f5da83e..1d4b0322 100644 --- a/front/packages/primitives/src/links.tsx +++ b/front/packages/primitives/src/links.tsx @@ -75,7 +75,8 @@ export const PressableFeedback = forwardRef< const pressProps = { onBlur, onFocus, onPressIn, onPressOut, onPress }; const wrapperProps = Platform.select({ android: { - style: { borderRadius: StyleSheet.flatten(props?.style)?.borderRadius, overflow: "hidden" }, + ...props, + style: { ...StyleSheet.flatten(props?.style), overflow: "hidden" }, ref, }, default: {}, diff --git a/front/packages/ui/src/navbar/index.tsx b/front/packages/ui/src/navbar/index.tsx index 1e34e694..f5944aed 100644 --- a/front/packages/ui/src/navbar/index.tsx +++ b/front/packages/ui/src/navbar/index.tsx @@ -30,7 +30,7 @@ import { ts, Link, } from "@kyoo/primitives"; -import { Platform, View } from "react-native"; +import { Platform, TextInput, View } from "react-native"; import { useTranslation } from "react-i18next"; import { createParam } from "solito"; import { useRouter } from "solito/router"; @@ -39,7 +39,7 @@ import Menu from "@material-symbols/svg-400/rounded/menu-fill.svg"; import Search from "@material-symbols/svg-400/rounded/search-fill.svg"; import { Fetch } from "../fetch"; import { KyooLongLogo } from "./icon"; -import { useState } from "react"; +import { forwardRef, useRef, useState } from "react"; export const NavbarTitle = (props: Stylable) => { const { t } = useTranslation(); @@ -53,19 +53,21 @@ export const NavbarTitle = (props: Stylable) => { const { useParam } = createParam<{ q?: string }>(); -const SearchBar = () => { +const SearchBar = forwardRef< + TextInput, + { onBlur?: (value: string | undefined) => void } & Stylable +>(function _SearchBar({ onBlur, ...props }, ref) { const { css, theme } = useYoshiki(); const { t } = useTranslation(); const { push, replace, back } = useRouter(); - // eslint-disable-next-line react-hooks/rules-of-hooks - // const [query, setQuery] = Platform.OS === "web" ? useState("") : useParam("q"); - const [query, setQuery] = useParam("q"); + const [query] = useParam("q"); return ( { - setQuery(q); if (Platform.OS === "web") { const action = window.location.pathname.startsWith("/search") ? replace : push; if (q) action(`/search?q=${q}`, undefined, { shallow: true }); @@ -75,27 +77,59 @@ const SearchBar = () => { placeholder={t("navbar.search")} placeholderTextColor={theme.light.overlay0} {...tooltip(t("navbar.search"))} - {...css({ borderColor: (theme) => theme.colors.white })} + {...css({ borderColor: (theme) => theme.colors.white }, props)} /> ); -}; +}); -const Right = () => { - const theme = useTheme(); - const { css } = useYoshiki(); +export const NavbarProfile = () => { + const { css, theme } = useYoshiki(); const { t } = useTranslation(); return ( - <> - {Platform.OS === "web" ? ( - - ) : ( - + + + + ); +}; +export const NavbarRight = () => { + const { css } = useYoshiki(); + const { t } = useTranslation(); + const [isSearching, setSearch] = useState(false); + const ref = useRef(null); + const [query] = useParam("q"); + const searchExpanded = isSearching || query; + + return ( + + { + if (!q) setSearch(false); + }} + {...css( + Platform.OS === "web" && { + display: { xs: searchExpanded ? "flex" : "none", md: "flex" }, + }, + )} + /> + {!searchExpanded && ( + { + setSearch(true); + setTimeout(() => ref.current?.focus(), 0); + }} + {...tooltip(t("navbar.search"))} + {...css(Platform.OS === "web" && { display: { xs: "flex", md: "none" } })} + /> )} - - - - + + ); }; @@ -163,7 +197,7 @@ export const Navbar = (props: Stylable) => { } - + ); };