diff --git a/lang/en/messages.php b/lang/en/messages.php index f5e7e230fb7..4b2008fcf65 100644 --- a/lang/en/messages.php +++ b/lang/en/messages.php @@ -291,5 +291,15 @@ 'user_wizard_invitation_subject' => 'Activate your new Statamic account on :site', 'user_wizard_roles_groups_intro' => 'Users can be assigned to roles that customize their permissions, access, and abilities throughout the Control Panel.', 'user_wizard_super_admin_instructions' => 'Super admins have complete control and access to everything in the control panel. Grant this role wisely.', + 'widget_classes_instructions' => 'Additional CSS classes applied to the widget wrapper.', + 'widget_collection_description' => 'Shows recent entries from a collection.', + 'widget_collection_fields_instructions' => 'Field handles to display as columns. Defaults to title.', + 'widget_collection_order_by_instructions' => 'Field and direction, e.g. date:desc or title:asc.', + 'widget_collection_title_instructions' => 'Override the widget title. Defaults to the collection title.', + 'widget_form_description' => 'Shows recent submissions for a form.', + 'widget_form_form_instructions' => 'The handle of the form to display submissions for.', + 'widget_template_description' => 'Renders a custom Blade or Antlers template.', + 'widget_template_template_instructions' => 'Path to the template, relative to the views directory.', + 'widget_updater_description' => 'Shows available updates for Statamic and your installed addons.', 'width_x_height' => ':width × :height', ]; diff --git a/resources/css/components/dashboard.css b/resources/css/components/dashboard.css new file mode 100644 index 00000000000..7323634b90b --- /dev/null +++ b/resources/css/components/dashboard.css @@ -0,0 +1,40 @@ +/* ========================================================================== + DASHBOARD WIDGET EDITING + ========================================================================== */ + +.dashboard-widget-inner { + @apply @container/widget relative rounded-xl; +} + +/* Hide the chrome on the dragging source — the mirror is what the user sees */ +.dashboard-widget-sortable.draggable-source--is-dragging .dashboard-widget-inner { + @apply opacity-50; +} + +.dashboard-widget-sortable.draggable-source--is-dragging [data-widget-edit-chrome] { + @apply opacity-0; +} + +.dashboard-widget-sortable.draggable-source--is-dragging .dashboard-widget-inner::after { + content: ''; + @apply pointer-events-none absolute inset-0 rounded-xl border-2 border-dashed border-ui-accent-bg/40 bg-ui-accent-bg/5 dark:bg-ui-accent-bg/10; +} + +/* Mirror — the floating element that follows the cursor while dragging */ +body > .draggable-mirror.dashboard-widget-mirror { + @apply rounded-xl shadow-ui-lg ring-1 ring-black/5 dark:ring-white/10; + transition: none !important; + will-change: transform; +} + +body > .draggable-mirror.dashboard-widget-mirror [data-widget-edit-chrome] { + @apply bg-white/95 dark:bg-gray-850/95; +} + +.dashboard-widget-placeholder { + @apply flex min-h-54 flex-col items-center justify-center gap-3 rounded-xl bg-gray-50 px-6 py-10 text-center ring-1 ring-black/5 dark:bg-gray-900/40 dark:ring-white/10; +} + +.dashboard-widget-empty { + @apply flex min-h-64 flex-col items-center justify-center gap-4 rounded-xl bg-gray-50 px-8 py-16 text-center ring-1 ring-black/5 dark:bg-gray-900/30 dark:ring-white/10; +} diff --git a/resources/css/cp.css b/resources/css/cp.css index dd8ab0f1172..542e7b73093 100644 --- a/resources/css/cp.css +++ b/resources/css/cp.css @@ -13,6 +13,7 @@ @import './components/assets.css'; @import './components/blueprints.css'; @import './components/configure.css'; +@import './components/dashboard.css'; @import './components/focal-point.css'; @import './components/index-fields.css'; @import './components/notifications.css'; diff --git a/resources/js/components/dashboard/WidgetConfigStack.vue b/resources/js/components/dashboard/WidgetConfigStack.vue new file mode 100644 index 00000000000..3b664b187c2 --- /dev/null +++ b/resources/js/components/dashboard/WidgetConfigStack.vue @@ -0,0 +1,54 @@ + + + diff --git a/resources/js/components/dashboard/WidgetEditChrome.vue b/resources/js/components/dashboard/WidgetEditChrome.vue new file mode 100644 index 00000000000..02768d79c8e --- /dev/null +++ b/resources/js/components/dashboard/WidgetEditChrome.vue @@ -0,0 +1,62 @@ + + + diff --git a/resources/js/components/dashboard/WidgetPicker.vue b/resources/js/components/dashboard/WidgetPicker.vue new file mode 100644 index 00000000000..28618f8d5a3 --- /dev/null +++ b/resources/js/components/dashboard/WidgetPicker.vue @@ -0,0 +1,26 @@ + + + diff --git a/resources/js/components/fields/WidthSelector.vue b/resources/js/components/fields/WidthSelector.vue index da07abae1af..fdf87f2e930 100644 --- a/resources/js/components/fields/WidthSelector.vue +++ b/resources/js/components/fields/WidthSelector.vue @@ -23,10 +23,11 @@ const selected = computed(() => { }) const wrapperClasses = cva({ - base: 'relative text-gray-600 dark:text-gray-400 font-mono antialiased bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 with-contrast:border-gray-500 overflow-hidden flex cursor-pointer', + base: 'relative text-gray-600 dark:text-gray-400 font-mono antialiased bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 with-contrast:border-gray-500 overflow-hidden flex cursor-pointer shadow-ui-sm', variants: { size: { base: 'h-6 w-14 text-xs rounded-md', + md: 'h-8 w-16 text-xs rounded-lg', lg: 'h-10 w-24 text-sm rounded-lg', }, }, diff --git a/resources/js/components/ui/Widget.vue b/resources/js/components/ui/Widget.vue index f4c9e791ed3..9665e5f104c 100644 --- a/resources/js/components/ui/Widget.vue +++ b/resources/js/components/ui/Widget.vue @@ -11,7 +11,6 @@ const props = defineProps({ const slots = useSlots(); const hasHeader = computed(() => Boolean(props.title || props.icon || slots.actions)); -