diff --git a/src/Gargantext/Components/NgramsTable.purs b/src/Gargantext/Components/NgramsTable.purs
index eec934197eb36633ed4ea87b45630253406becf7..cacb18ed8907dafa4148a945f0cb074043450973 100644
--- a/src/Gargantext/Components/NgramsTable.purs
+++ b/src/Gargantext/Components/NgramsTable.purs
@@ -16,6 +16,7 @@ import Data.Map (Map)
 import Data.Map as Map
 import Data.Maybe (Maybe(..), maybe, isJust, isNothing)
 import Data.Monoid.Additive (Additive(..))
+import Data.Nullable (Nullable, toMaybe, null)
 import Data.Ord.Down (Down(..))
 import Data.Set (Set)
 import Data.Set as Set
@@ -53,16 +54,11 @@ type State' =
                      --   be removed.
   , ngramsSelection  :: Set NgramsTerm
                      -- ^ The set of selected checkboxes of the first column.
-  , ngramsSelectAll  :: Boolean
-                     -- ^ The checkbox to select all the checkboxes of the first column.
   )
 
 _ngramsChildren :: forall row. Lens' { ngramsChildren :: Map NgramsTerm Boolean | row } (Map NgramsTerm Boolean)
 _ngramsChildren = prop (SProxy :: SProxy "ngramsChildren")
 
-_ngramsSelectAll :: forall row. Lens' { ngramsSelectAll :: Boolean | row } Boolean
-_ngramsSelectAll = prop (SProxy :: SProxy "ngramsSelectAll")
-
 _ngramsSelection :: forall row. Lens' { ngramsSelection :: Set NgramsTerm | row } (Set NgramsTerm)
 _ngramsSelection = prop (SProxy :: SProxy "ngramsSelection")
 
@@ -74,7 +70,6 @@ initialState' (Versioned {version}) =
   , ngramsVersion:    version
   , ngramsParent:     Nothing
   , ngramsChildren:   mempty
-  , ngramsSelectAll:  false
   , ngramsSelection:  mempty
   }
 
@@ -88,8 +83,6 @@ type State =
                      --   be removed.
   , ngramsSelection  :: Set NgramsTerm
                      -- ^ The set of selected checkboxes of the first column.
-  , ngramsSelectAll  :: Boolean
-                     -- ^ The checkbox to select all the checkboxes of the first column.
   )
 
 initialState :: VersionedNgramsTable -> State
@@ -100,7 +93,6 @@ initialState (Versioned {version}) = {
   , ngramsVersion:    version
   , ngramsParent:     Nothing
   , ngramsChildren:   mempty
-  , ngramsSelectAll:  false
   , ngramsSelection:  mempty
   }
 
@@ -143,16 +135,16 @@ addNewNgramA :: NgramsTerm -> Action
 addNewNgramA ngram = CommitPatch $ addNewNgram ngram CandidateTerm
 
 type Dispatch = Action -> Effect Unit
+type PreConversionRows = L.List (Tuple NgramsTerm NgramsElement)
 
 type TableContainerProps =
-  ( dispatch        :: Dispatch
-  , ngramsChildren  :: Map NgramsTerm Boolean
-  , ngramsParent    :: Maybe NgramsTerm
-  , ngramsSelectAll :: Boolean
-  , ngramsSelection :: Set NgramsTerm
-  , ngramsTable     :: NgramsTable
-  , path            :: R.State PageParams
-  , tabNgramType    :: CTabNgramType
+  ( dispatch         :: Dispatch
+  , ngramsChildren   :: Map NgramsTerm Boolean
+  , ngramsParent     :: Maybe NgramsTerm
+  , ngramsSelection  :: Set NgramsTerm
+  , ngramsTable      :: NgramsTable
+  , path             :: R.State PageParams
+  , tabNgramType     :: CTabNgramType
   )
 
 tableContainer :: Record TableContainerProps -> Record T.TableContainerProps -> R.Element
@@ -162,7 +154,6 @@ tableContainerCpt :: Record TableContainerProps -> R.Component T.TableContainerP
 tableContainerCpt { dispatch
                   , ngramsChildren
                   , ngramsParent
-                  , ngramsSelectAll
                   , ngramsSelection
                   , ngramsTable: ngramsTableCache
                   , path: {searchQuery, termListFilter, termSizeFilter} /\ setPath
@@ -234,13 +225,13 @@ tableContainerCpt { dispatch
                            , H.button {className: "btn btn-primary", on: {click: (const $ dispatch AddTermChildren)}} [H.text "Save"]
                            , H.button {className: "btn btn-secondary", on: {click: (const $ dispatch $ SetParentResetChildren Nothing)}} [H.text "Cancel"]
                            ]) ngramsParent)
-            , selectAllButtons ngramsSelectAll
+            , selectButtons (selectionsExist ngramsSelection)
             , H.div {id: "terms_table", className: "panel-body"}
               [ H.table {className: "table able"}
                 [ H.thead {className: "tableHeader"} [props.tableHead]
                 , H.tbody {} props.tableBody] ]
 
-            , selectAllButtons ngramsSelectAll
+            , selectButtons (selectionsExist ngramsSelection)
             ]
           ]
         ]
@@ -250,8 +241,11 @@ tableContainerCpt { dispatch
     setTermSizeFilter x = setPath $ _ { termSizeFilter = x }
     setSelection = dispatch <<< setTermListSetA ngramsTableCache ngramsSelection
 
-    selectAllButtons false = H.div {} []
-    selectAllButtons true =
+    selectionsExist :: Set NgramsTerm -> Boolean
+    selectionsExist = not <<< Set.isEmpty
+
+    selectButtons false = H.div {} []
+    selectButtons true =
       H.li {className: " list-group-item"} [
         H.button { className: "btn btn-primary"
                 , on: {click: const $ setSelection GraphTerm }
@@ -339,7 +333,6 @@ loadedNgramsTableSpecCpt = R.hooksComponent "G.C.NT.loadedNgramsTable" cpt
         , state: (state@{ ngramsChildren
                         , ngramsLocalPatch
                         , ngramsParent
-                        , ngramsSelectAll
                         , ngramsSelection
                         , ngramsVersion } /\ setState)
         , tabNgramType
@@ -353,16 +346,18 @@ loadedNgramsTableSpecCpt = R.hooksComponent "G.C.NT.loadedNgramsTable" cpt
                   , container: tableContainer { dispatch: performAction
                                               , ngramsChildren
                                               , ngramsParent
-                                              , ngramsSelectAll
                                               , ngramsSelection
                                               , ngramsTable
                                               , path
                                               , tabNgramType
                                               }
                   , params: params /\ setParams -- TODO-LENS
-                  , rows: filteredRows
+                  , rows: filteredConvertedRows
                   , totalRecords
-                  , wrapColElts
+                  , wrapColElts: wrapColElts { allNgramsSelected
+                                             , dispatch: performAction
+                                             , ngramsSelection
+                                             }
                   }
         ]
       where
@@ -393,10 +388,11 @@ loadedNgramsTableSpecCpt = R.hooksComponent "G.C.NT.loadedNgramsTable" cpt
         performAction ToggleSelectAll =
           setState toggler
           where
-            toggler s@{ ngramsSelectAll: true } = s { ngramsSelection = Set.empty :: Set NgramsTerm
-                                                    , ngramsSelectAll = false }
-            toggler s = s { ngramsSelection = roots
-                          , ngramsSelectAll = true }
+            toggler s@{ ngramsSelection } =
+              if allNgramsSelected then
+                s { ngramsSelection = Set.empty :: Set NgramsTerm }
+              else
+                s { ngramsSelection = selectNgramsOnFirstPage filteredRows }
         performAction Synchronize = syncPatchesR path' (state /\ setState)
         performAction (CommitPatch pt) =
           commitPatchR (Versioned {version: ngramsVersion, data: pt}) (state /\ setState)
@@ -415,8 +411,11 @@ loadedNgramsTableSpecCpt = R.hooksComponent "G.C.NT.loadedNgramsTable" cpt
               commitPatchR (Versioned {version: ngramsVersion, data: pt}) (state /\ setState)
 
         totalRecords = L.length rows
-        filteredRows = convertRow <$> T.filterRows { params } rows
-        rows :: L.List (Tuple NgramsTerm NgramsElement)
+        filteredConvertedRows :: T.Rows
+        filteredConvertedRows = convertRow <$> filteredRows
+        filteredRows :: PreConversionRows
+        filteredRows = T.filterRows { params } rows
+        rows :: PreConversionRows
         rows = orderWith (
           addOccT <$> (
              L.filter rowsFilterT $ Map.toUnfoldable (ngramsTable ^. _NgramsTable)
@@ -447,6 +446,8 @@ loadedNgramsTableSpecCpt = R.hooksComponent "G.C.NT.loadedNgramsTable" cpt
         --   let Additive occurrences = sumOccurrences ngramsTable ngramsElement in
         --   Tuple ne (ngramsElement # _NgramsElement <<< _occurrences .~ occurrences)
 
+        allNgramsSelected = allNgramsSelectedOnFirstPage ngramsSelection filteredRows
+
         ngramsTable = applyNgramsPatches state initTable
         roots = rootsOf ngramsTable
         ngramsParentRoot :: Maybe NgramsTerm
@@ -477,15 +478,10 @@ loadedNgramsTableSpecCpt = R.hooksComponent "G.C.NT.loadedNgramsTable" cpt
             _              -> identity -- the server ordering is enough here
 
         colNames = T.ColumnName <$> ["Select", "Map", "Stop", "Terms", "Score"] -- see convOrderBy
-        selected =
-          H.input { checked: ngramsSelectAll
-                  , className: "checkbox"
-                  , on: { change: const $ performAction $ ToggleSelectAll }
-                  , type: "checkbox" }
         -- This is used to *decorate* the Select header with the checkbox.
-        wrapColElts (T.ColumnName "Select") = const [selected]
-        wrapColElts (T.ColumnName "Score")  = (_ <> [H.text ("(" <> show scoreType <> ")")])
-        wrapColElts _                       = identity
+        wrapColElts scProps (T.ColumnName "Select") = const [selectionCheckbox scProps]
+        wrapColElts _       (T.ColumnName "Score")  = (_ <> [H.text ("(" <> show scoreType <> ")")])
+        wrapColElts _       _                       = identity
         setParams f = setPath $ \p@{params: ps} -> p {params = f ps}
 
         search :: R.Element
@@ -496,6 +492,48 @@ loadedNgramsTableSpecCpt = R.hooksComponent "G.C.NT.loadedNgramsTable" cpt
         setSearchQuery x    = setPath $ _ { searchQuery    = x }
 
 
+allNgramsSelectedOnFirstPage :: Set NgramsTerm -> PreConversionRows -> Boolean
+allNgramsSelectedOnFirstPage selected rows = selected == (selectNgramsOnFirstPage rows)
+
+selectNgramsOnFirstPage :: PreConversionRows -> Set NgramsTerm
+selectNgramsOnFirstPage rows = Set.fromFoldable $ fst <$> rows
+
+
+type SelectionCheckboxProps =
+  (
+    allNgramsSelected :: Boolean
+  , dispatch          :: Dispatch
+  , ngramsSelection   :: Set NgramsTerm
+  )
+
+selectionCheckbox :: Record SelectionCheckboxProps -> R.Element
+selectionCheckbox props = R.createElement selectionCheckboxCpt props []
+
+selectionCheckboxCpt :: R.Component SelectionCheckboxProps
+selectionCheckboxCpt = R.hooksComponent "G.C.NT.selectionCheckbox" cpt
+  where
+    cpt { allNgramsSelected, dispatch, ngramsSelection } _ = do
+      ref <- R.useRef null
+
+      R.useEffect' $ do
+        let mCb = toMaybe $ R.readRef ref
+        case mCb of
+          Nothing -> pure unit
+          Just cb -> do
+            log2 "[loadedNgramsTableSpec] ngramsSelection" ngramsSelection
+            _ <- if allNgramsSelected || (Set.isEmpty ngramsSelection) then
+              R2.setIndeterminateCheckbox cb false
+            else
+              R2.setIndeterminateCheckbox cb true
+            pure unit
+
+      pure $ H.input { checked: allNgramsSelected
+                     , className: "checkbox"
+                     , on: { change: const $ dispatch $ ToggleSelectAll }
+                     , ref
+                     , type: "checkbox" }
+
+
 displayRow :: State -> SearchQuery -> NgramsTable -> Maybe NgramsTerm -> Maybe TermList -> NgramsElement -> Boolean
 displayRow state@{ ngramsChildren
                  , ngramsLocalPatch
diff --git a/src/Gargantext/Utils/Reactix.purs b/src/Gargantext/Utils/Reactix.purs
index 4db369696bbc858dbc65308013ebe574e8f6d504..a95612ea57c2d38321f147a7e624f6e2a8f45bfd 100644
--- a/src/Gargantext/Utils/Reactix.purs
+++ b/src/Gargantext/Utils/Reactix.purs
@@ -21,9 +21,9 @@ import Effect (Effect)
 import Effect.Aff (Aff, launchAff, launchAff_, killFiber)
 import Effect.Class (liftEffect)
 import Effect.Exception (error)
-import Effect.Uncurried (EffectFn1, mkEffectFn1, mkEffectFn2, runEffectFn1)
+import Effect.Uncurried (EffectFn1, EffectFn2, mkEffectFn1, mkEffectFn2, runEffectFn1, runEffectFn2)
 import Effect.Unsafe (unsafePerformEffect)
-import FFI.Simple ((..), (...), defineProperty, delay, args2, args3)
+import FFI.Simple ((..), (...), (.=), defineProperty, delay, args2, args3)
 import Partial.Unsafe (unsafePartial)
 import React (class ReactPropFields, Children, ReactClass, ReactElement)
 import React as React
@@ -305,3 +305,9 @@ focus :: Nullable R.Element -> Effect Unit
 focus nEl = case toMaybe nEl of
   Nothing -> pure unit
   Just el -> el ... "focus" $ []
+
+setIndeterminateCheckbox :: R.Element -> Boolean -> Effect R.Element
+setIndeterminateCheckbox el val = do
+  log2 "[setIntederminateCheckbox] el" el
+  log2 "[setIntederminateCheckbox] val" val
+  pure $ (el .= "indeterminate") val