Skip to content
Draft
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
13 changes: 10 additions & 3 deletions site/lib/_sass/components/_tooltip.scss
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
.tooltip-wrapper {
position: relative;

a.tooltip-target {
color: inherit;
a.tooltip-target:has(+.tooltip) {
text-decoration: underline;
text-decoration-style: dotted;
}

a.tooltip-target[href*="glossary"] {
color: inherit;
}

.tooltip {
visibility: hidden;

Expand All @@ -30,6 +33,10 @@
font-weight: normal;
font-style: normal;

&.large {
width: 20rem;
}

.tooltip-header {
font-size: 1.2rem;
font-weight: 500;
Expand All @@ -53,7 +60,7 @@
}
}

// On touch devices, show tooltip on click (see global_scripts.dart).
// On touch devices, show tooltip on click.
@media all and (pointer: coarse) {
.tooltip.visible {
visibility: visible;
Expand Down
95 changes: 53 additions & 42 deletions site/lib/jaspr_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,36 @@
import 'package:jaspr/jaspr.dart';
import 'package:docs_flutter_dev_site/src/client/global_scripts.dart'
as prefix0;
import 'package:docs_flutter_dev_site/src/components/common/client/cookie_notice.dart'
import 'package:docs_flutter_dev_site/src/components/common/client/api_link_tooltip.dart'
as prefix1;
import 'package:docs_flutter_dev_site/src/components/common/client/copy_button.dart'
import 'package:docs_flutter_dev_site/src/components/common/client/cookie_notice.dart'
as prefix2;
import 'package:docs_flutter_dev_site/src/components/common/client/download_latest_button.dart'
import 'package:docs_flutter_dev_site/src/components/common/client/copy_button.dart'
as prefix3;
import 'package:docs_flutter_dev_site/src/components/common/client/feedback.dart'
import 'package:docs_flutter_dev_site/src/components/common/client/download_latest_button.dart'
as prefix4;
import 'package:docs_flutter_dev_site/src/components/common/client/on_this_page_button.dart'
import 'package:docs_flutter_dev_site/src/components/common/client/feedback.dart'
as prefix5;
import 'package:docs_flutter_dev_site/src/components/common/client/os_selector.dart'
import 'package:docs_flutter_dev_site/src/components/common/client/on_this_page_button.dart'
as prefix6;
import 'package:docs_flutter_dev_site/src/components/dartpad/dartpad_injector.dart'
import 'package:docs_flutter_dev_site/src/components/common/client/os_selector.dart'
as prefix7;
import 'package:docs_flutter_dev_site/src/components/layout/menu_toggle.dart'
import 'package:docs_flutter_dev_site/src/components/dartpad/dartpad_injector.dart'
as prefix8;
import 'package:docs_flutter_dev_site/src/components/layout/site_switcher.dart'
import 'package:docs_flutter_dev_site/src/components/layout/menu_toggle.dart'
as prefix9;
import 'package:docs_flutter_dev_site/src/components/layout/theme_switcher.dart'
import 'package:docs_flutter_dev_site/src/components/layout/site_switcher.dart'
as prefix10;
import 'package:docs_flutter_dev_site/src/components/pages/archive_table.dart'
import 'package:docs_flutter_dev_site/src/components/layout/theme_switcher.dart'
as prefix11;
import 'package:docs_flutter_dev_site/src/components/pages/glossary_search_section.dart'
import 'package:docs_flutter_dev_site/src/components/pages/archive_table.dart'
as prefix12;
import 'package:docs_flutter_dev_site/src/components/pages/learning_resource_filters.dart'
import 'package:docs_flutter_dev_site/src/components/pages/glossary_search_section.dart'
as prefix13;
import 'package:docs_flutter_dev_site/src/components/pages/learning_resource_filters_sidebar.dart'
import 'package:docs_flutter_dev_site/src/components/pages/learning_resource_filters.dart'
as prefix14;
import 'package:docs_flutter_dev_site/src/components/pages/learning_resource_filters_sidebar.dart'
as prefix15;

/// Default [JasprOptions] for use with your jaspr project.
///
Expand All @@ -58,92 +60,101 @@ JasprOptions get defaultJasprOptions => JasprOptions(
'src/client/global_scripts',
),

prefix1.CookieNotice: ClientTarget<prefix1.CookieNotice>(
prefix1.ApiLinkTooltip: ClientTarget<prefix1.ApiLinkTooltip>(
'src/components/common/client/api_link_tooltip',
params: _prefix1ApiLinkTooltip,
),

prefix2.CookieNotice: ClientTarget<prefix2.CookieNotice>(
'src/components/common/client/cookie_notice',
),

prefix2.CopyButton: ClientTarget<prefix2.CopyButton>(
prefix3.CopyButton: ClientTarget<prefix3.CopyButton>(
'src/components/common/client/copy_button',
params: _prefix2CopyButton,
params: _prefix3CopyButton,
),

prefix3.DownloadLatestButton: ClientTarget<prefix3.DownloadLatestButton>(
prefix4.DownloadLatestButton: ClientTarget<prefix4.DownloadLatestButton>(
'src/components/common/client/download_latest_button',
params: _prefix3DownloadLatestButton,
params: _prefix4DownloadLatestButton,
),

prefix4.FeedbackComponent: ClientTarget<prefix4.FeedbackComponent>(
prefix5.FeedbackComponent: ClientTarget<prefix5.FeedbackComponent>(
'src/components/common/client/feedback',
params: _prefix4FeedbackComponent,
params: _prefix5FeedbackComponent,
),

prefix5.OnThisPageButton: ClientTarget<prefix5.OnThisPageButton>(
prefix6.OnThisPageButton: ClientTarget<prefix6.OnThisPageButton>(
'src/components/common/client/on_this_page_button',
),

prefix6.OsSelector: ClientTarget<prefix6.OsSelector>(
prefix7.OsSelector: ClientTarget<prefix7.OsSelector>(
'src/components/common/client/os_selector',
),

prefix7.DartPadInjector: ClientTarget<prefix7.DartPadInjector>(
prefix8.DartPadInjector: ClientTarget<prefix8.DartPadInjector>(
'src/components/dartpad/dartpad_injector',
params: _prefix7DartPadInjector,
params: _prefix8DartPadInjector,
),

prefix8.MenuToggle: ClientTarget<prefix8.MenuToggle>(
prefix9.MenuToggle: ClientTarget<prefix9.MenuToggle>(
'src/components/layout/menu_toggle',
),

prefix9.SiteSwitcher: ClientTarget<prefix9.SiteSwitcher>(
prefix10.SiteSwitcher: ClientTarget<prefix10.SiteSwitcher>(
'src/components/layout/site_switcher',
),

prefix10.ThemeSwitcher: ClientTarget<prefix10.ThemeSwitcher>(
prefix11.ThemeSwitcher: ClientTarget<prefix11.ThemeSwitcher>(
'src/components/layout/theme_switcher',
),

prefix11.ArchiveTable: ClientTarget<prefix11.ArchiveTable>(
prefix12.ArchiveTable: ClientTarget<prefix12.ArchiveTable>(
'src/components/pages/archive_table',
params: _prefix11ArchiveTable,
params: _prefix12ArchiveTable,
),

prefix12.GlossarySearchSection:
ClientTarget<prefix12.GlossarySearchSection>(
prefix13.GlossarySearchSection:
ClientTarget<prefix13.GlossarySearchSection>(
'src/components/pages/glossary_search_section',
),

prefix13.LearningResourceFilters:
ClientTarget<prefix13.LearningResourceFilters>(
prefix14.LearningResourceFilters:
ClientTarget<prefix14.LearningResourceFilters>(
'src/components/pages/learning_resource_filters',
),

prefix14.LearningResourceFiltersSidebar:
ClientTarget<prefix14.LearningResourceFiltersSidebar>(
prefix15.LearningResourceFiltersSidebar:
ClientTarget<prefix15.LearningResourceFiltersSidebar>(
'src/components/pages/learning_resource_filters_sidebar',
),
},
styles: () => [],
);

Map<String, dynamic> _prefix2CopyButton(prefix2.CopyButton c) => {
Map<String, dynamic> _prefix1ApiLinkTooltip(prefix1.ApiLinkTooltip c) => {
'url': c.url,
'text': c.text,
};
Map<String, dynamic> _prefix3CopyButton(prefix3.CopyButton c) => {
'toCopy': c.toCopy,
'buttonText': c.buttonText,
'classes': c.classes,
'title': c.title,
};
Map<String, dynamic> _prefix3DownloadLatestButton(
prefix3.DownloadLatestButton c,
Map<String, dynamic> _prefix4DownloadLatestButton(
prefix4.DownloadLatestButton c,
) => {'os': c.os, 'arch': c.arch};
Map<String, dynamic> _prefix4FeedbackComponent(prefix4.FeedbackComponent c) => {
Map<String, dynamic> _prefix5FeedbackComponent(prefix5.FeedbackComponent c) => {
'issueUrl': c.issueUrl,
};
Map<String, dynamic> _prefix7DartPadInjector(prefix7.DartPadInjector c) => {
Map<String, dynamic> _prefix8DartPadInjector(prefix8.DartPadInjector c) => {
'title': c.title,
'theme': c.theme,
'height': c.height,
'runAutomatically': c.runAutomatically,
};
Map<String, dynamic> _prefix11ArchiveTable(prefix11.ArchiveTable c) => {
Map<String, dynamic> _prefix12ArchiveTable(prefix12.ArchiveTable c) => {
'os': c.os,
'channel': c.channel,
};
45 changes: 25 additions & 20 deletions site/lib/src/client/global_scripts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -458,13 +458,14 @@ void _setUpTooltips() {
void setup({required bool setUpClickListener}) {
for (var i = 0; i < tooltipWrappers.length; i++) {
final linkWrapper = tooltipWrappers.item(i) as web.HTMLElement;
final target = linkWrapper.querySelector('.tooltip-target');
final target =
linkWrapper.querySelector('.tooltip-target') as web.HTMLElement?;
final tooltip = linkWrapper.querySelector('.tooltip') as web.HTMLElement?;

if (target == null || tooltip == null) {
continue;
}
_ensureVisible(tooltip);
_ensureVisible(target, tooltip);

if (setUpClickListener && isTouchscreen) {
// On touchscreen devices, toggle tooltip visibility on tap.
Expand All @@ -483,9 +484,7 @@ void _setUpTooltips() {
}

void closeAll() {
final visibleTooltips = web.document.querySelectorAll(
'.tooltip.visible',
);
final visibleTooltips = web.document.querySelectorAll('.tooltip.visible');
for (var i = 0; i < visibleTooltips.length; i++) {
final tooltip = visibleTooltips.item(i) as web.HTMLElement;
tooltip.classList.remove('visible');
Expand Down Expand Up @@ -516,26 +515,32 @@ void _setUpTooltips() {

/// Adjust the tooltip position to ensure it is fully inside the
/// ancestor .content element.
void _ensureVisible(web.HTMLElement tooltip) {
final containerRect = tooltip.closest('.content')?.getBoundingClientRect();
void _ensureVisible(web.HTMLElement target, web.HTMLElement tooltip) {
final newOffset = calculateTooltipOffset(target, tooltip);
tooltip.style.left = newOffset == 0
? '50%'
: 'calc(50% ${newOffset > 0 ? '+' : '-'} ${newOffset.abs()}px)';
}

double calculateTooltipOffset(web.HTMLElement target, web.HTMLElement tooltip) {
final targetRect = target.getBoundingClientRect();
final tooltipRect = tooltip.getBoundingClientRect();
final offset = double.parse(tooltip.getAttribute('data-adjusted') ?? '0');
final containerRect = tooltip.closest('.content')?.getBoundingClientRect();

final targetCenter = targetRect.left + (targetRect.width / 2);
final tooltipWidth = tooltipRect.width;

final initialLeft = targetCenter - (tooltipWidth / 2);
final initialRight = targetCenter + (tooltipWidth / 2);

final tooltipLeft = tooltipRect.left - offset;
final tooltipRight = tooltipRect.right - offset;
final containerLeft = containerRect?.left ?? 0.0;
final containerRight = containerRect?.right ?? web.window.innerWidth;

if (tooltipLeft < containerLeft) {
final offset = containerLeft - tooltipLeft;
tooltip.style.left = 'calc(50% + ${offset}px)';
tooltip.dataset['adjusted'] = offset.toString();
} else if (tooltipRight > containerRight) {
final offset = tooltipRight - containerRight;
tooltip.style.left = 'calc(50% - ${offset}px)';
tooltip.dataset['adjusted'] = (-offset).toString();
if (initialLeft < containerLeft) {
return containerLeft - initialLeft;
} else if (initialRight > containerRight) {
return containerRight - initialRight;
} else {
tooltip.style.left = '50%';
tooltip.dataset['adjusted'] = '0';
return 0;
}
}
Loading
Loading