diff --git a/README.md b/README.md
index eb0b4c1ac..d7ba52f6f 100644
--- a/README.md
+++ b/README.md
@@ -135,6 +135,7 @@ npm start
 | isDisabled     | bool     | Disables all action for current task.                                                                 |
 | fontSize       | string   | Specifies the taskbar font size locally.                                                              |
 | project        | string   | Task project name                                                                                     |
+| hideChildren   | bool     | Hide children items.                                                                                  |
 
 \*Required
 
diff --git a/example/package-lock.json b/example/package-lock.json
index 7614e022e..4c9c93ecf 100644
--- a/example/package-lock.json
+++ b/example/package-lock.json
@@ -104,9 +104,9 @@
           }
         },
         "@types/node": {
-          "version": "16.4.10",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.10.tgz",
-          "integrity": "sha512-TmVHsm43br64js9BqHWqiDZA+xMtbUpI1MBIA0EyiBmoV9pcEYFOSdj5fr6enZNfh4fChh+AGOLIzGwJnkshyQ=="
+          "version": "16.4.13",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.13.tgz",
+          "integrity": "sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg=="
         },
         "@types/testing-library__jest-dom": {
           "version": "5.14.1",
@@ -179,9 +179,9 @@
           "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
         },
         "core-js-pure": {
-          "version": "3.16.0",
-          "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.0.tgz",
-          "integrity": "sha512-wzlhZNepF/QA9yvx3ePDgNGudU5KDB8lu/TRPKelYA/QtSnkS/cLl2W+TIdEX1FAFcBr0YpY7tPDlcmXJ7AyiQ=="
+          "version": "3.16.1",
+          "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.1.tgz",
+          "integrity": "sha512-TyofCdMzx0KMhi84mVRS8rL1XsRk2SPUNz2azmth53iRN0/08Uim9fdhQTaZTG1LqaXHYVci4RDHka6WrXfnvg=="
         },
         "css": {
           "version": "3.0.0",
@@ -436,9 +436,9 @@
           }
         },
         "@types/node": {
-          "version": "16.4.10",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.10.tgz",
-          "integrity": "sha512-TmVHsm43br64js9BqHWqiDZA+xMtbUpI1MBIA0EyiBmoV9pcEYFOSdj5fr6enZNfh4fChh+AGOLIzGwJnkshyQ=="
+          "version": "16.4.13",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.13.tgz",
+          "integrity": "sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg=="
         },
         "@types/yargs": {
           "version": "15.0.14",
@@ -534,14 +534,14 @@
           "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
         },
         "core-js-pure": {
-          "version": "3.16.0",
-          "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.0.tgz",
-          "integrity": "sha512-wzlhZNepF/QA9yvx3ePDgNGudU5KDB8lu/TRPKelYA/QtSnkS/cLl2W+TIdEX1FAFcBr0YpY7tPDlcmXJ7AyiQ=="
+          "version": "3.16.1",
+          "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.1.tgz",
+          "integrity": "sha512-TyofCdMzx0KMhi84mVRS8rL1XsRk2SPUNz2azmth53iRN0/08Uim9fdhQTaZTG1LqaXHYVci4RDHka6WrXfnvg=="
         },
         "dom-accessibility-api": {
-          "version": "0.5.6",
-          "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.6.tgz",
-          "integrity": "sha512-DplGLZd8L1lN64jlT27N9TVSESFR5STaEJvX+thCby7fuCHonfPpAlodYc3vuUYbDuDec5w8AMP7oCM5TWFsqw=="
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.7.tgz",
+          "integrity": "sha512-ml3lJIq9YjUfM9TUnEPvEYWFSwivwIGBPKpewX7tii7fwCazA8yCioGdqQcNsItPpfFvSJ3VIdMQPj60LJhcQA=="
         },
         "escape-string-regexp": {
           "version": "1.0.5",
@@ -681,9 +681,9 @@
           }
         },
         "@types/node": {
-          "version": "16.4.10",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.10.tgz",
-          "integrity": "sha512-TmVHsm43br64js9BqHWqiDZA+xMtbUpI1MBIA0EyiBmoV9pcEYFOSdj5fr6enZNfh4fChh+AGOLIzGwJnkshyQ=="
+          "version": "16.4.13",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.13.tgz",
+          "integrity": "sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg=="
         },
         "@types/yargs": {
           "version": "15.0.14",
@@ -828,9 +828,9 @@
           "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ=="
         },
         "@types/react": {
-          "version": "17.0.15",
-          "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.15.tgz",
-          "integrity": "sha512-uTKHDK9STXFHLaKv6IMnwp52fm0hwU+N89w/p9grdUqcFA6WuqDyPhaWopbNyE1k/VhgzmHl8pu1L4wITtmlLw==",
+          "version": "17.0.16",
+          "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.16.tgz",
+          "integrity": "sha512-3kCUiOOlQTwUUvjNFkbBTWMTxdTGybz/PfjCw9JmaRGcEDBQh+nGMg7/E9P2rklhJuYVd25IYLNcvqgSPCPksg==",
           "requires": {
             "@types/prop-types": "*",
             "@types/scheduler": "*",
diff --git a/example/src/App.tsx b/example/src/App.tsx
index e2717d636..16d40f9d1 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -16,7 +16,7 @@ const App = () => {
     columnWidth = 250;
   }
 
-  const onTaskChange = (task: Task) => {
+  const handleTaskChange = (task: Task) => {
     console.log("On date change Id:" + task.id);
     let newTasks = tasks.map(t => (t.id === task.id ? task : t));
     if (task.project) {
@@ -35,7 +35,7 @@ const App = () => {
     setTasks(newTasks);
   };
 
-  const onTaskDelete = (task: Task) => {
+  const handleTaskDelete = (task: Task) => {
     const conf = window.confirm("Are you sure about " + task.name + " ?");
     if (conf) {
       setTasks(tasks.filter(t => t.id !== task.id));
@@ -43,19 +43,24 @@ const App = () => {
     return conf;
   };
 
-  const onProgressChange = async (task: Task) => {
+  const handleProgressChange = async (task: Task) => {
     setTasks(tasks.map(t => (t.id === task.id ? task : t)));
     console.log("On progress change Id:" + task.id);
   };
 
-  const onDblClick = (task: Task) => {
+  const handleDblClick = (task: Task) => {
     alert("On Double Click event Id:" + task.id);
   };
 
-  const onSelect = (task: Task, isSelected: boolean) => {
+  const handleSelect = (task: Task, isSelected: boolean) => {
     console.log(task.name + " has " + (isSelected ? "selected" : "unselected"));
   };
 
+  const handleExpanderClick = (task: Task) => {
+    setTasks(tasks.map(t => (t.id === task.id ? task : t)));
+    console.log("On expander click Id:" + task.id);
+  };
+
   return (
     <div>
       <ViewSwitcher
@@ -67,11 +72,12 @@ const App = () => {
       <Gantt
         tasks={tasks}
         viewMode={view}
-        onDateChange={onTaskChange}
-        onDelete={onTaskDelete}
-        onProgressChange={onProgressChange}
-        onDoubleClick={onDblClick}
-        onSelect={onSelect}
+        onDateChange={handleTaskChange}
+        onDelete={handleTaskDelete}
+        onProgressChange={handleProgressChange}
+        onDoubleClick={handleDblClick}
+        onSelect={handleSelect}
+        onExpanderClick={handleExpanderClick}
         listCellWidth={isChecked ? "155px" : ""}
         columnWidth={columnWidth}
       />
@@ -79,11 +85,12 @@ const App = () => {
       <Gantt
         tasks={tasks}
         viewMode={view}
-        onDateChange={onTaskChange}
-        onDelete={onTaskDelete}
-        onProgressChange={onProgressChange}
-        onDoubleClick={onDblClick}
-        onSelect={onSelect}
+        onDateChange={handleTaskChange}
+        onDelete={handleTaskDelete}
+        onProgressChange={handleProgressChange}
+        onDoubleClick={handleDblClick}
+        onSelect={handleSelect}
+        onExpanderClick={handleExpanderClick}
         listCellWidth={isChecked ? "155px" : ""}
         ganttHeight={300}
         columnWidth={columnWidth}
diff --git a/package.json b/package.json
index 0eb4ba321..3db256793 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "gantt-task-react",
-  "version": "0.3.3",
+  "version": "0.3.4",
   "description": "Interactive Gantt Chart for React with TypeScript.",
   "author": "MaTeMaTuK <maksym.vikarii@gmail.com>",
   "homepage": "https://github.com/MaTeMaTuK/gantt-task-react",
diff --git a/src/components/gantt/gantt.tsx b/src/components/gantt/gantt.tsx
index e2eaf0671..53cd30e52 100644
--- a/src/components/gantt/gantt.tsx
+++ b/src/components/gantt/gantt.tsx
@@ -1,5 +1,5 @@
 import React, { useState, SyntheticEvent, useRef, useEffect } from "react";
-import { ViewMode, GanttProps } from "../../types/public-types";
+import { ViewMode, GanttProps, Task } from "../../types/public-types";
 import { GridProps } from "../grid/grid";
 import { ganttDateRange, seedDates } from "../../helpers/date-helper";
 import { CalendarProps } from "../calendar/calendar";
@@ -16,6 +16,7 @@ import { GanttEvent } from "../../types/gantt-task-actions";
 import { DateSetup } from "../../types/date-setup";
 import styles from "./gantt.module.css";
 import { HorizontalScroll } from "../other/horizontal-scroll";
+import { removeHiddenTasks } from "../../helpers/other-helper";
 
 export const Gantt: React.FunctionComponent<GanttProps> = ({
   tasks,
@@ -54,6 +55,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
   onDoubleClick,
   onDelete,
   onSelect,
+  onExpanderClick,
 }) => {
   const wrapperRef = useRef<HTMLDivElement>(null);
   const taskListRef = useRef<HTMLDivElement>(null);
@@ -83,7 +85,8 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
 
   // task change events
   useEffect(() => {
-    const [startDate, endDate] = ganttDateRange(tasks, viewMode);
+    const filteredTasks = removeHiddenTasks(tasks);
+    const [startDate, endDate] = ganttDateRange(filteredTasks, viewMode);
     let newDates = seedDates(startDate, endDate, viewMode);
     if (rtl) {
       newDates = newDates.reverse();
@@ -94,7 +97,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
     setDateSetup({ dates: newDates, viewMode });
     setBarTasks(
       convertToBarTasks(
-        tasks,
+        filteredTasks,
         newDates,
         columnWidth,
         rowHeight,
@@ -322,7 +325,11 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
     }
     setSelectedTask(newSelectedTask);
   };
-
+  const handleExpanderClick = (task: Task) => {
+    if (onExpanderClick && task.hideChildren !== undefined) {
+      onExpanderClick({ ...task, hideChildren: !task.hideChildren });
+    }
+  };
   const gridProps: GridProps = {
     columnWidth,
     svgWidth,
@@ -380,6 +387,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
     selectedTask,
     taskListRef,
     setSelectedTask: handleSelectedTask,
+    onExpanderClick: handleExpanderClick,
     TaskListHeader,
     TaskListTable,
   };
diff --git a/src/components/task-list/task-list-table.module.css b/src/components/task-list/task-list-table.module.css
index b1a753e6b..7f57268e8 100644
--- a/src/components/task-list/task-list-table.module.css
+++ b/src/components/task-list/task-list-table.module.css
@@ -20,3 +20,19 @@
   overflow: hidden;
   text-overflow: ellipsis;
 }
+.taskListNameWrapper {
+  display: flex;
+}
+
+.taskListExpander {
+  color: rgb(86 86 86);
+  font-size: 0.6rem;
+  padding: 0.15rem 0.2rem 0rem 0.2rem;
+  user-select: none;
+  cursor: pointer;
+}
+.taskListEmptyExpander {
+  font-size: 0.6rem;
+  padding-left: 1rem;
+  user-select: none;
+}
diff --git a/src/components/task-list/task-list-table.tsx b/src/components/task-list/task-list-table.tsx
index e2a7229c8..c2203e32e 100644
--- a/src/components/task-list/task-list-table.tsx
+++ b/src/components/task-list/task-list-table.tsx
@@ -11,7 +11,16 @@ export const TaskListTableDefault: React.FC<{
   tasks: Task[];
   selectedTaskId: string;
   setSelectedTask: (taskId: string) => void;
-}> = ({ rowHeight, rowWidth, tasks, fontFamily, fontSize, locale }) => {
+  onExpanderClick: (task: Task) => void;
+}> = ({
+  rowHeight,
+  rowWidth,
+  tasks,
+  fontFamily,
+  fontSize,
+  locale,
+  onExpanderClick,
+}) => {
   const dateTimeOptions: Intl.DateTimeFormatOptions = {
     weekday: "short",
     year: "numeric",
@@ -27,6 +36,13 @@ export const TaskListTableDefault: React.FC<{
       }}
     >
       {tasks.map(t => {
+        let expanderSymbol = "";
+        if (t.hideChildren === false) {
+          expanderSymbol = "▼";
+        } else if (t.hideChildren === true) {
+          expanderSymbol = "▶";
+        }
+
         return (
           <div
             className={styles.taskListTableRow}
@@ -41,7 +57,19 @@ export const TaskListTableDefault: React.FC<{
               }}
               title={t.name}
             >
-              &nbsp;{t.name}
+              <div className={styles.taskListNameWrapper}>
+                <div
+                  className={
+                    expanderSymbol
+                      ? styles.taskListExpander
+                      : styles.taskListEmptyExpander
+                  }
+                  onClick={() => onExpanderClick(t)}
+                >
+                  {expanderSymbol}
+                </div>
+                <div>{t.name}</div>
+              </div>
             </div>
             <div
               className={styles.taskListCell}
diff --git a/src/components/task-list/task-list.tsx b/src/components/task-list/task-list.tsx
index 3da854100..bbfed4365 100644
--- a/src/components/task-list/task-list.tsx
+++ b/src/components/task-list/task-list.tsx
@@ -16,6 +16,7 @@ export type TaskListProps = {
   horizontalContainerClass?: string;
   selectedTask: BarTask | undefined;
   setSelectedTask: (task: string) => void;
+  onExpanderClick: (task: Task) => void;
   TaskListHeader: React.FC<{
     headerHeight: number;
     rowWidth: string;
@@ -31,6 +32,7 @@ export type TaskListProps = {
     tasks: Task[];
     selectedTaskId: string;
     setSelectedTask: (taskId: string) => void;
+    onExpanderClick: (task: Task) => void;
   }>;
 };
 
@@ -44,6 +46,7 @@ export const TaskList: React.FC<TaskListProps> = ({
   tasks,
   selectedTask,
   setSelectedTask,
+  onExpanderClick,
   locale,
   ganttHeight,
   taskListRef,
@@ -74,6 +77,7 @@ export const TaskList: React.FC<TaskListProps> = ({
     locale,
     selectedTaskId: selectedTaskId,
     setSelectedTask,
+    onExpanderClick,
   };
 
   return (
diff --git a/src/helpers/bar-helper.ts b/src/helpers/bar-helper.ts
index 9531c0cb0..0dd5b37da 100644
--- a/src/helpers/bar-helper.ts
+++ b/src/helpers/bar-helper.ts
@@ -63,6 +63,19 @@ export const convertToBarTasks = (
     }
     return task;
   });
+  // normalize flags for hideChildren
+  barTasks = barTasks.map(task => {
+    if (task.barChildren.length > 0) {
+      if (!task.hideChildren) {
+        task.hideChildren = false;
+      }
+    } else if (!task.hideChildren && task.type === "project") {
+      task.hideChildren = false;
+    } else if (!task.hideChildren) {
+      task.hideChildren = undefined;
+    }
+    return task;
+  });
 
   return barTasks;
 };
diff --git a/src/helpers/other-helper.ts b/src/helpers/other-helper.ts
index d45939dae..4718857a4 100644
--- a/src/helpers/other-helper.ts
+++ b/src/helpers/other-helper.ts
@@ -16,3 +16,33 @@ export function isMouseEvent(
 export function isBarTask(task: Task | BarTask): task is BarTask {
   return (task as BarTask).x1 !== undefined;
 }
+
+export function removeHiddenTasks(tasks: Task[]) {
+  const groupedTasks = tasks.filter(t => t.hideChildren);
+  if (groupedTasks.length > 0) {
+    for (let i = 0; groupedTasks.length > i; i++) {
+      const groupedTask = groupedTasks[i];
+      const children = getChildren(tasks, groupedTask);
+      tasks = tasks.filter(t => children.indexOf(t) === -1);
+    }
+  }
+  return tasks;
+}
+
+function getChildren(taskList: Task[], task: Task) {
+  let tasks: Task[] = [];
+  if (task.type !== "project") {
+    tasks = taskList.filter(
+      t => t.dependencies && t.dependencies.indexOf(task.id) !== -1
+    );
+  } else {
+    tasks = taskList.filter(t => t.project && t.project === task.id);
+  }
+  const taskChildren = tasks.reduce(
+    (children: Task[], t) =>
+      children.concat(children, getChildren(taskList, t)),
+    []
+  );
+  tasks = tasks.concat(tasks, taskChildren);
+  return tasks;
+}
diff --git a/src/helpers/reducer.ts b/src/helpers/reducer.ts
deleted file mode 100644
index 6c4811c8c..000000000
--- a/src/helpers/reducer.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-export function foo() {
-  return 1;
-}
-// import { BarTask } from "../types/bar-task";
-// export type TaskListAction =
-//   | { type: GanttContentMoveAction; task: BarTask }
-//   | { type: "update"; tasks: BarTask[] };
-
-// export type TaskListState = {
-//   tasks: BarTask[];
-//   changedTask?: BarTask;
-//   originalTask?: BarTask;
-//   selectedTask?: BarTask;
-//   activeAction: GanttContentMoveAction;
-// };
-
-// export function taskListReducer(state: TaskListState, action: TaskListAction) {
-//   switch (action.type) {
-//     case "update":
-//       return { ...state, tasks: action.tasks };
-//     case "select":
-//       return { ...state, selectedTask: action.task };
-//     default:
-//       return state;
-//   }
-// }
diff --git a/src/types/public-types.ts b/src/types/public-types.ts
index f51b88c1c..b405bb8d6 100644
--- a/src/types/public-types.ts
+++ b/src/types/public-types.ts
@@ -26,6 +26,7 @@ export interface Task {
   isDisabled?: boolean;
   project?: string;
   dependencies?: string[];
+  hideChildren?: boolean;
 }
 
 export interface EventOption {
@@ -57,6 +58,10 @@ export interface EventOption {
    * Invokes on delete selected task. Chart undoes operation if method return false or error.
    */
   onDelete?: (task: Task) => void | boolean | Promise<void> | Promise<boolean>;
+  /**
+   * Invokes on expander on task list
+   */
+  onExpanderClick?: (task: Task) => void;
 }
 
 export interface DisplayOption {
@@ -119,6 +124,7 @@ export interface StylingOption {
      * Sets selected task by id
      */
     setSelectedTask: (taskId: string) => void;
+    onExpanderClick: (task: Task) => void;
   }>;
 }