Ver Fonte

CSS transitions on the dropdowns

Kirk Trombley há 5 anos atrás
pai
commit
970de81163

+ 13 - 3
client/src/components/util/GameCreationForm/Dropdown.jsx

@@ -1,4 +1,5 @@
 import React from 'react';
+import { CSSTransition } from 'react-transition-group';
 import styles from './Dropdown.module.css';
 
 export const Item = ({ value, onSelect, children }) => (
@@ -7,9 +8,18 @@ export const Item = ({ value, onSelect, children }) => (
   </div>
 );
 
-export const Dropdown = ({ selected, onSelect, children }) => (
+export const Dropdown = ({ open, selected, onSelect, onClick, children }) => (
   <div className={styles.container}>
-    <div className={styles.button}>{selected}</div>
-    <div className={styles.list}>{children.map((child, key) => React.cloneElement(child, { onSelect, key }))}</div>
+    <div className={styles.button} onClick={onClick}>{selected}</div>
+    <CSSTransition in={open} timeout={200} mountOnEnter unmountOnExit classNames={{
+      enter: styles['list-enter'],
+      enterActive: styles['list-enter-active'],
+      exit: styles['list-exit'],
+      exitActive: styles['list-exit-active'],
+    }}>
+      <div className={styles.list}>
+        {children.map((child, key) => React.cloneElement(child, { onSelect, key }))}
+      </div>
+    </CSSTransition>
   </div>
 );

+ 25 - 8
client/src/components/util/GameCreationForm/Dropdown.module.css

@@ -2,6 +2,9 @@
   width: 100%;
   position: relative;
   display: inline-block;
+  margin-left: 4px;
+  margin-right: 4px;
+  text-align: center;
 }
 
 .button {
@@ -23,34 +26,48 @@
   transition: background-color 300ms;
 }
 
-.container:hover .button {
-  background-color: #333;
+.button:hover {
+  background-color: #777;
 }
 
 .list {
-  display: none;
-  opacity: 0;
+  margin-top: 5px;
+  display: block;
   position: absolute;
   background-color: #333;
-  width: calc(100% - 8px);
+  /* width: calc(100% - 8px); */
+  min-width: 120px;
   z-index: 1;
   border-radius: 12px;
   overflow: hidden;
   border: 4px solid #333;
-  transition: opacity 500ms;
 }
 
-.container:hover .list {
-  display: block;
+.list-enter {
+  opacity: 0;
+}
+
+.list-enter-active {
+  opacity: 1;
+  transition: opacity 200ms;
+}
+
+.list-exit {
   opacity: 1;
 }
 
+.list-exit-active {
+  opacity: 0;
+  transition: opacity 200ms;
+}
+
 .item {
   padding: 6px 4px;
   text-align: center;
   display: block;
   cursor: pointer;
   transition: background-color 300ms;
+  white-space: nowrap;
 }
 
 .item:hover {

+ 22 - 4
client/src/components/util/GameCreationForm/GameCreationForm.jsx

@@ -12,6 +12,7 @@ export default ({ afterCreate }) => {
   const [ rounds, setRounds ] = useState(5);
   const [ onlyAmerica, setOnlyAmerica ] = useState(false);
   const [ genMethod, setGenMethod ] = useState(MAP_CRUNCH);
+  const [ open, setOpen ] = useState(null);
 
   if (loading) {
     return <Loading />;
@@ -28,19 +29,34 @@ export default ({ afterCreate }) => {
   return (
     <div className={styles.form}>
       <div className={styles.dropdowns}>
-        <Dropdown selected={ms(timer * 1000)} onSelect={setTimer}>
+        <Dropdown 
+          selected={ms(timer * 1000)} 
+          onSelect={v => { setTimer(v); setOpen(null); }} 
+          open={open === "timer"} 
+          onClick={() => setOpen(o => o === "timer" ? null : "timer")}
+        >
           <Item value={30}>30 Seconds</Item>
           <Item value={120}>2 Minutes</Item>
           <Item value={300}>5 Minutes</Item>
           <Item value={3600}>1 Hour</Item>
         </Dropdown>
-        <Dropdown selected={rounds} onSelect={setRounds}>
+        <Dropdown 
+          selected={rounds} 
+          onSelect={v => { setRounds(v); setOpen(null); }} 
+          open={open === "rounds"} 
+          onClick={() => setOpen(o => o === "rounds" ? null : "rounds")}
+        >
           <Item value={1}>1 Round</Item>
           <Item value={3}>3 Rounds</Item>
           <Item value={5}>5 Rounds</Item>
           <Item value={10}>10 Rounds</Item>
         </Dropdown>
-        <Dropdown selected={onlyAmerica ? '🇺🇸' : '🌎'} onSelect={setOnlyAmerica}>
+        <Dropdown 
+          selected={onlyAmerica ? '🇺🇸' : '🌎'} 
+          onSelect={v => { setOnlyAmerica(v); setOpen(null); }} 
+          open={open === "america"} 
+          onClick={() => setOpen(o => o === "america" ? null : "america")}
+        >
           <Item value={false}>All Countries</Item>
           <Item value={true}>Just America</Item>
         </Dropdown>
@@ -48,7 +64,9 @@ export default ({ afterCreate }) => {
           selected={genMethod === MAP_CRUNCH
             ? 'MC'
             : genMethod === RANDOM_STREET_VIEW ? 'RSV' : '🏙️'}
-          onSelect={setGenMethod}
+            onSelect={v => { setGenMethod(v); setOpen(null); }} 
+            open={open === "gen"} 
+            onClick={() => setOpen(o => o === "gen" ? null : "gen")}
         >
           <Item value={MAP_CRUNCH}>Map Crunch</Item>
           <Item value={RANDOM_STREET_VIEW}>Random Street View</Item>

+ 1 - 1
client/src/components/util/GameCreationForm/GameCreationForm.module.css

@@ -16,6 +16,6 @@
 }
 
 .start {
-  min-width: 500px;
+  min-width: 200px;
   flex: 1;
 }