From 7cb8c5e4210dd65b216957b7c17f0033e1352e6c Mon Sep 17 00:00:00 2001 From: tom Date: Fri, 29 May 2026 12:54:06 -0400 Subject: [PATCH 1/4] refactor button styles --- package.json | 2 +- .../book-selector/book-selector.scss | 2 + src/app/components/carousel/carousel.scss | 2 + src/app/components/dialog/dialog.scss | 2 + src/app/components/jsx-helpers/raw-html.scss | 41 ++++++++++++ src/app/components/jsx-helpers/raw-html.tsx | 8 ++- src/app/components/more-fewer/more-fewer.scss | 2 + .../multiselect/book-tags/book-tags.scss | 2 + src/app/components/search-bar/search-bar.scss | 4 +- .../components/student-form/student-form.scss | 1 + .../menus/main-menu/dropdown/dropdown.scss | 5 ++ .../menus/menu-expander/menu-expander.scss | 6 +- .../header/sticky-note/sticky-note.scss | 2 + src/app/layouts/default/shared.scss | 1 + src/app/layouts/landing/footer/flex.scss | 2 + src/app/pages/ally-logos/ally-logos.scss | 4 ++ .../pages/assignable/sections/cta/cta.scss | 6 ++ .../get-this-title-files/get-this-title.scss | 4 ++ .../recommended-callout.scss | 2 + src/app/pages/details/details.scss | 2 + .../pages/errata-form/form/FileUploader.scss | 3 + src/app/pages/k12/k12-main/testimonial.scss | 2 + .../active-filters/active-filters.scss | 2 + .../mobile-controls/mobile-controls.scss | 2 + src/app/pages/partners/partners.scss | 2 + src/app/pages/research/research.scss | 18 ++++++ .../separatemap/search-box/inputs/inputs.scss | 3 +- src/app/pages/separatemap/separatemap.scss | 4 ++ src/styles/components/buttons.scss | 64 ------------------- src/styles/components/forms.scss | 6 +- src/styles/components/social.scss | 7 ++ src/styles/main.scss | 1 - yarn.lock | 6 +- 33 files changed, 139 insertions(+), 81 deletions(-) create mode 100644 src/app/components/jsx-helpers/raw-html.scss delete mode 100644 src/styles/components/buttons.scss diff --git a/package.json b/package.json index 4fa332489..549ebcaae 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "node-localstorage": "^2.2.1", "node-sass": "^8.0.0", "particles.js": "^2.0.0", - "pattern-library": "openstax/pattern-library", + "pattern-library": "openstax/pattern-library#semver:^1.5.0", "preact": "~10.24", "prettier": "^3", "react-modal": "^3.16.1", diff --git a/src/app/components/book-selector/book-selector.scss b/src/app/components/book-selector/book-selector.scss index c304e2b1c..f78f8c88d 100644 --- a/src/app/components/book-selector/book-selector.scss +++ b/src/app/components/book-selector/book-selector.scss @@ -73,6 +73,8 @@ overflow: hidden; .subject-toggle { + @include button-reset(); + align-items: center; background: none; border: 0; diff --git a/src/app/components/carousel/carousel.scss b/src/app/components/carousel/carousel.scss index a8ad5188b..462c85f24 100644 --- a/src/app/components/carousel/carousel.scss +++ b/src/app/components/carousel/carousel.scss @@ -7,6 +7,8 @@ max-width: calc(100vw - 3rem); .frame-changer { + @include button-reset(); + align-items: center; background-color: rgba(ui-color(black), 0.4); display: flex; diff --git a/src/app/components/dialog/dialog.scss b/src/app/components/dialog/dialog.scss index 44abf4916..3f0ec4cd9 100644 --- a/src/app/components/dialog/dialog.scss +++ b/src/app/components/dialog/dialog.scss @@ -51,6 +51,8 @@ dialog, .put-away { @include body-font(3.6rem); + @include button-reset(); + background-color: transparent; border: 0; box-shadow: none; diff --git a/src/app/components/jsx-helpers/raw-html.scss b/src/app/components/jsx-helpers/raw-html.scss new file mode 100644 index 000000000..5194cb39a --- /dev/null +++ b/src/app/components/jsx-helpers/raw-html.scss @@ -0,0 +1,41 @@ +@import 'pattern-library/core/pattern-library/headers'; + +// Styles for CMS-authored markup rendered by the adjacent component, +// whose container is tagged `.cms-content`. Buttons authored in CMS rich-text +// render through it. The base button plus the variant classes editors use +// (`btn-orange`, `cta`, `btn-cyan`, `btn-gold`, `btn-large`) are built from the +// pattern-library button mixins and scoped to that container, so they apply +// only to editor content and never globally. +.cms-content { + button, + .btn { + @include button(); + } + + .btn-large { + padding: 2.5rem; + } + + // Call-to-action buttons generally have this style + .cta > .btn { + padding: 1.5rem 2rem; + text-transform: uppercase; + } + + .cta > .btn, + .btn-orange { + @include button-type-specific(primary); + } + + .btn-cyan { + background-color: os-color(light-blue); + border: 0; + color: ui-color(white); + } + + .btn-gold { + background-color: os-color(gold); + border: 0; + color: ui-color(white); + } +} diff --git a/src/app/components/jsx-helpers/raw-html.tsx b/src/app/components/jsx-helpers/raw-html.tsx index d07df019d..5b21c0369 100644 --- a/src/app/components/jsx-helpers/raw-html.tsx +++ b/src/app/components/jsx-helpers/raw-html.tsx @@ -1,5 +1,7 @@ import React from 'react'; +import cn from 'classnames'; import usePortalContext from '~/contexts/portal'; +import './raw-html.scss'; // Making scripts work, per https://stackoverflow.com/a/47614491/392102 function activateScripts(el: HTMLElement) { @@ -45,6 +47,7 @@ export default function RawHTML({ Tag = 'div', html = '', embed = false, + className, ...otherProps }: RawHTMLArgs) { const ref = React.useRef(); @@ -60,6 +63,9 @@ export default function RawHTML({ return React.createElement(Tag, { ref, dangerouslySetInnerHTML: {__html: html}, - ...otherProps + ...otherProps, + // Tag all CMS-authored markup with `cms-content` so styles for editor + // content (e.g. buttons) can target it specifically. + className: cn('cms-content', className) }); } diff --git a/src/app/components/more-fewer/more-fewer.scss b/src/app/components/more-fewer/more-fewer.scss index f55de1a77..baeef4c31 100644 --- a/src/app/components/more-fewer/more-fewer.scss +++ b/src/app/components/more-fewer/more-fewer.scss @@ -5,6 +5,8 @@ grid-row-gap: 2rem; [role="button"] { + @include focus-indicator(); + cursor: pointer; } diff --git a/src/app/components/multiselect/book-tags/book-tags.scss b/src/app/components/multiselect/book-tags/book-tags.scss index a2240b308..cf6c874cf 100644 --- a/src/app/components/multiselect/book-tags/book-tags.scss +++ b/src/app/components/multiselect/book-tags/book-tags.scss @@ -30,6 +30,8 @@ padding: 0 1rem; .put-away { + @include button-reset(); + font-size: inherit; } } diff --git a/src/app/components/search-bar/search-bar.scss b/src/app/components/search-bar/search-bar.scss index b5d53986b..2dc9406c5 100644 --- a/src/app/components/search-bar/search-bar.scss +++ b/src/app/components/search-bar/search-bar.scss @@ -41,6 +41,8 @@ } .clear-search { + @include button-reset(); + grid-column: 1; grid-row: 1; justify-self: end; @@ -57,7 +59,7 @@ width: 100%; &:focus-within { - outline: 0.2 solid ui-color(focus-outline); + @include focus-style(); } .floating-label { diff --git a/src/app/components/student-form/student-form.scss b/src/app/components/student-form/student-form.scss index d1e222001..380d0c158 100644 --- a/src/app/components/student-form/student-form.scss +++ b/src/app/components/student-form/student-form.scss @@ -6,6 +6,7 @@ .cta .btn { @include button(); + @include button-type-specific(primary); margin: 2rem auto; text-transform: none; } diff --git a/src/app/layouts/default/header/menus/main-menu/dropdown/dropdown.scss b/src/app/layouts/default/header/menus/main-menu/dropdown/dropdown.scss index b655cac25..38b6721d2 100644 --- a/src/app/layouts/default/header/menus/main-menu/dropdown/dropdown.scss +++ b/src/app/layouts/default/header/menus/main-menu/dropdown/dropdown.scss @@ -38,6 +38,11 @@ .dropdown { position: relative; + // The dropdown toggle is an ``, so it carries the ring itself. + > a[role="button"] { + @include focus-indicator(); + } + // Keeps rightmost menu from hanging off the screen &.rightmost .dropdown-container { right: -1rem; diff --git a/src/app/layouts/default/header/menus/menu-expander/menu-expander.scss b/src/app/layouts/default/header/menus/menu-expander/menu-expander.scss index ea820ee86..6a2322fb1 100644 --- a/src/app/layouts/default/header/menus/menu-expander/menu-expander.scss +++ b/src/app/layouts/default/header/menus/menu-expander/menu-expander.scss @@ -34,11 +34,7 @@ $button-size: 1.6rem; top: 0; } - &:hover, - &:focus, - &:active { - outline: none; - } + @include button-reset(); span { // create middle line diff --git a/src/app/layouts/default/header/sticky-note/sticky-note.scss b/src/app/layouts/default/header/sticky-note/sticky-note.scss index f392f10d5..15b7bb5ad 100644 --- a/src/app/layouts/default/header/sticky-note/sticky-note.scss +++ b/src/app/layouts/default/header/sticky-note/sticky-note.scss @@ -51,6 +51,8 @@ } .put-away { + @include button-reset(); + align-items: center; align-self: flex-end; display: flex; diff --git a/src/app/layouts/default/shared.scss b/src/app/layouts/default/shared.scss index b748e72c2..8159da34d 100644 --- a/src/app/layouts/default/shared.scss +++ b/src/app/layouts/default/shared.scss @@ -3,6 +3,7 @@ #lower-sticky-note .put-away, #microsurvey .put-away { @include body-font(1.4rem); + @include button-reset(); background-color: rgba(ui-color(black), 0.56); border-radius: 0.3rem; diff --git a/src/app/layouts/landing/footer/flex.scss b/src/app/layouts/landing/footer/flex.scss index bc7050c7a..e73b1ce22 100644 --- a/src/app/layouts/landing/footer/flex.scss +++ b/src/app/layouts/landing/footer/flex.scss @@ -73,6 +73,8 @@ } button { + @include button-reset(); + background-color: transparent; color: inherit; display: inline; diff --git a/src/app/pages/ally-logos/ally-logos.scss b/src/app/pages/ally-logos/ally-logos.scss index f0c54ed0a..c9c1b2a6f 100644 --- a/src/app/pages/ally-logos/ally-logos.scss +++ b/src/app/pages/ally-logos/ally-logos.scss @@ -36,6 +36,10 @@ .url { padding: 0.5rem 0 0.5rem 1rem; } + + button { + @include button-reset(); + } } .boxed.smaller-icon img { diff --git a/src/app/pages/assignable/sections/cta/cta.scss b/src/app/pages/assignable/sections/cta/cta.scss index 6ac5fdd3e..83c7abd23 100644 --- a/src/app/pages/assignable/sections/cta/cta.scss +++ b/src/app/pages/assignable/sections/cta/cta.scss @@ -29,4 +29,10 @@ .primary { @extend %primary; } + + // CTA buttons are large and uppercased. + .btn { + padding: 1.5rem 2rem; + text-transform: uppercase; + } } diff --git a/src/app/pages/details/common/get-this-title-files/get-this-title.scss b/src/app/pages/details/common/get-this-title-files/get-this-title.scss index 0028b6bc2..6bd4d2dac 100644 --- a/src/app/pages/details/common/get-this-title-files/get-this-title.scss +++ b/src/app/pages/details/common/get-this-title-files/get-this-title.scss @@ -72,6 +72,10 @@ } } + .show-toc { + @include focus-indicator(); + } + .options { display: flex; flex-direction: column; diff --git a/src/app/pages/details/common/get-this-title-files/recommended-callout/recommended-callout.scss b/src/app/pages/details/common/get-this-title-files/recommended-callout/recommended-callout.scss index 600d98925..2f897de2e 100644 --- a/src/app/pages/details/common/get-this-title-files/recommended-callout/recommended-callout.scss +++ b/src/app/pages/details/common/get-this-title-files/recommended-callout/recommended-callout.scss @@ -50,6 +50,8 @@ $extra-dark-mask: rgba(0, 0, 0, 0.4); } .put-away { + @include button-reset(); + background-color: text-color(link); background-blend-mode: multiply; background-image: linear-gradient(to bottom, $darkening-mask, $darkening-mask); diff --git a/src/app/pages/details/details.scss b/src/app/pages/details/details.scss index 9a051eeaa..71f5dcea0 100644 --- a/src/app/pages/details/details.scss +++ b/src/app/pages/details/details.scss @@ -91,6 +91,8 @@ $gradient-sequence: ui-color(white), ui-color(white) 50%, transparent; } .close-toc { + @include focus-indicator(); + align-items: center; border-radius: 50%; cursor: pointer; diff --git a/src/app/pages/errata-form/form/FileUploader.scss b/src/app/pages/errata-form/form/FileUploader.scss index eb189f107..f01484676 100644 --- a/src/app/pages/errata-form/form/FileUploader.scss +++ b/src/app/pages/errata-form/form/FileUploader.scss @@ -1,3 +1,4 @@ + @mixin file-button() { align-items: center; display: grid; @@ -13,6 +14,8 @@ } .clear-file { + @include button-reset(); + appearance: none; background-color: inherit; color: inherit; diff --git a/src/app/pages/k12/k12-main/testimonial.scss b/src/app/pages/k12/k12-main/testimonial.scss index 999b87ef5..caa713c4e 100644 --- a/src/app/pages/k12/k12-main/testimonial.scss +++ b/src/app/pages/k12/k12-main/testimonial.scss @@ -97,6 +97,8 @@ padding: 5rem $normal-margin 7rem; button { + @include button-reset(); + appearance: auto; background-color: ui-color(white); width: 1rem; diff --git a/src/app/pages/partners/active-filters/active-filters.scss b/src/app/pages/partners/active-filters/active-filters.scss index fc2d385b5..a5cafb5af 100644 --- a/src/app/pages/partners/active-filters/active-filters.scss +++ b/src/app/pages/partners/active-filters/active-filters.scss @@ -43,6 +43,8 @@ } button { + @include button-reset(); + appearance: none; background-color: transparent; color: text-color(normal); diff --git a/src/app/pages/partners/mobile-controls/mobile-controls.scss b/src/app/pages/partners/mobile-controls/mobile-controls.scss index c76408db3..25866f68b 100644 --- a/src/app/pages/partners/mobile-controls/mobile-controls.scss +++ b/src/app/pages/partners/mobile-controls/mobile-controls.scss @@ -35,6 +35,8 @@ top: 0; .put-away { + @include button-reset(); + font-size: 3rem; font-weight: normal; transform: translateY(-0.5rem); diff --git a/src/app/pages/partners/partners.scss b/src/app/pages/partners/partners.scss index add421c78..0d9428262 100644 --- a/src/app/pages/partners/partners.scss +++ b/src/app/pages/partners/partners.scss @@ -28,6 +28,8 @@ } .put-away { + @include button-reset(); + background-color: inherit; color: inherit; margin-left: $normal-margin; diff --git a/src/app/pages/research/research.scss b/src/app/pages/research/research.scss index 31943e176..11b3a32d2 100644 --- a/src/app/pages/research/research.scss +++ b/src/app/pages/research/research.scss @@ -41,11 +41,23 @@ @extend %content; } + // contact-us renders ` {/* @ts-expect-error-next-line label is not a known attribute */}
diff --git a/src/app/pages/research/components/publications.tsx b/src/app/pages/research/components/publications.tsx index 486f659b0..230db6813 100644 --- a/src/app/pages/research/components/publications.tsx +++ b/src/app/pages/research/components/publications.tsx @@ -45,11 +45,11 @@ export const Publications = ({ {publicationList.map((publication, index) => ( ))} - { if (viewAll) { scrollToPublications(); @@ -57,7 +57,6 @@ export const Publications = ({ setViewAll(!viewAll); }} css={{ - cursor: 'pointer', color: colors.linkText, alignSelf: 'center' }} @@ -67,7 +66,7 @@ export const Publications = ({ />   {viewAll ? 'View Less' : 'View All Publications'} - + ); diff --git a/src/app/pages/research/research.scss b/src/app/pages/research/research.scss index 11b3a32d2..f8975ebe0 100644 --- a/src/app/pages/research/research.scss +++ b/src/app/pages/research/research.scss @@ -72,10 +72,27 @@ padding-bottom: 2rem; } - // `.py-4` is a padding utility, but the research "view all" toggles are - // `role="button"` spans/paragraphs carrying it — give those a focus ring. - .py-4[role="button"] { + // The "view all" toggles are real