diff --git a/.changeset/scope-preflight-css.md b/.changeset/scope-preflight-css.md new file mode 100644 index 00000000..65df1bbb --- /dev/null +++ b/.changeset/scope-preflight-css.md @@ -0,0 +1,7 @@ +--- +'@youversion/platform-react-ui': patch +'@youversion/platform-core': patch +'@youversion/platform-react-hooks': patch +--- + +Fix Tailwind preflight CSS leaking globally into consumer apps. The unscoped `@import 'tailwindcss/preflight.css'` was resetting styles on all elements (h1–h6 font size/weight, margins, padding, list styles, etc.) across the entire page. Preflight resets are now scoped to `[data-yv-sdk]` so they only apply inside SDK components. diff --git a/packages/ui/src/styles/global.css b/packages/ui/src/styles/global.css index ebd5fe6b..2e4e1291 100644 --- a/packages/ui/src/styles/global.css +++ b/packages/ui/src/styles/global.css @@ -20,13 +20,168 @@ * Note: CSS linter warnings on these imports are a known issue and do not * affect functionality. */ -@import 'tailwindcss/preflight.css' prefix(yv); +/* + * NOTE: We intentionally do NOT import 'tailwindcss/preflight.css' globally. + * Instead, preflight resets are scoped to [data-yv-sdk] below so our SDK + * components get the reset without nuking consumer app styles. + */ @import 'tailwindcss/theme.css' prefix(yv); @import 'tailwindcss/utilities.css' prefix(yv); - @import 'tw-animate-css'; @import './bible-reader.css'; +/* #region Tailwind's Reset CSS, scoped to [data-yv-sdk] */ +/* + * :where() is a CSS pseudo-class that drops the specificity of + * everything inside it to zero (0,0,0,0). The selectors still + * match, but they never win a specificity fight. This is desired. + */ +:where([data-yv-sdk]) { + *, + ::after, + ::before, + ::backdrop, + ::file-selector-button { + font: inherit; + font-family: var(--yv-font-sans); + box-sizing: border-box; + margin: 0; + padding: 0; + border: 0 solid; + } + + line-height: 1.5; + -webkit-text-size-adjust: 100%; + tab-size: 4; + -webkit-tap-highlight-color: transparent; + + hr { + height: 0; + color: inherit; + border-top-width: 1px; + } + + abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + font-size: inherit; + font-weight: inherit; + } + + a { + color: inherit; + -webkit-text-decoration: inherit; + text-decoration: inherit; + } + + b, + strong { + font-weight: bolder; + } + + code, + kbd, + samp, + pre { + font-family: var(--yv-font-mono); + font-size: 1em; + } + + small { + font-size: 80%; + } + + sub, + sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; + } + + sub { + bottom: -0.25em; + } + + sup { + top: -0.5em; + } + + table { + text-indent: 0; + border-color: inherit; + border-collapse: collapse; + } + + ol, + ul, + menu { + list-style: none; + } + + img, + svg, + video, + canvas, + audio, + iframe, + embed, + object { + display: block; + vertical-align: middle; + } + + img, + video { + max-width: 100%; + height: auto; + } + + button, + input, + select, + optgroup, + textarea, + ::file-selector-button { + font: inherit; + font-family: var(--yv-font-sans); + font-feature-settings: inherit; + font-variation-settings: inherit; + letter-spacing: inherit; + color: inherit; + border-radius: 0; + background-color: transparent; + opacity: 1; + } + + ::placeholder { + opacity: 1; + } + + textarea { + resize: vertical; + } + + button, + input:where([type='button'], [type='reset'], [type='submit']), + ::file-selector-button { + appearance: button; + } + + [hidden]:where(:not([hidden='until-found'])) { + display: none !important; + } +} +/* #endregion Scoped Preflight */ + /* #region shadcn UI theme */ @custom-variant dark (&:is([data-yv-sdk][data-yv-theme='dark'] *));