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 0d74ed9d56
commit 095480e9d6
11 changed files with 145 additions and 169 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,23 +1,24 @@
---
title: Content body
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.
title: Prose
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
---
## 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.
- Normalize the spacing of lists
- 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.
## 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
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

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

View File

@ -27,7 +27,7 @@ const { description, title } = Astro.props
</div>
</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">
<slot />
<slot name="main-content" />

View File

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

View File

@ -6,165 +6,119 @@
// Bootstrap docs content theming
//
.bd-content {
> h2,
> h3,
> h4 {
@layer custom {
.docs-content-body {
// 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);
}
// Offset content from fixed navbar when jumping to headings
> h2:not(:first-child) {
margin-top: 3rem;
.bd-subtitle {
@include font-size(1.5rem);
font-weight: 300;
}
> h3 {
margin-top: 2rem;
.bi {
width: 1em;
height: 1em;
vertical-align: -.125em;
fill: currentcolor;
}
> ul li,
> ol li {
margin-bottom: .25rem;
// stylelint-disable selector-max-type, selector-max-compound-selectors
> p ~ ul {
margin-top: -.5rem;
margin-bottom: 1rem;
.border-lg-start {
@include media-breakpoint-up(lg) {
border-left: var(--bs-border-width) solid var(--bs-border-color);
}
// stylelint-enable selector-max-type, selector-max-compound-selectors
}
// Override Bootstrap defaults
> .table,
> .table-responsive .table {
--bs-table-border-color: 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};
max-width: 100%;
margin-bottom: 1.5rem;
@include font-size(.875rem);
@include media-breakpoint-down(lg) {
&.table-bordered {
border: 0;
}
.dropdown-menu {
--bs-dropdown-bg: color-mix(in srgb, #{$blue-500}, #{$blue-600});
--bs-dropdown-link-active-bg: #{$blue-700};
}
thead {
border-bottom: 2px solid currentcolor;
.btn-secondary {
--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) {
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
}
// scss-docs-end custom-color-mode
}
.table-options {
td:nth-child(2) {
min-width: 160px;
}
}
.table-options td:last-child,
.table-utilities td:last-child {
min-width: 280px;
}
.table-swatches {
th {
color: var(--bs-emphasis-color);
}
td code {
white-space: nowrap;
}
}
.bd-title {
--bs-heading-color: var(--bs-emphasis-color);
@include font-size(3rem);
}
.bd-lead {
@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);
}
}
// stylelint-disable selector-no-qualifying-type
.bd-summary-link {
color: var(--bs-link-color);
&:hover,
details[open] > & {
color: var(--bs-link-hover-color);
}
}
// stylelint-enable selector-no-qualifying-type
// 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};
}
.btn-secondary {
--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);
}
}
// scss-docs-end custom-color-mode

View File

@ -7,7 +7,6 @@
}
.bd-layout {
@include media-breakpoint-up(lg) {
display: grid;
grid-template-areas: "sidebar main";
@ -55,7 +54,8 @@
grid-area: toc;
}
.bd-content {
.docs-content-body {
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
}