Skip to content
Merged
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
38 changes: 1 addition & 37 deletions site/lib/_sass/base/_base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -158,43 +158,6 @@ main figure {
font-style: italic;
text-align: center;
}

&.code-and-image {
gap: 0.25rem;
justify-content: space-between;
flex-direction: row;
flex-wrap: wrap;

>div {
width: 100%;

&:last-child {
text-align: center;
}
}

@media(min-width: 769px) {
>div {
&:first-child {
flex: 0 0 58%;
max-width: 58%;
}

&:last-child {
flex: 0 0 40%;
max-width: 40%;
}
}

figcaption {
text-align: left;
}

img {
max-width: 100%;
}
}
}
}

.text-icon {
Expand Down Expand Up @@ -439,6 +402,7 @@ p+dl {
}

.figure-caption {
margin-top: 0.25rem;
font-size: .875rem;
font-style: italic;
color: var(--site-base-fgColor-lighter);
Expand Down
65 changes: 63 additions & 2 deletions site/lib/_sass/components/_code.scss
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@ pre {
}

.code-block-wrapper {
display: flex;
flex-direction: column;

margin-block-start: 1rem;
margin-block-end: 1rem;
border: 1px solid var(--site-inset-borderColor);
Expand All @@ -292,6 +295,8 @@ pre {
}

.code-block-body {
flex-grow: 1;

position: relative;
background: none;

Expand Down Expand Up @@ -328,6 +333,7 @@ pre {
}

pre {
height: 100%;
margin: 0;
padding-right: 0;
padding-left: 0;
Expand Down Expand Up @@ -358,8 +364,8 @@ iframe[src^="https://dartpad"] {
--file-tree-text: var(--site-base-fgColor);
--file-tree-icon: var(--site-base-fgColor-alt);
--file-tree-highlight: var(--site-link-fgColor);
font-family: var(--site-code-fontFamily);

font-family: var(--site-code-fontFamily);

border: 1px solid var(--site-inset-borderColor);
margin-block-start: 1rem;
Expand All @@ -374,3 +380,58 @@ iframe[src^="https://dartpad"] {
}
}
}

.code-preview {
display: flex;
flex-direction: column;

border: 1px solid var(--site-inset-borderColor);
margin-block-start: 1rem;
margin-block-end: 1rem;

.preview-area {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;

padding: 2rem;
text-align: center;

&.fixed-bg * {
// --site-base-fgColor-lighter, but fixed to light mode variant.
color: #{color.scale(#212121, $lightness: 20%)}
}
}

.code-block-wrapper {
border: none;
margin: 0;

border-top: inherit;
}

&[data-direction="row"] {
flex-direction: row-reverse;
flex-wrap: wrap;

>* {
width: 100%;
}

@media (min-width: 760px) {
.preview-area {
flex: 0 0 42%;
max-width: 42%;
}

.code-block-wrapper {
flex: 0 0 58%;
max-width: 58%;

border-top: none;
border-right: inherit;
}
}
}
}
2 changes: 2 additions & 0 deletions site/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'jaspr_options.dart'; // Generated. Do not remove or edit.
import 'src/components/common/card.dart';
import 'src/components/common/client/download_latest_button.dart';
import 'src/components/common/client/os_selector.dart';
import 'src/components/common/code_preview.dart';
import 'src/components/common/dash_image.dart';
import 'src/components/common/tabs.dart';
import 'src/components/common/youtube_embed.dart';
Expand Down Expand Up @@ -97,6 +98,7 @@ final RegExp _passThroughPattern = RegExp(r'.*\.(txt|json|pdf)$');
List<CustomComponent> get _embeddableComponents => [
const DashTabs(),
const DashImage(),
const CodePreview(),
const YoutubeEmbed(),
const FileTree(),
const Quiz(),
Expand Down
74 changes: 74 additions & 0 deletions site/lib/src/components/common/code_preview.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2025 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:jaspr/jaspr.dart';
import 'package:jaspr_content/jaspr_content.dart';

import '../../util.dart';
import 'wrapped_code_block.dart';

/// A component that displays a preview area alongside a code block.
///
/// The `<CodePreview>` component takes in standard markdown content, but
/// expects at least two children, with the last child being a code block.
/// Any content before the last child is treated as the preview area.
class CodePreview extends CustomComponent {
const CodePreview() : super.base();

@override
Component? create(Node node, NodesBuilder builder) {
if (node case ElementNode(
tag: 'CodePreview',
:final attributes,
:final children?,
)) {
if (children.length < 2) {
throw Exception('CodePreview requires at least two child elements.');
}
final lastChild = children.last;
if (lastChild is! ComponentNode ||
lastChild.component is! WrappedCodeBlock) {
throw Exception(
'The last child of CodePreview must be a code block.',
);
}

final previewChildren = <Node>[];

for (var i = 0; i < children.length - 1; i++) {
if (children[i] case ElementNode(tag: 'p', :final children?)) {
// Unwrap paragraph nodes to avoid extra spacing.
previewChildren.addAll(children);
} else {
previewChildren.add(children[i]);
}
}

final direction = attributes['direction'] ?? 'column';
final previewColor = attributes['previewcolor'];

return div(
classes: 'code-preview',
attributes: {'data-direction': direction},
[
div(
classes: [
'preview-area',
if (previewColor != null) 'fixed-bg',
].toClasses,
styles: previewColor != null
? Styles(backgroundColor: Color(previewColor))
: null,
[
builder.build(previewChildren),
],
),
lastChild.component,
],
);
}

return null;
}
}
2 changes: 1 addition & 1 deletion site/lib/src/style_hash.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
// dart format off

/// The generated hash of the `main.css` file.
const generatedStylesHash = 'zSDH5bNiGRA1';
const generatedStylesHash = 'xNb0lgKhtevj';
27 changes: 0 additions & 27 deletions src/_includes/docs/code-and-image.md

This file was deleted.

40 changes: 22 additions & 18 deletions src/content/app-architecture/case-study/ui-layer.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,26 +404,30 @@ a [`Dismissible`][] widget.

Recall this code from the previous snippet:

{% render "docs/code-and-image.md",
image:"app-architecture/case-study/dismissible.webp",
img-style:"max-height: 480px; border-radius: 12px; border: black 2px solid;",
alt: "A clip that demonstrates the 'dismissible' functionality of the Compass app."
code:"
```dart title=home_screen.dart highlightLines=9-10
SliverList.builder(
itemCount: widget.viewModel.bookings.length,
itemBuilder: (_, index) => _Booking(
key: ValueKey(viewModel.bookings[index].id),
booking: viewModel.bookings[index],
onTap: () => context.push(
Routes.bookingWithId(viewModel.bookings[index].id)
<CodePreview direction="row">

<DashImage
image="app-architecture/case-study/dismissible.webp"
alt="A clip that demonstrates the 'dismissible' functionality of the Compass app."
img-style="max-height: 480px; border-radius: 12px; border: black 2px solid;"
/>

```dart title=home_screen.dart highlightLines=9-10
SliverList.builder(
itemCount: widget.viewModel.bookings.length,
itemBuilder: (_, index) => _Booking(
key: ValueKey(viewModel.bookings[index].id),
booking: viewModel.bookings[index],
onTap: () => context.push(
Routes.bookingWithId(viewModel.bookings[index].id)
),
onDismissed: (_) =>
viewModel.deleteBooking.execute(widget.viewModel.bookings[index].id),
),
onDismissed: (_) =>
viewModel.deleteBooking.execute(widget.viewModel.bookings[index].id),
),
),
```
" %}
```

</CodePreview>

On the `HomeScreen`, a user's saved trip is represented by
the `_Booking` widget. When a `_Booking` is dismissed,
Expand Down
Loading