aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/SearchForm/SearchForm.tsx
blob: da6f25c1cc22a2114ea418236d2e657ad92b6529 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { ButtonSubmit } from '@components/Buttons';
import { Form, Input } from '@components/Form';
import { SearchIcon } from '@components/Icons';
import { useRouter } from 'next/router';
import { FormEvent, useEffect, useRef, useState } from 'react';
import { useIntl } from 'react-intl';
import styles from './SearchForm.module.scss';

const SearchForm = ({ isOpened }: { isOpened: boolean }) => {
  const intl = useIntl();
  const [query, setQuery] = useState('');
  const inputRef = useRef<HTMLInputElement>(null);
  const router = useRouter();

  useEffect(() => {
    setTimeout(() => {
      if (isOpened && inputRef.current) {
        inputRef.current.focus();
      }
    }, 400);
  }, [isOpened]);

  const launchSearch = (e: FormEvent) => {
    e.preventDefault();
    router.push({ pathname: '/recherche', query: { s: query } });
    setQuery('');
  };

  return (
    <>
      <div className={styles.title}>
        {intl.formatMessage({
          defaultMessage: 'Search',
          description: 'SearchForm : form title',
        })}
      </div>
      <Form submitHandler={launchSearch} modifier="search">
        <label htmlFor="search-query" className="screen-reader-text">
          {intl.formatMessage({
            defaultMessage: 'Keywords:',
            description: 'SearchForm: search field label',
          })}
        </label>
        <Input
          ref={inputRef}
          id="search-query"
          name="search-query"
          type="search"
          value={query}
          setValue={setQuery}
        />
        <ButtonSubmit modifier="search">
          <SearchIcon />
          <span className="screen-reader-text">
            {intl.formatMessage({
              defaultMessage: 'Search',
              description: 'SearchForm: search button text',
            })}
          </span>
        </ButtonSubmit>
      </Form>
    </>
  );
};

export default SearchForm;
hlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
@use "@styles/abstracts/functions" as fun;
@use "@styles/abstracts/mixins" as mix;

.title {
  margin: 0;
  padding: 0;
  background: none;
  font-size: var(--font-size-xl);
  text-align: left;
}

.icon {
  display: flex;
  flex-flow: row nowrap;
  align-items: center;
  justify-content: center;
  width: fun.convert-px(30);
  height: fun.convert-px(30);
  background: var(--color-bg);
  border: fun.convert-px(1) solid var(--color-primary);
  border-radius: fun.convert-px(3);
  color: var(--color-primary);
  font-weight: 800;
  transition: all 0.25s ease-in-out 0s;

  &::before,
  &::after {
    content: "";
    background: var(--color-primary);
    transition: all 0.4s ease-out 0s;
  }

  &::before {
    width: 10%;
    height: 60%;
    position: relative;
    left: 30%;
  }

  &::after {
    width: 60%;
    height: 10%;
    position: relative;
    left: -5%;
  }
}

.body {
  width: 100%;
  max-height: 0;
  margin: 0 0 fun.convert-px(-6); // collapse borders
  overflow: hidden;
  visibility: hidden;
  transition: all 0.6s cubic-bezier(0, 1, 0, 1) 0s, margin 0.2s ease-in-out 0s,
    border 0.1s ease-in-out 0.3s, visibility 0.1s linear 0.6s;

  &--borders {
    border: 0 solid transparent;
  }

  > *:last-child {
    margin-bottom: 0;
  }

  @include mix.media("screen") {
    @include mix.dimensions("md") {
      font-size: var(--font-size-sm);
      font-weight: 500;
    }
  }
}

.wrapper {
  --header-height: #{fun.convert-px(65)};

  display: flex;
  flex-flow: column;

  &--expanded {
    .icon::before {
      height: 0;
    }

    .body {
      max-height: 10000px; // needs a fixed value for transition.
      margin: var(--spacing-sm) 0;
      overflow: visible;
      visibility: visible;
      transition: visibility 0.1s linear 0s, max-height 0.6s linear 0s,
        margin 0.2s ease-in-out 0s;

      &--borders {
        border: fun.convert-px(2) solid var(--color-primary-dark);
      }
    }
  }
}

.wrapper--expanded.wrapper--toc {
  @include mix.media("screen") {
    @include mix.dimensions("lg") {
      max-height: 100vh;

      .body {
        overflow-y: auto;
      }
    }
  }
}

.header {
  display: flex;
  flex-flow: row nowrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-md);
  width: 100%;
  min-height: var(--header-height);
  padding: 0;
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--color-bg);
  border: none;
  border-top: fun.convert-px(2) solid var(--color-primary-dark);
  border-bottom: fun.convert-px(2) solid var(--color-primary-dark);
  cursor: pointer;

  &:hover,
  &:focus {
    .icon {
      background: var(--color-primary-light);
      color: var(--color-fg-inverted);
      transform: scale(1.2);

      &::before,
      &::after {
        background: var(--color-bg);
      }
    }
  }

  > button {
    padding: 0 var(--spacing-xs);
  }
}