From 8a6f87ebf1715c922e746dc576742aa0f9b936a2 Mon Sep 17 00:00:00 2001 From: Afiq Date: Wed, 6 Aug 2025 15:33:55 +0800 Subject: [PATCH] Enhance Button Customization in Form Builder - Updated ComponentPreview.vue to support custom button styles, allowing users to define background color, text color, border color, border width, border radius, and hover effects for buttons. - Enhanced FormBuilderFieldSettingsModal.vue with new fields for customizing button appearance, including color pickers and number inputs for border properties. - Implemented a color preview feature in the settings modal to visualize button styles based on user selections, improving usability and customization options. - Added utility functions for generating custom button styles dynamically, ensuring consistent styling across the application. --- components/ComponentPreview.vue | 165 +++++++++++++++++-- components/FormBuilderFieldSettingsModal.vue | 143 +++++++++++++++- 2 files changed, 291 insertions(+), 17 deletions(-) diff --git a/components/ComponentPreview.vue b/components/ComponentPreview.vue index d70abb2..892dbd2 100644 --- a/components/ComponentPreview.vue +++ b/components/ComponentPreview.vue @@ -336,26 +336,66 @@ {{ component.props.label }} - - - +
+ + + + + + + +
+ + +
+ + + + {{ component.props.buttonText || component.props.label || 'Button' }} + + + + + + {{ component.props.buttonText || component.props.label || 'Button' }} - - - - - {{ component.props.buttonText || component.props.label || 'Button' }} - - +
{{ component.props.help }} @@ -1382,6 +1422,61 @@ const getButtonLink = () => { return null; }; + +// Custom button styling functions +const getCustomButtonStyles = (props) => { + if (!props || props.variant !== 'custom') return {}; + + const styles = { + backgroundColor: props.customBackgroundColor || '#3b82f6', + color: props.customTextColor || '#ffffff', + border: 'none', + cursor: 'pointer', + transition: 'all 0.2s ease-in-out' + }; + + // Add border if specified + if (props.customBorderColor && props.customBorderWidth) { + styles.border = `${props.customBorderWidth}px solid ${props.customBorderColor}`; + } + + // Add border radius + if (props.customBorderRadius) { + styles.borderRadius = `${props.customBorderRadius}px`; + } + + // Add hover effects + const hoverEffect = props.customHoverEffect; + if (hoverEffect && hoverEffect !== 'none') { + switch (hoverEffect) { + case 'darken': + styles[':hover'] = { filter: 'brightness(0.9)' }; + break; + case 'lighten': + styles[':hover'] = { filter: 'brightness(1.1)' }; + break; + case 'scale': + styles[':hover'] = { transform: 'scale(1.05)' }; + break; + case 'glow': + styles[':hover'] = { + boxShadow: `0 0 10px ${props.customBackgroundColor || '#3b82f6'}` + }; + break; + } + } + + return styles; +}; + +const getButtonSizeClass = (size) => { + const sizeClasses = { + 'sm': 'px-3 py-1.5 text-sm', + 'md': 'px-4 py-2 text-sm', + 'lg': 'px-6 py-3 text-base' + }; + return sizeClasses[size] || sizeClasses['md']; +}; \ No newline at end of file diff --git a/components/FormBuilderFieldSettingsModal.vue b/components/FormBuilderFieldSettingsModal.vue index b6f5fcb..0045192 100644 --- a/components/FormBuilderFieldSettingsModal.vue +++ b/components/FormBuilderFieldSettingsModal.vue @@ -503,13 +503,111 @@ { label: 'Secondary (Gray)', value: 'secondary' }, { label: 'Success (Green)', value: 'success' }, { label: 'Danger (Red)', value: 'danger' }, - { label: 'Warning (Orange)', value: 'warning' } + { label: 'Warning (Orange)', value: 'warning' }, + { label: 'Custom Color', value: 'custom' } ]" help="Visual appearance of the button" :classes="{ outer: 'field-wrapper' }" />
+ +
+
Custom Color Settings
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ + +
+
Color Preview
+
+ +
+
Background: {{ configModel.customBackgroundColor || '#3b82f6' }}
+
Text: {{ configModel.customTextColor || '#ffffff' }}
+
Border: {{ configModel.customBorderColor || 'transparent' }}
+
+
+
+
+
{ return queryString ? `${baseUrl}?${queryString}` : baseUrl } +// Generate custom button styles for preview +const getCustomButtonStyles = () => { + const styles = { + backgroundColor: configModel.value.customBackgroundColor || '#3b82f6', + color: configModel.value.customTextColor || '#ffffff', + border: 'none', + cursor: 'pointer' + } + + // Add border if specified + if (configModel.value.customBorderColor && configModel.value.customBorderWidth) { + styles.border = `${configModel.value.customBorderWidth}px solid ${configModel.value.customBorderColor}` + } + + // Add border radius + if (configModel.value.customBorderRadius) { + styles.borderRadius = `${configModel.value.customBorderRadius}px` + } + + // Add hover effects + const hoverEffect = configModel.value.customHoverEffect + if (hoverEffect && hoverEffect !== 'none') { + switch (hoverEffect) { + case 'darken': + styles[':hover'] = { filter: 'brightness(0.9)' } + break + case 'lighten': + styles[':hover'] = { filter: 'brightness(1.1)' } + break + case 'scale': + styles[':hover'] = { transform: 'scale(1.05)' } + break + case 'glow': + styles[':hover'] = { + boxShadow: `0 0 10px ${configModel.value.customBackgroundColor || '#3b82f6'}` + } + break + } + } + + return styles +} + // Type changing functionality const compatibilityGroups = { // Text-based inputs (can switch between each other)