Skip to content

feat(flutter_sanity_portable_text): support scoped PortableTextConfig per block#56

Open
JoshStrobl wants to merge 2 commits intovyuh-tech:mainfrom
JoshStrobl:feat/portable-text-custom-spacing
Open

feat(flutter_sanity_portable_text): support scoped PortableTextConfig per block#56
JoshStrobl wants to merge 2 commits intovyuh-tech:mainfrom
JoshStrobl:feat/portable-text-custom-spacing

Conversation

@JoshStrobl
Copy link
Copy Markdown

PortableTextBlock always reads from the global PortableTextConfig.shared singleton, which means properties like itemPadding cannot be overridden per-instance.

I ran into this when I was trying to render blocks inside a Row with CrossAxisAlignment.center. The default 8px bottom itemPadding inflates each block's layout height, causing the cross-axis center to be calculated against the padded height rather than the visible text.

I checked using Flutter's debugDumpApp widget tree output, which showed the padding persisting regardless of attempts to temporarily mutate the shared config, since PortableTextBlock.build() reads the config at framework build time, not at widget creation time.

Added PortableTextConfig.from() factory constructor that creates a new config instance by copying an existing one with optional overrides. Added an optional config parameter to PortableTextBlock so callers can pass a scoped config instead of relying on the shared singleton. This means the PortableTextBlock styling can more easily differ across multiple instances in an app.

Not specify will use the default shared config, so there should be no functional regressions. Just in case I added a bunch of tests.

… per block

PortableTextBlock always reads from the global PortableTextConfig.shared singleton, which means properties like itemPadding cannot be overridden per-instance.

I ran into this when I was trying to render blocks inside a Row with CrossAxisAlignment.center. The default 8px bottom itemPadding inflates each block's layout height, causing the cross-axis center to be calculated against the padded height rather than the visible text.

I checked using Flutter's debugDumpApp widget tree output, which showed the padding persisting regardless of attempts to temporarily mutate the shared config, since PortableTextBlock.build() reads the config at framework build time, not at widget creation time.

Added PortableTextConfig.from() factory constructor that creates a new config instance by copying an existing one with optional overrides. Added an optional config parameter to PortableTextBlock so callers can pass a scoped config instead of relying on the shared singleton. This means the PortableTextBlock styling can more easily differ across multiple instances in an app.

Not specify will use the default shared config, so there should be no functional regressions. Just in case I added a bunch of tests.
Comment on lines +83 to +100
factory PortableTextConfig.from(
PortableTextConfig source, {
EdgeInsets? itemPadding,
double? listIndent,
BulletRenderer? bulletRenderer,
TextStyle? Function(BuildContext)? baseStyle,
}) {
final copy = PortableTextConfig._();
copy.styles.addAll(source.styles);
copy.blocks.addAll(source.blocks);
copy.blockContainers.addAll(source.blockContainers);
copy.markDefs.addAll(source.markDefs);
copy.baseStyle = baseStyle ?? source.baseStyle;
copy.bulletRenderer = bulletRenderer ?? source.bulletRenderer;
copy.itemPadding = itemPadding ?? source.itemPadding;
copy.listIndent = listIndent ?? source.listIndent;
return copy;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a factory method, you can actually use an instance method with copyFrom, which is the typical Flutter-based pattern, or you can name it apply, where you pass on all the parameters that you want to overwrite. That way, you can use an existing instance and then override from that.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair! I'll get this squared away :)

Copy link
Copy Markdown
Author

@JoshStrobl JoshStrobl Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pavanpodila I went ahead and implemented it as a copyWith as there was already an apply function that would simply override the existing properties on the class. The copyWith will return a new PortableTextConfig, using the existing one as a baseline for properties.

So in my app I'd do something like PortableTextConfig.shared.copyWith(...) which provides me the same end result, enabling me to override styling and item padding in a copy without impacting the shared instance.

Does this seem good to you?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya that should work for your use case. You will baseline from shared and override with your values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants