Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: enhancement

Donations block: add modal display mode with trigger button, configurable icon, and animated overlay.
34 changes: 22 additions & 12 deletions projects/plugins/jetpack/extensions/blocks/donations/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,6 @@
"fontWeight": true,
"lineHeight": true,
"letterSpacing": true
},
"__experimentalBorder": {
"color": true,
"radius": true,
"style": true,
"width": true,
"__experimentalDefaultControls": {
"color": true,
"radius": true,
"style": true,
"width": true
}
}
},
"attributes": {
Expand Down Expand Up @@ -180,6 +168,28 @@
},
"maximumAmount": {
"type": "number"
},
"displayMode": {
"type": "string",
"enum": [ "inline", "modal" ],
"default": "inline"
},
"triggerButtonText": {
"type": "string"
},
"triggerIcon": {
"type": "string",
"default": "heart"
},
"triggerSticky": {
"type": "boolean",
"default": false
},
"blockBorder": {
"type": "object"
},
"blockBorderRadius": {
"type": [ "string", "object" ]
}
},
"example": {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ const buildCustomStyles = ( attributes, scope ) => {
buttonAlignment,
buttonBorderRadius,
contentAlignment,
blockBorder,
blockBorderRadius,
displayMode,
} = attributes;

const rules = [];
Expand Down Expand Up @@ -190,6 +193,20 @@ const buildCustomStyles = ( attributes, scope ) => {
}
}

if ( displayMode !== 'modal' ) {
const wrapperBorderDecls = [
...borderDecls( blockBorder ),
...radiusDecls( blockBorderRadius ),
];
if ( wrapperBorderDecls.length ) {
rules.push( `.wp-block-jetpack-donations${ scope }{${ wrapperBorderDecls.join( ';' ) }}` );
}
}

if ( displayMode === 'modal' && [ 'left', 'center', 'right' ].includes( contentAlignment ) ) {
rules.push( `${ scope }{text-align:${ contentAlignment }}` );
}

return rules.join( '' );
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@
margin: 0;
}

// Pop-up display mode: suppress the default border — the block wrapper is
// larger than just the trigger button, so a border here looks wrong.
// User-set borders in In-page mode are handled via the per-instance <style>.
&.is-display-modal {
border: none;
}

// "Buttons" style variation: render the frequency selectors as a row of
// pill-shaped buttons instead of edge-to-edge tabs. Per-state colors and
// tab dimensions set in the inspector still apply on top of these rules.
Expand Down
118 changes: 116 additions & 2 deletions projects/plugins/jetpack/extensions/blocks/donations/controls.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
import formatCurrency, { CURRENCIES } from '@automattic/format-currency';
import { getSiteFragment } from '@automattic/jetpack-shared-extension-utils';
import { AlignmentControl, BlockControls, InspectorControls } from '@wordpress/block-editor';
import {
AlignmentControl,
BlockControls,
InspectorControls,
__experimentalBorderRadiusControl as BorderRadiusControl, // eslint-disable-line @wordpress/no-unsafe-wp-apis
} from '@wordpress/block-editor';
import {
BorderBoxControl,
Button,
Dashicon,
Dropdown,
ExternalLink,
Flex,
FlexBlock,
FlexItem,
Icon,
MenuGroup,
MenuItem,
PanelBody,
SelectControl,
TextControl,
ToggleControl,
__experimentalToggleGroupControl as ToggleGroupControl, // eslint-disable-line @wordpress/no-unsafe-wp-apis
__experimentalToggleGroupControlOption as ToggleGroupControlOption, // eslint-disable-line @wordpress/no-unsafe-wp-apis
__experimentalToolsPanel as ToolsPanel, // eslint-disable-line @wordpress/no-unsafe-wp-apis
__experimentalToolsPanelItem as ToolsPanelItem, // eslint-disable-line @wordpress/no-unsafe-wp-apis
ToolbarGroup,
ToolbarItem,
ToolbarButton,
Tooltip,
} from '@wordpress/components';
import { useCallback } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
Expand All @@ -26,6 +39,7 @@ import {
minimumTransactionAmountForCurrency,
SUPPORTED_CURRENCIES,
} from '../../shared/currencies';
import { TRIGGER_ICONS } from './icons';
import { firstShownInterval } from './utils';

const INTERVAL_TO_ATTRIBUTE = {
Expand All @@ -35,7 +49,7 @@ const INTERVAL_TO_ATTRIBUTE = {
};

const Controls = props => {
const { attributes, setAttributes } = props;
const { attributes, setAttributes, clientId } = props;
const {
currency,
oneTimeDonation,
Expand All @@ -47,6 +61,12 @@ const Controls = props => {
customAmountPlaceholder,
minimumAmount,
maximumAmount,
displayMode,
triggerButtonText,
triggerIcon,
triggerSticky,
blockBorder,
blockBorderRadius,
} = attributes;

const stripeMin = minimumTransactionAmountForCurrency( currency );
Expand Down Expand Up @@ -216,6 +236,60 @@ const Controls = props => {
</ToolbarGroup>
</BlockControls>
<InspectorControls>
<PanelBody title={ __( 'Display', 'jetpack' ) }>
<ToggleGroupControl
label={ __( 'Display mode', 'jetpack' ) }
value={ displayMode }
onChange={ value => setAttributes( { displayMode: value } ) }
isBlock
__nextHasNoMarginBottom={ true }
>
<ToggleGroupControlOption value="inline" label={ __( 'In-page', 'jetpack' ) } />
<ToggleGroupControlOption value="modal" label={ __( 'Pop-up', 'jetpack' ) } />
</ToggleGroupControl>
{ displayMode === 'modal' && (
<>
<ToggleControl
label={ __( 'Sticky', 'jetpack' ) }
help={ __( 'Fix the button to the bottom right corner of the page.', 'jetpack' ) }
checked={ !! triggerSticky }
onChange={ value => setAttributes( { triggerSticky: value } ) }
style={ { marginTop: 16 } }
__nextHasNoMarginBottom={ true }
/>
<TextControl
label={ __( 'Button text', 'jetpack' ) }
value={ triggerButtonText ?? '' }
placeholder={ __( 'Donate', 'jetpack' ) }
onChange={ value => setAttributes( { triggerButtonText: value || undefined } ) }
__nextHasNoMarginBottom={ true }
/>
<ToggleControl
label={ __( 'Show icon', 'jetpack' ) }
checked={ triggerIcon !== 'none' }
onChange={ value => setAttributes( { triggerIcon: value ? 'heart' : 'none' } ) }
style={ { marginTop: 16 } }
__nextHasNoMarginBottom={ true }
/>
{ triggerIcon !== 'none' && (
<div className="jetpack-donations__icon-picker">
{ TRIGGER_ICONS.map( ( { key, label, icon } ) => (
<Tooltip key={ key } text={ label }>
<Button
className="jetpack-donations__icon-option"
onClick={ () => setAttributes( { triggerIcon: key } ) }
aria-label={ label }
isPressed={ triggerIcon === key }
>
<Icon icon={ icon } size={ 20 } />
</Button>
</Tooltip>
) ) }
</div>
) }
</>
) }
</PanelBody>
<PanelBody title={ __( 'Settings', 'jetpack' ) }>
<ToggleControl
checked={ oneTimeOn }
Expand Down Expand Up @@ -385,6 +459,46 @@ const Controls = props => {
/>
</PanelBody>
</InspectorControls>
{ displayMode !== 'modal' && (
<InspectorControls group="border">
<ToolsPanel
label={ __( 'Border', 'jetpack' ) }
resetAll={ () =>
setAttributes( { blockBorder: undefined, blockBorderRadius: undefined } )
}
panelId={ clientId }
>
<ToolsPanelItem
label={ __( 'Border', 'jetpack' ) }
hasValue={ () => !! blockBorder }
onDeselect={ () => setAttributes( { blockBorder: undefined } ) }
isShownByDefault
panelId={ clientId }
>
<BorderBoxControl
label={ __( 'Border', 'jetpack' ) }
value={ blockBorder }
onChange={ value => setAttributes( { blockBorder: value } ) }
enableAlpha
enableStyle
__next40pxDefaultSize
/>
</ToolsPanelItem>
<ToolsPanelItem
label={ __( 'Radius', 'jetpack' ) }
hasValue={ () => !! blockBorderRadius }
onDeselect={ () => setAttributes( { blockBorderRadius: undefined } ) }
isShownByDefault
panelId={ clientId }
>
<BorderRadiusControl
values={ blockBorderRadius }
onChange={ value => setAttributes( { blockBorderRadius: value } ) }
/>
</ToolsPanelItem>
</ToolsPanel>
</InspectorControls>
) }
</>
);
};
Expand Down
Loading
Loading