diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCard.js b/packages/core/upload/admin/src/components/FolderCard/FolderCard.js
new file mode 100644
index 0000000000..a297ffa2ba
--- /dev/null
+++ b/packages/core/upload/admin/src/components/FolderCard/FolderCard.js
@@ -0,0 +1,92 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import styled from 'styled-components';
+
+import { pxToRem } from '@strapi/helper-plugin';
+import { Box } from '@strapi/design-system/Box';
+import { Stack } from '@strapi/design-system/Stack';
+import Folder from '@strapi/icons/Folder';
+
+import { FolderCardContext } from './FolderCardContext';
+import useId from './utils/useId';
+
+const FauxClickWrapper = styled.button`
+ height: 100%;
+ left: 0;
+ position: absolute;
+ opacity: 0;
+ top: 0;
+ width: 100%;
+
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ }
+`;
+
+const StyledFolder = styled(Folder)`
+ path {
+ fill: currentColor;
+ }
+`;
+
+export const FolderCard = ({ children, id, startAction, ariaLabel, onDoubleClick, ...props }) => {
+ const generatedId = useId(id);
+
+ return (
+
+
+ event.preventDefault()}
+ onDoubleClick={onDoubleClick}
+ zIndex={1}
+ tabIndex={-1}
+ aria-label={ariaLabel}
+ aria-hidden
+ />
+
+
+ {startAction}
+
+
+
+
+
+ {children}
+
+
+
+ );
+};
+
+FolderCard.defaultProps = {
+ id: undefined,
+};
+
+FolderCard.propTypes = {
+ ariaLabel: PropTypes.string.isRequired,
+ children: PropTypes.node.isRequired,
+ id: PropTypes.string,
+ onDoubleClick: PropTypes.func.isRequired,
+ startAction: PropTypes.element.isRequired,
+};
diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardBody.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardBody.js
new file mode 100644
index 0000000000..bd7ecb5cb5
--- /dev/null
+++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardBody.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import styled from 'styled-components';
+
+import { Flex } from '@strapi/design-system/Flex';
+
+import { useFolderCard } from './FolderCardContext';
+
+const StyledBox = styled(Flex)`
+ user-select: none;
+`;
+
+export const FolderCardBody = props => {
+ const { id } = useFolderCard();
+
+ return (
+
+ );
+};
diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox.js
new file mode 100644
index 0000000000..ced28a17cc
--- /dev/null
+++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardCheckbox.js
@@ -0,0 +1,14 @@
+import React from 'react';
+import { Box } from '@strapi/design-system/Box';
+import { BaseCheckbox } from '@strapi/design-system/BaseCheckbox';
+import { useFolderCard } from './FolderCardContext';
+
+export const FolderCardCheckbox = props => {
+ const { id } = useFolderCard();
+
+ return (
+
+
+
+ );
+};
diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardContext.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardContext.js
new file mode 100644
index 0000000000..985ae836d9
--- /dev/null
+++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardContext.js
@@ -0,0 +1,7 @@
+import { createContext, useContext } from 'react';
+
+export const FolderCardContext = createContext();
+
+export function useFolderCard() {
+ return useContext(FolderCardContext);
+}
diff --git a/packages/core/upload/admin/src/components/FolderCard/FolderCardLink.js b/packages/core/upload/admin/src/components/FolderCard/FolderCardLink.js
new file mode 100644
index 0000000000..f5cf80ceb5
--- /dev/null
+++ b/packages/core/upload/admin/src/components/FolderCard/FolderCardLink.js
@@ -0,0 +1,7 @@
+import styled from 'styled-components';
+
+import { BaseLink } from '@strapi/design-system/BaseLink';
+
+export const FolderCardLink = styled(BaseLink)`
+ text-decoration: none;
+`;
diff --git a/packages/core/upload/admin/src/components/FolderCard/utils/tests/useId.test.js b/packages/core/upload/admin/src/components/FolderCard/utils/tests/useId.test.js
new file mode 100644
index 0000000000..2012b24645
--- /dev/null
+++ b/packages/core/upload/admin/src/components/FolderCard/utils/tests/useId.test.js
@@ -0,0 +1,42 @@
+import React from 'react';
+import { render, act } from '@testing-library/react';
+
+import useId from '../useId';
+
+function setup(...args) {
+ let returnVal;
+
+ function TestComponent() {
+ returnVal = useId(...args);
+
+ return null;
+ }
+
+ render();
+
+ return returnVal;
+}
+
+describe('useId', () => {
+ let id;
+
+ test('increments', () => {
+ id = setup('one');
+
+ expect(id).toBe('one-1');
+
+ act(() => {
+ id = setup('one');
+ });
+
+ expect(id).toBe('one-2');
+ });
+
+ test('works with namespaces', () => {
+ act(() => {
+ id = setup('two');
+ });
+
+ expect(id).toBe('two-3');
+ });
+});
diff --git a/packages/core/upload/admin/src/components/FolderCard/utils/useId.js b/packages/core/upload/admin/src/components/FolderCard/utils/useId.js
new file mode 100644
index 0000000000..91b8b43377
--- /dev/null
+++ b/packages/core/upload/admin/src/components/FolderCard/utils/useId.js
@@ -0,0 +1,13 @@
+import { useRef } from 'react';
+
+let id = 0;
+
+const genId = () => ++id;
+
+const useId = (prefix, initialId) => {
+ const idRef = useRef(initialId || `${prefix}-${genId()}`);
+
+ return idRef.current;
+};
+
+export default useId;