diff --git a/packages/shared-ui/src/index.ts b/packages/shared-ui/src/index.ts index 4f08f1e03..1eacc976c 100644 --- a/packages/shared-ui/src/index.ts +++ b/packages/shared-ui/src/index.ts @@ -20,8 +20,11 @@ export { SkeletonBox, SkeletonText } from './molecules'; // Feedback export { EmptyState } from './molecules'; +// Layout +export { ModalFooter, DataCard, PageHeader } from './molecules'; + // Organisms -export { Modal, ConfirmationModal, AppSlider } from './organisms'; +export { Modal, ConfirmationModal, FormModal, AppSlider } from './organisms'; export type { AppItem } from './organisms'; // Navigation diff --git a/packages/shared-ui/src/molecules/DataCard.svelte b/packages/shared-ui/src/molecules/DataCard.svelte new file mode 100644 index 000000000..0555951ab --- /dev/null +++ b/packages/shared-ui/src/molecules/DataCard.svelte @@ -0,0 +1,154 @@ + + +
{ + if (isClickable && onclick && (e.key === 'Enter' || e.key === ' ')) { + e.preventDefault(); + onclick(); + } + }} + role={isClickable ? 'button' : undefined} + tabindex={isClickable ? 0 : undefined} +> +
+ + {#if icon} +
+ {@render icon()} +
+ {/if} + + +
+
+
+ + + {title} + + + + {#if description} + + {description} + + {/if} +
+ + + {#if badge} +
+ {@render badge()} +
+ {/if} +
+ + + {#if metadata} + + {/if} +
+ + + {#if actions} +
e.stopPropagation()}> + {@render actions()} +
+ {/if} +
+
+ + diff --git a/packages/shared-ui/src/molecules/ModalFooter.svelte b/packages/shared-ui/src/molecules/ModalFooter.svelte new file mode 100644 index 000000000..2d7a96d96 --- /dev/null +++ b/packages/shared-ui/src/molecules/ModalFooter.svelte @@ -0,0 +1,85 @@ + + + diff --git a/packages/shared-ui/src/molecules/PageHeader.svelte b/packages/shared-ui/src/molecules/PageHeader.svelte new file mode 100644 index 000000000..e2bb74f1b --- /dev/null +++ b/packages/shared-ui/src/molecules/PageHeader.svelte @@ -0,0 +1,139 @@ + + + diff --git a/packages/shared-ui/src/molecules/index.ts b/packages/shared-ui/src/molecules/index.ts index dd03d9b1a..0c10faf53 100644 --- a/packages/shared-ui/src/molecules/index.ts +++ b/packages/shared-ui/src/molecules/index.ts @@ -19,3 +19,8 @@ export { SkeletonBox, SkeletonText } from './loaders'; // Feedback components export { EmptyState } from './feedback'; + +// Layout components +export { default as ModalFooter } from './ModalFooter.svelte'; +export { default as DataCard } from './DataCard.svelte'; +export { default as PageHeader } from './PageHeader.svelte'; diff --git a/packages/shared-ui/src/organisms/FormModal.svelte b/packages/shared-ui/src/organisms/FormModal.svelte new file mode 100644 index 000000000..e472394c9 --- /dev/null +++ b/packages/shared-ui/src/organisms/FormModal.svelte @@ -0,0 +1,117 @@ + + + +
+ + {#if error} +
+ + {error} + +
+ {/if} + + + {@render children()} +
+ + {#snippet footer()} +
+ + +
+ {/snippet} +
diff --git a/packages/shared-ui/src/organisms/index.ts b/packages/shared-ui/src/organisms/index.ts index 2dc96f6c6..893900c0e 100644 --- a/packages/shared-ui/src/organisms/index.ts +++ b/packages/shared-ui/src/organisms/index.ts @@ -1,4 +1,5 @@ export { default as Modal } from './Modal.svelte'; export { default as ConfirmationModal } from './ConfirmationModal.svelte'; +export { default as FormModal } from './FormModal.svelte'; export { default as AppSlider } from './AppSlider.svelte'; export type { AppItem } from './AppSlider.types';