diff --git a/ghost/admin-x-settings/src/admin-x-ds/global/List.stories.tsx b/ghost/admin-x-settings/src/admin-x-ds/global/List.stories.tsx
new file mode 100644
index 0000000000..ad06dc8216
--- /dev/null
+++ b/ghost/admin-x-settings/src/admin-x-ds/global/List.stories.tsx
@@ -0,0 +1,40 @@
+import type {Meta, StoryObj} from '@storybook/react';
+
+import * as ListItemStories from './ListItem.stories';
+import List from './List';
+import ListItem from './ListItem';
+
+const meta = {
+ title: 'Global / List',
+ component: List,
+ tags: ['autodocs'],
+ decorators: [(_story: any) => (
{_story()}
)]
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+const listItemProps = {
+ title: ListItemStories.HiddenActions.args?.title,
+ detail: ListItemStories.HiddenActions.args?.detail,
+ action: ListItemStories.HiddenActions.args?.action,
+ hideActions: ListItemStories.HiddenActions.args?.hideActions,
+ separator: true,
+ onClick: ListItemStories.HiddenActions.args?.onClick
+};
+
+const listItems = (
+ <>
+
+
+
+ >
+);
+
+export const Default: Story = {
+ args: {
+ title: 'This is a list',
+ children: listItems,
+ hint: 'And here is a hint for the whole list'
+ }
+};
diff --git a/ghost/admin-x-settings/src/admin-x-ds/global/List.tsx b/ghost/admin-x-settings/src/admin-x-ds/global/List.tsx
new file mode 100644
index 0000000000..0e4d1e63ee
--- /dev/null
+++ b/ghost/admin-x-settings/src/admin-x-ds/global/List.tsx
@@ -0,0 +1,39 @@
+import Heading from './Heading';
+import Hint from './Hint';
+import React from 'react';
+import Separator from './Separator';
+
+interface ListProps {
+ title?: React.ReactNode;
+ titleSeparator?: boolean;
+ children?: React.ReactNode;
+ hint?: React.ReactNode;
+ hintSeparator?: boolean;
+}
+
+const List: React.FC = ({title, titleSeparator, children, hint, hintSeparator}) => {
+ titleSeparator = (titleSeparator === undefined) ? true : titleSeparator;
+ hintSeparator = (hintSeparator === undefined) ? true : hintSeparator;
+
+ return (
+
+ {title &&
+
+ {title}
+ {titleSeparator && }
+
+ }
+
+ {children}
+
+ {hint &&
+ <>
+ {hintSeparator && }
+ {hint}
+ >
+ }
+
+ );
+};
+
+export default List;
\ No newline at end of file
diff --git a/ghost/admin-x-settings/src/admin-x-ds/global/ListItem.stories.tsx b/ghost/admin-x-settings/src/admin-x-ds/global/ListItem.stories.tsx
new file mode 100644
index 0000000000..2b6b3f8144
--- /dev/null
+++ b/ghost/admin-x-settings/src/admin-x-ds/global/ListItem.stories.tsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import type {Meta, StoryObj} from '@storybook/react';
+
+import Button from './Button';
+import ListItem from './ListItem';
+
+const meta = {
+ title: 'Global / List / List Item',
+ component: ListItem,
+ tags: ['autodocs'],
+ decorators: [(_story: any) => ({_story()}
)],
+ argTypes: {
+ title: {control: 'text'},
+ detail: {control: 'text'}
+ }
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ id: 'list-item',
+ title: 'A list item',
+ detail: 'Some details',
+ action: ,
+ separator: true,
+ onClick: (e: React.MouseEvent) => {
+ const clickedDiv = e.currentTarget;
+ alert(`Clicked on "${clickedDiv.id}"`);
+ }
+ }
+};
+
+export const HiddenActions: Story = {
+ args: {
+ id: 'list-item',
+ title: 'A list item',
+ detail: 'Some details',
+ action: ,
+ separator: true,
+ hideActions: true,
+ onClick: (e: React.MouseEvent) => {
+ const clickedDiv = e.currentTarget;
+ alert(`Clicked on "${clickedDiv.id}"`);
+ }
+ }
+};
diff --git a/ghost/admin-x-settings/src/admin-x-ds/global/ListItem.tsx b/ghost/admin-x-settings/src/admin-x-ds/global/ListItem.tsx
new file mode 100644
index 0000000000..86e6a03290
--- /dev/null
+++ b/ghost/admin-x-settings/src/admin-x-ds/global/ListItem.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+
+interface ListItemProps {
+ id: string;
+ title?: React.ReactNode;
+ detail?: React.ReactNode;
+ action?: React.ReactNode;
+ hideActions?: boolean;
+
+ /**
+ * Hidden for the last item in the list
+ */
+ separator?: boolean;
+ onClick?: (e: React.MouseEvent) => void;
+}
+
+const ListItem: React.FC = ({id, title, detail, action, hideActions, separator, onClick}) => {
+ const handleClick = (e: React.MouseEvent) => {
+ onClick?.(e);
+ };
+
+ return (
+
+
+ {title}
+ {detail && {detail}}
+
+ {action &&
+
+ {action}
+
+ }
+
+ );
+};
+
+export default ListItem;
\ No newline at end of file
diff --git a/ghost/admin-x-settings/tailwind.config.cjs b/ghost/admin-x-settings/tailwind.config.cjs
index d4a23fe584..4200c5102e 100644
--- a/ghost/admin-x-settings/tailwind.config.cjs
+++ b/ghost/admin-x-settings/tailwind.config.cjs
@@ -186,7 +186,7 @@ module.exports = {
supertight: '1.1em'
},
transition: {
- basic: 'all 0.4 ease'
+ basic: 'all 0.4s ease'
}
}
}