1
0
mirror of https://github.com/twbs/bootstrap.git synced 2025-08-27 15:19:52 +02:00

New .prose component, put it to work in the docs

This commit is contained in:
Mark Otto
2025-04-02 10:00:53 -07:00
parent 12fb082b3b
commit e311985f1e
11 changed files with 153 additions and 63 deletions

View File

@@ -2,9 +2,10 @@
@use "../mixins/transition" as *; @use "../mixins/transition" as *;
@layer content { @layer content {
.content-body { .prose {
--#{$prefix}content-font-size: 16px; --#{$prefix}content-font-size: 16px;
--#{$prefix}content-gap: 24px; --#{$prefix}content-gap: 24px;
--#{$prefix}heading-color: light-dark(var(--bs-gray-900), var(--bs-white));
position: relative; position: relative;
max-width: 1000px; max-width: 1000px;
@@ -38,12 +39,30 @@
h4, h4,
h5, h5,
h6 { h6 {
--bs-heading-color: var(--bs-emphasis-color);
margin-top: 0; margin-top: 0;
margin-bottom: calc(var(--#{$prefix}content-gap) / 2); margin-bottom: calc(var(--#{$prefix}content-gap) / 2);
font-weight: 500; font-weight: 500;
line-height: 1.25; line-height: 1.25;
} }
h1,
h2 {
&:not(:first-child) {
margin-top: calc(var(--#{$prefix}content-gap) * 1.5);
}
}
h3,
h4,
h5,
h6 {
&:not(:first-child) {
margin-top: calc(var(--#{$prefix}content-gap) * 1.25);
}
}
h1 { h1 {
font-size: 2.25em; font-size: 2.25em;
line-height: 1.1; line-height: 1.1;
@@ -66,15 +85,15 @@
} }
a:not([class]) { a:not([class]) {
color: var(--ui-theme-primary-text); color: var(--#{$prefix}link-color);
text-decoration: underline; text-decoration: underline;
text-decoration-color: color-mix(in srgb, var(--ui-theme-primary-text) 25%, transparent); text-decoration-color: color-mix(in srgb, var(--#{$prefix}link-color) 25%, transparent);
text-underline-offset: 4px; text-underline-offset: 4px;
@include transition(.1s text-decoration-color ease-in-out); @include transition(.1s text-decoration-color ease-in-out);
} }
a:not([class]):hover { a:not([class]):hover {
text-decoration-color: var(--ui-theme-primary-text); text-decoration-color: var(--#{$prefix}link-hover-color);
} }
img { img {
@@ -100,6 +119,7 @@
border: 1px solid var(--#{$prefix}border-color); border: 1px solid var(--#{$prefix}border-color);
} }
dt { dt {
font-weight: 500; font-weight: 500;
} }

View File

@@ -212,7 +212,7 @@
b, b,
strong { strong {
font-weight: $font-weight-bolder; font-weight: $font-weight-medium;
} }
@@ -220,14 +220,16 @@
// //
// Add the correct font size in all browsers // Add the correct font size in all browsers
small, .small { small,
.small {
@include font-size($small-font-size); @include font-size($small-font-size);
} }
// Mark // Mark
mark, .mark { mark,
.mark {
padding: $mark-padding; padding: $mark-padding;
color: var(--#{$prefix}highlight-color); color: var(--#{$prefix}highlight-color);
background-color: var(--#{$prefix}highlight-bg); background-color: var(--#{$prefix}highlight-bg);
@@ -456,8 +458,7 @@
display: none !important; display: none !important;
} }
// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` // 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` // controls in Android 4.
// controls in Android 4.
// 2. Correct the inability to style clickable types in iOS and Safari. // 2. Correct the inability to style clickable types in iOS and Safari.
// 3. Opinionated: add "hand" cursor to non-disabled button elements. // 3. Opinionated: add "hand" cursor to non-disabled button elements.

View File

@@ -2,4 +2,4 @@
@forward "type"; @forward "type";
@forward "tables"; @forward "tables";
@forward "images"; @forward "images";
@forward "content-body"; @forward "prose";

View File

@@ -52,7 +52,7 @@
- title: Images - title: Images
- title: Tables - title: Tables
- title: Figures - title: Figures
- title: Content body - title: Prose
- title: Forms - title: Forms
icon: ui-radios icon: ui-radios

View File

@@ -121,7 +121,7 @@ export default () => {
// Links // Links
// ------------------------------- // -------------------------------
// Disable empty links in docs examples only // Disable empty links in docs examples only
document.querySelectorAll('.bd-content [href="#"]') document.querySelectorAll('.docs-content-body [href="#"]')
.forEach(link => { .forEach(link => {
link.addEventListener('click', event => { link.addEventListener('click', event => {
event.preventDefault() event.preventDefault()

View File

@@ -1,23 +1,24 @@
--- ---
title: Content body title: Prose
description: Use the `.content-body` wrapper class to make long form content more easily without the need for specifying Bootstrap classes on every element. Especially useful for converting Markdown or MDX to HTML, or simply for making content heavy pages more readable. description: Use the `.prose` wrapper class to make long form content more easily without the need for specifying Bootstrap classes on every element. Especially useful for converting Markdown or MDX to HTML, or simply for making content heavy pages more readable.
toc: true toc: true
--- ---
## How it works ## How it works
Wrap your content in the `.content-body` class to get modified font-size, line-height, and spacing specifically designed for long form content that originals from source Markdown files or WYSIWYG editors. Here's what we do with that class: Wrap your content in the `.prose` class to get modified font-size, line-height, and spacing specifically designed for long form content that originals from source Markdown files or WYSIWYG editors. Here's what we do with that class:
- Set a base `font-size`, `line-height`, and some local CSS variables on the parent element. - Set a base `font-size`, `line-height`, and some local CSS variables on the parent element.
- Normalize the spacing of lists - Normalize the spacing of lists
- Set a default `margin-bottom` for headings. - Set a default `margin-bottom` for headings.
- Some headings get an additional `margin-top` to ensure proper spacing between headings and other content.
- Style blockquotes, code, and other inline elements. - Style blockquotes, code, and other inline elements.
## Example ## Example
This is an example of source Markdown that shows several types of HTML content supported in this `.content-body` wrapper class. This is an example of source Markdown that shows several types of HTML content supported in this `.prose` wrapper class.
<div class="bd-example content-body"> <div class="bd-example prose">
# Lorem ipsum dolor sit amet # Lorem ipsum dolor sit amet
Cum sociis natoque penatibus et magnis [dis parturient montes](#), nascetur ridiculus mus. *Aenean eu leo quam.* Pellentesque ornare sem lacinia quam venenatis vestibulum. Sed posuere consectetur est at lobortis. Cras mattis consectetur purus sit amet fermentum. Cum sociis natoque penatibus et magnis [dis parturient montes](#), nascetur ridiculus mus. *Aenean eu leo quam.* Pellentesque ornare sem lacinia quam venenatis vestibulum. Sed posuere consectetur est at lobortis. Cras mattis consectetur purus sit amet fermentum.

View File

@@ -109,7 +109,7 @@ if (frontmatter.toc) {
<Ads /> <Ads />
</div> </div>
<div class="bd-content ps-lg-2"> <div class="docs-content-body prose ps-lg-2">
{ {
frontmatter.sections && ( frontmatter.sections && (
<div class="row g-3"> <div class="row g-3">

View File

@@ -27,7 +27,7 @@ const { description, title } = Astro.props
</div> </div>
</header> </header>
<main class="bd-content order-1 py-5" id="content"> <main class="docs-content-body order-1 py-5" id="content">
<div class="container-2xl bd-gutter"> <div class="container-2xl bd-gutter">
<slot /> <slot />
<slot name="main-content" /> <slot name="main-content" />

View File

@@ -8,7 +8,7 @@ import { getSlug } from '@libs/utils'
{ {
getData('examples').map(({ category, description, examples, external }) => { getData('examples').map(({ category, description, examples, external }) => {
return ( return (
<div class="bd-content"> <div class="docs-content-body">
<h2 id={getSlug(category)}>{category}</h2> <h2 id={getSlug(category)}>{category}</h2>
<p>{description}</p> <p>{description}</p>
{category === 'RTL' && ( {category === 'RTL' && (

View File

@@ -6,51 +6,118 @@
// Bootstrap docs content theming // Bootstrap docs content theming
// //
.bd-content { @layer custom {
> h2, .docs-content-body {
> h3, // Override Bootstrap defaults
> h4 { > .table,
--bs-heading-color: var(--bs-emphasis-color); > .table-responsive .table {
} --bs-table-border-color: var(--bs-border-color);
// Offset content from fixed navbar when jumping to headings max-width: 100%;
> h2:not(:first-child) { margin-bottom: 1.5rem;
margin-top: 3rem; @include font-size(.875rem);
}
> h3 { @include media-breakpoint-down(lg) {
margin-top: 2rem; &.table-bordered {
} border: 0;
}
> ul li,
> ol li {
margin-bottom: .25rem;
// stylelint-disable selector-max-type, selector-max-compound-selectors
> p ~ ul {
margin-top: -.5rem;
margin-bottom: 1rem;
}
// stylelint-enable selector-max-type, selector-max-compound-selectors
}
// Override Bootstrap defaults
> .table,
> .table-responsive .table {
--bs-table-border-color: var(--bs-border-color);
max-width: 100%;
margin-bottom: 1.5rem;
@include font-size(.875rem);
@include media-breakpoint-down(lg) {
&.table-bordered {
border: 0;
} }
thead {
border-bottom: 2px solid currentcolor;
}
tbody:not(:first-child) {
border-top: 2px solid currentcolor;
}
th,
td {
&:first-child {
padding-left: 0;
}
&:not(:last-child) {
padding-right: 1.5rem;
}
}
th {
color: var(--bs-emphasis-color);
}
strong {
color: var(--bs-emphasis-color);
}
// Prevent breaking of code
// stylelint-disable selector-max-compound-selectors
th,
td:first-child > code {
white-space: nowrap;
}
// stylelint-enable selector-max-compound-selectors
}
}
.table-options {
td:nth-child(2) {
min-width: 160px;
}
}
.table-options td:last-child,
.table-utilities td:last-child {
min-width: 280px;
}
.bd-title {
--bs-heading-color: var(--bs-emphasis-color);
@include font-size(3rem);
}
.bd-subtitle {
@include font-size(1.5rem);
font-weight: 300;
}
.bi {
width: 1em;
height: 1em;
vertical-align: -.125em;
fill: currentcolor;
}
.border-lg-start {
@include media-breakpoint-up(lg) {
border-left: var(--bs-border-width) solid var(--bs-border-color);
}
}
// scss-docs-start custom-color-mode
[data-bs-theme="blue"] {
--bs-body-color: var(--bs-white);
// --bs-body-color-rgb: #{to-rgb($white)};
--bs-body-bg: var(--bs-blue);
// --bs-body-bg-rgb: #{to-rgb($blue)};
--bs-tertiary-bg: #{$blue-600};
.dropdown-menu {
--bs-dropdown-bg: color-mix(in srgb, #{$blue-500}, #{$blue-600});
--bs-dropdown-link-active-bg: #{$blue-700};
} }
thead { .btn-secondary {
border-bottom: 2px solid currentcolor; --bs-btn-bg: #{color-mix(in srgb, #{$gray-600}, #{$blue-400})};
--bs-btn-border-color: #{rgba($white, .25)};
// --bs-btn-hover-bg: #{darken(color-mix(in srgb, #{$gray-600}, #{$blue-400}, .5), 5%)};
--bs-btn-hover-bg: color-mix(in srgb, #{$gray-600}, #{$blue-400});
--bs-btn-hover-border-color: #{rgba($white, .25)};
// --bs-btn-active-bg: #{darken(color-mix(in srgb, #{$gray-600}, #{$blue-400}, .5), 10%)};
--bs-btn-active-bg: color-mix(in srgb, #{$gray-600}, #{$blue-400});
--bs-btn-active-border-color: #{rgba($white, .5)};
--bs-btn-focus-border-color: #{rgba($white, .5)};
--bs-btn-focus-box-shadow: 0 0 0 .25rem rgb(255, 255, 255, .2);
} }
tbody:not(:first-child) { tbody:not(:first-child) {
@@ -84,6 +151,7 @@
} }
// stylelint-enable selector-max-compound-selectors // stylelint-enable selector-max-compound-selectors
} }
// scss-docs-end custom-color-mode
} }
.table-options { .table-options {

View File

@@ -7,7 +7,6 @@
} }
.bd-layout { .bd-layout {
@include media-breakpoint-up(lg) { @include media-breakpoint-up(lg) {
display: grid; display: grid;
grid-template-areas: "sidebar main"; grid-template-areas: "sidebar main";
@@ -55,7 +54,8 @@
grid-area: toc; grid-area: toc;
} }
.bd-content { .docs-content-body {
grid-area: content; grid-area: content;
min-width: 1px; // Fix width when bd-content contains a `<pre>` https://github.com/twbs/bootstrap/issues/25410 width: 100%;
min-width: 1px; // Fix width when this element contains a `<pre>` https://github.com/twbs/bootstrap/issues/25410
} }