index.tsx 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import React from "react";
  2. import { AiOutlineSearch } from "react-icons/ai";
  3. import { IoCloseSharp } from "react-icons/io5";
  4. import { useFocusNode } from "src/hooks/useFocusNode";
  5. import styled from "styled-components";
  6. const StyledInputWrapper = styled.div`
  7. display: flex;
  8. align-items: center;
  9. justify-content: space-between;
  10. background: ${({ theme }) => theme.BACKGROUND_TERTIARY};
  11. border-radius: 4px;
  12. height: 25px;
  13. `;
  14. const StyledForm = styled.form`
  15. display: flex;
  16. align-items: center;
  17. padding: 4px 6px;
  18. `;
  19. const StyledInput = styled.input<{ hasInput: boolean }>`
  20. background: none;
  21. color: ${({ theme }) => theme.TEXT_NORMAL};
  22. outline: none;
  23. border: none;
  24. width: 112px;
  25. font-size: 14px;
  26. font-weight: 500;
  27. transition: width 0.3s;
  28. &::-webkit-search-decoration,
  29. &::-webkit-search-cancel-button,
  30. &::-webkit-search-results-button,
  31. &::-webkit-search-results-decoration {
  32. display: none;
  33. }
  34. &:focus {
  35. width: ${({ hasInput }) => hasInput && "165px"};
  36. }
  37. `;
  38. const StyledSearchButton = styled.button`
  39. display: grid;
  40. background: none;
  41. color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
  42. padding: 0;
  43. min-height: unset;
  44. &:hover {
  45. box-shadow: none;
  46. }
  47. `;
  48. const StyledCountInfo = styled.span`
  49. font-size: 14px;
  50. letter-spacing: 2px;
  51. padding: 0 6px;
  52. opacity: 0.5;
  53. `;
  54. export const SearchInput: React.FC = () => {
  55. const [content, setContent, skip, nodeCount, currentNode] = useFocusNode();
  56. const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
  57. e.preventDefault();
  58. skip();
  59. };
  60. const handleClear = (e: React.MouseEvent<HTMLButtonElement>) => {
  61. e.preventDefault();
  62. setContent({ value: "", debounced: "" });
  63. };
  64. return (
  65. <StyledInputWrapper>
  66. <StyledForm onSubmit={onSubmit}>
  67. <StyledInput
  68. type="search"
  69. value={content.value}
  70. onChange={e => setContent(val => ({ ...val, value: e.target.value }))}
  71. placeholder="Search Node"
  72. hasInput={!!content.value.length}
  73. />
  74. <StyledCountInfo>
  75. {content.value && `${nodeCount}/${nodeCount > 0 ? currentNode + 1 : "0"}`}
  76. </StyledCountInfo>
  77. <StyledSearchButton type="reset" aria-label="search" onClick={handleClear}>
  78. {content.value ? <IoCloseSharp size={18} /> : <AiOutlineSearch size={18} />}
  79. </StyledSearchButton>
  80. </StyledForm>
  81. </StyledInputWrapper>
  82. );
  83. };