diff --git a/src/_data/glossary.yml b/src/_data/glossary.yml index 16dad21cd7..f2e0183b85 100644 --- a/src/_data/glossary.yml +++ b/src/_data/glossary.yml @@ -10,6 +10,7 @@ related_links: - text: "Refactor" link: "#refactor" + type: "term" labels: - "tools" - "analyzer" @@ -62,8 +63,10 @@ related_links: - text: "Final and const variables" link: "/language/variables#final-and-const" + type: "doc" - text: "Don't use const redundantly" link: "/effective-dart/usage#dont-use-const-redundantly" + type: "doc" labels: - "language" - "const" @@ -166,8 +169,10 @@ related_links: - text: "Definite assignment specification" link: "https://github.com/dart-lang/language/blob/main/resources/type-system/flow-analysis.md" + type: "doc" - text: "Understanding definite assignment analysis" link: "/null-safety/understanding-null-safety#definite-assignment-analysis" + type: "doc" labels: - "language" - "flow analysis" @@ -180,8 +185,10 @@ related_links: - text: "Functions overview" link: "/language/functions" + type: "doc" - text: "Instance methods" link: "/language/methods" + type: "doc" labels: - "language" - "umbrella term" @@ -202,8 +209,10 @@ related_links: - text: "Places patterns can appear" link: "/language/patterns#places-patterns-can-appear" + type: "doc" - text: "Dive into Dart patterns and records" link: "https://codelabs.developers.google.com/codelabs/dart-patterns-records" + type: "tutorial" labels: - "language" - "patterns" @@ -249,6 +258,7 @@ related_links: - text: "Mixins in Dart" link: "/language/mixins" + type: "doc" labels: - "language" - "understanding diagnostics" @@ -321,6 +331,7 @@ related_links: - text: "Inheritance in Dart" link: "/language/extend" + type: "doc" labels: - "language" - "type inference" @@ -335,8 +346,10 @@ related_links: - text: "Guidance on libraries and parts" link: "/tools/pub/create-packages#organizing-a-package" + type: "doc" - text: "Use library URIs in `part of` directives" link: "/effective-dart/usage#do-use-strings-in-part-of-directives" + type: "doc" labels: - "language" - "libraries" @@ -365,6 +378,7 @@ related_links: - text: "Nullability and generics" link: "/null-safety/understanding-null-safety#nullability-and-generics" + type: "doc" labels: - "language" - "type system" @@ -383,8 +397,10 @@ related_links: - text: "Organizing a package's libraries" link: "/tools/pub/create-packages#organizing-a-package" + type: "doc" - text: "Public package directories" link: "/tools/pub/package-layout#public-directories" + type: "doc" labels: - "language" - "libraries" @@ -396,10 +412,13 @@ related_links: - text: "Quick fixes for analysis issues" link: "https://medium.com/dartlang/quick-fixes-for-analysis-issues-c10df084971a" + type: "article" - text: "Diagnostic messages" link: "/tools/diagnostic-messages" + type: "doc" - text: "Linter rules" link: "/tools/linter-rules" + type: "doc" labels: - "tools" - "understanding diagnostics" @@ -415,6 +434,7 @@ related_links: - text: "Assist" link: "#assist" + type: "term" labels: - "tools" - "analysis" @@ -432,8 +452,10 @@ related_links: - text: "Places patterns can appear" link: "/language/patterns#places-patterns-can-appear" + type: "doc" - text: "Dive into Dart patterns and records" link: "https://codelabs.developers.google.com/codelabs/dart-patterns-records" + type: "tutorial" labels: - "language" - "patterns" @@ -472,8 +494,10 @@ related_links: - text: "Inheritance in Dart" link: "/language/extend" + type: "doc" - text: "Subtype relationship" link: "#subtype" + type: "term" labels: - "language" - "type system" @@ -519,8 +543,10 @@ related_links: - text: "Subclass" link: "#subclass" + type: "term" - text: "Substituting types" link: "/language/type-system#substituting-types" + type: "doc" labels: - "language" - "type system" @@ -611,10 +637,13 @@ related_links: - text: "Subtype relationship" link: "#subtype" + type: "term" - text: "Covariance and contravariance" link: "https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)" + type: "article" - text: "The covariant keyword" link: "/language/type-system#covariant-keyword" + type: "doc" labels: - "language" - "type system" diff --git a/src/_sass/_site.scss b/src/_sass/_site.scss index c9c2b06ba7..15e744d90f 100644 --- a/src/_sass/_site.scss +++ b/src/_sass/_site.scss @@ -9,6 +9,7 @@ @use 'components/code'; @use 'components/cookie-notice'; @use 'components/form'; +@use 'components/glossary'; @use 'components/header'; @use 'components/linter-rules'; @use 'components/search'; diff --git a/src/_sass/components/_glossary.scss b/src/_sass/components/_glossary.scss new file mode 100644 index 0000000000..1be8916be5 --- /dev/null +++ b/src/_sass/components/_glossary.scss @@ -0,0 +1,515 @@ +@mixin interaction-style($percentage: 4%) { + --site-interaction-base-values: 0 0 0; + background-image: linear-gradient(rgb(var(--site-interaction-base-values) / $percentage) 0 0); +} + +body.glossary-page { + --filled-button-container-color: #06599C; + --filled-button-text-color: #ffffff; + + --outline-button-border-color: rgba(0, 0, 0, .125); + --outline-button-text-color: #3a3a3a; + --text-button-text-color: #3a3a3a; + + --chip-container-color: transparent; + --chip-border-color: rgba(0, 0, 0, .5); + --chip-selected-container-color: rgb(194 229 255); + --chip-text-color: #3a3a3a; + + --text-field-border-color: rgba(0, 0, 0, .5); + --text-field-text-color: #3a3a3a; + + --menu-border-color: rgba(0, 0, 0, .5); + --menu-container-color: #ffffff; + --menu-item-container-color: transparent; + --menu-item-selected-container-color: rgb(194 229 255); + --menu-item-text-color: #3a3a3a; + + //--icon-button-container-color: ; + //--icon-button-color: ; + + --card-container-color: rgb(242, 245, 255); + --card-border-color: rgba(0, 0, 0, .125); + --card-text-color: #3a3a3a; + --card-min-width: 22rem; + + --card-grid-gap: 1rem; + + --focus-outline-color: #1967D2; + + .material-symbols { + user-select: none; + } + + #filter-and-search { + display: flex; + flex-direction: column; + flex-wrap: wrap; + justify-content: center; + gap: 0.75rem; + margin-bottom: 1rem; + + &.hidden { + display: none; + } + } + + .filter-group { + display: flex; + align-items: center; + gap: 0.25rem; + } + + .card-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--card-min-width)), 1fr)); + align-items: flex-start; + gap: var(--card-grid-gap); + margin: 0; + justify-content: center; + } + + .glossary-card { + display: flex; + flex-direction: column; + + border: 1px solid var(--card-border-color); + border-radius: 8px; + padding: 0.75rem; + gap: 0.5rem; + background-color: var(--card-container-color); + height: auto; + + scroll-margin: 4rem; + + &.collapsed { + height: 10rem; + overflow: hidden; + + .initial-content { + > :not(:first-child) { + display: none; + } + } + + .expandable-content { + display: none; + } + + .expand-button { + transform: rotate(180deg); + } + } + + .expand-button { + transition: transform .25s ease-in-out; + } + + p { + font-size: 0.95em; + + code { + font-size: 0.95em; + background-color: rgba(0, 0, 0, .05); + color: #212121; + border-radius: .25rem; + padding: .1rem .25rem; + text-wrap: nowrap; + } + } + + &.hidden { + display: none; + } + + .card-header { + // TODO(parlough): Remove these resets after bootstrap removed. + border: none; + background: none; + margin: 0; + padding: 0; + + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + } + } + + .card-title { + font-size: 1.25rem; + font-weight: 700; + margin: 0; + overflow: hidden; + } + + .filled-button { + color: var(--filled-button-text-color); + background-color: var(--filled-button-container-color); + + &:hover { + @include interaction-style(6%); + } + + &:active { + @include interaction-style(10%); + } + } + + .details-header { + font-weight: 500; + margin-bottom: 0.5rem; + font-size: 1rem; + } + + .resources-list { + list-style: none; + padding: 0.5rem; + margin: 0; + + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 0.5rem; + + li { + display: flex; + a { + display: flex; + flex-direction: row; + align-items: center; + gap: 0.35rem; + color: var(--filled-button-text-color); + background-color: var(--filled-button-container-color); + padding: 0.25rem 0.75rem; + font-size: 0.9em; + border-radius: 20px; + + .material-symbols { + font-variation-settings: 'FILL' 1; + font-size: 20px; + } + } + } + } + + .initial-content, .expandable-content { + > :last-child { + margin-bottom: 0; + } + } + + .card-details { + display: flex; + align-items: center; + gap: 10px; + font-size: 0.8em; + } + + .card-actions { + margin-top: auto; + padding-top: 0.5rem; + + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-end; + gap: 0.5rem; + + div { + display: flex; + + &.leading { + gap: 0.25rem; + user-select: none; + + span { + color: var(--card-text-color); + font-size: 20px; + font-variation-settings: 'FILL' 1; + } + } + + &.trailing { + gap: 0.5rem; + + a, button { + display: flex; + align-items: center; + + text-decoration: none; + background: none; + border-radius: 20px; + padding: 0 0.75rem; + height: 32px; + color: var(--outline-button-text-color); + border: 1px solid var(--outline-button-border-color); + + &:last-child { + border: none; + color: var(--filled-button-text-color); + background-color: var(--filled-button-container-color); + } + + &:hover { + @include interaction-style(6%); + } + + &:active { + @include interaction-style(10%); + } + + &:focus-visible { + outline-offset: 1px; + } + } + + button.hidden { + display: none; + } + } + } + } + + .chip-set { + display: flex; + flex-direction: row; + text-wrap: nowrap; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 0.5rem; + padding: 0 0.5rem; + } + + button.chip { + border: 1px solid var(--chip-border-color); + border-radius: 8px; + height: 2rem; + padding: 0 .5rem; + background: none; + color: var(--chip-text-color); + font-weight: 500; + user-select: none; + + display: flex; + align-items: center; + gap: 0.2rem; + + .label { + background: none; + } + + &:hover { + @include interaction-style(4%); + } + + &:active { + @include interaction-style(8%); + } + + .chip-icon { + align-self: center; + fill: currentcolor; + position: relative; + height: 18px; + width: 18px; + } + + .leading-icon { + display: none; + margin-right: 0.25rem; + } + } + + button.chip { + &.selected { + background-color: var(--chip-selected-container-color); + border: none; + + .leading-icon { + display: flex; + } + } + } + + .text-button { + background: none; + border: none; + color: var(--text-button-text-color); + border-radius: 8px; + user-select: none; + + padding: 0 .5rem; + height: 1.75rem; + + &:hover { + @include interaction-style(4%); + color: var(--text-button-text-color); + } + + &:active { + @include interaction-style(8%); + color: var(--text-button-text-color); + } + + &:focus { + color: var(--text-button-text-color); + } + } + + button { + background: none; + text-decoration: none; + padding: 0; + border: none; + user-select: none; + } + + .icon-button { + appearance: none; + display: flex; + flex-direction: row; + align-items: center; + height: 2rem; + + border-radius: 20px; + padding: 0.25rem; + color: var(--outline-button-text-color); + + &:hover { + @include interaction-style(6%); + } + + &:active { + @include interaction-style(10%); + } + } + + .search-row { + display: flex; + flex-direction: row; + align-items: center; + width: 100%; + gap: 0.5rem; + + .search-wrapper { + display: flex; + align-items: center; + width: 100%; + + border: 1px solid var(--text-field-border-color); + border-radius: 20px; + height: 3rem; + padding: 0 .5rem; + + .leading-icon { + padding-left: 0.25rem; + user-select: none; + } + + input { + background: none; + width: 100%; + font-size: 1rem; + cursor: text; + + &::-webkit-search-cancel-button { + display: none; + } + } + } + } + + section.content-search-results { + margin: 0.5rem 0 1rem; + } + + .button-menu-wrapper { + position: relative; + + .select-menu { + display: none; + position: absolute; + overflow: auto; + z-index: 5; + background-color: var(--menu-container-color); + border-radius: 0.5rem; + border: 1px solid var(--menu-border-color); + min-width: 100%; + max-height: 15rem; + overflow-y: scroll; + scrollbar-width: thin; + overscroll-behavior: contain; + margin-top: 0.25rem; + + ul { + list-style-type: none; + padding: 0; + margin: 0; + width: 100%; + + li { + &:first-child { + padding-top: 0.5rem; + } + + &:last-child { + padding-bottom: 0.5rem; + } + } + + // Menu item button. + button { + padding: 0.2rem 0.75rem 0.2rem 0.5rem; + width: 100%; + border: none; + background: none; + color: var(--menu-item-text-color); + font-weight: 500; + text-align: left; + user-select: none; + + &:hover { + @include interaction-style(4%); + } + + &:focus { + @include interaction-style(6%); + } + + &:active { + @include interaction-style(8%); + } + + display: flex; + flex-direction: row; + + span.material-symbols { + align-self: center; + vertical-align: center; + fill: currentcolor; + position: relative; + font-size: 1.25rem; + margin-right: 0.4rem; + + font-variation-settings: 'FILL' 1; + } + + &.selected { + background-color: var(--menu-item-selected-container-color); + } + } + } + + &.show-menu { + display: flex; + } + } + } + + .search-wrapper:has(:focus-visible), .chip:focus-visible, .text-button:focus-visible, .trailing a:focus-visible, .filled-button:focus-visible, .icon-button:focus-visible { + outline: 2px solid var(--focus-outline-color); + border-color: transparent; + } +} diff --git a/src/content/assets/js/main.js b/src/content/assets/js/main.js index 3944121623..b2197b28f4 100644 --- a/src/content/assets/js/main.js +++ b/src/content/assets/js/main.js @@ -208,6 +208,25 @@ function setupCopyButtons() { }); } +function setupExpandableCards() { + const currentFragment = window?.location.hash.trim().toLowerCase().substring(1); + const expandableCards = document.querySelectorAll('.expandable-card'); + expandableCards.forEach(card => { + const expandButton = card.querySelector('.expand-button'); + if (!expandButton) return; + + expandButton.addEventListener('click', (e) => { + e.preventDefault(); + e.target?.closest('.expandable-card').classList.toggle('collapsed'); + }); + if (card.querySelector('.card-title')?.id === currentFragment) { + card.scrollIntoView({block: 'start'}); + } else { + card.classList.add('collapsed'); + } + }); +} + $(function() { fixNav(); // Adjust heights for navigation elements setupOsTabs(); @@ -256,6 +275,8 @@ $(function() { // Initialize the video on the homepage, if it exists. initVideoModal(); + setupExpandableCards(); + document.addEventListener('keydown', handleSearchShortcut); createGallery( diff --git a/src/content/resources/glossary.md b/src/content/resources/glossary.md index 535257f436..00635f834d 100644 --- a/src/content/resources/glossary.md +++ b/src/content/resources/glossary.md @@ -2,6 +2,7 @@ title: Glossary description: A glossary reference for terminology used across dart.dev. body_class: glossary-page +toc: false --- {% comment %} @@ -12,19 +13,68 @@ The following are definitions of terms used across the Dart documentation. {% assign sorted_terms = glossary | sort: "term" %} + + +
+
+ {% for term in sorted_terms -%} - +
+
+

{{term.term}}

+ + +
+
-## {{term.term}}{% if term.id %} {:#{{term.id}}}{% endif %} +{{term.short_description}} + +
+
{{term.long_description | default: term.short_description }} -{% if term.related_links != empty -%} -**Related docs and resources:** +
+

Related docs and resources

+ + + + +
+
+
+ {% endfor -%} +
+